gre: set proper fib index for unnumbered interfaces, unset fib index before forwardin... 57/33157/6
authorStanislav Zaikin <zstaseg@gmail.com>
Thu, 15 Jul 2021 14:27:29 +0000 (16:27 +0200)
committerNeale Ranns <neale@graphiant.com>
Wed, 28 Jul 2021 08:25:38 +0000 (08:25 +0000)
This commit introduces 2 fixes:
1) After GRE decapsulation sw_if_index[VLIB_TX] is set as fib index of GRE tunnel.
But since GRE tunnel can work on v4 endpoints and have v6 payload, we need to reset it.
In case we get IPv6 packet inside IPv4 GRE tunnel (or vice-versa) fib index can be (and usually is) invalid.
2) Check that ip-table and ip6-table are the same when setting interface as an unnumbered one.

Also, fix for the pipe test include setting the right unnumbered interface for the pipes

Type: fix

Signed-off-by: Stanislav Zaikin <zstaseg@gmail.com>
Change-Id: Id13d239cfdd21e0db6b1c9725f01c40d4af4d800

src/vnet/gre/node.c
src/vnet/interface.c
src/vnet/interface_api.c
src/vnet/interface_cli.c
src/vnet/interface_funcs.h
test/test_pipe.py

index 9252306..fdd3118 100644 (file)
@@ -301,6 +301,9 @@ gre_input (vlib_main_t * vm,
          vnet_buffer (b[1])->sw_if_index[VLIB_RX] = tun_sw_if_index[1];
        }
 
+      vnet_buffer (b[0])->sw_if_index[VLIB_TX] = (u32) ~0;
+      vnet_buffer (b[1])->sw_if_index[VLIB_TX] = (u32) ~0;
+
       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
        gre_trace (vm, node, b[0], tun_sw_if_index[0], ip6[0], ip4[0],
                   is_ipv6);
@@ -411,6 +414,8 @@ gre_input (vlib_main_t * vm,
          vnet_buffer (b[0])->sw_if_index[VLIB_RX] = tun_sw_if_index[0];
        }
 
+      vnet_buffer (b[0])->sw_if_index[VLIB_TX] = (u32) ~0;
+
       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
        gre_trace (vm, node, b[0], tun_sw_if_index[0], ip6[0], ip4[0],
                   is_ipv6);
index 44ea52a..e79722d 100644 (file)
@@ -1610,20 +1610,58 @@ vnet_hw_interface_change_mac_address (vnet_main_t * vnm, u32 hw_if_index,
     (vnm, hw_if_index, mac_address);
 }
 
+static int
+vnet_sw_interface_check_table_same (u32 unnumbered_sw_if_index,
+                                   u32 ip_sw_if_index)
+{
+  vec_validate (ip4_main.fib_index_by_sw_if_index, unnumbered_sw_if_index);
+  vec_validate (ip4_main.mfib_index_by_sw_if_index, unnumbered_sw_if_index);
+  vec_validate (ip6_main.fib_index_by_sw_if_index, unnumbered_sw_if_index);
+  vec_validate (ip6_main.mfib_index_by_sw_if_index, unnumbered_sw_if_index);
+
+  vec_validate (ip4_main.fib_index_by_sw_if_index, ip_sw_if_index);
+  vec_validate (ip4_main.mfib_index_by_sw_if_index, ip_sw_if_index);
+  vec_validate (ip6_main.fib_index_by_sw_if_index, ip_sw_if_index);
+  vec_validate (ip6_main.mfib_index_by_sw_if_index, ip_sw_if_index);
+
+  if (ip4_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+      ip4_main.fib_index_by_sw_if_index[ip_sw_if_index])
+    return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+  if (ip4_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+      ip4_main.mfib_index_by_sw_if_index[ip_sw_if_index])
+    return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+  if (ip6_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+      ip6_main.fib_index_by_sw_if_index[ip_sw_if_index])
+    return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+  if (ip6_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
+      ip6_main.mfib_index_by_sw_if_index[ip_sw_if_index])
+    return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
+
+  return 0;
+}
+
 /* update the unnumbered state of an interface*/
-void
+int
 vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index,
                                     u32 ip_sw_if_index, u8 enable)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vnet_sw_interface_t *si;
   u32 was_unnum;
+  int rv = 0;
 
   si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
   was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED);
 
   if (enable)
     {
+      rv = vnet_sw_interface_check_table_same (unnumbered_sw_if_index,
+                                              ip_sw_if_index);
+      if (rv != 0)
+       return rv;
       si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
       si->unnumbered_sw_if_index = ip_sw_if_index;
 
@@ -1660,6 +1698,8 @@ vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index,
       ip4_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
       ip6_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
     }
+
+  return 0;
 }
 
 vnet_l3_packet_type_t
index a1450bd..9b606dd 100644 (file)
@@ -682,8 +682,8 @@ static void vl_api_sw_interface_set_unnumbered_t_handler
       goto done;
     }
 
-  vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
-                                      sw_if_index, mp->is_add);
+  rv = vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
+                                           sw_if_index, mp->is_add);
 done:
   REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
 }
index 73b2757..6843186 100644 (file)
@@ -976,8 +976,23 @@ set_unnumbered (vlib_main_t * vm,
     return clib_error_return (0, "When enabling unnumbered specify the"
                              " IP enabled interface that it uses");
 
-  vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
-                                      inherit_from_sw_if_index, enable);
+  int rv = vnet_sw_interface_update_unnumbered (
+    unnumbered_sw_if_index, inherit_from_sw_if_index, enable);
+
+  switch (rv)
+    {
+    case 0:
+      break;
+
+    case VNET_API_ERROR_UNEXPECTED_INTF_STATE:
+      return clib_error_return (
+       0,
+       "When enabling unnumbered both interfaces must be in the same tables");
+
+    default:
+      return clib_error_return (
+       0, "vnet_sw_interface_update_unnumbered returned %d", rv);
+    }
 
   return (NULL);
 }
index 1416840..3db5a2d 100644 (file)
@@ -430,8 +430,8 @@ void vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
                                         u32 mtu[]);
 
 /* update the unnumbered state of an interface */
-void vnet_sw_interface_update_unnumbered (u32 sw_if_index,
-                                         u32 ip_sw_if_index, u8 enable);
+int vnet_sw_interface_update_unnumbered (u32 sw_if_index, u32 ip_sw_if_index,
+                                        u8 enable);
 
 int vnet_sw_interface_stats_collect_enable_disable (u32 sw_if_index,
                                                    u8 enable);
index 0e76665..937a28e 100644 (file)
@@ -53,11 +53,13 @@ class VppPipe(VppInterface):
                 return True
         return False
 
-    def set_unnumbered(self, ip_sw_if_index, is_add=True):
-        res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
-                                                          self.east, is_add)
-        res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
-                                                          self.west, is_add)
+    def set_unnumbered(self, ip_sw_if_index, is_east, is_add=True):
+        if is_east:
+            res = self._test.vapi.sw_interface_set_unnumbered(
+                ip_sw_if_index, self.east, is_add)
+        else:
+            res = self._test.vapi.sw_interface_set_unnumbered(
+                ip_sw_if_index, self.west, is_add)
 
 
 class TestPipe(VppTestCase):
@@ -203,8 +205,8 @@ class TestPipe(VppTestCase):
         self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
 
         # IP enable the Pipes by making them unnumbered
-        pipes[0].set_unnumbered(self.pg2.sw_if_index)
-        pipes[1].set_unnumbered(self.pg3.sw_if_index)
+        pipes[1].set_unnumbered(self.pg2.sw_if_index, True)
+        pipes[1].set_unnumbered(self.pg3.sw_if_index, False)
 
         self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)