Get a full tcp handshake, send data, and close cleanly
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from http import server
|
||||
from turtle import xcor
|
||||
from scapy.layers.inet import Ether, IP, TCP
|
||||
from scapy.layers.l2 import ARP
|
||||
from scapy.data import IP_PROTOS
|
||||
@@ -107,7 +108,7 @@ async def test_irl(dut):
|
||||
|
||||
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
serversocket.bind((tb_ip, 5678))
|
||||
serversocket.listen(5)
|
||||
serversocket.listen(1)
|
||||
t = TunTapInterface('tun0')
|
||||
|
||||
|
||||
@@ -176,7 +177,10 @@ async def test_irl(dut):
|
||||
|
||||
t.send(ip_packet)
|
||||
|
||||
pkt = t.recv()
|
||||
while True:
|
||||
pkt = t.recv()
|
||||
if (pkt.proto == IP_PROTOS.tcp):
|
||||
break
|
||||
print(pkt)
|
||||
|
||||
tcp_synack = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||
@@ -206,6 +210,28 @@ async def test_irl(dut):
|
||||
|
||||
con, addr = serversocket.accept()
|
||||
|
||||
# Construct a descriptor in memry
|
||||
tb.axil_ram.write_dword(0x00000000, 0x00001000)
|
||||
tb.axil_ram.write_dword(0x00000004, 64)
|
||||
tb.axil_ram.write_dword(0x00000008, 0)
|
||||
tb.axil_ram.write_dword(0x0000000c, 0)
|
||||
|
||||
test_data = bytearray([x % 256 for x in range(256)])
|
||||
|
||||
tb.axil_ram.write(0x1000, test_data)
|
||||
|
||||
await tb.axil_master.write_dword(0x22c, 0)
|
||||
await tb.axil_master.write_dword(0x220, 0x00000000)
|
||||
await tb.axil_master.write_dword(0x224, 0x00000000)
|
||||
|
||||
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||
packet = Ether(resp.get_payload())
|
||||
|
||||
t.send(packet.payload)
|
||||
|
||||
con.recv(64)
|
||||
tb.log.info("Received 64 packets")
|
||||
|
||||
con.close()
|
||||
serversocket.close()
|
||||
|
||||
@@ -215,6 +241,18 @@ async def test_irl(dut):
|
||||
break
|
||||
print(pkt)
|
||||
|
||||
tcp_ack = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||
|
||||
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_ack.build()))
|
||||
|
||||
tb.log.info("Expecting to send an F here")
|
||||
|
||||
while True:
|
||||
pkt = t.recv()
|
||||
if (pkt.proto == IP_PROTOS.tcp):
|
||||
break
|
||||
print(pkt)
|
||||
|
||||
tcp_fin = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||
|
||||
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_fin.build()))
|
||||
@@ -240,31 +278,16 @@ async def test_irl(dut):
|
||||
|
||||
t.send(ip_packet)
|
||||
|
||||
return
|
||||
tb.log.info("Expecting to send last ACK here")
|
||||
|
||||
while True:
|
||||
pkt = t.recv()
|
||||
if (pkt.proto == IP_PROTOS.tcp):
|
||||
break
|
||||
print(pkt)
|
||||
|
||||
tcp_fin = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||
|
||||
# Construct a descriptor in memry
|
||||
tb.axil_ram.write_dword(0x00000000, 0x00001000)
|
||||
tb.axil_ram.write_dword(0x00000004, 64)
|
||||
tb.axil_ram.write_dword(0x00000008, 0)
|
||||
tb.axil_ram.write_dword(0x0000000c, 0)
|
||||
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_fin.build()))
|
||||
|
||||
test_data = bytearray([x % 256 for x in range(256)])
|
||||
|
||||
tb.axil_ram.write(0x1000, test_data)
|
||||
|
||||
|
||||
|
||||
await tb.axil_master.write_dword(0x22c, 0)
|
||||
await tb.axil_master.write_dword(0x220, 0x00000000)
|
||||
await tb.axil_master.write_dword(0x224, 0x00000000)
|
||||
|
||||
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||
packet = Ether(resp.get_payload())
|
||||
|
||||
t.send(packet.payload)
|
||||
|
||||
# con.recv(64)
|
||||
|
||||
serversocket.close()
|
||||
await Timer(Decimal(CLK_PERIOD_NS * 1000), units='ns')
|
||||
|
||||
@@ -4,6 +4,8 @@ module tcp_packet_generator (
|
||||
|
||||
axis_intf.SLAVE s_axis_data,
|
||||
|
||||
input wire i_no_data,
|
||||
|
||||
input wire [15:0] i_ip_len,
|
||||
input wire [31:0] i_seq_number,
|
||||
input wire [31:0] i_ack_number,
|
||||
@@ -21,8 +23,33 @@ module tcp_packet_generator (
|
||||
ip_intf.MASTER m_ip
|
||||
);
|
||||
|
||||
axis_intf #(.DATA_WIDTH(8)) pre_checksum_data();
|
||||
axis_intf #(.DATA_WIDTH(8)) post_checksum_data();
|
||||
|
||||
logic saf_ready;
|
||||
|
||||
assign pre_checksum_data.tdata = s_axis_data.tdata;
|
||||
assign pre_checksum_data.tkeep = s_axis_data.tkeep;
|
||||
assign pre_checksum_data.tvalid = s_axis_data.tvalid & saf_ready;
|
||||
assign s_axis_data.tready = pre_checksum_data.tready & saf_ready;
|
||||
assign pre_checksum_data.tlast = s_axis_data.tlast;
|
||||
assign pre_checksum_data.tuser = s_axis_data.tuser;
|
||||
|
||||
axis_saf_fifo #(
|
||||
.DATA_DEPTH_L2(11),
|
||||
.CTRL_DEPTH_L2(1)
|
||||
) u_checksum_fifo (
|
||||
.sclk(i_clk),
|
||||
.srst(i_rst),
|
||||
.s_axis(pre_checksum_data),
|
||||
|
||||
.mclk(i_clk),
|
||||
.mrst(i_rst),
|
||||
.m_axis(post_checksum_data)
|
||||
);
|
||||
|
||||
logic [31:0] counter, counter_next;
|
||||
enum logic [1:0] {IDLE, HEADER, DATA} state, state_next;
|
||||
enum logic [1:0] {IDLE, DATA_CHECKSUM, HEADER, DATA} state, state_next;
|
||||
|
||||
|
||||
logic [31:0] checksum_counter, checksum_counter_next;
|
||||
@@ -34,7 +61,13 @@ logic checksum_clear;
|
||||
logic [31:0] checksum_data;
|
||||
logic [15:0] checksum_final;
|
||||
|
||||
checksum_calc u_checksum_calc(
|
||||
logic [31:0] data_expand, data_expand_next;
|
||||
logic data_checksum_enable;
|
||||
logic data_checksum_clear;
|
||||
logic [31:0] data_checksum_data;
|
||||
logic [15:0] data_checksum_final;
|
||||
|
||||
checksum_calc u_header_checksum_calc(
|
||||
.i_rst (i_rst),
|
||||
.i_clk (i_clk),
|
||||
.i_clear (checksum_clear),
|
||||
@@ -49,10 +82,12 @@ always_ff @(posedge i_clk) begin
|
||||
counter <= '0;
|
||||
checksum_counter <= '0;
|
||||
state <= IDLE;
|
||||
data_expand <= '0;
|
||||
end else begin
|
||||
counter <= counter_next;
|
||||
checksum_counter <= checksum_counter_next;
|
||||
state <= state_next;
|
||||
data_expand <= data_expand_next;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,6 +99,10 @@ always_comb begin
|
||||
checksum_clear = '0;
|
||||
checksum_enable = '0;
|
||||
|
||||
saf_ready = '0;
|
||||
|
||||
data_expand_next = data_expand;
|
||||
|
||||
case (state)
|
||||
|
||||
IDLE: begin
|
||||
@@ -82,7 +121,32 @@ always_comb begin
|
||||
m_ip.ip_dest_ip = i_dst_ip;
|
||||
|
||||
if (m_ip.ip_hdr_ready) begin
|
||||
if (i_no_data) begin
|
||||
state_next = HEADER;
|
||||
end else begin
|
||||
state_next = DATA_CHECKSUM;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DATA_CHECKSUM: begin
|
||||
saf_ready = '1;
|
||||
|
||||
data_expand_next = {data_expand[23:0], pre_checksum_data.tdata};
|
||||
// data_expand_next = {pre_checksum_data.tdata, data_expand[31:8]};
|
||||
|
||||
if (checksum_counter[1:0] == '1) begin
|
||||
checksum_enable = '1;
|
||||
checksum_data = data_expand_next;
|
||||
end
|
||||
|
||||
|
||||
if (s_axis_data.tready & s_axis_data.tvalid) begin
|
||||
checksum_counter_next = checksum_counter + 1;
|
||||
if (s_axis_data.tlast) begin
|
||||
state_next = HEADER;
|
||||
checksum_counter_next = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -97,7 +161,7 @@ always_comb begin
|
||||
case (checksum_counter)
|
||||
0: checksum_data = m_ip.ip_source_ip;
|
||||
1: checksum_data = m_ip.ip_dest_ip;
|
||||
2: checksum_data = {8'b0, m_ip.ip_protocol, 16'd20}; // tcp length, not IP length
|
||||
2: checksum_data = {8'b0, m_ip.ip_protocol, (i_ip_len - 16'd20)}; // tcp length, not IP length
|
||||
3: checksum_data = {i_source_port, i_dest_port};
|
||||
4: checksum_data = i_seq_number;
|
||||
5: checksum_data = i_ack_number;
|
||||
@@ -127,7 +191,7 @@ always_comb begin
|
||||
18: m_ip.ip_payload_axis_tdata = '0;
|
||||
19: begin
|
||||
m_ip.ip_payload_axis_tdata = '0;
|
||||
m_ip.ip_payload_axis_tlast = ~s_axis_data.tvalid; // kinda hacky
|
||||
m_ip.ip_payload_axis_tlast = i_no_data; // kinda hacky
|
||||
end
|
||||
endcase
|
||||
|
||||
@@ -147,12 +211,12 @@ always_comb begin
|
||||
|
||||
DATA: begin
|
||||
state_next = DATA;
|
||||
s_axis_data.tready = m_ip.ip_payload_axis_tready;
|
||||
m_ip.ip_payload_axis_tvalid = s_axis_data.tvalid;
|
||||
m_ip.ip_payload_axis_tdata = s_axis_data.tdata;
|
||||
m_ip.ip_payload_axis_tlast = s_axis_data.tlast;
|
||||
post_checksum_data.tready = m_ip.ip_payload_axis_tready;
|
||||
m_ip.ip_payload_axis_tvalid = post_checksum_data.tvalid;
|
||||
m_ip.ip_payload_axis_tdata = post_checksum_data.tdata;
|
||||
m_ip.ip_payload_axis_tlast = post_checksum_data.tlast;
|
||||
|
||||
if (s_axis_data.tlast && s_axis_data.tvalid && s_axis_data.tready) begin
|
||||
if (post_checksum_data.tlast && post_checksum_data.tvalid && post_checksum_data.tready) begin
|
||||
state_next = IDLE;
|
||||
o_packet_done = '1;
|
||||
end
|
||||
|
||||
@@ -43,7 +43,13 @@ always_comb begin
|
||||
o_rx_msg = RX_MSG_RECV_FIN;
|
||||
o_rx_msg_valid = '1;
|
||||
end
|
||||
|
||||
if (i_flags == 8'h10) begin
|
||||
o_rx_msg = RX_MSG_RECV_ACK;
|
||||
o_rx_msg_valid = '1;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
@@ -50,6 +50,7 @@ always_comb begin
|
||||
tcp_state_next = tcp_state;
|
||||
|
||||
o_tx_ctrl_valid = '0;
|
||||
o_open_clr = '0;
|
||||
|
||||
o_tx_ctrl = TX_CTRL_NOP;
|
||||
o_tx_ctrl_valid = '0;
|
||||
@@ -80,6 +81,7 @@ always_comb begin
|
||||
|
||||
if (i_tx_ctrl_ack) begin
|
||||
tcp_state_next = ESTABLISHED;
|
||||
o_open_clr = '1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,9 +94,11 @@ always_comb begin
|
||||
end
|
||||
|
||||
LAST_ACK: begin
|
||||
|
||||
if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_ACK) begin
|
||||
tcp_state_next = IDLE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
@@ -49,6 +49,8 @@ tcp_pkg::rx_msg_t rx_msg;
|
||||
logic rx_msg_valid;
|
||||
logic rx_msg_ack;
|
||||
|
||||
logic w_no_data;
|
||||
|
||||
logic [15:0] w_saf_pkt_len;
|
||||
logic [15:0] w_tx_ip_len;
|
||||
logic [31:0] w_tx_seq_number;
|
||||
@@ -166,6 +168,7 @@ tcp_tx_ctrl u_tcp_tx_ctrl (
|
||||
.i_tx_ctrl_valid (tx_ctrl_valid),
|
||||
.o_tx_ctrl_ack (tx_ctrl_ack),
|
||||
|
||||
.o_no_data (w_no_data),
|
||||
.o_ip_len (w_tx_ip_len),
|
||||
.o_seq_number (w_tx_seq_number),
|
||||
// .o_ack_number (w_tx_ack_number),
|
||||
@@ -187,6 +190,7 @@ tcp_packet_generator u_tcp_packet_generator (
|
||||
|
||||
.s_axis_data (m_tx_ctrl_axis_data),
|
||||
|
||||
.i_no_data (w_no_data),
|
||||
.i_ip_len (w_tx_ip_len),
|
||||
.i_seq_number (w_tx_seq_number),
|
||||
.i_ack_number (w_tx_ack_number),
|
||||
@@ -238,4 +242,4 @@ tcp_rx_ctrl u_tcp_rx_ctrl (
|
||||
|
||||
// rx buffer
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
@@ -8,6 +8,8 @@ module tcp_tx_ctrl(
|
||||
input logic i_tx_ctrl_valid,
|
||||
output logic o_tx_ctrl_ack,
|
||||
|
||||
output logic o_no_data,
|
||||
|
||||
output logic [15:0] o_ip_len,
|
||||
output logic [31:0] o_seq_number,
|
||||
output logic [31:0] o_ack_number,
|
||||
@@ -57,10 +59,11 @@ end
|
||||
|
||||
always_comb begin
|
||||
state_next = state;
|
||||
o_no_data = '0;
|
||||
|
||||
o_ack_number = '0;
|
||||
o_flags = '0;
|
||||
o_window_size = 16'b1;
|
||||
o_window_size = 16'h100;
|
||||
o_hdr_valid = '0;
|
||||
|
||||
seq_num_next = seq_num;
|
||||
@@ -86,6 +89,7 @@ always_comb begin
|
||||
|
||||
SEND_SYN: begin
|
||||
o_flags = FLAG_SYN;
|
||||
o_no_data = '1;
|
||||
o_hdr_valid = '1;
|
||||
|
||||
if (i_packet_done) begin
|
||||
@@ -96,6 +100,7 @@ always_comb begin
|
||||
|
||||
SEND_ACK: begin
|
||||
o_flags = FLAG_ACK;
|
||||
o_no_data = '1;
|
||||
o_hdr_valid = '1;
|
||||
|
||||
if (i_packet_done) begin
|
||||
@@ -106,6 +111,7 @@ always_comb begin
|
||||
|
||||
SEND_DATA: begin
|
||||
o_flags = FLAG_ACK | FLAG_PSH;
|
||||
o_no_data = '0;
|
||||
o_ip_len = 16'd40 + s_axis_len; // default length of IP packet
|
||||
o_hdr_valid = '1;
|
||||
|
||||
@@ -117,7 +123,8 @@ always_comb begin
|
||||
|
||||
SEND_FIN: begin
|
||||
o_flags = FLAG_ACK | FLAG_FIN;
|
||||
o_ip_len = 16'd40 + s_axis_len; // default length of IP packet
|
||||
o_no_data = '1;
|
||||
o_ip_len = 16'd40; // default length of IP packet
|
||||
o_hdr_valid = '1;
|
||||
|
||||
if (i_packet_done) begin
|
||||
|
||||
Reference in New Issue
Block a user