Fix bug #53667: ARP table max size is to small

arp table functions, nd6 destination cache and struct netif_hint
can now be u16_t or u8_t depending on table size, so up to 32K
entries can be used in these tables (s16_t)

Signed-off-by: Simon Goldschmidt <goldsimon@gmx.de>
This commit is contained in:
Simon Goldschmidt 2018-05-17 21:51:46 +02:00
parent 0f165ff136
commit 0c2fdfcf42
3 changed files with 55 additions and 49 deletions

View File

@ -105,7 +105,7 @@ struct etharp_entry {
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
#if !LWIP_NETIF_HWADDRHINT
static u8_t etharp_cached_entry;
static netif_addr_idx_t etharp_cached_entry;
#endif /* !LWIP_NETIF_HWADDRHINT */
/** Try hard to create a new entry - we want the IP address to appear in
@ -196,7 +196,7 @@ etharp_free_entry(int i)
void
etharp_tmr(void)
{
u8_t i;
int i;
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
/* remove expired entries from the ARP table */
@ -212,8 +212,8 @@ etharp_tmr(void)
((arp_table[i].state == ETHARP_STATE_PENDING) &&
(arp_table[i].ctime >= ARP_MAXPENDING))) {
/* pending or stable entry has become old! */
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %d.\n",
arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", i));
/* clean up entries that have just been expired */
etharp_free_entry(i);
} else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) {
@ -252,14 +252,14 @@ etharp_tmr(void)
* @return The ARP entry index that matched or is created, ERR_MEM if no
* entry is found or could be recycled.
*/
static s8_t
static s16_t
etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
{
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
s8_t empty = ARP_TABLE_SIZE;
u8_t i = 0;
s16_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
s16_t empty = ARP_TABLE_SIZE;
s16_t i = 0;
/* oldest entry with packets on queue */
s8_t old_queue = ARP_TABLE_SIZE;
s16_t old_queue = ARP_TABLE_SIZE;
/* its age */
u16_t age_queue = 0, age_pending = 0, age_stable = 0;
@ -284,9 +284,9 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
u8_t state = arp_table[i].state;
/* no empty entry found yet and now we do find one? */
if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %d\n", (int)i));
/* remember first empty entry */
empty = (s8_t)i;
empty = i;
} else if (state != ETHARP_STATE_EMPTY) {
LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE",
state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE);
@ -296,23 +296,23 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
&& ((netif == NULL) || (netif == arp_table[i].netif))
#endif /* ETHARP_TABLE_MATCH_NETIF */
) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %d\n", (int)i));
/* found exact IP address match, simply bail out */
return (s8_t)i;
return i;
}
/* pending entry? */
if (state == ETHARP_STATE_PENDING) {
/* pending with queued packets? */
if (arp_table[i].q != NULL) {
if (arp_table[i].ctime >= age_queue) {
old_queue = (s8_t)i;
old_queue = i;
age_queue = arp_table[i].ctime;
}
} else
/* pending without queued packets? */
{
if (arp_table[i].ctime >= age_pending) {
old_pending = (s8_t)i;
old_pending = i;
age_pending = arp_table[i].ctime;
}
}
@ -325,7 +325,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
{
/* remember entry with oldest stable entry in oldest, its age in maxtime */
if (arp_table[i].ctime >= age_stable) {
old_stable = (s8_t)i;
old_stable = i;
age_stable = arp_table[i].ctime;
}
}
@ -339,7 +339,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
/* or no empty entry found and not allowed to recycle? */
((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n"));
return (s8_t)ERR_MEM;
return (s16_t)ERR_MEM;
}
/* b) choose the least destructive entry to recycle:
@ -353,30 +353,30 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
/* 1) empty entry available? */
if (empty < ARP_TABLE_SIZE) {
i = (u8_t)empty;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
i = empty;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %d\n", (int)i));
} else {
/* 2) found recyclable stable entry? */
if (old_stable < ARP_TABLE_SIZE) {
/* recycle oldest stable*/
i = (u8_t)old_stable;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
i = old_stable;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %d\n", (int)i));
/* no queued packets should exist on stable entries */
LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
/* 3) found recyclable pending entry without queued packets? */
} else if (old_pending < ARP_TABLE_SIZE) {
/* recycle oldest pending */
i = (u8_t)old_pending;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
i = old_pending;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d (without queue)\n", (int)i));
/* 4) found recyclable pending entry with queued packets? */
} else if (old_queue < ARP_TABLE_SIZE) {
/* recycle oldest pending (queued packets are free in etharp_free_entry) */
i = (u8_t)old_queue;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
i = old_queue;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %d, freeing packet queue %p\n", (int)i, (void *)(arp_table[i].q)));
/* no empty or recyclable entries found */
} else {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n"));
return (s8_t)ERR_MEM;
return (s16_t)ERR_MEM;
}
/* { empty or recyclable entry found } */
@ -397,7 +397,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
#if ETHARP_TABLE_MATCH_NETIF
arp_table[i].netif = netif;
#endif /* ETHARP_TABLE_MATCH_NETIF */
return (s8_t)i;
return (s16_t)i;
}
/**
@ -421,7 +421,7 @@ etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif *netif)
static err_t
etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
{
s8_t i;
s16_t i;
LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
@ -460,7 +460,7 @@ etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct et
/* insert in SNMP ARP index tree */
mib2_add_arp_entry(netif, &arp_table[i].ipaddr);
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", i));
/* update address */
SMEMCPY(&arp_table[i].ethaddr, ethaddr, ETH_HWADDR_LEN);
/* reset time stamp */
@ -528,7 +528,7 @@ etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr)
err_t
etharp_remove_static_entry(const ip4_addr_t *ipaddr)
{
s8_t i;
s16_t i;
LWIP_ASSERT_CORE_LOCKED();
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
@ -558,7 +558,7 @@ etharp_remove_static_entry(const ip4_addr_t *ipaddr)
void
etharp_cleanup_netif(struct netif *netif)
{
u8_t i;
int i;
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
u8_t state = arp_table[i].state;
@ -583,7 +583,7 @@ ssize_t
etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr,
struct eth_addr **eth_ret, const ip4_addr_t **ip_ret)
{
s8_t i;
s16_t i;
LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
eth_ret != NULL && ip_ret != NULL);
@ -745,7 +745,7 @@ etharp_input(struct pbuf *p, struct netif *netif)
* in the arp_table specified by the index 'arp_idx'.
*/
static err_t
etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx)
etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx)
{
LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE",
arp_table[arp_idx].state >= ETHARP_STATE_STABLE);
@ -819,7 +819,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
dest = &mcastaddr;
/* unicast destination IP address? */
} else {
u8_t i;
u16_t i;
/* outside local network? if so, this can neither be a global broadcast nor
a subnet broadcast. */
if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) &&
@ -855,7 +855,7 @@ etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
#if LWIP_NETIF_HWADDRHINT
if (netif->hints != NULL) {
/* per-pcb cached entry was given */
u8_t etharp_cached_entry = netif->hints->addr_hint;
netif_addr_idx_t etharp_cached_entry = netif->hints->addr_hint;
if (etharp_cached_entry < ARP_TABLE_SIZE) {
#endif /* LWIP_NETIF_HWADDRHINT */
if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) &&
@ -935,8 +935,8 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
struct eth_addr *srcaddr = (struct eth_addr *)netif->hwaddr;
err_t result = ERR_MEM;
int is_new_entry = 0;
s8_t i_err;
u8_t i;
s16_t i_err;
u16_t i;
/* non-unicast address? */
if (ip4_addr_isbroadcast(ipaddr, netif) ||
@ -958,7 +958,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
}
return (err_t)i_err;
}
i = (u8_t)i_err;
i = (u16_t)i_err;
/* mark a fresh entry as pending (we just sent a request) */
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
@ -1054,7 +1054,7 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
memp_free(MEMP_ARP_QUEUE, old);
}
#endif
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, i));
result = ERR_OK;
} else {
/* the pool MEMP_ARP_QUEUE is empty */
@ -1065,12 +1065,12 @@ etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q)
#else /* ARP_QUEUEING */
/* always queue one packet per ARP request only, freeing a previously queued packet */
if (arp_table[i].q != NULL) {
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"U16_F"\n", (void *)q, i));
pbuf_free(arp_table[i].q);
}
arp_table[i].q = p;
result = ERR_OK;
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"U16_F"\n", (void *)q, i));
#endif /* ARP_QUEUEING */
} else {
ETHARP_STATS_INC(etharp.memerr);

View File

@ -85,7 +85,7 @@ u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in t
/* Index for cache entries. */
static u8_t nd6_cached_neighbor_index;
static u8_t nd6_cached_destination_index;
static netif_addr_idx_t nd6_cached_destination_index;
/* Multicast address holder. */
static ip6_addr_t multicast_address;
@ -105,9 +105,9 @@ static union ra_options nd6_ra_buffer;
static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr);
static s8_t nd6_new_neighbor_cache_entry(void);
static void nd6_free_neighbor_cache_entry(s8_t i);
static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
static s8_t nd6_new_destination_cache_entry(void);
static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
static s16_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr);
static s16_t nd6_new_destination_cache_entry(void);
static int nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif);
static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif);
static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif);
static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif);
@ -1561,7 +1561,7 @@ nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr)
* @return The destination cache entry index that was created, -1 if no
* entry was created
*/
static s8_t
static s16_t
nd6_new_destination_cache_entry(void)
{
s8_t i, j;
@ -1609,7 +1609,7 @@ nd6_clear_destination_cache(void)
* @param ip6addr the IPv6 address to match
* @return 1 if the address is on-link, 0 otherwise
*/
static s8_t
static int
nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif)
{
s8_t i;
@ -1916,7 +1916,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif)
#if LWIP_NETIF_HWADDRHINT
if (netif->hints != NULL) {
/* per-pcb cached entry was given */
u8_t addr_hint = netif->hints->addr_hint;
netif_addr_idx_t addr_hint = netif->hints->addr_hint;
if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) {
nd6_cached_destination_index = addr_hint;
}

View File

@ -237,10 +237,16 @@ u8_t netif_alloc_client_data_id(void);
#define netif_get_client_data(netif, id) (netif)->client_data[(id)]
#endif
#if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f))
typedef u16_t netif_addr_idx_t;
#else
typedef u8_t netif_addr_idx_t;
#endif
#if LWIP_NETIF_HWADDRHINT
#define LWIP_NETIF_USE_HINTS 1
struct netif_hint {
u8_t addr_hint;
netif_addr_idx_t addr_hint;
};
#else /* LWIP_NETIF_HWADDRHINT */
#define LWIP_NETIF_USE_HINTS 0