Added option LWIP_NETIF_HWADDRHINT (default=off) to cache ARP table indices with each pcb instead of single-entry cache for the complete stack.

This commit is contained in:
goldsimon 2007-07-02 20:41:22 +00:00
parent fa4b711495
commit 96e4ec4a15
12 changed files with 146 additions and 7 deletions

View File

@ -241,7 +241,13 @@ HISTORY
++ Bug fixes:
2007-06-28 Simon Goldschmidt
2007-07-02 Simon Goldschmidt
* ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c,
tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off)
to cache ARP table indices with each pcb instead of single-entry cache for
the complete stack.
2007-07-02 Simon Goldschmidt
* tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent
warnings when assigning to smaller types.

View File

@ -96,6 +96,11 @@ ip_route(struct ip_addr *dest)
return netif;
}
}
if (netif_default == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes();
}
/* no matching netif found, use default netif */
return netif_default;
}
@ -515,10 +520,6 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
struct netif *netif;
if ((netif = ip_route(dest)) == NULL) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutnoroutes();
return ERR_RTE;
}

View File

@ -105,6 +105,9 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
netif->state = state;
netif->num = netifnum++;
netif->input = input;
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/
netif_set_addr(netif, ipaddr, netmask, gw);

View File

@ -248,7 +248,13 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
src_ip = &(pcb->local_ip);
}
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = &(pcb->addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT*/
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/
/* did we chain a header earlier? */
if (q != p) {

View File

@ -456,8 +456,21 @@ tcp_output(struct tcp_pcb *pcb)
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
#endif
#if LWIP_NETIF_HWADDRHINT
{
struct netif *netif;
netif = ip_route(&pcb->remote_ip);
if(netif != NULL){
netif->addr_hint = &(pcb->addr_hint);
ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
pcb->tos, IP_PROTO_TCP, netif);
netif->addr_hint = NULL;
}
}
#else /* LWIP_NETIF_HWADDRHINT*/
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
pbuf_free(p);
return ERR_OK;
@ -602,8 +615,21 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
#endif
TCP_STATS_INC(tcp.xmit);
#if LWIP_NETIF_HWADDRHINT
{
struct netif *netif;
netif = ip_route(&pcb->remote_ip);
if(netif != NULL){
netif->addr_hint = &(pcb->addr_hint);
ip_output_if(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
pcb->tos, IP_PROTO_TCP, netif);
netif->addr_hint = NULL;
}
}
#else /* LWIP_NETIF_HWADDRHINT*/
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
}
/**
@ -776,7 +802,20 @@ tcp_keepalive(struct tcp_pcb *pcb)
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
#if LWIP_NETIF_HWADDRHINT
{
struct netif *netif;
netif = ip_route(&pcb->remote_ip);
if(netif != NULL){
netif->addr_hint = &(pcb->addr_hint);
ip_output_if(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl,
0, IP_PROTO_TCP, netif);
netif->addr_hint = NULL;
}
}
#else /* LWIP_NETIF_HWADDRHINT*/
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
pbuf_free(p);

View File

@ -439,7 +439,13 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
#endif /* CHECKSUM_CHECK_UDP */
/* output to IP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = &(pcb->addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT*/
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/
} else
#endif /* LWIP_UDPLITE */
{ /* UDP */
@ -456,7 +462,13 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
/* output to IP */
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = &(pcb->addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT*/
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/
}
/* TODO: must this be increased even if error occured? */
snmp_inc_udpoutdatagrams();

View File

@ -83,7 +83,9 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl
u8_t ttl; \
/* link layer address resolution hint */ \
u8_t addr_hint
/*
* Option flags per-socket. These are the same like SO_XXX.

View File

@ -69,7 +69,9 @@ extern "C" {
/* Type Of Service */ \
u8_t tos; \
/* Time To Live */ \
u8_t ttl
u8_t ttl; \
/* link layer address resolution hint */ \
u8_t addr_hint
/* The IPv6 header. */

View File

@ -155,6 +155,9 @@ struct netif {
/* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/
err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);
#endif /* LWIP_IGMP */
#if LWIP_NETIF_HWADDRHINT
u8_t *addr_hint;
#endif /* LWIP_NETIF_HWADDRHINT */
};
#if LWIP_SNMP

View File

@ -481,6 +481,15 @@
#define LWIP_NETIF_CALLBACK 0
#endif
/** Cache link-layer-address hints (e.g. table indices) in struct netif.
TCP and UDP can make use of this to prevent scanning the ARP table
for every sent packet. While this is faster for big ARP tables or many
concurrent connections, it might be contra-productive if having a tiny
ARP table only or there never are concurrent connections. */
#ifndef LWIP_NETIF_HWADDRHINT
#define LWIP_NETIF_HWADDRHINT 0
#endif
/* Support loop interface (127.0.0.1) */
#ifndef LWIP_HAVE_LOOPIF
#define LWIP_HAVE_LOOPIF 0

View File

@ -157,6 +157,11 @@ err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0)
/* finally, check some defines */
#if ARP_TABLE_SIZE > 0x7f
#error ARP_TABLE_SIZE must fit in an s8_t
#endif
#ifdef __cplusplus
}
#endif

View File

@ -105,7 +105,9 @@ struct etharp_entry {
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
static const struct eth_addr ethzero = {{0,0,0,0,0,0}};
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
#if !LWIP_NETIF_HWADDRHINT
static u8_t etharp_cached_entry = 0;
#endif
/**
* Try hard to create a new entry - we want the IP address to appear in
@ -113,7 +115,14 @@ static u8_t etharp_cached_entry = 0;
#define ETHARP_TRY_HARD 1
#define ETHARP_FIND_ONLY 2
#if LWIP_NETIF_HWADDRHINT
#define NETIF_SET_HINT(netif, hint) (((netif) != NULL) && ((netif)->addr_hint != NULL)) ? \
*((netif)->addr_hint) = (hint) : LWIP_UNUSED_ARG(hint) ;
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif);
#else /* LWIP_NETIF_HWADDRHINT */
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
#endif /* LWIP_NETIF_HWADDRHINT */
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
/**
@ -231,7 +240,11 @@ etharp_tmr(void)
* entry is found or could be recycled.
*/
static s8_t
#if LWIP_NETIF_HWADDRHINT
find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif)
#else /* LWIP_NETIF_HWADDRHINT */
find_entry(struct ip_addr *ipaddr, u8_t flags)
#endif /* LWIP_NETIF_HWADDRHINT */
{
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
s8_t empty = ARP_TABLE_SIZE;
@ -247,6 +260,19 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
* same address. If so, we're really fast! */
if (ipaddr) {
/* ipaddr to search for was given */
#if LWIP_NETIF_HWADDRHINT
if ((netif != NULL) && (netif->addr_hint != NULL)) {
/* per-pcb cached entry was given */
u8_t per_pcb_cache = *(netif->addr_hint);
if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) {
/* the per-pcb-cached entry is stable */
if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) {
/* per-pcb cached entry was the right one! */
return per_pcb_cache;
}
}
}
#else /* #if LWIP_NETIF_HWADDRHINT */
if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) {
/* the cached entry is stable */
if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) {
@ -254,6 +280,7 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
return etharp_cached_entry;
}
}
#endif /* #if LWIP_NETIF_HWADDRHINT */
}
/**
@ -284,7 +311,11 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
/* found exact IP address match, simply bail out */
#if LWIP_NETIF_HWADDRHINT
NETIF_SET_HINT(netif, i);
#else /* #if LWIP_NETIF_HWADDRHINT */
etharp_cached_entry = i;
#endif /* #if LWIP_NETIF_HWADDRHINT */
return i;
#if ARP_QUEUEING
/* pending with queued packets? */
@ -308,7 +339,11 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
/* found exact IP address match, simply bail out */
#if LWIP_NETIF_HWADDRHINT
NETIF_SET_HINT(netif, i);
#else /* #if LWIP_NETIF_HWADDRHINT */
etharp_cached_entry = i;
#endif /* #if LWIP_NETIF_HWADDRHINT */
return i;
/* remember entry with oldest stable entry in oldest, its age in maxtime */
} else if (arp_table[i].ctime >= age_stable) {
@ -384,7 +419,11 @@ find_entry(struct ip_addr *ipaddr, u8_t flags)
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
}
arp_table[i].ctime = 0;
#if LWIP_NETIF_HWADDRHINT
NETIF_SET_HINT(netif, i);
#else /* #if LWIP_NETIF_HWADDRHINT */
etharp_cached_entry = i;
#endif /* #if LWIP_NETIF_HWADDRHINT */
return (err_t)i;
}
@ -456,7 +495,11 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
return ERR_ARG;
}
/* find or create ARP entry */
#if LWIP_NETIF_HWADDRHINT
i = find_entry(ipaddr, flags, netif);
#else /* LWIP_NETIF_HWADDRHINT */
i = find_entry(ipaddr, flags);
#endif /* LWIP_NETIF_HWADDRHINT */
/* bail out if no entry could be found */
if (i < 0)
return (err_t)i;
@ -516,7 +559,11 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
{
s8_t i;
#if LWIP_NETIF_HWADDRHINT
i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL);
#else /* LWIP_NETIF_HWADDRHINT */
i = find_entry(ipaddr, ETHARP_FIND_ONLY);
#endif /* LWIP_NETIF_HWADDRHINT */
if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
*eth_ret = &arp_table[i].ethaddr;
*ip_ret = &arp_table[i].ipaddr;
@ -833,7 +880,11 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
}
/* find entry in ARP cache, ask to create entry if queueing packet */
#if LWIP_NETIF_HWADDRHINT
i = find_entry(ipaddr, ETHARP_TRY_HARD, netif);
#else /* LWIP_NETIF_HWADDRHINT */
i = find_entry(ipaddr, ETHARP_TRY_HARD);
#endif /* LWIP_NETIF_HWADDRHINT */
/* could not find or create entry? */
if (i < 0) {