zircon: Reorganize metadata for better rules engine interface

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-04-07 15:47:43 -07:00
parent 00878c9717
commit f2ff93f09f
4 changed files with 75 additions and 75 deletions

View File

@@ -38,12 +38,12 @@ module zircon_ip_rx_parse #
// Metadata output (64 bit blocks):
// 00: flags / payload len, pkt sum
// 01: RSS hash / header and payload offsets
// 02: vlan tags / dscp, ecn
// 02: vlan tags
// 03: eth dst
// 04: eth src, ethtype
// 05: protos/hdrs with offsets
// 06: protos/hdrs with offsets
// 07: ip id/fl / protocol, ttl/hl
// 07: protocol, ttl/hl / dscp, ecn, ip id/fl
// 08: ipv6 dst
// 09: ipv6 dst
// 10: ipv6 src
@@ -51,7 +51,7 @@ module zircon_ip_rx_parse #
// 12: l4 ports / tcp flags
// 13: tcp wnd/urg
// 14: tcp seq/ack
// 15:
// 15:
localparam DATA_W = s_axis_pkt.DATA_W;
localparam META_W = m_axis_meta.DATA_W;
@@ -176,7 +176,7 @@ logic s_axis_pkt_tready_reg = 1'b0, s_axis_pkt_tready_next;
// metadata RAM
localparam META_AW = 5;
logic [31:0] meta_ram_a[2**META_AW];
logic [31:0] meta_ram_a[2**META_AW] = '{default: '0};
logic [31:0] meta_ram_a_wr_data;
logic [3:0] meta_ram_a_wr_strb;
logic [META_AW-1:0] meta_ram_a_wr_addr;
@@ -185,7 +185,7 @@ logic [31:0] meta_ram_a_rd_data_reg = '0;
logic [META_AW-1:0] meta_ram_a_rd_addr;
logic meta_ram_a_rd_en;
logic [31:0] meta_ram_b[2**META_AW];
logic [31:0] meta_ram_b[2**META_AW] = '{default: '0};
logic [31:0] meta_ram_b_wr_data;
logic [3:0] meta_ram_b_wr_strb;
logic [META_AW-1:0] meta_ram_b_wr_addr;
@@ -504,6 +504,12 @@ always_comb begin
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd4};
meta_ram_b_wr_en = 1'b1;
// clear VLAN tags
meta_ram_a_wr_data = '0;
meta_ram_a_wr_strb = 4'b1111;
meta_ram_a_wr_addr = {meta_wr_slot_reg[0], 4'd2};
meta_ram_a_wr_en = 1'b1;
l3_offset_next = offset_reg;
payload_offset_next = offset_reg;
@@ -580,9 +586,9 @@ always_comb begin
payload_len_next = pkt_data_be[15:0] - 4;
// store DSCP and ECN
meta_ram_b_wr_data = {pkt_data_be[15:0], pkt_data_be[31:16]};
meta_ram_b_wr_strb = 4'b0001;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd2};
meta_ram_b_wr_data = {pkt_data_be[23:0], pkt_data_be[31:24]};
meta_ram_b_wr_strb = 4'b1000;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_b_wr_en = 1'b1;
if (pkt_data_be[31:28] == 4'd4) begin
@@ -594,10 +600,10 @@ always_comb begin
end
STATE_IPV4_2: begin
// store IP ID
meta_ram_a_wr_data = {pkt_data_be[15:0], pkt_data_be[31:16]};
meta_ram_a_wr_strb = 4'b0011;
meta_ram_a_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_a_wr_en = 1'b1;
meta_ram_b_wr_data = {pkt_data_be[15:0], pkt_data_be[31:16]};
meta_ram_b_wr_strb = 4'b0011;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_b_wr_en = 1'b1;
if (pkt_data_be[13] || pkt_data_be[12:0] != 0) begin
// MF bit set or nonzero fragment offset
@@ -608,10 +614,10 @@ always_comb begin
end
STATE_IPV4_3: begin
// store TTL and protocol
meta_ram_b_wr_data = {pkt_data_be[15:0], pkt_data_be[31:16]}; // TODO check this
meta_ram_b_wr_strb = 4'b0011;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_b_wr_en = 1'b1;
meta_ram_a_wr_data = {pkt_data_be[15:0], pkt_data_be[31:16]}; // TODO check this
meta_ram_a_wr_strb = 4'b0011;
meta_ram_a_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_a_wr_en = 1'b1;
next_hdr_next = pkt_data_be[23:16];
@@ -693,16 +699,10 @@ always_comb begin
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// from https://www.ietf.org/rfc/rfc2460.txt
STATE_IPV6_1: begin
// store flow label
meta_ram_a_wr_data = pkt_data_be;
meta_ram_a_wr_strb = 4'b0111;
meta_ram_a_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_a_wr_en = 1'b1;
// store DSCP and ECN
meta_ram_b_wr_data = {24'd0, pkt_data_be[27:20]};
meta_ram_b_wr_strb = 4'b0001;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd2};
// store flow label, DSCP, and ECN
meta_ram_b_wr_data = {pkt_data_be[27:20], 4'd0, pkt_data_be[19:0]};
meta_ram_b_wr_strb = 4'b1111;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_b_wr_en = 1'b1;
if (pkt_data_be[31:28] == 4'd6) begin
@@ -714,10 +714,10 @@ always_comb begin
end
STATE_IPV6_2: begin
// store next header, hop limit
meta_ram_b_wr_data = pkt_data; // TODO check this
meta_ram_b_wr_strb = 4'b0011;
meta_ram_b_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_b_wr_en = 1'b1;
meta_ram_a_wr_data = pkt_data; // TODO check this
meta_ram_a_wr_strb = 4'b0011;
meta_ram_a_wr_addr = {meta_wr_slot_reg[0], 4'd7};
meta_ram_a_wr_en = 1'b1;
payload_len_next = pkt_data_be[31:16];
next_hdr_next = pkt_data_be[15:8];
@@ -870,8 +870,8 @@ always_comb begin
end
end
// TCP header
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source Port | Destination Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -965,8 +965,8 @@ always_comb begin
end
end
// UDP header
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source Port | Destination Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

View File

@@ -39,13 +39,13 @@ module zircon_ip_tx_deparse #
// Metadata input (64 bit blocks):
// 00: flags / payload len, payload sum
// 01:
// 02: vlan tags / dscp, ecn
// 01:
// 02: vlan tags
// 03: eth dst
// 04: eth src, ethtype
// 05:
// 06:
// 07: ip id/fl / protocol, ttl/hl
// 05:
// 06:
// 07: protocol, ttl/hl / dscp, ecn, ip id/fl
// 08: ipv6 dst
// 09: ipv6 dst
// 10: ipv6 src
@@ -53,7 +53,7 @@ module zircon_ip_tx_deparse #
// 12: l4 ports / tcp flags
// 13: tcp wnd/urg
// 14: tcp seq/ack
// 15:
// 15:
localparam DATA_W = m_axis_pkt.DATA_W;
localparam KEEP_W = m_axis_pkt.KEEP_W;
@@ -193,7 +193,7 @@ logic m_axis_pkt_tlast_reg = 1'b0, m_axis_pkt_tlast_next;
// metadata RAM
localparam META_AW = 5;
logic [31:0] meta_ram_a[2**META_AW];
logic [31:0] meta_ram_a[2**META_AW] = '{default: '0};
logic [31:0] meta_ram_a_wr_data;
logic [3:0] meta_ram_a_wr_strb;
logic [META_AW-1:0] meta_ram_a_wr_addr;
@@ -203,7 +203,7 @@ logic [META_AW-1:0] meta_ram_a_rd_addr;
wire [31:0] meta_ram_a_rd_data = meta_ram_a[meta_ram_a_rd_addr];
wire [31:0] meta_ram_a_rd_data_be = swab32(meta_ram_a_rd_data);
logic [31:0] meta_ram_b[2**META_AW];
logic [31:0] meta_ram_b[2**META_AW] = '{default: '0};
logic [31:0] meta_ram_b_wr_data;
logic [3:0] meta_ram_b_wr_strb;
logic [META_AW-1:0] meta_ram_b_wr_addr;
@@ -319,15 +319,16 @@ always_comb begin
end
end
4'd2: begin
// vlan tags / DSCP, ECN
meta_l3_cksum_next = 21'({8'h45, s_axis_meta.tdata[47:40]});
// vlan tags
meta_l3_cksum_next = 21'({8'h45, 8'd0}); // IP version, IHL
meta_common_cksum_next = 21'(meta_payload_len_reg);
end
4'd3: begin
// eth dst
meta_l3_cksum_next = meta_l3_cksum_reg + 21'd20;
meta_l3_cksum_next = meta_l3_cksum_reg + 21'd20; // IP header length
if (meta_flag_reg[FLG_UDP]) begin
meta_l4_cksum_next = meta_l4_cksum_reg + 21'(meta_payload_len_reg);
@@ -343,10 +344,11 @@ always_comb begin
// nothing
end
4'd7: begin
// IP ID/FL / protocol, TTL/HL
meta_cksum_in[31:0] = {16'd0, s_axis_meta.tdata[15:0]};
meta_cksum_in[63:32] = {16'd0, s_axis_meta.tdata[47:40], 8'd0};
// protocol, TTL/HL / IP ID/FL, dscp, ecn
meta_cksum_in[31:0] = {8'd0, s_axis_meta.tdata[63:56], s_axis_meta.tdata[47:32]}; // DSCP, ECN, IP ID
meta_cksum_in[63:32] = {16'd0, s_axis_meta.tdata[15:8], 8'd0}; // TTL
// protocol
if (meta_flag_reg[FLG_TCP]) begin
meta_common_cksum_next = meta_common_cksum_reg + 21'(PROTO_TCP);
end else if (meta_flag_reg[FLG_UDP]) begin
@@ -354,7 +356,7 @@ always_comb begin
end else if (meta_flag_reg[FLG_ICMP]) begin
meta_common_cksum_next = meta_common_cksum_reg + 21'(PROTO_ICMP);
end else begin
meta_common_cksum_next = meta_common_cksum_reg + 21'(s_axis_meta.tdata[39:32]);
meta_common_cksum_next = meta_common_cksum_reg + 21'(s_axis_meta.tdata[7:0]);
end
end
4'd8: begin
@@ -629,8 +631,8 @@ always_comb begin
PKT_STATE_IPV4_1: begin
data_next[7:4] = 4'd4; // version
data_next[3:0] = 4'd5; // IHL
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd2};
data_next[15:8] = meta_ram_b_rd_data[23:16]; // DSCP and ECN
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[15:8] = meta_ram_b_rd_data[31:24]; // DSCP and ECN
data_next[31:16] = swab16(pkt_l3_len_reg); // total length
data_valid_next = 1'b1;
@@ -638,8 +640,8 @@ always_comb begin
end
PKT_STATE_IPV4_2: begin
// IP ID
meta_ram_a_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[15:0] = swab16(meta_ram_a_rd_data[15:0]);
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[15:0] = swab16(meta_ram_b_rd_data[15:0]);
data_next[31:16] = '0; // flags, fragment offset
data_valid_next = 1'b1;
@@ -647,9 +649,9 @@ always_comb begin
end
PKT_STATE_IPV4_3: begin
// TTL, protocol, header checksum
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[7:0] = meta_ram_b_rd_data[15:8]; // TTL
data_next[15:8] = meta_ram_b_rd_data[7:0]; // protocol
meta_ram_a_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[7:0] = meta_ram_a_rd_data[15:8]; // TTL
data_next[15:8] = meta_ram_a_rd_data[7:0]; // protocol
data_next[31:16] = swab16(pkt_l3_cksum_reg[15:0]); // header checksum
data_valid_next = 1'b1;
@@ -660,7 +662,7 @@ always_comb begin
end else if (pkt_flag_reg[FLG_ICMP]) begin
data_next[15:8] = PROTO_ICMP;
end else begin
data_next[15:8] = meta_ram_b_rd_data[7:0];
data_next[15:8] = meta_ram_a_rd_data[7:0];
end
pkt_state_next = PKT_STATE_IPV4_4;
@@ -715,19 +717,18 @@ always_comb begin
PKT_STATE_IPV6_1: begin
// flow label
data_next[7:4] = 4'd6; // version
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd2};
{data_next[3:0], data_next[15:12]} = meta_ram_b_rd_data[23:16]; // Traffic class
meta_ram_a_rd_addr = {meta_rd_slot_reg[0], 4'd7};
{data_next[11:8], data_next[23:16], data_next[31:24]} = meta_ram_a_rd_data[19:0]; // Flow label
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd7};
{data_next[3:0], data_next[15:12]} = meta_ram_b_rd_data[31:24]; // Traffic class
{data_next[11:8], data_next[23:16], data_next[31:24]} = meta_ram_b_rd_data[19:0]; // Flow label
data_valid_next = 1'b1;
pkt_state_next = PKT_STATE_IPV6_2;
end
PKT_STATE_IPV6_2: begin
// hop limit
meta_ram_b_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[31:24] = meta_ram_b_rd_data[15:8]; // hop limit
data_next[23:16] = meta_ram_b_rd_data[7:0]; // next header
meta_ram_a_rd_addr = {meta_rd_slot_reg[0], 4'd7};
data_next[31:24] = meta_ram_a_rd_data[15:8]; // hop limit
data_next[23:16] = meta_ram_a_rd_data[7:0]; // next header
data_next[15:0] = swab16(pkt_l3_len_reg); // payload length
data_valid_next = 1'b1;
@@ -738,7 +739,7 @@ always_comb begin
end else if (pkt_flag_reg[FLG_ICMP]) begin
data_next[23:16] = PROTO_IPV6_ICMP;
end else begin
data_next[23:16] = meta_ram_b_rd_data[7:0];
data_next[23:16] = meta_ram_a_rd_data[7:0];
end
pkt_state_next = PKT_STATE_IPV6_3;
@@ -814,8 +815,8 @@ always_comb begin
end
end
// Build TCP header
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source Port | Destination Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -880,8 +881,8 @@ always_comb begin
pkt_state_next = PKT_STATE_FINISH_1;
end
// Build UDP header
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source Port | Destination Port |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

View File

@@ -288,11 +288,10 @@ async def run_test(dut):
tb.log.info("L4 offset: %d (%d)", l4_offset*4+2, l4_offset)
tb.log.info("Payload offset: %d (%d)", payload_offset*4+2, payload_offset)
s_tag, c_tag, dscp_ecn = struct.unpack_from('>HHB', meta.tdata, 16)
s_tag, c_tag = struct.unpack_from('>HH', meta.tdata, 16)
tb.log.info("VLAN S-tag: 0x%04x", s_tag)
tb.log.info("VLAN C-tag: 0x%04x", c_tag)
tb.log.info("DSCP/ECN: 0x%02x", dscp_ecn)
eth_dst = meta.tdata[24:30]
eth_src = meta.tdata[32:38]

View File

@@ -264,8 +264,8 @@ async def run_test(dut):
meta[64:68] = scapy.utils.inet_aton(pkt[IP].dst)
meta[80:84] = scapy.utils.inet_aton(pkt[IP].src)
struct.pack_into('<L', meta, 56, pkt[IP].id)
struct.pack_into('BB', meta, 60, pkt[IP].proto, pkt[IP].ttl)
struct.pack_into('BB', meta, 56, pkt[IP].proto, pkt[IP].ttl)
struct.pack_into('<L', meta, 60, pkt[IP].id)
payload = bytes(pkt[IP].payload)
hdr_size += len(pkt[IP]) - len(payload)
@@ -277,8 +277,8 @@ async def run_test(dut):
meta[64:80] = scapy.pton_ntop.inet_pton(socket.AF_INET6, pkt[IPv6].dst)
meta[80:96] = scapy.pton_ntop.inet_pton(socket.AF_INET6, pkt[IPv6].src)
struct.pack_into('<L', meta, 56, pkt[IPv6].fl)
struct.pack_into('BB', meta, 60, pkt[IPv6].nh, pkt[IPv6].hlim)
struct.pack_into('BB', meta, 56, pkt[IPv6].nh, pkt[IPv6].hlim)
struct.pack_into('<L', meta, 60, pkt[IPv6].fl)
payload = bytes(pkt[IPv6].payload)
hdr_size += len(pkt[IPv6]) - len(payload)