aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/packet_proc/arp_responder
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/packet_proc/arp_responder')
-rw-r--r--fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd204
-rw-r--r--fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd185
2 files changed, 389 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd b/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd
new file mode 100644
index 000000000..8481132c6
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd
@@ -0,0 +1,204 @@
+--
+-- Copyright 2019 Ettus Research, A National Instruments brand
+--
+-- SPDX-License-Identifier: LGPL-3.0
+--
+-- Module: arp_responder
+-- Description: Processing IP to send replies for ARP frames (for IPv4)
+-- arp_responder checks the incoming ARP frame against the input port ip_addr,
+-- and if the frame is a request for this module's ip_addr, the module will
+-- format an ARP reply and send it on the outgoing AXI-S interface.
+--
+-- mac_addr and ip_addr must be kept stable for this module to function. They
+-- are not registered within the IP.
+--
+-- s_axis_tuser indicates there is an error in the packet, and it should be discarded
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity arp_responder is
+port (
+ aclk : in std_logic;
+ aresetn : in std_logic;
+ mac_addr : in std_logic_vector(47 downto 0);
+ ip_addr : in std_logic_vector(31 downto 0);
+ s_axis_tdata : in std_logic_vector(63 downto 0);
+ s_axis_tvalid : in std_logic;
+ s_axis_tready : out std_logic;
+ s_axis_tkeep : in std_logic_vector(7 downto 0);
+ s_axis_tlast : in std_logic;
+ s_axis_tuser : in std_logic;
+ m_axis_tdata : out std_logic_vector(63 downto 0);
+ m_axis_tvalid : out std_logic;
+ m_axis_tready : in std_logic;
+ m_axis_tkeep : out std_logic_vector(7 downto 0);
+ m_axis_tlast : out std_logic;
+ m_axis_tuser : out std_logic
+);
+end arp_responder;
+
+architecture arch of arp_responder is
+ type pkt_state_t is (PKT_IDLE, PKT_RECV, PKT_SEND, PKT_DROP);
+ signal pkt_state : pkt_state_t;
+ signal pkt_recv_count : unsigned(3 downto 0);
+ signal pkt_send_count : unsigned(3 downto 0);
+
+ --All of these are LSB-0 for bits, but first byte transmitted is byte 0
+ -- In ChipScope, bytes will appear swapped versus typical diagrams
+ signal src_mac_be : std_logic_vector(47 downto 0);
+ signal sender_hw_addr_be : std_logic_vector(47 downto 0);
+ signal sender_protocol_addr_be : std_logic_vector(31 downto 0);
+ signal target_protocol_addr_be : std_logic_vector(31 downto 0);
+ signal ip_addr_be : std_logic_vector(31 downto 0);
+begin
+ m_axis_tuser <= '0';
+ m_axis_tvalid <= '1' when (pkt_state = PKT_SEND) else '0';
+ ip_addr_be <= ip_addr(7 downto 0) & ip_addr(15 downto 8) &
+ ip_addr(23 downto 16) & ip_addr(31 downto 24);
+
+ s_axis_tready <= '1' when (pkt_state = PKT_IDLE) or (pkt_state = PKT_RECV) or (pkt_state = PKT_DROP)
+ else '0';
+
+ tx_reply : process (src_mac_be, mac_addr, ip_addr, sender_hw_addr_be,
+ sender_protocol_addr_be, pkt_send_count)
+ begin
+ m_axis_tdata <= (others => 'X');
+ m_axis_tkeep <= (others => '1');
+ m_axis_tlast <= '0';
+ case (to_integer(pkt_send_count)) is
+ when 0 =>
+ m_axis_tdata(47 downto 0) <= src_mac_be;
+ m_axis_tdata(63 downto 48) <= mac_addr(39 downto 32) & mac_addr(47 downto 40);
+ m_axis_tkeep <= X"FF";
+ m_axis_tlast <= '0';
+ when 1 =>
+ m_axis_tdata(31 downto 0) <= mac_addr(7 downto 0) & mac_addr(15 downto 8) &
+ mac_addr(23 downto 16) & mac_addr(31 downto 24);
+ m_axis_tdata(47 downto 32) <= X"0608";
+ m_axis_tdata(63 downto 48) <= X"0100";
+ m_axis_tkeep <= X"FF";
+ m_axis_tlast <= '0';
+ when 2 =>
+ m_axis_tdata(15 downto 0) <= X"0008"; --PTYPE
+ m_axis_tdata(23 downto 16) <= X"06"; --HLEN
+ m_axis_tdata(31 downto 24) <= X"04"; --PLEN
+ m_axis_tdata(47 downto 32) <= X"0200"; --OPER
+ m_axis_tdata(63 downto 48) <= mac_addr(39 downto 32) & mac_addr(47 downto 40); --SHA
+ m_axis_tkeep <= X"FF";
+ m_axis_tlast <= '0';
+ when 3 =>
+ m_axis_tdata(31 downto 0) <= mac_addr(7 downto 0) & mac_addr(15 downto 8) &
+ mac_addr(23 downto 16) & mac_addr(31 downto 24); --SHA
+ m_axis_tdata(63 downto 32) <= ip_addr(7 downto 0) & ip_addr(15 downto 8) &
+ ip_addr(23 downto 16) & ip_addr(31 downto 24); --SPA
+ m_axis_tkeep <= X"FF";
+ m_axis_tlast <= '0';
+ when 4 =>
+ m_axis_tdata(47 downto 0) <= sender_hw_addr_be; --THA
+ m_axis_tdata(63 downto 48) <= sender_protocol_addr_be(15 downto 0); --TPA
+ m_axis_tkeep <= X"FF";
+ m_axis_tlast <= '0';
+ when 5 =>
+ m_axis_tdata(15 downto 0) <= sender_protocol_addr_be(31 downto 16); --TPA
+ m_axis_tdata(63 downto 16) <= (others => '0');
+ m_axis_tkeep <= X"03";
+ m_axis_tlast <= '1';
+ when others =>
+ null;
+ end case;
+ end process;
+
+ process (aclk)
+ variable pkt_nonmatch : boolean := false;
+ begin
+ if rising_edge(aclk) then
+ case (pkt_state) is
+ when PKT_IDLE =>
+ if (s_axis_tvalid = '1') and (s_axis_tlast = '0') and (s_axis_tuser = '0') then
+ pkt_state <= PKT_RECV;
+ pkt_recv_count <= to_unsigned(1, pkt_recv_count'length);
+ src_mac_be(15 downto 0) <= s_axis_tdata(63 downto 48);
+ end if;
+ when PKT_RECV =>
+ pkt_nonmatch := false;
+
+ pkt_send_count <= to_unsigned(0, pkt_send_count'length);
+
+ if (s_axis_tvalid = '1') and (s_axis_tuser = '1') then
+ pkt_nonmatch := true;
+ elsif (s_axis_tvalid = '1') and (s_axis_tuser = '0') then
+ if (to_integer(pkt_recv_count) < 7) then
+ pkt_recv_count <= pkt_recv_count + 1;
+ end if;
+
+ case (to_integer(pkt_recv_count)) is
+ when 1 =>
+ src_mac_be(47 downto 16) <= s_axis_tdata(31 downto 0);
+ if (s_axis_tdata(47 downto 32) /= X"0608") or --eth_type
+ (s_axis_tdata(63 downto 48) /= X"0100") or --HTYPE
+ (s_axis_tlast = '1') then
+ pkt_nonmatch := true;
+ end if;
+ when 2 =>
+ sender_hw_addr_be(15 downto 0) <= s_axis_tdata(63 downto 48);
+ if (s_axis_tdata(15 downto 0) /= X"0008") or --PTYPE
+ (s_axis_tdata(23 downto 16) /= X"06") or --HLEN
+ (s_axis_tdata(31 downto 24) /= X"04") or --PLEN
+ (s_axis_tdata(47 downto 32) /= X"0100") or --OPER
+ (s_axis_tlast = '1') then
+ pkt_nonmatch := true;
+ end if;
+ when 3 =>
+ sender_hw_addr_be(47 downto 16) <= s_axis_tdata(31 downto 0);
+ sender_protocol_addr_be <= s_axis_tdata(63 downto 32);
+ if (s_axis_tlast = '1') then
+ pkt_nonmatch := true;
+ end if;
+ when 4 =>
+ --THA = s_axis_tdata(47 downto 0)
+ target_protocol_addr_be(15 downto 0) <= s_axis_tdata(63 downto 48);
+ if (s_axis_tdata(63 downto 48) /= ip_addr_be(15 downto 0)) or
+ (s_axis_tlast = '1') then
+ pkt_nonmatch := true;
+ end if;
+ when 5 =>
+ target_protocol_addr_be(31 downto 16) <= s_axis_tdata(15 downto 0);
+ if (s_axis_tdata(15 downto 0) /= ip_addr_be(31 downto 16)) then
+ pkt_nonmatch := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ if (pkt_nonmatch) then
+ if (s_axis_tlast = '1') then
+ pkt_state <= PKT_IDLE;
+ else
+ pkt_state <= PKT_DROP;
+ end if;
+ elsif (s_axis_tlast = '1') then
+ pkt_state <= PKT_SEND;
+ end if;
+ when PKT_SEND =>
+ if (m_axis_tready = '1') then
+ pkt_send_count <= pkt_send_count + 1;
+
+ if (pkt_send_count = 5) then
+ pkt_state <= PKT_IDLE;
+ end if;
+ end if;
+ when PKT_DROP =>
+ if (s_axis_tvalid = '1') and (s_axis_tlast = '1') then
+ pkt_state <= PKT_IDLE;
+ end if;
+ end case;
+
+ if aresetn = '0' then
+ pkt_state <= PKT_IDLE;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd b/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd
new file mode 100644
index 000000000..ef2e62980
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd
@@ -0,0 +1,185 @@
+--
+-- Copyright 2019 Ettus Research, A National Instruments brand
+--
+-- SPDX-License-Identifier: LGPL-3.0
+--
+-- Module: arp_responder_test
+-- Description: Simulation module to check the arp_responder IP
+-- Sends a request to the arp_responder and checks for the expected reply
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+library work;
+use work.arp_responder;
+
+entity arp_responder_test is
+end arp_responder_test;
+
+architecture sim of arp_responder_test is
+ signal test_fail : boolean := false;
+ signal aclk : std_logic := '0';
+ signal aresetn : std_logic;
+ signal mac_addr : std_logic_vector(47 downto 0) := X"017136E7BE02";
+ signal ip_addr : std_logic_vector(31 downto 0) := X"04030201";
+ signal s_axis_tdata : std_logic_vector(63 downto 0);
+ signal s_axis_tvalid : std_logic;
+ signal s_axis_tready : std_logic;
+ signal s_axis_tkeep : std_logic_vector(7 downto 0);
+ signal s_axis_tlast : std_logic;
+ signal s_axis_tuser : std_logic;
+ signal m_axis_tdata : std_logic_vector(63 downto 0);
+ signal m_axis_tvalid : std_logic;
+ signal m_axis_tready : std_logic;
+ signal m_axis_tkeep : std_logic_vector(7 downto 0);
+ signal m_axis_tlast : std_logic;
+ signal m_axis_tuser : std_logic;
+
+ constant HALFCYCLE : time := 4 ns;
+ constant CYCLE : time := 2*HALFCYCLE;
+ constant ARP_REQUEST_VECTOR : std_logic_vector(64*8-1 downto 0) :=
+ X"0000000000000000" & --Padding
+ X"0000000000000000" & --Padding
+ X"000000000000" & --Packet filler
+ X"04030201" & --
+ X"000000000000" &
+ X"020B010A" &
+ X"00D00D010101" &
+ X"0100" &
+ X"04" &
+ X"06" &
+ X"0008" &
+ X"0100" &
+ X"0608" &
+ X"00D00D010101" &
+ X"FFFFFFFFFFFF";
+ constant ARP_REPLY_VECTOR : std_logic_vector(64*8-1 downto 0) :=
+ X"0000000000000000" & --Padding
+ X"0000000000000000" & --Padding
+ X"000000000000" & --Packet filler
+ X"020B010A" &
+ X"00D00D010101" &
+ X"04030201" & --
+ X"017136E7BE02" &
+ X"0200" &
+ X"04" &
+ X"06" &
+ X"0008" &
+ X"0100" &
+ X"0608" &
+ X"017136E7BE02" &
+ X"00D00D010101";
+ --Dest --6
+ --Src --6
+ --Ethertype --2
+ --HTYPE = 0x0001 --2
+ --PTYPE = 0x0800 --2
+ --HLEN = 0x06 --1
+ --PLEN = 0x04 --1
+ --OPER = 0x0001 --2
+ --SHA = --6
+ --SPA = --4
+ --THA = --6
+ --TPA = --4
+ --Need to check...
+ -- ARP request to us
+ -- ARP request not to us
+ -- Malformed packet
+begin
+
+ process
+ begin
+ wait for HALFCYCLE;
+ aclk <= not aclk;
+ end process;
+
+ process
+ begin
+ wait for CYCLE;
+ aresetn <= '0';
+ wait for 3*CYCLE;
+ aresetn <= '1';
+ s_axis_tvalid <= '0';
+ s_axis_tkeep <= X"00";
+ s_axis_tlast <= '0';
+ s_axis_tuser <= '0';
+ m_axis_tready <= '0';
+ wait for CYCLE;
+ for i in 0 to 7 loop
+ s_axis_tdata <= ARP_REQUEST_VECTOR(64*i+63 downto 64*i);
+ s_axis_tkeep <= X"FF";
+ s_axis_tvalid <= '1';
+ if (i = 7) then
+ s_axis_tlast <= '1';
+ else
+ s_axis_tlast <= '0';
+ end if;
+ if (i >= 3) then
+ s_axis_tuser <= '1';
+ else
+ s_axis_tuser <= '0';
+ end if;
+ wait for CYCLE;
+ s_axis_tvalid <= '0';
+ wait for 7*CYCLE;
+ --wait until s_axis_tready = '1';
+ end loop;
+ wait for CYCLE;
+ s_axis_tvalid <= '0';
+ s_axis_tuser <= '0';
+ wait for CYCLE;
+ for i in 0 to 7 loop
+ s_axis_tdata <= ARP_REQUEST_VECTOR(64*i+63 downto 64*i);
+ s_axis_tkeep <= X"FF";
+ s_axis_tvalid <= '1';
+ if (i = 7) then
+ s_axis_tlast <= '1';
+ else
+ s_axis_tlast <= '0';
+ end if;
+ wait for CYCLE;
+ s_axis_tvalid <= '0';
+ wait for 7*CYCLE;
+ --wait until s_axis_tready = '1';
+ end loop;
+ wait for CYCLE;
+ s_axis_tvalid <= '0';
+ wait for CYCLE;
+ for i in 0 to 7 loop
+ m_axis_tready <= '1';
+ if (m_axis_tdata /= ARP_REPLY_VECTOR(64*i+63 downto 64*i)) then
+ test_fail <= true;
+ report "Reply vector mismatch";
+ end if;
+ wait for CYCLE;
+ m_axis_tready <= '0';
+ wait for 7*CYCLE;
+ end loop;
+ wait for CYCLE;
+ if (test_fail) then
+ report "Test FAILED" severity failure;
+ else
+ report "PASS: End of test" severity failure;
+ end if;
+ end process;
+
+dut : entity arp_responder
+port map (
+ aclk => aclk,
+ aresetn => aresetn,
+ mac_addr => mac_addr,
+ ip_addr => ip_addr,
+ s_axis_tdata => s_axis_tdata,
+ s_axis_tvalid => s_axis_tvalid,
+ s_axis_tready => s_axis_tready,
+ s_axis_tkeep => s_axis_tkeep,
+ s_axis_tlast => s_axis_tlast,
+ s_axis_tuser => s_axis_tuser,
+ m_axis_tdata => m_axis_tdata,
+ m_axis_tvalid => m_axis_tvalid,
+ m_axis_tready => m_axis_tready,
+ m_axis_tkeep => m_axis_tkeep,
+ m_axis_tlast => m_axis_tlast,
+ m_axis_tuser => m_axis_tuser
+);
+end sim;