urpf: add mode for specific fib index lookup 31/37131/19
authorhedi bouattour <hedibouattour2010@gmail.com>
Wed, 14 Sep 2022 12:39:23 +0000 (12:39 +0000)
committerNeale Ranns <neale@graphiant.com>
Fri, 7 Oct 2022 04:18:54 +0000 (04:18 +0000)
this patch adds a mode to urpf in order to perform the lookup in a specified vrf instead of the interface vrf
Type: feature
Change-Id: Ieb91de6ccdfbf32b6939364f3bebeecd2d57af19
Signed-off-by: hedi bouattour <hedibouattour2010@gmail.com>
src/plugins/urpf/urpf.api
src/plugins/urpf/urpf.c
src/plugins/urpf/urpf.h
src/plugins/urpf/urpf_api.c
src/plugins/urpf/urpf_dp.h

index 944db08..4665743 100644 (file)
@@ -50,6 +50,27 @@ autoreply define urpf_update
   vl_api_interface_index_t sw_if_index;
 };
 
+/**
+ * @brief Enable uRPF on a given interface in a given direction
+ * @param client_index - opaque cookie to identify the sender
+ * @param context - sender context, to match reply w/ request
+ * @param mode - Mode
+ * @param af - Address Family
+ * @param sw_if_index - Interface
+ * @param is_input - Direction.
+ * @param table-id - Table ID
+ */
+autoreply define urpf_update_v2
+{
+  u32 client_index;
+  u32 context;
+  bool is_input[default = true];
+  vl_api_urpf_mode_t mode;
+  vl_api_address_family_t af;
+  vl_api_interface_index_t sw_if_index;
+  u32 table_id [default=0xffffffff];
+};
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 6cf7cda..3c3b33c 100644 (file)
@@ -58,7 +58,8 @@ static const char *urpf_feats[N_AF][VLIB_N_DIR][URPF_N_MODES] =
 /**
  * Per-af, per-direction, per-interface uRPF configs
  */
-static urpf_mode_t *urpf_cfgs[N_AF][VLIB_N_DIR];
+
+urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR];
 
 u8 *
 format_urpf_mode (u8 * s, va_list * a)
@@ -95,34 +96,105 @@ unformat_urpf_mode (unformat_input_t * input, va_list * args)
     return 0;
 }
 
-void
-urpf_update (urpf_mode_t mode,
-            u32 sw_if_index, ip_address_family_t af, vlib_dir_t dir)
+int
+urpf_update (urpf_mode_t mode, u32 sw_if_index, ip_address_family_t af,
+            vlib_dir_t dir, u32 table_id)
 {
-  urpf_mode_t old;
+  fib_protocol_t proto;
+  u32 fib_index;
+  if (table_id != ~0)
+    {
+      proto = ip_address_family_to_fib_proto (af);
+      fib_index = fib_table_find (proto, table_id);
+      if (fib_index == (~0))
+       return VNET_API_ERROR_INVALID_VALUE;
+    }
+  else
+    {
+      bool is_ip4 = (AF_IP4 == af);
+      u32 *fib_index_by_sw_if_index = is_ip4 ?
+                                             ip4_main.fib_index_by_sw_if_index :
+                                             ip6_main.fib_index_by_sw_if_index;
 
-  vec_validate_init_empty (urpf_cfgs[af][dir], sw_if_index, URPF_MODE_OFF);
+      fib_index = fib_index_by_sw_if_index[sw_if_index];
+    }
+  urpf_data_t old;
+  urpf_mode_t off = URPF_MODE_OFF;
+  urpf_data_t empty = { .fib_index = 0, .mode = off };
+  vec_validate_init_empty (urpf_cfgs[af][dir], sw_if_index, empty);
   old = urpf_cfgs[af][dir][sw_if_index];
 
-  if (mode != old)
+  urpf_data_t data = { .fib_index = fib_index,
+                      .mode = mode,
+                      .fib_index_is_custom = (table_id != ~0) };
+  urpf_cfgs[af][dir][sw_if_index] = data;
+  if (data.mode != old.mode || data.fib_index != old.fib_index)
     {
-      if (URPF_MODE_OFF != old)
+      if (URPF_MODE_OFF != old.mode)
        /* disable what we have */
        vnet_feature_enable_disable (urpf_feat_arcs[af][dir],
-                                    urpf_feats[af][dir][old],
+                                    urpf_feats[af][dir][old.mode],
                                     sw_if_index, 0, 0, 0);
 
-      if (URPF_MODE_OFF != mode)
+      if (URPF_MODE_OFF != data.mode)
        /* enable what's new */
        vnet_feature_enable_disable (urpf_feat_arcs[af][dir],
-                                    urpf_feats[af][dir][mode],
+                                    urpf_feats[af][dir][data.mode],
                                     sw_if_index, 1, 0, 0);
     }
   /* else - no change to existing config */
+  return 0;
+}
+
+static void
+urpf_table_bind_v4 (ip4_main_t *im, uword opaque, u32 sw_if_index,
+                   u32 new_fib_index, u32 old_fib_index)
+{
+  vlib_dir_t dir;
+  urpf_data_t empty = { .fib_index = 0, .mode = URPF_MODE_OFF };
+  FOREACH_VLIB_DIR (dir)
+  {
+    vec_validate_init_empty (urpf_cfgs[AF_IP4][dir], sw_if_index, empty);
+    if (!urpf_cfgs[AF_IP4][dir][sw_if_index].fib_index_is_custom)
+      {
+       urpf_cfgs[AF_IP4][dir][sw_if_index].fib_index = new_fib_index;
+      }
+  }
+}
 
-  urpf_cfgs[af][dir][sw_if_index] = mode;
+static void
+urpf_table_bind_v6 (ip6_main_t *im, uword opaque, u32 sw_if_index,
+                   u32 new_fib_index, u32 old_fib_index)
+{
+  vlib_dir_t dir;
+  urpf_data_t empty = { .fib_index = 0, .mode = URPF_MODE_OFF };
+  FOREACH_VLIB_DIR (dir)
+  {
+    vec_validate_init_empty (urpf_cfgs[AF_IP6][dir], sw_if_index, empty);
+    if (!urpf_cfgs[AF_IP6][dir][sw_if_index].fib_index_is_custom)
+      {
+       urpf_cfgs[AF_IP6][dir][sw_if_index].fib_index = new_fib_index;
+      }
+  }
 }
 
+static clib_error_t *
+urpf_init (vlib_main_t *vm)
+{
+  ip4_table_bind_callback_t cb4 = {
+    .function = urpf_table_bind_v4,
+  };
+  vec_add1 (ip4_main.table_bind_callbacks, cb4);
+
+  ip6_table_bind_callback_t cb6 = {
+    .function = urpf_table_bind_v6,
+  };
+  vec_add1 (ip6_main.table_bind_callbacks, cb6);
+  return (NULL);
+}
+
+VLIB_INIT_FUNCTION (urpf_init);
+
 static clib_error_t *
 urpf_cli_update (vlib_main_t * vm,
                 unformat_input_t * input, vlib_cli_command_t * cmd)
@@ -134,11 +206,13 @@ urpf_cli_update (vlib_main_t * vm,
   urpf_mode_t mode;
   u32 sw_if_index;
   vlib_dir_t dir;
+  u32 table_id;
 
   sw_if_index = ~0;
   af = AF_IP4;
   dir = VLIB_RX;
   mode = URPF_MODE_STRICT;
+  table_id = ~0;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -150,6 +224,8 @@ urpf_cli_update (vlib_main_t * vm,
        ;
       else if (unformat (line_input, "%U", unformat_urpf_mode, &mode))
        ;
+      else if (unformat (line_input, "table %d", &table_id))
+       ;
       else if (unformat (line_input, "%U", unformat_ip_address_family, &af))
        ;
       else if (unformat (line_input, "%U", unformat_vlib_rx_tx, &dir))
@@ -168,7 +244,13 @@ urpf_cli_update (vlib_main_t * vm,
       goto done;
     }
 
-  urpf_update (mode, sw_if_index, af, dir);
+  int rv = 0;
+  rv = urpf_update (mode, sw_if_index, af, dir, table_id);
+  if (rv)
+    {
+      error = clib_error_return (0, "unknown table id");
+      goto done;
+    }
 done:
   unformat_free (line_input);
 
@@ -233,7 +315,8 @@ done:
 VLIB_CLI_COMMAND (set_interface_ip_source_check_command, static) = {
   .path = "set urpf",
   .function = urpf_cli_update,
-  .short_help = "set urpf [ip4|ip6] [rx|tx] [off|strict|loose] <INTERFACE>",
+  .short_help = "set urpf [ip4|ip6] [rx|tx] [off|strict|loose] "
+               "<INTERFACE> [table <table>]",
 };
 /* *INDENT-ON* */
 
index 941cda2..c2ce6b0 100644 (file)
 
 #include <vnet/ip/ip_types.h>
 
-#define foreach_urpf_mode \
-  _(OFF, "off")           \
-  _(LOOSE, "loose")       \
-  _(STRICT, "strict")     \
+#define foreach_urpf_mode                                                     \
+  _ (OFF, "off")                                                              \
+  _ (LOOSE, "loose")                                                          \
+  _ (STRICT, "strict")
 
 typedef enum urpf_mode_t_
 {
@@ -34,10 +34,17 @@ typedef enum urpf_mode_t_
 
 extern u8 *format_urpf_mode (u8 * s, va_list * a);
 
-extern void urpf_update (urpf_mode_t mode,
-                        u32 sw_if_index,
-                        ip_address_family_t af, vlib_dir_t dir);
+typedef struct
+{
+  urpf_mode_t mode;
+  u32 fib_index;
+  u8 fib_index_is_custom;
+} urpf_data_t;
+
+extern urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR];
 
+extern int urpf_update (urpf_mode_t mode, u32 sw_if_index,
+                       ip_address_family_t af, vlib_dir_t dir, u32 fib_index);
 
 #endif
 
index ad06039..472f0e4 100644 (file)
@@ -26,6 +26,8 @@
 #include <vnet/format_fns.h>
 #include <urpf/urpf.api_enum.h>
 #include <urpf/urpf.api_types.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/ip/ip_types.h>
 
 /**
  * Base message ID fot the plugin
@@ -62,7 +64,34 @@ vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp)
   VALIDATE_SW_IF_INDEX (mp);
 
   rv = urpf_mode_decode (mp->mode, &mode);
+  if (rv)
+    goto done;
+
+  rv = ip_address_family_decode (mp->af, &af);
+  if (rv)
+    goto done;
+
+  rv = urpf_update (mode, htonl (mp->sw_if_index), af,
+                   (mp->is_input ? VLIB_RX : VLIB_TX), 0);
+  if (rv)
+    goto done;
+
+  BAD_SW_IF_INDEX_LABEL;
+done:
+  REPLY_MACRO (VL_API_URPF_UPDATE_REPLY);
+}
 
+static void
+vl_api_urpf_update_v2_t_handler (vl_api_urpf_update_v2_t *mp)
+{
+  vl_api_urpf_update_reply_t *rmp;
+  ip_address_family_t af;
+  urpf_mode_t mode;
+  int rv = 0;
+
+  VALIDATE_SW_IF_INDEX (mp);
+
+  rv = urpf_mode_decode (mp->mode, &mode);
   if (rv)
     goto done;
 
@@ -71,12 +100,15 @@ vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp)
   if (rv)
     goto done;
 
-  urpf_update (mode, htonl (mp->sw_if_index), af,
-              (mp->is_input ? VLIB_RX : VLIB_TX));
+  rv = urpf_update (mode, htonl (mp->sw_if_index), af,
+                   (mp->is_input ? VLIB_RX : VLIB_TX), ntohl (mp->table_id));
+
+  if (rv)
+    goto done;
 
   BAD_SW_IF_INDEX_LABEL;
 done:
-  REPLY_MACRO (VL_API_URPF_UPDATE_REPLY);
+  REPLY_MACRO (VL_API_URPF_UPDATE_V2_REPLY);
 }
 
 #include <urpf/urpf.api.c>
index bfe1f65..816d8b7 100644 (file)
@@ -128,6 +128,11 @@ urpf_inline (vlib_main_t * vm,
          h1 += vnet_buffer (b[1])->ip.save_rewrite_length;
        }
 
+      fib_index0 =
+       urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
+      fib_index1 =
+       urpf_cfgs[af][dir][vnet_buffer (b[1])->sw_if_index[dir]].fib_index;
+
       if (AF_IP4 == af)
        {
          const ip4_header_t *ip0, *ip1;
@@ -135,11 +140,6 @@ urpf_inline (vlib_main_t * vm,
          ip0 = (ip4_header_t *) h0;
          ip1 = (ip4_header_t *) h1;
 
-         fib_index0 = ip4_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[0])->sw_if_index[dir]];
-         fib_index1 = ip4_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[1])->sw_if_index[dir]];
-
          ip4_fib_forwarding_lookup_x2 (fib_index0,
                                        fib_index1,
                                        &ip0->src_address,
@@ -155,11 +155,6 @@ urpf_inline (vlib_main_t * vm,
        {
          const ip6_header_t *ip0, *ip1;
 
-         fib_index0 = ip6_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[0])->sw_if_index[dir]];
-         fib_index1 = ip6_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[1])->sw_if_index[dir]];
-
          ip0 = (ip6_header_t *) h0;
          ip1 = (ip6_header_t *) h1;
 
@@ -255,12 +250,13 @@ urpf_inline (vlib_main_t * vm,
       if (VLIB_TX == dir)
        h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
 
+      fib_index0 =
+       urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
+
       if (AF_IP4 == af)
        {
          const ip4_header_t *ip0;
 
-         fib_index0 = ip4_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[0])->sw_if_index[dir]];
          ip0 = (ip4_header_t *) h0;
 
          lb_index0 = ip4_fib_forwarding_lookup (fib_index0,
@@ -275,8 +271,6 @@ urpf_inline (vlib_main_t * vm,
          const ip6_header_t *ip0;
 
          ip0 = (ip6_header_t *) h0;
-         fib_index0 = ip6_main.fib_index_by_sw_if_index
-           [vnet_buffer (b[0])->sw_if_index[dir]];
 
          lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
                                                   &ip0->src_address);