ip-neighbor: Fix aging timeout

Before this patch VPP checked age for ARP/NDP records every 1e5 seconds
for any configured aging time. This is 27 hours and it looks like
misprint because 1e5 is the number of 10us ticks in a second.

Also time to wait is now difference between aging time and time alive
for nodes in alive state.

Type: fix
Signed-off-by: Vladimir Isaev <visaev@netgate.com>
Change-Id: Ib5baa85032a44402d5f48c1145245260a42c7bae
This commit is contained in:
Vladimir Isaev
2020-02-18 15:26:12 +03:00
committed by Neale Ranns
parent f145c15631
commit 1284f8c71d
2 changed files with 41 additions and 13 deletions

View File

@ -1402,22 +1402,24 @@ static ip_neighbor_age_state_t
ip_neighbour_age_out (index_t ipni, f64 now, f64 * wait)
{
ip_neighbor_t *ipn;
f64 ttl;
u32 ipndb_age;
u32 ttl;
ipn = ip_neighbor_get (ipni);
ipndb_age = ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age;
ttl = now - ipn->ipn_time_last_updated;
*wait = IP_NEIGHBOR_PROCESS_SLEEP_LONG;
*wait = ipndb_age;
if (ttl > ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age)
if (ttl > ipndb_age)
{
IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
format_ip_neighbor, ipni, now,
ipn->ipn_time_last_updated,
ip_neighbor_db[ipn->ipn_key->ipnk_type].ipndb_age);
ipn->ipn_time_last_updated, ipndb_age);
if (ipn->ipn_n_probes > 2)
{
/* 3 strikes and yea-re out */
IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
*wait = 1;
return (IP_NEIGHBOR_AGE_DEAD);
}
else
@ -1436,7 +1438,8 @@ ip_neighbour_age_out (index_t ipni, f64 now, f64 * wait)
}
else
{
*wait = ttl;
/* here we are sure that ttl <= ipndb_age */
*wait = ipndb_age - ttl + 1;
return (IP_NEIGHBOR_AGE_ALIVE);
}
@ -1481,7 +1484,7 @@ ip_neighbor_age_loop (vlib_main_t * vm,
ip_neighbor_elt_t *elt, *head;
f64 wait;
timeout = 1e5;
timeout = ip_neighbor_db[type].ipndb_age;
head = pool_elt_at_index (ip_neighbor_elt_pool,
ip_neighbor_list_head[type]);
@ -1498,6 +1501,7 @@ ip_neighbor_age_loop (vlib_main_t * vm,
if (IP_NEIGHBOR_AGE_ALIVE == res) {
/* the oldest neighbor has not yet expired, go back to sleep */
timeout = clib_min (wait, timeout);
break;
}
else if (IP_NEIGHBOR_AGE_DEAD == res) {
@ -1525,13 +1529,16 @@ ip_neighbor_age_loop (vlib_main_t * vm,
head = pool_elt_at_index (ip_neighbor_elt_pool,
ip_neighbor_list_head[type]);
elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
/* no neighbors yet */
if (clib_llist_is_empty (ip_neighbor_elt_pool, ipne_anchor, head))
{
timeout = ip_neighbor_db[type].ipndb_age;
break;
}
/* poke the oldset neighbour for aging, which returns how long we sleep for */
if (IP_NEIGHBOR_AGE_PROBE ==
ip_neighbour_age_out (elt->ipne_index, now, &timeout))
/* we probed for the oldest entry, sleep for a short time to get to the next */
timeout = 0.01;
elt = clib_llist_prev (ip_neighbor_elt_pool, ipne_anchor, head);
ip_neighbour_age_out (elt->ipne_index, now, &timeout);
break;
}
}

View File

@ -1731,7 +1731,7 @@ class NeighborAgeTestCase(VppTestCase):
#
# Set the neighbor configuration:
# limi = 200
# age = 2 seconds
# age = 0 seconds
# recycle = false
#
self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
@ -1808,6 +1808,27 @@ class NeighborAgeTestCase(VppTestCase):
self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
af=vaf.ADDRESS_IP4))
#
# load up some neighbours again with 2s aging enabled
# they should be removed after 10s (2s age + 4s for probes + gap)
#
for ii in range(10):
VppNeighbor(self,
self.pg0.sw_if_index,
self.pg0.remote_hosts[ii].mac,
self.pg0.remote_hosts[ii].ip4).add_vpp_config()
self.sleep(10)
self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
af=vaf.ADDRESS_IP4))
#
# check if we can set age and recycle with empty neighbor list
#
self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
max_number=200,
max_age=1000,
recycle=True)
#
# load up some neighbours again, then disable the aging
# they should still be there in 10 seconds time