ip-neighbor: Allow to replace dynamic entry 50/27950/4
authorVladimir Isaev <visaev@netgate.com>
Thu, 16 Jul 2020 14:05:18 +0000 (17:05 +0300)
committerMatthew Smith <mgsmith@netgate.com>
Fri, 31 Jul 2020 16:02:49 +0000 (16:02 +0000)
Before this patch it was not allowed to replace
a dynamic ARP entry with a static one with the
same mac-address.

Type: fix

Signed-off-by: Vladimir Isaev <visaev@netgate.com>
Change-Id: I6cfc0e510ffdf141c61874288f11a60395182374

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

index 09b5605..4111b02 100644 (file)
@@ -141,6 +141,8 @@ ip_neighbor_list_remove (ip_neighbor_t * ipn)
       elt = pool_elt_at_index (ip_neighbor_elt_pool, ipn->ipn_elt);
 
       clib_llist_remove (ip_neighbor_elt_pool, ipne_anchor, elt);
+
+      ipn->ipn_elt = ~0;
     }
 }
 
@@ -492,6 +494,17 @@ ip_neighbor_add (const ip46_address_t * ip,
          return -2;
        }
 
+      /* A dynamic entry can become static, but not vice-versa.
+       * i.e. since if it was programmed by the CP then it must
+       * be removed by the CP */
+      if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
+         !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
+       {
+         ip_neighbor_list_remove (ipn);
+         ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STATIC;
+         ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
+       }
+
       /*
        * prevent a DoS attack from the data-plane that
        * spams us with no-op updates to the MAC address
@@ -503,17 +516,6 @@ ip_neighbor_add (const ip46_address_t * ip,
        }
 
       mac_address_copy (&ipn->ipn_mac, mac);
-
-      /* A dynamic entry can become static, but not vice-versa.
-       * i.e. since if it was programmed by the CP then it must
-       * be removed by the CP */
-      if ((flags & IP_NEIGHBOR_FLAG_STATIC) &&
-         !(ipn->ipn_flags & IP_NEIGHBOR_FLAG_STATIC))
-       {
-         ip_neighbor_list_remove (ipn);
-         ipn->ipn_flags |= IP_NEIGHBOR_FLAG_STATIC;
-         ipn->ipn_flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
-       }
     }
   else
     {
index 416241e..1045f4b 100644 (file)
@@ -1247,6 +1247,116 @@ class ARPTestCase(VppTestCase):
         static_arp.remove_vpp_config()
         self.pg2.set_table_ip4(0)
 
+    def test_arp_static_replace_dynamic_same_mac(self):
+        """ ARP Static can replace Dynamic (same mac) """
+        self.pg2.generate_remote_hosts(1)
+
+        dyn_arp = VppNeighbor(self,
+                              self.pg2.sw_if_index,
+                              self.pg2.remote_hosts[0].mac,
+                              self.pg2.remote_hosts[0].ip4)
+        static_arp = VppNeighbor(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[0].mac,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=1)
+
+        #
+        # Add a dynamic ARP entry
+        #
+        dyn_arp.add_vpp_config()
+
+        #
+        # We should find the dynamic nbr
+        #
+        self.assertFalse(find_nbr(self,
+                                  self.pg2.sw_if_index,
+                                  self.pg2.remote_hosts[0].ip4,
+                                  is_static=1))
+        self.assertTrue(find_nbr(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=0,
+                                 mac=self.pg2.remote_hosts[0].mac))
+
+        #
+        # Add a static ARP entry with the same mac
+        #
+        static_arp.add_vpp_config()
+
+        #
+        # We should now find the static nbr with the same mac
+        #
+        self.assertFalse(find_nbr(self,
+                                  self.pg2.sw_if_index,
+                                  self.pg2.remote_hosts[0].ip4,
+                                  is_static=0))
+        self.assertTrue(find_nbr(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=1,
+                                 mac=self.pg2.remote_hosts[0].mac))
+
+        #
+        # clean-up
+        #
+        static_arp.remove_vpp_config()
+
+    def test_arp_static_replace_dynamic_diff_mac(self):
+        """ ARP Static can replace Dynamic (diff mac) """
+        self.pg2.generate_remote_hosts(2)
+
+        dyn_arp = VppNeighbor(self,
+                              self.pg2.sw_if_index,
+                              self.pg2.remote_hosts[0].mac,
+                              self.pg2.remote_hosts[0].ip4)
+        static_arp = VppNeighbor(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[1].mac,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=1)
+
+        #
+        # Add a dynamic ARP entry
+        #
+        dyn_arp.add_vpp_config()
+
+        #
+        # We should find the dynamic nbr
+        #
+        self.assertFalse(find_nbr(self,
+                                  self.pg2.sw_if_index,
+                                  self.pg2.remote_hosts[0].ip4,
+                                  is_static=1))
+        self.assertTrue(find_nbr(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=0,
+                                 mac=self.pg2.remote_hosts[0].mac))
+
+        #
+        # Add a static ARP entry with a changed mac
+        #
+        static_arp.add_vpp_config()
+
+        #
+        # We should now find the static nbr with a changed mac
+        #
+        self.assertFalse(find_nbr(self,
+                                  self.pg2.sw_if_index,
+                                  self.pg2.remote_hosts[0].ip4,
+                                  is_static=0))
+        self.assertTrue(find_nbr(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[0].ip4,
+                                 is_static=1,
+                                 mac=self.pg2.remote_hosts[1].mac))
+
+        #
+        # clean-up
+        #
+        static_arp.remove_vpp_config()
+
     def test_arp_incomplete(self):
         """ ARP Incomplete"""
         self.pg1.generate_remote_hosts(3)