Start work on parser
This commit is contained in:
127
sim/net_core/parser/parser_sanity.py
Normal file
127
sim/net_core/parser/parser_sanity.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import cocotb
|
||||
|
||||
import logging
|
||||
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import Timer, RisingEdge, FallingEdge
|
||||
from cocotb.handle import Immediate
|
||||
from cocotb.queue import Queue
|
||||
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink
|
||||
|
||||
import socket
|
||||
|
||||
from scapy.volatile import RandMAC, RandIP, RandShort, RandInt, RandLong
|
||||
|
||||
from scapy.layers.l2 import Ether
|
||||
from scapy.layers.inet import IP, UDP, TCP
|
||||
from scapy.contrib.wireguard import Wireguard, WireguardTransport
|
||||
|
||||
from scapy.utils import str2mac
|
||||
|
||||
from scapy.packet import Packet
|
||||
|
||||
CLK_PERIOD = 20
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = logging.getLogger("cocotb.tb")
|
||||
self.log.setLevel(logging.INFO)
|
||||
|
||||
self.input_queue = Queue()
|
||||
|
||||
self.expected_queue = Queue()
|
||||
self.output_queue = Queue()
|
||||
|
||||
self.s_axis = AxiStreamSource(AxiStreamBus.from_entity(dut.s_axis), dut.i_clk, dut.i_rst)
|
||||
self.m_axis = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis), dut.i_clk, dut.i_rst)
|
||||
|
||||
cocotb.start_soon(Clock(self.dut.i_clk, CLK_PERIOD, unit="ns").start())
|
||||
|
||||
|
||||
async def cycle_reset(self):
|
||||
await self._cycle_reset(self.dut.i_rst, self.dut.i_clk)
|
||||
|
||||
async def _cycle_reset(self, rst, clk):
|
||||
rst.value = Immediate(0)
|
||||
await RisingEdge(clk)
|
||||
await RisingEdge(clk)
|
||||
rst.value = 1
|
||||
await RisingEdge(clk)
|
||||
await RisingEdge(clk)
|
||||
rst.value = 0
|
||||
await RisingEdge(clk)
|
||||
await RisingEdge(clk)
|
||||
|
||||
def assertEqual(self, a, b, name):
|
||||
if a != b:
|
||||
self.log.error(f"{name}: {a} != {b}!")
|
||||
|
||||
def check_header(self, real_packet: Packet):
|
||||
for f, v in zip(["src", "dst"], ["ether_source", "ether_dest"]):
|
||||
actual = real_packet[Ether].getfieldval(f)
|
||||
parsed = str2mac(self.dut[v].value.to_unsigned().to_bytes(6))
|
||||
self.assertEqual(actual, parsed, v)
|
||||
|
||||
actual_ethertype = real_packet[Ether].getfieldval("type")
|
||||
parsed_ethertype = self.dut.ether_type.value.to_unsigned()
|
||||
self.assertEqual(actual_ethertype, parsed_ethertype, "ether_type")
|
||||
|
||||
for f, v in zip(["src", "dst"], ["ip_source", "ip_dest"]):
|
||||
actual = real_packet[IP].getfieldval(f)
|
||||
parsed = socket.inet_ntoa(self.dut[v].value.to_unsigned().to_bytes(4))
|
||||
self.assertEqual(actual, parsed, v)
|
||||
|
||||
actual_ip_len = real_packet[IP].getfieldval("len")
|
||||
parsed_ip_len = self.dut.ip_length.value.to_unsigned()
|
||||
self.assertEqual(actual_ip_len, parsed_ip_len, "ip_length")
|
||||
|
||||
actual_ip_proto = real_packet[IP].getfieldval("proto")
|
||||
parsed_ip_proto = self.dut.ip_proto.value.to_unsigned()
|
||||
self.assertEqual(actual_ip_proto, parsed_ip_proto, "ip_proto")
|
||||
|
||||
for f, v in zip(["sport", "dport"], ["udp_source_port", "udp_dest_port"]):
|
||||
actual = real_packet[IP].getfieldval(f)
|
||||
parsed = self.dut[v].value.to_unsigned()
|
||||
self.assertEqual(actual, parsed, v)
|
||||
|
||||
actual_udp_len = real_packet[UDP].getfieldval("len")
|
||||
parsed_udp_len = self.dut.udp_length.value.to_unsigned()
|
||||
self.assertEqual(actual_udp_len, parsed_udp_len, "udp_length")
|
||||
|
||||
actual_wg_type = real_packet[Wireguard].getfieldval("message_type")
|
||||
parsed_wg_type = self.dut.wg_type.value.to_unsigned()
|
||||
self.assertEqual(actual_wg_type, parsed_wg_type, "wg_type")
|
||||
|
||||
actual_wg_receiver_index = real_packet[Wireguard].getfieldval("receiver_index")
|
||||
parsed_wg_receiver_index = self.dut.wg_receiver_index.value.to_unsigned()
|
||||
self.assertEqual(actual_wg_receiver_index, parsed_wg_receiver_index, "wg_receiver_index")
|
||||
|
||||
actual_wg_counter = real_packet[Wireguard].getfieldval("counter")
|
||||
parsed_wg_counter = self.dut.wg_counter.value.to_unsigned()
|
||||
self.assertEqual(actual_wg_counter, parsed_wg_counter, "wg_counter")
|
||||
|
||||
@cocotb.test
|
||||
async def test_sanity(dut):
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.cycle_reset()
|
||||
|
||||
|
||||
for _ in range(16):
|
||||
packet: Packet = Ether(src=RandMAC(), dst=RandMAC()) / IP(src=RandIP(), dst=RandIP()) / UDP(sport=RandShort(), dport=51820) / Wireguard() / WireguardTransport(receiver_index=RandInt(), counter=RandLong()) / b"Random encrypted data here, who knows what"
|
||||
|
||||
packet_bytes = packet.build()
|
||||
real_packet = Ether(packet_bytes)
|
||||
|
||||
await tb.s_axis.send(packet_bytes)
|
||||
|
||||
await RisingEdge(tb.dut.o_parser_data_valid)
|
||||
|
||||
tb.check_header(real_packet)
|
||||
|
||||
await Timer(10, "us")
|
||||
|
||||
59
sim/net_core/parser/parser_wrapper.sv
Normal file
59
sim/net_core/parser/parser_wrapper.sv
Normal file
@@ -0,0 +1,59 @@
|
||||
import net_core_pkg::*;
|
||||
|
||||
module parser_wrapper();
|
||||
|
||||
logic i_clk;
|
||||
logic i_rst;
|
||||
|
||||
taxi_axis_if #(.DATA_W(32)) s_axis();
|
||||
taxi_axis_if #(.DATA_W(32)) m_axis();
|
||||
|
||||
taxi_axis_if #(.DATA_W(32)) s_axis_be();
|
||||
taxi_axis_if #(.DATA_W(32)) m_axis_be();
|
||||
|
||||
taxi_axis_endian_swap u_s_axis_swap(.s_axis(s_axis), .m_axis(s_axis_be), .swap('1));
|
||||
taxi_axis_endian_swap u_m_axis_swap(.s_axis(m_axis_be), .m_axis(m_axis), .swap('1));
|
||||
|
||||
parser_data_t o_parser_data;
|
||||
logic o_parser_data_valid;
|
||||
|
||||
logic [47:0] ether_dest;
|
||||
logic [47:0] ether_source;
|
||||
logic [15:0] ether_type;
|
||||
logic [15:0] ip_length;
|
||||
logic [31:0] ip_source;
|
||||
logic [31:0] ip_dest;
|
||||
logic [7:0] ip_proto;
|
||||
logic [15:0] udp_source_port;
|
||||
logic [15:0] udp_dest_port;
|
||||
logic [15:0] udp_length;
|
||||
logic [7:0] wg_type;
|
||||
logic [31:0] wg_receiver_index;
|
||||
logic [63:0] wg_counter;
|
||||
|
||||
assign ether_dest = o_parser_data.ether_dest;
|
||||
assign ether_source = o_parser_data.ether_source;
|
||||
assign ether_type = o_parser_data.ether_type;
|
||||
assign ip_length = o_parser_data.ip_length;
|
||||
assign ip_source = o_parser_data.ip_source;
|
||||
assign ip_dest = o_parser_data.ip_dest;
|
||||
assign ip_proto = o_parser_data.ip_proto;
|
||||
assign udp_source_port = o_parser_data.udp_source_port;
|
||||
assign udp_dest_port = o_parser_data.udp_dest_port;
|
||||
assign udp_length = o_parser_data.udp_length;
|
||||
assign wg_type = o_parser_data.wg_type;
|
||||
assign wg_receiver_index = o_parser_data.wg_receiver_index;
|
||||
assign wg_counter = o_parser_data.wg_counter;
|
||||
|
||||
parser u_dut (
|
||||
.i_clk (i_clk),
|
||||
.i_rst (i_rst),
|
||||
|
||||
.s_axis (s_axis_be),
|
||||
.m_axis (m_axis_be),
|
||||
|
||||
.o_parser_data (o_parser_data),
|
||||
.o_parser_data_valid (o_parser_data_valid)
|
||||
);
|
||||
|
||||
endmodule
|
||||
7
sim/net_core/parser/sim.yaml
Normal file
7
sim/net_core/parser/sim.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
tests:
|
||||
- name: "parser_sanity"
|
||||
toplevel: "parser_wrapper"
|
||||
modules:
|
||||
- "parser_sanity"
|
||||
sources: "sources.list"
|
||||
waves: True
|
||||
6
sim/net_core/parser/sources.list
Normal file
6
sim/net_core/parser/sources.list
Normal file
@@ -0,0 +1,6 @@
|
||||
../../verilator.vlt
|
||||
|
||||
../../../src/net_core/sources.list
|
||||
../../../src/common/taxi_sources.list
|
||||
|
||||
parser_wrapper.sv
|
||||
2
sim/net_core/sim.yaml
Normal file
2
sim/net_core/sim.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
yaml:
|
||||
- "parser/sim.yaml"
|
||||
2
sim/sim.yaml
Normal file
2
sim/sim.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
yaml:
|
||||
- "net_core/sim.yaml"
|
||||
3
sim/verilator.vlt
Normal file
3
sim/verilator.vlt
Normal file
@@ -0,0 +1,3 @@
|
||||
`verilator_config
|
||||
|
||||
lint_off -rule TIMESCALEMOD
|
||||
Reference in New Issue
Block a user