Merge branch '97-calculate-checksum-for-tcp-data-also' into '93-network-processor'

Calculate checksum for tcp data also

See merge request bslathi19/super6502!77
This commit is contained in:
Byron Lathi
2024-10-02 06:30:19 +00:00
8 changed files with 201 additions and 26 deletions

View File

@@ -1,6 +1,8 @@
from http import server from http import server
from turtle import xcor
from scapy.layers.inet import Ether, IP, TCP from scapy.layers.inet import Ether, IP, TCP
from scapy.layers.l2 import ARP from scapy.layers.l2 import ARP
from scapy.data import IP_PROTOS
from scapy import sendrecv from scapy import sendrecv
@@ -106,7 +108,7 @@ async def test_irl(dut):
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((tb_ip, 5678)) serversocket.bind((tb_ip, 5678))
serversocket.listen(5) serversocket.listen(1)
t = TunTapInterface('tun0') t = TunTapInterface('tun0')
@@ -175,7 +177,10 @@ async def test_irl(dut):
t.send(ip_packet) t.send(ip_packet)
pkt = t.recv() while True:
pkt = t.recv()
if (pkt.proto == IP_PROTOS.tcp):
break
print(pkt) print(pkt)
tcp_synack = Ether(dst=dut_mac, src=tb_mac) / pkt tcp_synack = Ether(dst=dut_mac, src=tb_mac) / pkt
@@ -215,8 +220,6 @@ async def test_irl(dut):
tb.axil_ram.write(0x1000, test_data) tb.axil_ram.write(0x1000, test_data)
await tb.axil_master.write_dword(0x22c, 0) await tb.axil_master.write_dword(0x22c, 0)
await tb.axil_master.write_dword(0x220, 0x00000000) await tb.axil_master.write_dword(0x220, 0x00000000)
await tb.axil_master.write_dword(0x224, 0x00000000) await tb.axil_master.write_dword(0x224, 0x00000000)
@@ -226,6 +229,65 @@ async def test_irl(dut):
t.send(packet.payload) t.send(packet.payload)
# con.recv(64) con.recv(64)
tb.log.info("Received 64 packets")
serversocket.close() con.close()
serversocket.close()
while True:
pkt = t.recv()
if (pkt.proto == IP_PROTOS.tcp):
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()))
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
packet = Ether(resp.get_payload())
tb.log.info(f"Packet Type: {packet.type:x}")
ip_packet = packet.payload
assert isinstance(ip_packet, IP)
tcp_packet = ip_packet.payload
assert isinstance(tcp_packet, TCP)
tb.log.info(f"Source Port: {tcp_packet.sport}")
tb.log.info(f"Dest Port: {tcp_packet.dport}")
tb.log.info(f"Seq: {tcp_packet.seq}")
tb.log.info(f"Ack: {tcp_packet.ack}")
tb.log.info(f"Data Offs: {tcp_packet.dataofs}")
tb.log.info(f"flags: {tcp_packet.flags}")
tb.log.info(f"window: {tcp_packet.window}")
tb.log.info(f"Checksum: {tcp_packet.chksum}")
t.send(ip_packet)
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
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_fin.build()))
await Timer(Decimal(CLK_PERIOD_NS * 1000), units='ns')

View File

@@ -128,6 +128,10 @@ always_comb begin
m_ip.ip_payload_axis_tdata = pipe[31:24]; m_ip.ip_payload_axis_tdata = pipe[31:24];
valid = '1; valid = '1;
if (pipe_last[3] && pipe_valid[3]) begin
state_next = PORTS;
end
end end
endcase endcase
end end

View File

@@ -4,6 +4,8 @@ module tcp_packet_generator (
axis_intf.SLAVE s_axis_data, axis_intf.SLAVE s_axis_data,
input wire i_no_data,
input wire [15:0] i_ip_len, input wire [15:0] i_ip_len,
input wire [31:0] i_seq_number, input wire [31:0] i_seq_number,
input wire [31:0] i_ack_number, input wire [31:0] i_ack_number,
@@ -21,8 +23,33 @@ module tcp_packet_generator (
ip_intf.MASTER m_ip 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; 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; logic [31:0] checksum_counter, checksum_counter_next;
@@ -34,7 +61,13 @@ logic checksum_clear;
logic [31:0] checksum_data; logic [31:0] checksum_data;
logic [15:0] checksum_final; 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_rst (i_rst),
.i_clk (i_clk), .i_clk (i_clk),
.i_clear (checksum_clear), .i_clear (checksum_clear),
@@ -49,10 +82,12 @@ always_ff @(posedge i_clk) begin
counter <= '0; counter <= '0;
checksum_counter <= '0; checksum_counter <= '0;
state <= IDLE; state <= IDLE;
data_expand <= '0;
end else begin end else begin
counter <= counter_next; counter <= counter_next;
checksum_counter <= checksum_counter_next; checksum_counter <= checksum_counter_next;
state <= state_next; state <= state_next;
data_expand <= data_expand_next;
end end
end end
@@ -64,6 +99,10 @@ always_comb begin
checksum_clear = '0; checksum_clear = '0;
checksum_enable = '0; checksum_enable = '0;
saf_ready = '0;
data_expand_next = data_expand;
case (state) case (state)
IDLE: begin IDLE: begin
@@ -82,7 +121,32 @@ always_comb begin
m_ip.ip_dest_ip = i_dst_ip; m_ip.ip_dest_ip = i_dst_ip;
if (m_ip.ip_hdr_ready) begin 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; state_next = HEADER;
checksum_counter_next = '0;
end end
end end
end end
@@ -97,7 +161,7 @@ always_comb begin
case (checksum_counter) case (checksum_counter)
0: checksum_data = m_ip.ip_source_ip; 0: checksum_data = m_ip.ip_source_ip;
1: checksum_data = m_ip.ip_dest_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}; 3: checksum_data = {i_source_port, i_dest_port};
4: checksum_data = i_seq_number; 4: checksum_data = i_seq_number;
5: checksum_data = i_ack_number; 5: checksum_data = i_ack_number;
@@ -127,7 +191,7 @@ always_comb begin
18: m_ip.ip_payload_axis_tdata = '0; 18: m_ip.ip_payload_axis_tdata = '0;
19: begin 19: begin
m_ip.ip_payload_axis_tdata = '0; 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 end
endcase endcase
@@ -147,12 +211,12 @@ always_comb begin
DATA: begin DATA: begin
state_next = DATA; state_next = DATA;
s_axis_data.tready = m_ip.ip_payload_axis_tready; post_checksum_data.tready = m_ip.ip_payload_axis_tready;
m_ip.ip_payload_axis_tvalid = s_axis_data.tvalid; m_ip.ip_payload_axis_tvalid = post_checksum_data.tvalid;
m_ip.ip_payload_axis_tdata = s_axis_data.tdata; m_ip.ip_payload_axis_tdata = post_checksum_data.tdata;
m_ip.ip_payload_axis_tlast = s_axis_data.tlast; 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; state_next = IDLE;
o_packet_done = '1; o_packet_done = '1;
end end

View File

@@ -32,13 +32,24 @@ end
always_comb begin always_comb begin
if (i_hdr_valid) begin if (i_hdr_valid) begin
if (i_flags & 8'h12) begin if (i_flags == 8'h12) begin
o_rx_msg = RX_MSG_RECV_SYNACK; o_rx_msg = RX_MSG_RECV_SYNACK;
o_rx_msg_valid = '1; o_rx_msg_valid = '1;
ack_num_next = i_seq_number + 1; ack_num_next = i_seq_number + 1;
end end
if (i_flags == 8'h11) 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
end end
endmodule endmodule

View File

@@ -50,6 +50,7 @@ always_comb begin
tcp_state_next = tcp_state; tcp_state_next = tcp_state;
o_tx_ctrl_valid = '0; o_tx_ctrl_valid = '0;
o_open_clr = '0;
o_tx_ctrl = TX_CTRL_NOP; o_tx_ctrl = TX_CTRL_NOP;
o_tx_ctrl_valid = '0; o_tx_ctrl_valid = '0;
@@ -80,13 +81,24 @@ always_comb begin
if (i_tx_ctrl_ack) begin if (i_tx_ctrl_ack) begin
tcp_state_next = ESTABLISHED; tcp_state_next = ESTABLISHED;
o_open_clr = '1;
end end
end end
ESTABLISHED: begin ESTABLISHED: begin
if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_FIN) begin
o_tx_ctrl = TX_CTRL_SEND_FIN;
o_tx_ctrl_valid = '1;
tcp_state_next = LAST_ACK;
end
end
LAST_ACK: begin
if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_ACK) begin
tcp_state_next = IDLE;
end
end end
endcase endcase
end end
endmodule endmodule

View File

@@ -49,6 +49,8 @@ tcp_pkg::rx_msg_t rx_msg;
logic rx_msg_valid; logic rx_msg_valid;
logic rx_msg_ack; logic rx_msg_ack;
logic w_no_data;
logic [15:0] w_saf_pkt_len; logic [15:0] w_saf_pkt_len;
logic [15:0] w_tx_ip_len; logic [15:0] w_tx_ip_len;
logic [31:0] w_tx_seq_number; 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), .i_tx_ctrl_valid (tx_ctrl_valid),
.o_tx_ctrl_ack (tx_ctrl_ack), .o_tx_ctrl_ack (tx_ctrl_ack),
.o_no_data (w_no_data),
.o_ip_len (w_tx_ip_len), .o_ip_len (w_tx_ip_len),
.o_seq_number (w_tx_seq_number), .o_seq_number (w_tx_seq_number),
// .o_ack_number (w_tx_ack_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), .s_axis_data (m_tx_ctrl_axis_data),
.i_no_data (w_no_data),
.i_ip_len (w_tx_ip_len), .i_ip_len (w_tx_ip_len),
.i_seq_number (w_tx_seq_number), .i_seq_number (w_tx_seq_number),
.i_ack_number (w_tx_ack_number), .i_ack_number (w_tx_ack_number),
@@ -238,4 +242,4 @@ tcp_rx_ctrl u_tcp_rx_ctrl (
// rx buffer // rx buffer
endmodule endmodule

View File

@@ -8,6 +8,8 @@ module tcp_tx_ctrl(
input logic i_tx_ctrl_valid, input logic i_tx_ctrl_valid,
output logic o_tx_ctrl_ack, output logic o_tx_ctrl_ack,
output logic o_no_data,
output logic [15:0] o_ip_len, output logic [15:0] o_ip_len,
output logic [31:0] o_seq_number, output logic [31:0] o_seq_number,
output logic [31:0] o_ack_number, output logic [31:0] o_ack_number,
@@ -43,7 +45,7 @@ localparam FLAG_CWR = (1 << 7);
logic [31:0] seq_num, seq_num_next; logic [31:0] seq_num, seq_num_next;
assign o_seq_number = seq_num; assign o_seq_number = seq_num;
enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK, SEND_DATA} state, state_next; enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK, SEND_FIN, SEND_DATA} state, state_next;
always_ff @(posedge i_clk) begin always_ff @(posedge i_clk) begin
if (i_rst) begin if (i_rst) begin
@@ -57,10 +59,11 @@ end
always_comb begin always_comb begin
state_next = state; state_next = state;
o_no_data = '0;
o_ack_number = '0; o_ack_number = '0;
o_flags = '0; o_flags = '0;
o_window_size = 16'b1; o_window_size = 16'h100;
o_hdr_valid = '0; o_hdr_valid = '0;
seq_num_next = seq_num; seq_num_next = seq_num;
@@ -75,6 +78,7 @@ always_comb begin
case (i_tx_ctrl) case (i_tx_ctrl)
TX_CTRL_SEND_SYN: state_next = SEND_SYN; TX_CTRL_SEND_SYN: state_next = SEND_SYN;
TX_CTRL_SEND_ACK: state_next = SEND_ACK; TX_CTRL_SEND_ACK: state_next = SEND_ACK;
TX_CTRL_SEND_FIN: state_next = SEND_FIN;
endcase endcase
end end
@@ -85,6 +89,7 @@ always_comb begin
SEND_SYN: begin SEND_SYN: begin
o_flags = FLAG_SYN; o_flags = FLAG_SYN;
o_no_data = '1;
o_hdr_valid = '1; o_hdr_valid = '1;
if (i_packet_done) begin if (i_packet_done) begin
@@ -95,6 +100,7 @@ always_comb begin
SEND_ACK: begin SEND_ACK: begin
o_flags = FLAG_ACK; o_flags = FLAG_ACK;
o_no_data = '1;
o_hdr_valid = '1; o_hdr_valid = '1;
if (i_packet_done) begin if (i_packet_done) begin
@@ -105,6 +111,7 @@ always_comb begin
SEND_DATA: begin SEND_DATA: begin
o_flags = FLAG_ACK | FLAG_PSH; o_flags = FLAG_ACK | FLAG_PSH;
o_no_data = '0;
o_ip_len = 16'd40 + s_axis_len; // default length of IP packet o_ip_len = 16'd40 + s_axis_len; // default length of IP packet
o_hdr_valid = '1; o_hdr_valid = '1;
@@ -113,6 +120,18 @@ always_comb begin
seq_num_next = seq_num + s_axis_len; seq_num_next = seq_num + s_axis_len;
end end
end end
SEND_FIN: begin
o_flags = FLAG_ACK | FLAG_FIN;
o_no_data = '1;
o_ip_len = 16'd40; // default length of IP packet
o_hdr_valid = '1;
if (i_packet_done) begin
state_next = IDLE;
seq_num_next = seq_num + s_axis_len;
end
end
endcase endcase
end end

View File

@@ -8,12 +8,11 @@ export KICAD7_SYMBOL_DIR=$REPO_TOP/hw/kicad_library/symbols
export KICAD7_3DMODEL_DIR=$REPO_TOP/hw/kicad_library/3dmodels export KICAD7_3DMODEL_DIR=$REPO_TOP/hw/kicad_library/3dmodels
export KICAD7_FOOTPRINT_DIR=$REPO_TOP/hw/kicad_library/footprints export KICAD7_FOOTPRINT_DIR=$REPO_TOP/hw/kicad_library/footprints
#module load efinity/2023.1
module load verilator
module load gtkwave/3.3_gtk3
python3.11 -m venv .user_venv python3.12 -m venv .user_venv
. .user_venv/bin/activate . .user_venv/bin/activate
pip install -r requirements.txt pip install -r requirements.txt
module load efinity/2023.1
module load verilator
module load gtkwave/3.3_gtk3