|
|
|
|
@ -80,7 +80,8 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}};
|
|
|
|
|
#define ARP_MAXAGE 1200 |
|
|
|
|
/** 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. */ |
|
|
|
|
#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 60) |
|
|
|
|
#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) |
|
|
|
|
#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) |
|
|
|
|
|
|
|
|
|
/** the time an ARP entry stays pending after first request,
|
|
|
|
|
* for ARP_TMR_INTERVAL = 1000, this is |
|
|
|
|
@ -97,7 +98,8 @@ enum etharp_state {
|
|
|
|
|
ETHARP_STATE_EMPTY = 0, |
|
|
|
|
ETHARP_STATE_PENDING, |
|
|
|
|
ETHARP_STATE_STABLE, |
|
|
|
|
ETHARP_STATE_STABLE_REREQUESTING |
|
|
|
|
ETHARP_STATE_STABLE_REREQUESTING_1, |
|
|
|
|
ETHARP_STATE_STABLE_REREQUESTING_2 |
|
|
|
|
#if ETHARP_SUPPORT_STATIC_ENTRIES |
|
|
|
|
,ETHARP_STATE_STATIC |
|
|
|
|
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ |
|
|
|
|
@ -146,6 +148,9 @@ static u8_t etharp_cached_entry;
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static err_t etharp_request_dst(struct netif *netif, const ip_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if ARP_QUEUEING |
|
|
|
|
/**
|
|
|
|
|
* Free a complete queue of etharp entries |
|
|
|
|
@ -200,7 +205,7 @@ etharp_free_entry(int i)
|
|
|
|
|
/**
|
|
|
|
|
* Clears expired entries in the ARP table. |
|
|
|
|
* |
|
|
|
|
* This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), |
|
|
|
|
* This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), |
|
|
|
|
* in order to expire entries in the ARP table. |
|
|
|
|
*/ |
|
|
|
|
void |
|
|
|
|
@ -226,8 +231,10 @@ etharp_tmr(void)
|
|
|
|
|
arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); |
|
|
|
|
/* clean up entries that have just been expired */ |
|
|
|
|
etharp_free_entry(i); |
|
|
|
|
} |
|
|
|
|
else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { |
|
|
|
|
} else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { |
|
|
|
|
/* Don't send more than one request every 2 seconds. */ |
|
|
|
|
arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; |
|
|
|
|
} else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { |
|
|
|
|
/* Reset state to stable, so that the next transmitted packet will
|
|
|
|
|
re-send an ARP request. */ |
|
|
|
|
arp_table[i].state = ETHARP_STATE_STABLE; |
|
|
|
|
@ -863,10 +870,17 @@ etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
|
|
|
|
|
/* if arp table entry is about to expire: re-request it,
|
|
|
|
|
but only if its state is ETHARP_STATE_STABLE to prevent flooding the |
|
|
|
|
network with ARP requests if this address is used frequently. */ |
|
|
|
|
if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) &&
|
|
|
|
|
(arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { |
|
|
|
|
if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { |
|
|
|
|
arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; |
|
|
|
|
if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { |
|
|
|
|
if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { |
|
|
|
|
/* issue a standard request using broadcast */ |
|
|
|
|
if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { |
|
|
|
|
arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; |
|
|
|
|
} |
|
|
|
|
} else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { |
|
|
|
|
/* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ |
|
|
|
|
if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { |
|
|
|
|
arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1316,6 +1330,26 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send an ARP request packet asking for ipaddr to a specific eth address. |
|
|
|
|
* Used to send unicast request to refresh the ARP table just before an entry |
|
|
|
|
* times out |
|
|
|
|
* |
|
|
|
|
* @param netif the lwip network interface on which to send the request |
|
|
|
|
* @param ipaddr the IP address for which to ask |
|
|
|
|
* @param hw_dst_addr the ethernet address to send this packet to |
|
|
|
|
* @return ERR_OK if the request has been sent |
|
|
|
|
* ERR_MEM if the ARP packet couldn't be allocated |
|
|
|
|
* any other err_t on failure |
|
|
|
|
*/ |
|
|
|
|
static err_t |
|
|
|
|
etharp_request_dst(struct netif *netif, const ip_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) |
|
|
|
|
{ |
|
|
|
|
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, |
|
|
|
|
(struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, |
|
|
|
|
ipaddr, ARP_REQUEST); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send an ARP request packet asking for ipaddr. |
|
|
|
|
* |
|
|
|
|
@ -1329,9 +1363,7 @@ err_t
|
|
|
|
|
etharp_request(struct netif *netif, const ip_addr_t *ipaddr) |
|
|
|
|
{ |
|
|
|
|
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); |
|
|
|
|
return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, |
|
|
|
|
(struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, |
|
|
|
|
ipaddr, ARP_REQUEST); |
|
|
|
|
return etharp_request_dst(netif, ipaddr, ðbroadcast); |
|
|
|
|
} |
|
|
|
|
#endif /* LWIP_ARP */ |
|
|
|
|
|
|
|
|
|
|