ip-neighbor: Fix aging timeout 39/25239/6
authorVladimir Isaev <visaev@netgate.com>
Tue, 18 Feb 2020 12:26:12 +0000 (15:26 +0300)
committerNeale Ranns <nranns@cisco.com>
Thu, 20 Feb 2020 09:12:52 +0000 (09:12 +0000)
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

src/vnet/ip-neighbor/ip_neighbor.c
test/test_neighbor.py

index 6af76d2..960da12 100644 (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;
          }
        }
index d1fb8f8..7157839 100644 (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