fib: fix crash while adding intf-rx routes
[vpp.git] / src / vnet / ip / lookup.c
index 1753ffd..f86c8b6 100644 (file)
@@ -128,6 +128,42 @@ format_ip_flow_hash_config (u8 * s, va_list * args)
   return s;
 }
 
+uword
+unformat_ip_flow_hash_config (unformat_input_t *input, va_list *args)
+{
+  flow_hash_config_t *flow_hash_config = va_arg (*args, flow_hash_config_t *);
+  uword start_index = unformat_check_input (input);
+  int matched_once = 0;
+
+  if (unformat (input, "default"))
+    {
+      *flow_hash_config = IP_FLOW_HASH_DEFAULT;
+      return 1;
+    }
+  while (!unformat_is_eof (input) &&
+        !is_white_space (unformat_peek_input (input)))
+    {
+      if (unformat (input, "%_,"))
+       ;
+#define _(a, b, c)                                                            \
+  else if (unformat (input, "%_" #a))                                         \
+  {                                                                           \
+    *flow_hash_config |= c;                                                   \
+    matched_once = 1;                                                         \
+  }
+      foreach_flow_hash_bit
+#undef _
+       else
+      {
+       /* Roll back to our start */
+       input->index = start_index;
+       return 0;
+      }
+    }
+
+  return matched_once;
+}
+
 u8 *
 format_ip_adjacency_packet_data (u8 * s, va_list * args)
 {
@@ -184,6 +220,27 @@ const ip46_address_t zero_addr = {
             0, 0},
 };
 
+bool
+fib_prefix_validate (const fib_prefix_t *prefix)
+{
+  if (FIB_PROTOCOL_IP4 == prefix->fp_proto)
+    {
+      if (prefix->fp_len > 32)
+       {
+         return false;
+       }
+    }
+
+  if (FIB_PROTOCOL_IP6 == prefix->fp_proto)
+    {
+      if (prefix->fp_len > 128)
+       {
+         return false;
+       }
+    }
+  return true;
+}
+
 static clib_error_t *
 vnet_ip_route_cmd (vlib_main_t * vm,
                   unformat_input_t * main_input, vlib_cli_command_t * cmd)
@@ -304,22 +361,25 @@ vnet_ip_route_cmd (vlib_main_t * vm,
        }
       else if (0 < vec_len (rpaths))
        {
-         u32 k, n, incr;
-         ip46_address_t dst = prefixs[i].fp_addr;
+         u32 k, n;
          f64 t[2];
          n = count;
          t[0] = vlib_time_now (vm);
-         incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
-                      prefixs[i].fp_len);
 
          for (k = 0; k < n; k++)
            {
              fib_prefix_t rpfx = {
                .fp_len = prefixs[i].fp_len,
                .fp_proto = prefixs[i].fp_proto,
-               .fp_addr = dst,
+               .fp_addr = prefixs[i].fp_addr,
              };
 
+             if (!fib_prefix_validate (&rpfx))
+               {
+                 vlib_cli_output (vm, "Invalid prefix len: %d", rpfx.fp_len);
+                 continue;
+               }
+
              if (is_del)
                fib_table_entry_path_remove2 (fib_index,
                                              &rpfx, FIB_SOURCE_CLI, rpaths);
@@ -329,21 +389,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                                           FIB_SOURCE_CLI,
                                           FIB_ENTRY_FLAG_NONE, rpaths);
 
-             if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
-               {
-                 dst.ip4.as_u32 =
-                   clib_host_to_net_u32 (incr +
-                                         clib_net_to_host_u32 (dst.
-                                                               ip4.as_u32));
-               }
-             else
-               {
-                 int bucket = (incr < 64 ? 0 : 1);
-                 dst.ip6.as_u64[bucket] =
-                   clib_host_to_net_u64 (incr +
-                                         clib_net_to_host_u64 (dst.ip6.as_u64
-                                                               [bucket]));
-               }
+             fib_prefix_increment (&prefixs[i]);
            }
 
          t[1] = vlib_time_now (vm);
@@ -399,29 +445,35 @@ vnet_ip_table_cmd (vlib_main_t * vm,
        }
     }
 
-  if (~0 == table_id)
-    {
-      error = clib_error_return (0, "No table id");
-      goto done;
-    }
-  else if (0 == table_id)
+  if (0 == table_id)
     {
       error = clib_error_return (0, "Can't change the default table");
       goto done;
     }
   else
-    {
-      if (is_add)
-       {
-         ip_table_create (fproto, table_id, 0, name);
-       }
-      else
        {
-         ip_table_delete (fproto, table_id, 0);
+         if (is_add)
+           {
+             if (~0 == table_id)
+               {
+                 table_id = ip_table_get_unused_id (fproto);
+                 vlib_cli_output (vm, "%u\n", table_id);
+               }
+             ip_table_create (fproto, table_id, 0, name);
+           }
+         else
+           {
+             if (~0 == table_id)
+               {
+                 error = clib_error_return (0, "No table id");
+                 goto done;
+               }
+             ip_table_delete (fproto, table_id, 0);
+           }
        }
-    }
 
 done:
+  vec_free (name);
   unformat_free (line_input);
   return error;
 }
@@ -477,13 +529,13 @@ vnet_show_ip_table_cmd (vlib_main_t *vm, unformat_input_t *main_input,
        }
 
       fib = fib_table_get (fib_index, fproto);
-      vlib_cli_output (vm, "[%3u] table_id:%3u %v", fib->ft_index,
+      vlib_cli_output (vm, "[%u] table_id:%u %v", fib->ft_index,
                       fib->ft_table_id, fib->ft_desc);
     }
   else
     {
       pool_foreach (fib, fibs)
-       vlib_cli_output (vm, "[%3u] table_id:%3u %v", fib->ft_index,
+       vlib_cli_output (vm, "[%u] table_id:%u %v", fib->ft_index,
                         fib->ft_table_id, fib->ft_desc);
     }
 
@@ -563,7 +615,13 @@ VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (ip_route_command, static) = {
   .path = "ip route",
-  .short_help = "ip route [add|del] [count <n>] <dst-ip-addr>/<width> [table <table-id>] via [next-hop-address] [next-hop-interface] [next-hop-table <value>] [weight <value>] [preference <value>] [udp-encap-id <value>] [ip4-lookup-in-table <value>] [ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] [resolve-via-host] [resolve-via-connected] [rx-ip4 <interface>] [out-labels <value value value>]",
+  .short_help = "ip route [add|del] [count <n>] <dst-ip-addr>/<width> [table "
+               "<table-id>] via [next-hop-address] [next-hop-interface] "
+               "[next-hop-table <value>] [weight <value>] [preference "
+               "<value>] [udp-encap <value>] [ip4-lookup-in-table <value>] "
+               "[ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] "
+               "[resolve-via-host] [resolve-via-connected] [rx-ip4|rx-ip6 "
+               "<interface>] [out-labels <value value value>]",
   .function = vnet_ip_route_cmd,
   .is_mp_safe = 1,
 };
@@ -638,7 +696,7 @@ ip_table_bind_cmd (vlib_main_t * vm,
       goto done;
     }
 
-  rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
+  rv = ip_table_bind (fproto, sw_if_index, table_id);
 
   if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
     {
@@ -894,8 +952,8 @@ vnet_ip_mroute_cmd (vlib_main_t * vm,
                mfib_table_entry_path_remove (fib_index,
                                              &pfx, MFIB_SOURCE_CLI, rpaths);
              else
-               mfib_table_entry_path_update (fib_index,
-                                             &pfx, MFIB_SOURCE_CLI, rpaths);
+               mfib_table_entry_path_update (fib_index, &pfx, MFIB_SOURCE_CLI,
+                                             MFIB_ENTRY_FLAG_NONE, rpaths);
            }
 
          if (FIB_PROTOCOL_IP4 == pfx.fp_proto)