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 <string.h>
Data Structures | |
struct | etharp_entry |
Macros | |
#define | ARP_MAXAGE 240 |
the time an ARP entry stays valid after its last update, for ARP_TMR_INTERVAL = 5000, this is (240 * 5) seconds = 20 minutes. More... | |
#define | ARP_MAXPENDING 2 |
the time an ARP entry stays pending after first request, for ARP_TMR_INTERVAL = 5000, this is (2 * 5) seconds = 10 seconds. More... | |
#define | ETHARP_FLAG_FIND_ONLY 2 |
#define | ETHARP_FLAG_STATIC_ENTRY 4 |
#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 |
Enumerations | |
enum | etharp_state { ETHARP_STATE_EMPTY = 0, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE } |
Functions | |
static void | etharp_arp_input (struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) |
Responds to ARP requests to us. 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... | |
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... | |
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... | |
static 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... | |
err_t | ethernet_input (struct pbuf *p, struct netif *netif) |
Process received ethernet frames. More... | |
static s8_t | find_entry (ip_addr_t *ipaddr, u8_t flags) |
Search the ARP table for a matching or new entry. More... | |
static void | free_entry (int i) |
Clean up ARP table entries. More... | |
static err_t | 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... | |
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_MAXAGE 240 |
the time an ARP entry stays valid after its last update, for ARP_TMR_INTERVAL = 5000, this is (240 * 5) seconds = 20 minutes.
Referenced by etharp_tmr().
#define ARP_MAXPENDING 2 |
the time an ARP entry stays pending after first request, for ARP_TMR_INTERVAL = 5000, this is (2 * 5) seconds = 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 |
Referenced by etharp_arp_input(), etharp_find_addr(), find_entry(), and update_arp_entry().
#define ETHARP_FLAG_STATIC_ENTRY 4 |
Referenced by update_arp_entry().
#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_query(), find_entry(), and update_arp_entry().
#define ETHARP_SET_HINT | ( | netif, | |
hint | |||
) | (etharp_cached_entry = (hint)) |
Referenced by etharp_query().
#define free_etharp_q | ( | q | ) | pbuf_free(q) |
Compatibility define: free the queued pbuf.
Referenced by free_entry().
#define HWTYPE_ETHERNET 1 |
Referenced by etharp_arp_input(), and etharp_raw().
enum etharp_state |
|
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.
netif | The lwIP network interface on which the ARP packet pbuf arrived. |
ethaddr | Ethernet address of netif. |
p | The ARP packet that arrived on netif. Is freed by this function. |
References ARP_REPLY, ARP_REQUEST, ETHADDR16_COPY, ETHARP_DEBUG, ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_TRY_HARD, ETHARP_HWADDR_LEN, ETHARP_STATS_INC, 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, U16_F, and update_arp_entry().
Referenced by ethernet_input().
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.
netif | points to interface index |
ipaddr | points to the (network order) IP address index |
eth_ret | points to return pointer |
ip_ret | points to return pointer |
References arp_table, etharp_entry::ethaddr, ETHARP_FLAG_FIND_ONLY, ETHARP_STATE_STABLE, find_entry(), etharp_entry::ipaddr, LWIP_ASSERT, LWIP_UNUSED_ARG, NULL, and netif::state.
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.
netif | The lwIP network interface which the IP packet will be sent on. |
q | The pbuf(s) containing the IP packet to be sent. |
ipaddr | The IP address of the packet destination. |
References arp_table, ARP_TABLE_SIZE, ERR_BUF, ERR_RTE, etharp_entry::ethaddr, etharp_cached_entry, ETHARP_DEBUG, etharp_query(), etharp_send_ip(), 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, LWIP_DBG_LEVEL_SERIOUS, LWIP_DBG_TRACE, LWIP_DEBUGF, netif::netmask, NULL, pbuf::payload, and pbuf_header().
Referenced by ethernetif_init().
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.
netif | The lwIP network interface on which ipaddr must be queried for. |
ipaddr | The IP address to be resolved. |
q | If non-NULL, a pbuf that must be delivered to the IP address. q is not freed by this function. |
References arp_table, ERR_ARG, ERR_MEM, ERR_OK, ETHARP_DEBUG, ETHARP_FLAG_TRY_HARD, etharp_request(), etharp_send_ip(), ETHARP_SET_HINT, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHARP_STATS_INC, find_entry(), netif::hwaddr, if(), ip_addr_isany, ip_addr_isbroadcast, ip_addr_ismulticast, pbuf::len, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, memp_malloc(), 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 etharp_output().
|
static |
Send a raw ARP packet (opcode and all addresses can be modified)
netif | the lwip network interface on which to send the ARP packet |
ethsrc_addr | the source MAC address for the ethernet header |
ethdst_addr | the destination MAC address for the ethernet header |
hwsrc_addr | the source MAC address for the ARP protocol header |
ipsrc_addr | the source IP address for the ARP protocol header |
hwdst_addr | the destination MAC address for the ARP protocol header |
ipdst_addr | the destination IP address for the ARP protocol header |
opcode | the type of the ARP packet |
References ERR_MEM, ERR_OK, ETHADDR16_COPY, ETHARP_DEBUG, ETHARP_HWADDR_LEN, ETHARP_STATS_INC, ETHTYPE_ARP, ETHTYPE_IP, 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_RAM, PBUF_RAW, PP_HTONS, SIZEOF_ETH_HDR, and SIZEOF_ETHARP_PACKET.
Referenced by etharp_request().
Send an ARP request packet asking for ipaddr.
netif | the lwip network interface on which to send the request |
ipaddr | the IP address for which to ask |
References ARP_REQUEST, ETHARP_DEBUG, etharp_raw(), netif::hwaddr, netif::ip_addr, LWIP_DBG_TRACE, and LWIP_DEBUGF.
Referenced by etharp_query().
|
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
References ETHADDR16_COPY, ETHADDR32_COPY, ETHARP_DEBUG, ETHARP_HWADDR_LEN, ETHTYPE_IP, netif::hwaddr_len, netif::linkoutput, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, pbuf::payload, and PP_HTONS.
Referenced by etharp_output(), etharp_query(), and update_arp_entry().
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, ARP_TABLE_SIZE, etharp_entry::ctime, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, ETHARP_SUPPORT_STATIC_ENTRIES, free_entry(), LWIP_DEBUGF, etharp_entry::state, and U16_F.
Referenced by arp_timer().
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.
p | the recevied packet, p->payload pointing to the ethernet header |
netif | the network interface on which the packet was received |
References ERR_OK, etharp_arp_input(), ETHARP_DEBUG, ETHARP_STATS_INC, ETHTYPE_ARP, ETHTYPE_IP, ETHTYPE_PPPOE, ETHTYPE_PPPOEDISC, ETHTYPE_VLAN, netif::flags, htons, netif::hwaddr, ip_input(), pbuf::len, LWIP_ASSERT, LWIP_DBG_TRACE, LWIP_DEBUGF, NETIF_FLAG_ETHARP, pbuf::payload, pbuf_free(), pbuf_header(), PP_HTONS, SIZEOF_ETH_HDR, and X8_F.
Referenced by tcpip_input(), and tcpip_thread().
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.
ipaddr | IP address to find in ARP cache, or to add if not found. |
flags |
netif | netif related to this address (used for NETIF_HWADDRHINT) |
a) do a search through the cache, remember candidates b) select candidate entry c) create new entry
References arp_table, ARP_TABLE_SIZE, etharp_entry::ctime, ERR_MEM, ETHARP_DEBUG, ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_TRY_HARD, ETHARP_STATE_EMPTY, ETHARP_STATE_PENDING, ETHARP_STATE_STABLE, free_entry(), 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 update_arp_entry().
|
static |
Clean up ARP table entries.
References arp_table, etharp_entry::ctime, etharp_entry::ethaddr, ETHARP_DEBUG, ETHARP_STATE_EMPTY, ethzero, free_etharp_q, ip_addr_set_zero, LWIP_DEBUGF, NULL, etharp_entry::q, snmp_delete_arpidx_tree, etharp_entry::state, and U16_F.
Referenced by etharp_tmr(), find_entry(), and update_arp_entry().
|
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.
netif | netif related to this entry (used for NETIF_ADDRHINT) |
ipaddr | IP address of the inserted ARP entry. |
ethaddr | Ethernet address of the inserted ARP entry. |
flags |
References arp_table, etharp_entry::ctime, ERR_ARG, ERR_OK, ERR_RTE, ETHADDR32_COPY, ETHARP_DEBUG, ETHARP_FLAG_FIND_ONLY, ETHARP_FLAG_STATIC_ENTRY, ETHARP_FLAG_TRY_HARD, ETHARP_HWADDR_LEN, etharp_send_ip(), ETHARP_STATE_STABLE, find_entry(), free_entry(), 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(), 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().
|
static |
Referenced by etharp_find_addr(), etharp_output(), etharp_query(), etharp_tmr(), find_entry(), free_entry(), and update_arp_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}} |
Referenced by free_entry().