arp: Implement ARP replies
This commit is contained in:
parent
7bb82a9acf
commit
5f389b0c7b
@ -186,6 +186,9 @@ architecture eth of top_hwitl is
|
|||||||
constant ETH_CONFIG : configuration_t := (
|
constant ETH_CONFIG : configuration_t := (
|
||||||
mac_address => (x"00", x"ff", x"ff", x"11", x"22", x"33")
|
mac_address => (x"00", x"ff", x"ff", x"11", x"22", x"33")
|
||||||
);
|
);
|
||||||
|
constant IP_CONFIG : ip_configuration_t := (
|
||||||
|
ip_address => (x"C0", x"A8", x"02", x"02")
|
||||||
|
);
|
||||||
|
|
||||||
signal rst : std_logic;
|
signal rst : std_logic;
|
||||||
signal clk_phy : std_logic;
|
signal clk_phy : std_logic;
|
||||||
@ -199,12 +202,30 @@ architecture eth of top_hwitl is
|
|||||||
|
|
||||||
constant PROT_ARP : integer := 0;
|
constant PROT_ARP : integer := 0;
|
||||||
constant PROT_IP : integer := 1;
|
constant PROT_IP : integer := 1;
|
||||||
constant ETHERNET_II_PROTOCOLS : ethernet_ii_protocol_vector := (PROT_ARP => ETHERNET_II_PROTOCOL_ARP, PROT_IP => ETHERNET_II_PROTOCOL_IP);
|
constant ETHERNET_II_PROTOCOLS : ethernet_ii_protocol_vector := (
|
||||||
|
PROT_ARP => ETHERNET_II_PROTOCOL_ARP,
|
||||||
|
PROT_IP => ETHERNET_II_PROTOCOL_IP
|
||||||
|
);
|
||||||
signal ethernet_i_out : ethernet_i_out_t;
|
signal ethernet_i_out : ethernet_i_out_t;
|
||||||
signal ethernet_i_in : ethernet_i_in_t;
|
signal ethernet_i_in : ethernet_i_in_t;
|
||||||
signal ethernet_ii_out : ethernet_ii_out_vector(ETHERNET_II_PROTOCOLS'range);
|
signal ethernet_ii_out : ethernet_ii_out_vector(ETHERNET_II_PROTOCOLS'range);
|
||||||
signal ethernet_ii_in : ethernet_ii_in_vector(ETHERNET_II_PROTOCOLS'range);
|
signal ethernet_ii_in : ethernet_ii_in_vector(ETHERNET_II_PROTOCOLS'range);
|
||||||
|
|
||||||
|
signal arp_out : arp_out_t;
|
||||||
|
signal arp_in : arp_in_t;
|
||||||
begin
|
begin
|
||||||
|
trashernet_arp_inst : entity trashernet.trashernet_arp
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
rst => rst,
|
||||||
|
mac_config => ETH_CONFIG,
|
||||||
|
ip_config => IP_CONFIG,
|
||||||
|
arp_out => arp_out,
|
||||||
|
arp_in => arp_in,
|
||||||
|
ethernet_ii_out => ethernet_ii_out(PROT_ARP),
|
||||||
|
ethernet_ii_in => ethernet_ii_in(PROT_ARP)
|
||||||
|
);
|
||||||
|
|
||||||
trashernet_eth_inst : entity trashernet.trashernet_eth
|
trashernet_eth_inst : entity trashernet.trashernet_eth
|
||||||
generic map(
|
generic map(
|
||||||
ETHERNET_II_PROTOCOLS => ETHERNET_II_PROTOCOLS
|
ETHERNET_II_PROTOCOLS => ETHERNET_II_PROTOCOLS
|
||||||
|
210
trashernet/trashernet_arp.vhd
Normal file
210
trashernet/trashernet_arp.vhd
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- trashernet_arp.vhd : Address Resolution Protocol
|
||||||
|
-- Implements simple single-entry cache ARP.
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- Author : Markus Koch <markus@notsyncing.net>
|
||||||
|
-- Contributors : None
|
||||||
|
-- License : Mozilla Public License (MPL) Version 2
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
use work.trashernet_pkg.all;
|
||||||
|
|
||||||
|
entity trashernet_arp is
|
||||||
|
port(
|
||||||
|
-- Global
|
||||||
|
clk : in std_logic; -- Global clock
|
||||||
|
rst : in std_logic; -- Asynchronous reset
|
||||||
|
|
||||||
|
-- Configuration
|
||||||
|
mac_config : in configuration_t; -- Trashernet MAC configuration
|
||||||
|
ip_config : in ip_configuration_t; -- Trashernet IP configuration
|
||||||
|
|
||||||
|
-- ARP application interface
|
||||||
|
arp_out : out arp_out_t; -- ARP IF (out from ARP)
|
||||||
|
arp_in : in arp_in_t; -- ARP IF (into ARP)
|
||||||
|
|
||||||
|
-- Ethernet II application interface
|
||||||
|
ethernet_ii_out : in ethernet_ii_out_t; -- Ethernet II IF (out from MAC)
|
||||||
|
ethernet_ii_in : out ethernet_ii_in_t -- Ethernet II IF (into MAC)
|
||||||
|
);
|
||||||
|
end entity trashernet_arp;
|
||||||
|
|
||||||
|
architecture rtl of trashernet_arp is
|
||||||
|
constant HTYPE : byte_vector := (x"00", x"01");
|
||||||
|
constant PTYPE : byte_vector := (x"08", x"00");
|
||||||
|
constant HLEN : byte := x"06";
|
||||||
|
constant PLEN : byte := x"04";
|
||||||
|
constant OPER_REQUEST : byte_vector := (x"00", x"01");
|
||||||
|
constant OPER_REPLY : byte_vector := (x"00", x"02");
|
||||||
|
|
||||||
|
signal arp_reply_rq : std_logic; -- Request to transmit an ARP reply
|
||||||
|
signal arp_reply_tha : mac_addr_t; -- Target MAC to use in reply (SHA in received packet)
|
||||||
|
signal arp_reply_tpa : ip_addr_t; -- Target IP to use in reply (SPA in received packet)
|
||||||
|
signal arp_reply_ack : std_logic; -- ARP reply has been latched and is being sent
|
||||||
|
begin
|
||||||
|
rx : block
|
||||||
|
constant BYTECOUNT_HEAD : integer := 8; -- HTYPE -> OPER
|
||||||
|
constant BYTECOUNT_ADDRESSES : integer := 20; -- SHA -> TPA
|
||||||
|
|
||||||
|
signal sr : byte_vector(0 to BYTECOUNT_ADDRESSES - 1);
|
||||||
|
|
||||||
|
constant SR_HEAD_OFFSET : integer := BYTECOUNT_ADDRESSES - BYTECOUNT_HEAD;
|
||||||
|
alias sr_head_htype is sr(SR_HEAD_OFFSET + 0 to SR_HEAD_OFFSET + 1);
|
||||||
|
alias sr_head_ptype is sr(SR_HEAD_OFFSET + 2 to SR_HEAD_OFFSET + 3);
|
||||||
|
alias sr_head_hlen is sr(SR_HEAD_OFFSET + 4);
|
||||||
|
alias sr_head_plen is sr(SR_HEAD_OFFSET + 5);
|
||||||
|
alias sr_head_oper is sr(SR_HEAD_OFFSET + 6 to SR_HEAD_OFFSET + 7);
|
||||||
|
|
||||||
|
constant SR_ADDRESSES_OFFSET : integer := -8;
|
||||||
|
alias sr_addresses_sha is sr(8 + SR_ADDRESSES_OFFSET to 13 + SR_ADDRESSES_OFFSET);
|
||||||
|
alias sr_addresses_spa is sr(14 + SR_ADDRESSES_OFFSET to 17 + SR_ADDRESSES_OFFSET);
|
||||||
|
alias sr_addresses_tha is sr(18 + SR_ADDRESSES_OFFSET to 23 + SR_ADDRESSES_OFFSET);
|
||||||
|
alias sr_addresses_tpa is sr(24 + SR_ADDRESSES_OFFSET to 27 + SR_ADDRESSES_OFFSET);
|
||||||
|
|
||||||
|
type state_t is (HEAD, ADDRESSES, WAITCRC, SENDREPLY, IGNORE);
|
||||||
|
signal state : state_t;
|
||||||
|
signal bytecount : integer range 0 to BYTECOUNT_ADDRESSES;
|
||||||
|
signal shifted : std_logic;
|
||||||
|
|
||||||
|
signal block_done : std_logic;
|
||||||
|
|
||||||
|
signal header_ok : std_logic;
|
||||||
|
signal we_are_asked : std_logic;
|
||||||
|
|
||||||
|
signal is_request : std_logic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
block_done <= '1' when shifted = '1' and bytecount = 0 else '0';
|
||||||
|
|
||||||
|
header_ok <= '1' when --
|
||||||
|
sr_head_htype = HTYPE and --
|
||||||
|
sr_head_ptype = PTYPE and --
|
||||||
|
sr_head_hlen = HLEN and sr_head_plen = PLEN --
|
||||||
|
else
|
||||||
|
'0';
|
||||||
|
|
||||||
|
we_are_asked <= '1' when --
|
||||||
|
sr_addresses_tpa = ip_config.ip_address else
|
||||||
|
'0';
|
||||||
|
|
||||||
|
rx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
state <= HEAD;
|
||||||
|
shifted <= '0';
|
||||||
|
bytecount <= BYTECOUNT_HEAD;
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if (ethernet_ii_out.rx_crc_ok or ethernet_ii_out.rx_crc_error) then
|
||||||
|
state <= HEAD; -- Safe return from any state, may be overridden below
|
||||||
|
bytecount <= BYTECOUNT_HEAD;
|
||||||
|
end if;
|
||||||
|
shifted <= ethernet_ii_out.rx_data_valid;
|
||||||
|
if (ethernet_ii_out.rx_data_valid = '1') and (bytecount > 0) then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & ethernet_ii_out.rx_data;
|
||||||
|
bytecount <= bytecount - 1;
|
||||||
|
end if;
|
||||||
|
case state is
|
||||||
|
when HEAD =>
|
||||||
|
if block_done then
|
||||||
|
if header_ok then
|
||||||
|
bytecount <= BYTECOUNT_ADDRESSES;
|
||||||
|
state <= ADDRESSES;
|
||||||
|
is_request <= '1' when (sr_head_oper = OPER_REQUEST) else '0';
|
||||||
|
else
|
||||||
|
state <= IGNORE;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ADDRESSES =>
|
||||||
|
if block_done then
|
||||||
|
if (we_are_asked) then
|
||||||
|
state <= WAITCRC;
|
||||||
|
else
|
||||||
|
state <= IGNORE;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WAITCRC =>
|
||||||
|
if ethernet_ii_out.rx_crc_ok then
|
||||||
|
if is_request then
|
||||||
|
state <= SENDREPLY;
|
||||||
|
else
|
||||||
|
report "reply";
|
||||||
|
null; -- TODO: process response
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when SENDREPLY =>
|
||||||
|
if arp_reply_ack then
|
||||||
|
bytecount <= BYTECOUNT_HEAD;
|
||||||
|
state <= HEAD;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when IGNORE =>
|
||||||
|
null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process rx_fsm;
|
||||||
|
arp_reply_rq <= '1' when state = SENDREPLY else '0';
|
||||||
|
arp_reply_tha <= sr_addresses_sha;
|
||||||
|
arp_reply_tpa <= sr_addresses_spa;
|
||||||
|
end block rx;
|
||||||
|
|
||||||
|
tx : block
|
||||||
|
signal sr : byte_vector(0 to 27);
|
||||||
|
signal arp_reply_preload : byte_vector(sr'range);
|
||||||
|
constant BYTECOUNT_MAX : integer := sr'length + 1;
|
||||||
|
signal bytecount : integer range 0 to BYTECOUNT_MAX;
|
||||||
|
|
||||||
|
type state_t is (IDLE, TRANSMIT);
|
||||||
|
signal state : state_t;
|
||||||
|
begin
|
||||||
|
|
||||||
|
arp_reply_preload <= HTYPE & PTYPE & HLEN & PLEN & OPER_REPLY & -- Header
|
||||||
|
mac_config.mac_address & ip_config.ip_address & -- Sender
|
||||||
|
arp_reply_tha & arp_reply_tpa; -- Target
|
||||||
|
|
||||||
|
tx_fsm : process(clk, rst) is
|
||||||
|
begin
|
||||||
|
if rst then
|
||||||
|
arp_reply_ack <= '0';
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
arp_reply_ack <= '0';
|
||||||
|
|
||||||
|
if (ethernet_ii_out.tx_data_ack = '1') and (bytecount > 0) then
|
||||||
|
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||||
|
bytecount <= bytecount - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case state is
|
||||||
|
when IDLE =>
|
||||||
|
if arp_reply_rq then
|
||||||
|
state <= TRANSMIT;
|
||||||
|
arp_reply_ack <= '1';
|
||||||
|
sr <= arp_reply_preload;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
bytecount <= BYTECOUNT_MAX;
|
||||||
|
|
||||||
|
when TRANSMIT =>
|
||||||
|
if bytecount = 0 then
|
||||||
|
state <= IDLE;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process tx_fsm;
|
||||||
|
|
||||||
|
ethernet_ii_in.tx_mac_address <= arp_reply_tha;
|
||||||
|
ethernet_ii_in.tx_en <= '1' when state = TRANSMIT else '0';
|
||||||
|
ethernet_ii_in.tx_data <= sr(0);
|
||||||
|
|
||||||
|
end block tx;
|
||||||
|
end architecture rtl;
|
@ -34,6 +34,9 @@ package trashernet_pkg is
|
|||||||
type configuration_t is record
|
type configuration_t is record
|
||||||
mac_address : mac_addr_t; -- MAC address of this node
|
mac_address : mac_addr_t; -- MAC address of this node
|
||||||
end record configuration_t;
|
end record configuration_t;
|
||||||
|
type ip_configuration_t is record
|
||||||
|
ip_address : ip_addr_t; -- IP address of this node
|
||||||
|
end record ip_configuration_t;
|
||||||
|
|
||||||
-- PHY interface
|
-- PHY interface
|
||||||
type phy_in_t is record
|
type phy_in_t is record
|
||||||
|
Loading…
Reference in New Issue
Block a user