BFD: don't crash if interface is deleted 60/6560/3
authorKlement Sekera <ksekera@cisco.com>
Tue, 2 May 2017 05:38:01 +0000 (07:38 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Tue, 2 May 2017 19:24:38 +0000 (19:24 +0000)
Instead, drop the BFD session associated with it..

Change-Id: Ie09877d5c94844be2e833900d9dde7f23edaf8cd
Signed-off-by: Klement Sekera <ksekera@cisco.com>
src/vnet/bfd/bfd_udp.c
test/test_bfd.py

index ebee590..346c549 100644 (file)
@@ -177,11 +177,11 @@ bfd_udp_get_echo_src_ip4 (ip4_address_t * addr)
         if (ia->address_length <= 31)
           {
             addr->as_u32 = clib_host_to_net_u32 (x->as_u32);
-           /*
-            * flip the last bit to get a different address, might be network,
-            * we don't care ...
-            */
-           addr->as_u32 ^= 1;
+            /*
+             * flip the last bit to get a different address, might be network,
+             * we don't care ...
+             */
+            addr->as_u32 ^= 1;
             addr->as_u32 = clib_net_to_host_u32 (addr->as_u32);
             return 1;
           }
@@ -221,9 +221,9 @@ bfd_udp_get_echo_src_ip6 (ip6_address_t * addr)
 }
 
 void
-bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index, int *have_usable_ip4,
-                        ip4_address_t * ip4, int *have_usable_ip6,
-                        ip6_address_t * ip6)
+bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index,
+                        int *have_usable_ip4, ip4_address_t * ip4,
+                        int *have_usable_ip6, ip6_address_t * ip6)
 {
   if (bfd_udp_main.echo_source_is_set)
     {
@@ -239,8 +239,8 @@ bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index, int *have_usable_ip4,
 }
 
 int
-bfd_add_udp4_transport (vlib_main_t * vm, u32 bi,
-                       const bfd_session_t * bs, int is_echo)
+bfd_add_udp4_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
+                       int is_echo)
 {
   const bfd_udp_session_t *bus = &bs->udp;
   const bfd_udp_key_t *key = &bus->key;
@@ -294,8 +294,8 @@ bfd_add_udp4_transport (vlib_main_t * vm, u32 bi,
 }
 
 int
-bfd_add_udp6_transport (vlib_main_t * vm, u32 bi,
-                       const bfd_session_t * bs, int is_echo)
+bfd_add_udp6_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
+                       int is_echo)
 {
   const bfd_udp_session_t *bus = &bs->udp;
   const bfd_udp_key_t *key = &bus->key;
@@ -1200,8 +1200,8 @@ bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
              b0->current_data = 0;
              b0->current_length = 0;
              memset (vnet_buffer (b0), 0, sizeof (*vnet_buffer (b0)));
-             bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main,
-                                           bs, 0);
+             bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main, bs,
+                                           0);
              if (is_ipv6)
                {
                  vlib_node_increment_counter (vm, bfd_udp6_input_node.index,
@@ -1440,29 +1440,38 @@ VLIB_REGISTER_NODE (bfd_udp_echo6_input_node, static) = {
 /* *INDENT-ON* */
 
 static clib_error_t *
-bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
+bfd_udp_sw_if_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_create)
 {
-  // vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
-  if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
-    {
-      /* TODO */
-    }
-  return 0;
-}
-
-VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bfd_sw_interface_up_down);
-
-static clib_error_t *
-bfd_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
-{
-  if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
-    {
-      /* TODO */
-    }
+  bfd_session_t **to_be_freed = NULL;
+  BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index,
+          is_create);
+  if (!is_create)
+    {
+      bfd_session_t *bs;
+      pool_foreach (bs, bfd_udp_main.bfd_main->sessions,
+                   {
+                   if (bs->transport != BFD_TRANSPORT_UDP4 &&
+                       bs->transport != BFD_TRANSPORT_UDP6)
+                   {
+                   continue;}
+                   if (bs->udp.key.sw_if_index != sw_if_index)
+                   {
+                   continue;}
+                   vec_add1 (to_be_freed, bs);}
+      );
+    }
+  bfd_session_t **bs;
+  vec_foreach (bs, to_be_freed)
+  {
+    clib_warning ("removal of sw_if_index=%u forces removal of bfd session "
+                 "with bs_idx=%u", sw_if_index, (*bs)->bs_idx);
+    bfd_session_set_flags (*bs, 0);
+    bfd_udp_del_session_internal (*bs);
+  }
   return 0;
 }
 
-VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bfd_hw_interface_up_down);
+VNET_SW_INTERFACE_ADD_DEL_FUNCTION (bfd_udp_sw_if_add_del);
 
 /*
  * setup function
index 0923d36..be42cda 100644 (file)
@@ -17,6 +17,7 @@ from bfd import VppBFDAuthKey, BFD, BFDAuthType, VppBFDUDPSession, \
     BFDDiagCode, BFDState, BFD_vpp_echo
 from framework import VppTestCase, VppTestRunner, running_extended_tests
 from vpp_pg_interface import CaptureTimeoutError, is_ipv6_misc
+from vpp_lo_interface import VppLoInterface
 from util import ppp
 from vpp_papi_provider import UnexpectedApiReturnValueError
 from vpp_ip_route import VppIpRoute, VppRoutePath
@@ -1403,6 +1404,20 @@ class BFD4TestCase(VppTestCase):
         self.assert_equal(count, 0, "number of packets received")
         self.assert_equal(len(events), 0, "number of events received")
 
+    def test_intf_deleted(self):
+        """ interface with bfd session deleted """
+        intf = VppLoInterface(self, 0)
+        intf.config_ip4()
+        intf.admin_up()
+        sw_if_index = intf.sw_if_index
+        vpp_session = VppBFDUDPSession(self, intf, intf.remote_ip4)
+        vpp_session.add_vpp_config()
+        vpp_session.admin_up()
+        intf.remove_vpp_config()
+        e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
+        self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index")
+        self.assertFalse(vpp_session.query_vpp_config())
+
 
 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
 class BFD6TestCase(VppTestCase):
@@ -1597,6 +1612,21 @@ class BFD6TestCase(VppTestCase):
             self.test_session.send_packet()
         self.assertTrue(echo_seen, "No echo packets received")
 
+    def test_intf_deleted(self):
+        """ interface with bfd session deleted """
+        intf = VppLoInterface(self, 0)
+        intf.config_ip6()
+        intf.admin_up()
+        sw_if_index = intf.sw_if_index
+        vpp_session = VppBFDUDPSession(
+            self, intf, intf.remote_ip6, af=AF_INET6)
+        vpp_session.add_vpp_config()
+        vpp_session.admin_up()
+        intf.remove_vpp_config()
+        e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
+        self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index")
+        self.assertFalse(vpp_session.query_vpp_config())
+
 
 @unittest.skipUnless(running_extended_tests(), "part of extended tests")
 class BFDFIBTestCase(VppTestCase):