linux-cp: handle ipv4 routes when link goes down on subif 32/35532/6
authorAlexander Chernavin <[email protected]>
Mon, 14 Feb 2022 12:59:28 +0000 (12:59 +0000)
committerMatthew Smith <[email protected]>
Tue, 29 Mar 2022 13:31:02 +0000 (13:31 +0000)
Type: improvement

Currently, the plugin can monitor link state changes on hardware
interfaces for which a linux-cp pair exists. When the link goes down on
one of the hardware interfaces, the plugin processes IPv4 routes that
resolve through that interface according to the configurations:
del-static-on-link-down and del-dynamic-on-link-down.

The problem is that link state changes are not signaled for
subinterfaces and the code that handles IPv4 routes is not triggered.
When the link on a hardware interface goes down, it implies
that subinterfaces added to that interface also will have the link in
the down state.

With this change, when the link goes down on a hardware interface,
iterate over subinterfaces added to the interface and apply the same
logic of routes processing as for hardware interfaces.

Signed-off-by: Alexander Chernavin <[email protected]>
Change-Id: I97337d2e328437c73f2d99a00737768778f197a1

src/plugins/linux-cp/lcp_router.c

index 4aab148..05943e4 100644 (file)
@@ -512,33 +512,59 @@ lcp_router_link_up_down (vnet_main_t *vnm, u32 hw_if_index, u32 flags)
        lcp_get_del_dynamic_on_link_down ()))
     {
       u32 fib_index;
+      u32 **fib_index_to_sw_if_index_to_bool = NULL;
+      u32 id, sw_if_index;
       lcp_router_table_t *nlt;
 
       fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
                                                       hi->sw_if_index);
 
-      pool_foreach (nlt, lcp_router_table_pool)
+      vec_validate_init_empty (fib_index_to_sw_if_index_to_bool, fib_index,
+                              NULL);
+      vec_validate_init_empty (fib_index_to_sw_if_index_to_bool[fib_index],
+                              hi->sw_if_index, false);
+      fib_index_to_sw_if_index_to_bool[fib_index][hi->sw_if_index] = true;
+
+      /* clang-format off */
+      hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
+      ({
+       fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
+                                                        sw_if_index);
+       vec_validate_init_empty (fib_index_to_sw_if_index_to_bool, fib_index,
+                                NULL);
+       vec_validate_init_empty (fib_index_to_sw_if_index_to_bool[fib_index],
+                                sw_if_index, false);
+       fib_index_to_sw_if_index_to_bool[fib_index][sw_if_index] = true;
+      }));
+      /* clang-format on */
+
+      vec_foreach_index (fib_index, fib_index_to_sw_if_index_to_bool)
        {
-         if (fib_index == nlt->nlt_fib_index &&
-             FIB_PROTOCOL_IP4 == nlt->nlt_proto)
-           {
-             u32 *sw_if_index_to_bool = NULL;
-
-             vec_validate_init_empty (sw_if_index_to_bool, hi->sw_if_index,
-                                      false);
-             sw_if_index_to_bool[hi->sw_if_index] = true;
+         u32 *sw_if_index_to_bool;
 
-             if (lcp_get_del_static_on_link_down ())
-               lcp_router_table_flush (nlt, sw_if_index_to_bool,
-                                       lcp_rt_fib_src);
-             if (lcp_get_del_dynamic_on_link_down ())
-               lcp_router_table_flush (nlt, sw_if_index_to_bool,
-                                       lcp_rt_fib_src_dynamic);
+         sw_if_index_to_bool = fib_index_to_sw_if_index_to_bool[fib_index];
+         if (NULL == sw_if_index_to_bool)
+           continue;
 
-             vec_free (sw_if_index_to_bool);
-             break;
+         pool_foreach (nlt, lcp_router_table_pool)
+           {
+             if (fib_index == nlt->nlt_fib_index &&
+                 FIB_PROTOCOL_IP4 == nlt->nlt_proto)
+               {
+                 if (lcp_get_del_static_on_link_down ())
+                   lcp_router_table_flush (nlt, sw_if_index_to_bool,
+                                           lcp_rt_fib_src);
+                 if (lcp_get_del_dynamic_on_link_down ())
+                   lcp_router_table_flush (nlt, sw_if_index_to_bool,
+                                           lcp_rt_fib_src_dynamic);
+                 break;
+               }
            }
+
+         vec_free (sw_if_index_to_bool);
        }
+
+      vec_free (fib_index_to_sw_if_index_to_bool);
     }
 
   return 0;