FIB path preference
[vpp.git] / src / vnet / ip / lookup.c
old mode 100644 (file)
new mode 100755 (executable)
index 807b87b..533d010
@@ -49,6 +49,7 @@
 #include <vnet/dpo/punt_dpo.h>
 #include <vnet/dpo/receive_dpo.h>
 #include <vnet/dpo/ip_null_dpo.h>
+#include <vnet/ip/ip6_neighbor.h>
 
 /**
  * @file
@@ -72,7 +73,10 @@ ip_interface_address_add_del (ip_lookup_main_t * lm,
   a = p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0;
 
   /* Verify given length. */
-  if ((a && (address_length != a->address_length)) || (address_length == 0))
+  if ((a && (address_length != a->address_length)) ||
+      (address_length == 0) ||
+      (lm->is_ip6 && address_length > 128) ||
+      (!lm->is_ip6 && address_length > 32))
     {
       vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
       return clib_error_create
@@ -169,19 +173,24 @@ ip_interface_address_add_del (ip_lookup_main_t * lm,
   return /* no error */ 0;
 }
 
-void
-ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
+static clib_error_t *
+ip_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
 {
-  /* ensure that adjacency is cacheline aligned and sized */
-  STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0,
-                "Cache line marker must be 1st element in struct");
-  STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
-                CLIB_CACHE_LINE_BYTES,
-                "Data in cache line 0 is bigger than cache line size");
+  vec_validate_init_empty (ip4_main.
+                          lookup_main.if_address_pool_index_by_sw_if_index,
+                          sw_if_index, ~0);
+  vec_validate_init_empty (ip6_main.
+                          lookup_main.if_address_pool_index_by_sw_if_index,
+                          sw_if_index, ~0);
+
+  return (NULL);
+}
 
-  /* Preallocate three "special" adjacencies */
-  lm->adjacency_heap = adj_pool;
+VNET_SW_INTERFACE_ADD_DEL_FUNCTION (ip_sw_interface_add_del);
 
+void
+ip_lookup_init (ip_lookup_main_t * lm, u32 is_ip6)
+{
   if (!lm->fib_result_n_bytes)
     lm->fib_result_n_bytes = sizeof (uword);
 
@@ -235,7 +244,8 @@ format_ip_flow_hash_config (u8 * s, va_list * args)
 u8 *
 format_ip_lookup_next (u8 * s, va_list * args)
 {
-  ip_lookup_next_t n = va_arg (*args, ip_lookup_next_t);
+  /* int promotion of ip_lookup_next_t */
+  ip_lookup_next_t n = va_arg (*args, int);
   char *t = 0;
 
   switch (n)
@@ -275,7 +285,6 @@ format_ip_lookup_next (u8 * s, va_list * args)
 u8 *
 format_ip_adjacency_packet_data (u8 * s, va_list * args)
 {
-  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
   u32 adj_index = va_arg (*args, u32);
   u8 *packet_data = va_arg (*args, u8 *);
   u32 n_packet_data_bytes = va_arg (*args, u32);
@@ -284,10 +293,9 @@ format_ip_adjacency_packet_data (u8 * s, va_list * args)
   switch (adj->lookup_next_index)
     {
     case IP_LOOKUP_NEXT_REWRITE:
-      s = format (s, "%U",
-                 format_vnet_rewrite_header,
-                 vnm->vlib_main, &adj->rewrite_header, packet_data,
-                 n_packet_data_bytes);
+    case IP_LOOKUP_NEXT_MCAST:
+      s =
+       format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
       break;
 
     default:
@@ -342,32 +350,6 @@ const ip46_address_t zero_addr = {
             0, 0},
 };
 
-u32
-fib_table_id_find_fib_index (fib_protocol_t proto, u32 table_id)
-{
-  ip4_main_t *im4 = &ip4_main;
-  ip6_main_t *im6 = &ip6_main;
-  uword *p;
-
-  switch (proto)
-    {
-    case FIB_PROTOCOL_IP4:
-      p = hash_get (im4->fib_index_by_table_id, table_id);
-      break;
-    case FIB_PROTOCOL_IP6:
-      p = hash_get (im6->fib_index_by_table_id, table_id);
-      break;
-    default:
-      p = NULL;
-      break;
-    }
-  if (NULL != p)
-    {
-      return (p[0]);
-    }
-  return (~0);
-}
-
 clib_error_t *
 vnet_ip_route_cmd (vlib_main_t * vm,
                   unformat_input_t * main_input, vlib_cli_command_t * cmd)
@@ -378,6 +360,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
   fib_prefix_t *prefixs = NULL, pfx;
   mpls_label_t out_label, via_label;
   clib_error_t *error = NULL;
+  u32 weight, preference;
   u32 table_id, is_del;
   vnet_main_t *vnm;
   u32 fib_index;
@@ -439,6 +422,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                         unformat_mpls_unicast_label, &rpath.frp_local_label))
        {
          rpath.frp_weight = 1;
+         rpath.frp_eos = MPLS_NON_EOS;
          rpath.frp_proto = FIB_PROTOCOL_MPLS;
          rpath.frp_sw_if_index = ~0;
          vec_add1 (rpaths, rpath);
@@ -458,26 +442,6 @@ vnet_ip_route_cmd (vlib_main_t * vm,
          pfx.fp_proto = FIB_PROTOCOL_IP6;
          vec_add1 (prefixs, pfx);
        }
-      else if (unformat (line_input, "via %U %U weight %u",
-                        unformat_ip4_address,
-                        &rpath.frp_addr.ip4,
-                        unformat_vnet_sw_interface, vnm,
-                        &rpath.frp_sw_if_index, &rpath.frp_weight))
-       {
-         rpath.frp_proto = FIB_PROTOCOL_IP4;
-         vec_add1 (rpaths, rpath);
-       }
-
-      else if (unformat (line_input, "via %U %U weight %u",
-                        unformat_ip6_address,
-                        &rpath.frp_addr.ip6,
-                        unformat_vnet_sw_interface, vnm,
-                        &rpath.frp_sw_if_index, &rpath.frp_weight))
-       {
-         rpath.frp_proto = FIB_PROTOCOL_IP6;
-         vec_add1 (rpaths, rpath);
-       }
-
       else if (unformat (line_input, "via %U %U",
                         unformat_ip4_address,
                         &rpath.frp_addr.ip4,
@@ -499,6 +463,16 @@ vnet_ip_route_cmd (vlib_main_t * vm,
          rpath.frp_proto = FIB_PROTOCOL_IP6;
          vec_add1 (rpaths, rpath);
        }
+      else if (unformat (line_input, "weight %u", &weight))
+       {
+         ASSERT (vec_len (rpaths));
+         rpaths[vec_len (rpaths) - 1].frp_weight = weight;
+       }
+      else if (unformat (line_input, "preference %u", &preference))
+       {
+         ASSERT (vec_len (rpaths));
+         rpaths[vec_len (rpaths) - 1].frp_preference = preference;
+       }
       else if (unformat (line_input, "via %U next-hop-table %d",
                         unformat_ip4_address,
                         &rpath.frp_addr.ip4, &rpath.frp_fib_index))
@@ -590,7 +564,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
     }
   else
     {
-      fib_index = fib_table_id_find_fib_index (prefixs[0].fp_proto, table_id);
+      fib_index = fib_table_find (prefixs[0].fp_proto, table_id);
 
       if (~0 == fib_index)
        {
@@ -639,8 +613,8 @@ vnet_ip_route_cmd (vlib_main_t * vm,
                  /*
                   * the CLI parsing stored table Ids, swap to FIB indicies
                   */
-                 fi = fib_table_id_find_fib_index (prefixs[i].fp_proto,
-                                                   rpaths[i].frp_fib_index);
+                 fi = fib_table_find (prefixs[i].fp_proto,
+                                      rpaths[i].frp_fib_index);
 
                  if (~0 == fi)
                    {
@@ -830,12 +804,14 @@ vnet_ip_mroute_cmd (vlib_main_t * vm,
                         unformat_ip4_address,
                         &pfx.fp_grp_addr.ip4, &pfx.fp_len))
        {
+         memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
          pfx.fp_proto = FIB_PROTOCOL_IP4;
        }
       else if (unformat (line_input, "%U/%d",
                         unformat_ip6_address,
                         &pfx.fp_grp_addr.ip6, &pfx.fp_len))
        {
+         memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
          pfx.fp_proto = FIB_PROTOCOL_IP6;
        }
       else if (unformat (line_input, "%U",
@@ -857,7 +833,12 @@ vnet_ip_mroute_cmd (vlib_main_t * vm,
                         &rpath.frp_sw_if_index))
        {
          rpath.frp_weight = 1;
-         rpath.frp_proto = FIB_PROTOCOL_IP4;
+       }
+      else if (unformat (line_input, "via local"))
+       {
+         rpath.frp_sw_if_index = ~0;
+         rpath.frp_weight = 1;
+         rpath.frp_flags |= FIB_ROUTE_PATH_LOCAL;
        }
       else if (unformat (line_input, "%U", unformat_mfib_itf_flags, &iflags))
        ;
@@ -912,7 +893,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm,
          else if (eflags)
            {
              mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI,
-                                      eflags);
+                                      MFIB_RPF_ID_NONE, eflags);
            }
          else
            {