Browse Source

fixed bug #34617: Stable etharp entries that are about to expire are now refreshed using unicast to prevent unnecessary broadcast.

Only if no answer is received after 15 seconds, broadcast is used.
STABLE-2_1_x
sg 11 years ago
parent
commit
440c99100b
  1. 5
      CHANGELOG
  2. 56
      src/netif/etharp.c

5
CHANGELOG

@ -6,6 +6,11 @@ HISTORY
++ New features:
2015-03-23: Simon Goldschmidt
* etharp.c: Stable etharp entries that are about to expire are now refreshed
using unicast to prevent unnecessary broadcast. Only if no answer is received
after 15 seconds, broadcast is used.
2015-03-06: Philip Gladstone
* netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to
an interface)

56
src/netif/etharp.c

@ -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, &ethzero,
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, &ethbroadcast,
(struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
ipaddr, ARP_REQUEST);
return etharp_request_dst(netif, ipaddr, &ethbroadcast);
}
#endif /* LWIP_ARP */

Loading…
Cancel
Save