Microchip® Advanced Software Framework

etharp.c File Reference

Address Resolution Protocol module for IP over Ethernet.

Functionally, ARP is divided into two parts. The first maps an IP address to a physical address when sending a packet, and the second part answers requests from other machines for our physical address.

This implementation complies with RFC 826 (Ethernet ARP). It supports Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 if an interface calls etharp_gratuitous(our_netif) upon address change.

#include "lwip/opt.h"
#include "lwip/ip_addr.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "netif/etharp.h"
#include "lwip/ip6.h"
#include <string.h>

Data Structures

struct  etharp_entry
 

Macros

#define ARP_AGE_REREQUEST_USED   (ARP_MAXAGE - 60)
 Re-request a used ARP entry 1 minute before it would expire to prevent breaking a steadily used connection because the ARP entry timed out. More...
 
#define ARP_MAXAGE   1200
 the time an ARP entry stays valid after its last update, for ARP_TMR_INTERVAL = 1000, this is (60 * 20) seconds = 20 minutes. More...
 
#define ARP_MAXPENDING   5
 the time an ARP entry stays pending after first request, for ARP_TMR_INTERVAL = 1000, this is 10 seconds. More...
 
#define ETHARP_FLAG_FIND_ONLY   2
 
#define ETHARP_FLAG_TRY_HARD   1
 Try hard to create a new entry - we want the IP address to appear in the cache (even if this means removing an active entry or so). More...
 
#define ETHARP_SET_HINT(netif, hint)   (etharp_cached_entry = (hint))
 
#define free_etharp_q(q)   pbuf_free(q)
 Compatibility define: free the queued pbuf. More...
 
#define HWTYPE_ETHERNET   1
 
#define LL_MULTICAST_ADDR_0   0x01
 The 24-bit IANA multicast OUI is 01-00-5e: More...
 
#define LL_MULTICAST_ADDR_1   0x00
 
#define LL_MULTICAST_ADDR_2   0x5e
 

Enumerations

enum  etharp_state {
  ETHARP_STATE_EMPTY = 0,
  ETHARP_STATE_PENDING,
  ETHARP_STATE_STABLE,
  ETHARP_STATE_STABLE_REREQUESTING
}
 

Functions

static void etharp_arp_input (struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
 Responds to ARP requests to us. More...
 
void etharp_cleanup_netif (struct netif *netif)
 Remove all ARP table entries of the specified netif. More...
 
s8_t etharp_find_addr (struct netif *netif, ip_addr_t *ipaddr, struct eth_addr **eth_ret, ip_addr_t **ip_ret)
 Finds (stable) ethernet/IP address pair from ARP table using interface and IP address index. More...
 
static s8_t etharp_find_entry (ip_addr_t *ipaddr, u8_t flags)
 Search the ARP table for a matching or new entry. More...
 
static void etharp_free_entry (int i)
 Clean up ARP table entries. More...
 
err_t etharp_output (struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
 Resolve and fill-in Ethernet address header for outgoing IP packet. More...
 
static err_t etharp_output_to_arp_index (struct netif *netif, struct pbuf *q, u8_t arp_idx)
 Just a small helper function that sends a pbuf to an ethernet address in the arp_table specified by the index 'arp_idx'. More...
 
err_t etharp_query (struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
 Send an ARP request for the given IP address and/or queue a packet. More...
 
err_t etharp_raw (struct netif *netif, const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, const u16_t opcode)
 Send a raw ARP packet (opcode and all addresses can be modified) More...
 
err_t etharp_request (struct netif *netif, ip_addr_t *ipaddr)
 Send an ARP request packet asking for ipaddr. More...
 
static err_t etharp_send_ip (struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
 Send an IP packet on the network using netif->linkoutput The ethernet header is filled in before sending. More...
 
void etharp_tmr (void)
 Clears expired entries in the ARP table. More...
 
static err_t etharp_update_arp_entry (struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
 Update (or insert) a IP/MAC address pair in the ARP cache. More...
 
err_t ethernet_input (struct pbuf *p, struct netif *netif)
 Process received ethernet frames. More...
 

Variables

static struct etharp_entry arp_table [ARP_TABLE_SIZE]
 
static u8_t etharp_cached_entry
 
struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}
 
struct eth_addr ethzero = {{0,0,0,0,0,0}}
 

#define ARP_AGE_REREQUEST_USED   (ARP_MAXAGE - 60)

Re-request a used ARP entry 1 minute before it would expire to prevent breaking a steadily used connection because the ARP entry timed out.

Referenced by etharp_output_to_arp_index().

#define ARP_MAXAGE   1200

the time an ARP entry stays valid after its last update, for ARP_TMR_INTERVAL = 1000, this is (60 * 20) seconds = 20 minutes.

Referenced by etharp_tmr().

#define ARP_MAXPENDING   5

the time an ARP entry stays pending after first request, for ARP_TMR_INTERVAL = 1000, this is 10 seconds.

Keep this number at least 2, otherwise it might run out instantly if the timeout occurs directly after a request.

Referenced by etharp_tmr().

#define ETHARP_FLAG_FIND_ONLY   2
#define ETHARP_FLAG_TRY_HARD   1

Try hard to create a new entry - we want the IP address to appear in the cache (even if this means removing an active entry or so).

Referenced by etharp_arp_input(), etharp_find_entry(), etharp_query(), and etharp_update_arp_entry().

#define ETHARP_SET_HINT (   netif,
  hint 
)    (etharp_cached_entry = (hint))

Referenced by etharp_output(), and etharp_query().

#define free_etharp_q (   q)    pbuf_free(q)

Compatibility define: free the queued pbuf.

Referenced by etharp_free_entry().

#define HWTYPE_ETHERNET   1

Referenced by etharp_arp_input(), and etharp_raw().

#define LL_MULTICAST_ADDR_0   0x01

The 24-bit IANA multicast OUI is 01-00-5e:

Referenced by etharp_output(), and ethernet_input().

#define LL_MULTICAST_ADDR_1   0x00

Referenced by etharp_output(), and ethernet_input().

#define LL_MULTICAST_ADDR_2   0x5e

Referenced by etharp_output(), and ethernet_input().

Enumerator
ETHARP_STATE_EMPTY 
ETHARP_STATE_PENDING 
ETHARP_STATE_STABLE 
ETHARP_STATE_STABLE_REREQUESTING 

static void etharp_arp_input ( struct netif netif,
struct eth_addr ethaddr,
struct pbuf p 
)
static

Responds to ARP requests to us.

Upon ARP replies to us, add entry to cache send out queued IP packets. Updates cache with snooped address pairs.

Should be called for incoming ARP packets. The pbuf in the argument is freed by this function.

Parameters
netifThe lwIP network interface on which the ARP packet pbuf arrived.
ethaddrEthernet address of netif.
pThe ARP packet that arrived on netif. Is freed by this function.
Returns
NULL
See Also
pbuf_free()

References ARP_REPLY, ARP_REQUEST, autoip_arp_reply(), dhcp_arp_reply(), ETHADDR16_COPY, ETHARP_DEBUG, ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_TRY_HARD, ETHARP_HWADDR_LEN, ETHARP_STATS_INC, etharp_update_arp_entry(), ETHTYPE_IP, ETHTYPE_VLAN, htons, netif::hwaddr_len, HWTYPE_ETHERNET, netif::ip_addr, ip_addr_cmp, ip_addr_isany, ip_addr_islinklocal, IPADDR2_COPY, pbuf::len, netif::linkoutput, LWIP_ASSERT, LWIP_DBG_LEVEL_WARNING, LWIP_DBG_TRACE, LWIP_DEBUGF, LWIP_ERROR(), NULL, pbuf::payload, pbuf_free(), PP_HTONS, S16_F, SIZEOF_ETH_HDR, SIZEOF_ETHARP_PACKET, pbuf::tot_len, and U16_F.

Referenced by ethernet_input().

void etharp_cleanup_netif ( struct netif netif)

Remove all ARP table entries of the specified netif.

Parameters
netifpoints to a network interface

References arp_table, etharp_free_entry(), ETHARP_STATE_EMPTY, etharp_entry::state, and netif::state.

Referenced by netif_set_down().

s8_t etharp_find_addr ( struct netif netif,
ip_addr_t ipaddr,
struct eth_addr **  eth_ret,
ip_addr_t **  ip_ret 
)

Finds (stable) ethernet/IP address pair from ARP table using interface and IP address index.

Note
the addresses in the ARP table are in network order!
Parameters
netifpoints to interface index
ipaddrpoints to the (network order) IP address index
eth_retpoints to return pointer
ip_retpoints to return pointer
Returns
table index if found, -1 otherwise

References arp_table, etharp_entry::ethaddr, etharp_find_entry(), ETHARP_FLAG_FIND_ONLY, ETHARP_STATE_STABLE, etharp_entry::ipaddr, LWIP_ASSERT, NULL, and netif::state.

static s8_t etharp_find_entry ( ip_addr_t ipaddr,
u8_t  flags 
)
static

Search the ARP table for a matching or new entry.

If an IP address is given, return a pending or stable ARP entry that matches the address. If no match is found, create a new entry with this address set, but in state ETHARP_EMPTY. The caller must check and possibly change the state of the returned entry.

If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.

In all cases, attempt to create new entries from an empty entry. If no empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle old entries. Heuristic choose the least important entry for recycling.

Parameters
ipaddrIP address to find in ARP cache, or to add if not found.
flags
See Also
definition of ETHARP_FLAG_*
Parameters
netifnetif related to this address (used for NETIF_HWADDRHINT)
Returns
The ARP entry index that matched or is created, ERR_MEM if no entry is found or could be recycled.

a) do a search through the cache, remember candidates b) select candidate entry c) create new entry

References arp_table, etharp_entry::ctime, ERR_MEM, ETHARP_DEBUG, ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_TRY_HARD, etharp_free_entry(), ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ip_addr_cmp, ip_addr_copy, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, NULL, etharp_entry::state, and U16_F.

Referenced by etharp_find_addr(), etharp_query(), and etharp_update_arp_entry().

err_t etharp_output ( struct netif netif,
struct pbuf q,
ip_addr_t ipaddr 
)

Resolve and fill-in Ethernet address header for outgoing IP packet.

For IP multicast and broadcast, corresponding Ethernet addresses are selected and the packet is transmitted on the link.

For unicast addresses, the packet is submitted to etharp_query(). In case the IP address is outside the local network, the IP address of the gateway is used.

Parameters
netifThe lwIP network interface which the IP packet will be sent on.
qThe pbuf(s) containing the IP packet to be sent.
ipaddrThe IP address of the packet destination.
Returns

References arp_table, ERR_BUF, ERR_RTE, etharp_cached_entry, ETHARP_DEBUG, etharp_output_to_arp_index(), etharp_query(), etharp_send_ip(), ETHARP_SET_HINT, ETHARP_STATE_STABLE, ETHARP_STATS_INC, netif::gw, netif::hwaddr, ip4_addr2, ip4_addr3, ip4_addr4, netif::ip_addr, ip_addr_cmp, ip_addr_isany, ip_addr_isbroadcast, ip_addr_islinklocal, ip_addr_ismulticast, ip_addr_netcmp, LINK_STATS_INC, LL_MULTICAST_ADDR_0, LL_MULTICAST_ADDR_1, LL_MULTICAST_ADDR_2, LWIP_ASSERT, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_TRACE, LWIP_DEBUGF, netif::netmask, NULL, pbuf::payload, and pbuf_header().

Referenced by winc_netif_init().

static err_t etharp_output_to_arp_index ( struct netif netif,
struct pbuf q,
u8_t  arp_idx 
)
static

Just a small helper function that sends a pbuf to an ethernet address in the arp_table specified by the index 'arp_idx'.

References ARP_AGE_REREQUEST_USED, arp_table, ERR_OK, etharp_entry::ethaddr, etharp_request(), etharp_send_ip(), ETHARP_STATE_STABLE, ETHARP_STATE_STABLE_REREQUESTING, netif::hwaddr, LWIP_ASSERT, and etharp_entry::state.

Referenced by etharp_output().

err_t etharp_query ( struct netif netif,
ip_addr_t ipaddr,
struct pbuf q 
)

Send an ARP request for the given IP address and/or queue a packet.

If the IP address was not yet in the cache, a pending ARP cache entry is added and an ARP request is sent for the given address. The packet is queued on this entry.

If the IP address was already pending in the cache, a new ARP request is sent for the given address. The packet is queued on this entry.

If the IP address was already stable in the cache, and a packet is given, it is directly sent and no ARP request is sent out.

If the IP address was already stable in the cache, and no packet is given, an ARP request is sent out.

Parameters
netifThe lwIP network interface on which ipaddr must be queried for.
ipaddrThe IP address to be resolved.
qIf non-NULL, a pbuf that must be delivered to the IP address. q is not freed by this function.
Note
q must only be ONE packet, not a packet queue!
Returns
  • ERR_BUF Could not make room for Ethernet header.
  • ERR_MEM Hardware address unknown, and no more ARP entries available to query for address or queue the packet.
  • ERR_MEM Could not queue packet due to memory shortage.
  • ERR_RTE No route to destination (no gateway to external networks).
  • ERR_ARG Non-unicast address given, those will not appear in ARP cache.

References arp_table, ERR_ARG, ERR_MEM, ERR_OK, ETHARP_DEBUG, etharp_find_entry(), ETHARP_FLAG_TRY_HARD, etharp_request(), etharp_send_ip(), ETHARP_SET_HINT, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHARP_STATS_INC, netif::hwaddr, if(), ip_addr_isany, ip_addr_isbroadcast, ip_addr_ismulticast, pbuf::len, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, memp_free(), memp_malloc(), etharp_entry::netif, pbuf::next, NULL, pbuf_alloc(), pbuf_copy(), pbuf_free(), PBUF_RAM, PBUF_RAW, pbuf_ref(), PBUF_ROM, etharp_entry::q, S16_F, etharp_entry::state, pbuf::tot_len, and pbuf::type.

Referenced by dhcp_check(), and etharp_output().

err_t etharp_raw ( struct netif netif,
const struct eth_addr ethsrc_addr,
const struct eth_addr ethdst_addr,
const struct eth_addr hwsrc_addr,
const ip_addr_t ipsrc_addr,
const struct eth_addr hwdst_addr,
const ip_addr_t ipdst_addr,
const u16_t  opcode 
)

Send a raw ARP packet (opcode and all addresses can be modified)

Parameters
netifthe lwip network interface on which to send the ARP packet
ethsrc_addrthe source MAC address for the ethernet header
ethdst_addrthe destination MAC address for the ethernet header
hwsrc_addrthe source MAC address for the ARP protocol header
ipsrc_addrthe source IP address for the ARP protocol header
hwdst_addrthe destination MAC address for the ARP protocol header
ipdst_addrthe destination IP address for the ARP protocol header
opcodethe type of the ARP packet
Returns
ERR_OK if the ARP packet has been sent ERR_MEM if the ARP packet couldn't be allocated any other err_t on failure

References ERR_MEM, ERR_OK, ETHADDR16_COPY, ETHARP_DEBUG, ETHARP_HWADDR_LEN, ETHARP_STATS_INC, ETHTYPE_ARP, ETHTYPE_IP, ETHTYPE_VLAN, htons, netif::hwaddr_len, HWTYPE_ETHERNET, ip_addr_islinklocal, IPADDR2_COPY, pbuf::len, netif::linkoutput, LWIP_ASSERT, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_TRACE, LWIP_DEBUGF, NULL, pbuf::payload, pbuf_alloc(), pbuf_free(), pbuf_header(), PBUF_RAM, PBUF_RAW, PP_HTONS, SIZEOF_ETH_HDR, and SIZEOF_ETHARP_PACKET_TX.

Referenced by autoip_arp_announce(), autoip_arp_probe(), and etharp_request().

err_t etharp_request ( struct netif netif,
ip_addr_t ipaddr 
)

Send an ARP request packet asking for ipaddr.

Parameters
netifthe lwip network interface on which to send the request
ipaddrthe IP address for which to ask
Returns
ERR_OK if the request has been sent ERR_MEM if the ARP packet couldn't be allocated any other err_t on failure

References ARP_REQUEST, ETHARP_DEBUG, etharp_raw(), netif::hwaddr, netif::ip_addr, LWIP_DBG_TRACE, and LWIP_DEBUGF.

Referenced by etharp_output_to_arp_index(), etharp_query(), and etharp_tmr().

static err_t etharp_send_ip ( struct netif netif,
struct pbuf p,
struct eth_addr src,
struct eth_addr dst 
)
static

Send an IP packet on the network using netif->linkoutput The ethernet header is filled in before sending.

netif the lwIP network interface on which to send the packet p the packet to send, p->payload pointing to the (uninitialized) ethernet header src the source MAC address to be copied into the ethernet header dst the destination MAC address to be copied into the ethernet header

Returns
ERR_OK if the packet was sent, any other err_t on failure

References ETHADDR16_COPY, ETHADDR32_COPY, ETHARP_DEBUG, ETHARP_HWADDR_LEN, ETHTYPE_IP, ETHTYPE_VLAN, netif::hwaddr_len, netif::linkoutput, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, pbuf::payload, pbuf_header(), PP_HTONS, and SIZEOF_ETH_HDR.

Referenced by etharp_output(), etharp_output_to_arp_index(), etharp_query(), and etharp_update_arp_entry().

void etharp_tmr ( void  )

Clears expired entries in the ARP table.

This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), in order to expire entries in the ARP table.

References ARP_MAXAGE, ARP_MAXPENDING, arp_table, etharp_entry::ctime, ERR_OK, ETHARP_DEBUG, etharp_free_entry(), etharp_request(), ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHARP_STATE_STABLE_REREQUESTING, LWIP_DEBUGF, etharp_entry::state, and U16_F.

Referenced by arp_timer().

static err_t etharp_update_arp_entry ( struct netif netif,
ip_addr_t ipaddr,
struct eth_addr ethaddr,
u8_t  flags 
)
static

Update (or insert) a IP/MAC address pair in the ARP cache.

If a pending entry is resolved, any queued packets will be sent at this point.

Parameters
netifnetif related to this entry (used for NETIF_ADDRHINT)
ipaddrIP address of the inserted ARP entry.
ethaddrEthernet address of the inserted ARP entry.
flags
See Also
definition of ETHARP_FLAG_*
Returns
  • ERR_OK Successfully updated ARP cache.
  • ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set.
  • ERR_ARG Non-unicast address given, those will not appear in ARP cache.
See Also
pbuf_free()

References arp_table, etharp_entry::ctime, ERR_ARG, ERR_OK, ERR_RTE, ETHADDR32_COPY, ETHARP_DEBUG, etharp_find_entry(), ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_TRY_HARD, etharp_free_entry(), ETHARP_HWADDR_LEN, etharp_send_ip(), ETHARP_STATE_STABLE, netif::hwaddr, netif::hwaddr_len, ip4_addr1_16, ip4_addr2_16, ip4_addr3_16, ip4_addr4_16, ip_addr_isany, ip_addr_isbroadcast, ip_addr_ismulticast, ip_route(), LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, memp_free(), etharp_entry::netif, pbuf::next, NULL, pbuf_free(), etharp_entry::q, S16_F, snmp_insert_arpidx_tree, etharp_entry::state, netif::state, U16_F, and X16_F.

Referenced by etharp_arp_input().

err_t ethernet_input ( struct pbuf p,
struct netif netif 
)

Process received ethernet frames.

Using this function instead of directly calling ip_input and passing ARP frames through etharp in ethernetif_input, the ARP cache is protected from concurrent access.

Parameters
pthe received packet, p->payload pointing to the ethernet header
netifthe network interface on which the packet was received

References ERR_OK, eth_addr_cmp, etharp_arp_input(), ETHARP_DEBUG, ETHARP_STATS_INC, ETHTYPE_ARP, ETHTYPE_IP, ETHTYPE_IPV6, ETHTYPE_PPPOE, ETHTYPE_PPPOEDISC, ETHTYPE_VLAN, pbuf::flags, netif::flags, htons, netif::hwaddr, ip6_input(), ip_input(), pbuf::len, LL_MULTICAST_ADDR_0, LL_MULTICAST_ADDR_1, LL_MULTICAST_ADDR_2, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, NETIF_FLAG_ETHARP, pbuf::payload, PBUF_FLAG_LLBCAST, PBUF_FLAG_LLMCAST, pbuf_free(), pbuf_header(), PP_HTONS, and SIZEOF_ETH_HDR.

Referenced by tcpip_input(), and tcpip_thread().

u8_t etharp_cached_entry
static

Referenced by etharp_output().

struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}
struct eth_addr ethzero = {{0,0,0,0,0,0}}