fib: Fix crash on cover update to non activated adj source 45/23645/4
authorNeale Ranns <nranns@cisco.com>
Tue, 26 Nov 2019 19:30:08 +0000 (19:30 +0000)
committerDamjan Marion <dmarion@me.com>
Tue, 26 Nov 2019 23:19:32 +0000 (23:19 +0000)
if the adj source is not active then there is no existing cover
during a cover update

Type: fix
Ticket: VPP-1803
Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: Ie912f1c99345de4fb012bdcd97b443098d4a7351

src/vnet/fib/fib_entry_src_adj.c
test/test_ip4.py
test/vpp_ip_route.py

index b7f5946..2a5b46a 100644 (file)
@@ -373,19 +373,23 @@ fib_entry_src_adj_cover_update (fib_entry_src_t *src,
      * prefix is updated during the covers walk.
      */
     fib_entry_src_cover_res_t res = {
-        .install = !0,
+        .install = 0,
         .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
     };
     fib_entry_t *cover;
 
-    ASSERT(FIB_NODE_INDEX_INVALID != src->u.adj.fesa_cover);
-
-    cover = fib_entry_get(src->u.adj.fesa_cover);
-
-    res.install = (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover));
+    /*
+     * If there is no cover, then the source is not active and we can ignore
+     * this update
+     */
+    if (FIB_NODE_INDEX_INVALID != src->u.adj.fesa_cover)
+    {
+        cover = fib_entry_get(src->u.adj.fesa_cover);
 
-    FIB_ENTRY_DBG(fib_entry, "adj-src-cover-updated");
+        res.install = (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover));
 
+        FIB_ENTRY_DBG(fib_entry, "adj-src-cover-updated");
+    }
     return (res);
 }
 
index 7300679..705b151 100644 (file)
@@ -20,6 +20,7 @@ from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
 from vpp_papi import VppEnum
 from vpp_neighbor import VppNeighbor
+from vpp_lo_interface import VppLoInterface
 
 NUM_PKTS = 67
 
@@ -2091,5 +2092,68 @@ class TestIPReplace(VppTestCase):
             self.assertEqual(len(t.mdump()), 1)
 
 
+class TestIPCover(VppTestCase):
+    """ IPv4 Table Cover """
+
+    @classmethod
+    def setUpClass(cls):
+        super(TestIPCover, cls).setUpClass()
+
+    @classmethod
+    def tearDownClass(cls):
+        super(TestIPCover, cls).tearDownClass()
+
+    def setUp(self):
+        super(TestIPCover, self).setUp()
+
+        self.create_pg_interfaces(range(4))
+
+        table_id = 1
+        self.tables = []
+
+        for i in self.pg_interfaces:
+            i.admin_up()
+            i.config_ip4()
+            i.resolve_arp()
+            i.generate_remote_hosts(2)
+            self.tables.append(VppIpTable(self, table_id).add_vpp_config())
+            table_id += 1
+
+    def tearDown(self):
+        super(TestIPCover, self).tearDown()
+        for i in self.pg_interfaces:
+            i.admin_down()
+            i.unconfig_ip4()
+
+    def test_cover(self):
+        """ IP Table Cover """
+
+        # add a loop back with a /32 prefix
+        lo = VppLoInterface(self)
+        lo.admin_up()
+        a = VppIpInterfaceAddress(self, lo, "127.0.0.1", 32).add_vpp_config()
+
+        # add a neighbour that matches the loopback's /32
+        nbr = VppNeighbor(self,
+                          lo.sw_if_index,
+                          lo.remote_mac,
+                          "127.0.0.1").add_vpp_config()
+
+        # add the default route which will be the cover for /32
+        r = VppIpRoute(self, "0.0.0.0", 0,
+                       [VppRoutePath("127.0.0.1",
+                                     lo.sw_if_index)],
+                       register=False).add_vpp_config()
+
+        # add/remove/add a longer mask cover
+        r = VppIpRoute(self, "127.0.0.0", 8,
+                       [VppRoutePath("127.0.0.1",
+                                     lo.sw_if_index)]).add_vpp_config()
+        r.remove_vpp_config()
+        r.add_vpp_config()
+
+        # remove the default route
+        r.remove_vpp_config()
+
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index 031412c..3ac0e84 100644 (file)
@@ -246,6 +246,7 @@ class VppIpInterfaceAddress(VppObject):
             sw_if_index=self.intf.sw_if_index, prefix=self.prefix,
             is_add=1)
         self._test.registry.register(self, self._test.logger)
+        return self
 
     def remove_vpp_config(self):
         self._test.vapi.sw_interface_add_del_address(