ARP/ND entries for the same address on different interfaces (VPP-848) 61/6761/8
authorNeale Ranns <nranns@cisco.com>
Thu, 18 May 2017 10:03:22 +0000 (03:03 -0700)
committerDamjan Marion <dmarion.lists@gmail.com>
Tue, 23 May 2017 09:48:52 +0000 (09:48 +0000)
there are, intentionally, no validation checks in the ARP/ND code to prevent an ARP/ND entry from being installed for an address that is not local to the interface's sub-net. This is ok, since the adjacency/FIB code is designed to handle this case using the 'refinement' criteria - i.e. only installing a FIB entry for the address if the address 'refines' (i.e. is more specific than) the interface's sub-net.
However, the refinement criteria currently operates on the FIB entry's prefix (which is a /32, so on the address) and not on the next-hop in the path.
So, enter multiple ARP entries for the same address on different links, and this refinement criteria uses only the last added path, and so will remove the FIB entry should the ARP entries be added in the 'wrong' order.
This fix updates the refinement criteria to work on each path of the FIB entry. The entry is installed if one of the paths refines the covers and only paths refining the cover contribute forwarding.
Per-path refinement checks are stored in path-extensions. The patch is rather large as path-extension, which were previously used only for out-going MPLS labels, have been generalized.

Change-Id: I00be359148cb948c32c52109e832a70537a7920a
Signed-off-by: Neale Ranns <nranns@cisco.com>
18 files changed:
src/vnet/ethernet/arp.c
src/vnet/fib/fib_entry.c
src/vnet/fib/fib_entry.h
src/vnet/fib/fib_entry_src.c
src/vnet/fib/fib_entry_src_adj.c
src/vnet/fib/fib_entry_src_api.c
src/vnet/fib/fib_path.c
src/vnet/fib/fib_path.h
src/vnet/fib/fib_path_ext.c
src/vnet/fib/fib_path_ext.h
src/vnet/fib/fib_path_list.c
src/vnet/fib/fib_path_list.h
src/vnet/fib/fib_test.c
src/vnet/fib/fib_types.h
src/vnet/ip/ip6_neighbor.c
src/vnet/mfib/mfib_entry.c
src/vnet/mpls/mpls_tunnel.c
src/vnet/mpls/mpls_tunnel.h

index f44cb59..ad0c2c8 100644 (file)
@@ -582,11 +582,11 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
          fib_index =
            ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
          e->fib_entry_index =
-           fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_ADJ,
-                                            FIB_ENTRY_FLAG_ATTACHED,
-                                            FIB_PROTOCOL_IP4, &pfx.fp_addr,
-                                            e->sw_if_index, ~0, 1, NULL,
-                                            FIB_ROUTE_PATH_FLAG_NONE);
+           fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+                                     FIB_ENTRY_FLAG_ATTACHED,
+                                     FIB_PROTOCOL_IP4, &pfx.fp_addr,
+                                     e->sw_if_index, ~0, 1, NULL,
+                                     FIB_ROUTE_PATH_FLAG_NONE);
        }
       else
        {
index 29f5b35..cdebfbc 100644 (file)
@@ -88,7 +88,6 @@ format_fib_entry (u8 * s, va_list * args)
 {
     fib_forward_chain_type_t fct;
     fib_entry_attribute_t attr;
-    fib_path_ext_t *path_ext;
     fib_entry_t *fib_entry;
     fib_entry_src_t *src;
     fib_node_index_t fei;
@@ -126,14 +125,7 @@ format_fib_entry (u8 * s, va_list * args)
            {
                s = fib_path_list_format(src->fes_pl, s);
            }
-           if (NULL != src->fes_path_exts)
-           {
-               s = format(s, "    Extensions:");
-               vec_foreach(path_ext, src->fes_path_exts)
-               {
-                   s = format(s, "\n     %U", format_fib_path_ext, path_ext);
-               }
-           }
+            s = format(s, "%U", format_fib_path_ext_list, &src->fes_path_exts);
        }));
     
        s = format (s, "\n forwarding: ");
@@ -328,7 +320,7 @@ fib_entry_show_memory (void)
        n_srcs += vec_len(entry->fe_srcs);
        vec_foreach(esrc, entry->fe_srcs)
        {
-           n_exts += vec_len(esrc->fes_path_exts);
+           n_exts += fib_path_ext_list_length(&esrc->fes_path_exts);
        }
     }));
 
index aa1000e..5f6ff31 100644 (file)
@@ -290,7 +290,7 @@ typedef struct fib_entry_src_t_ {
     /**
      * A vector of path extensions
      */
-    struct fib_path_ext_t_ *fes_path_exts;
+    fib_path_ext_list_t fes_path_exts;
 
     /**
      * The path-list created by the source
index ab72565..8c50828 100644 (file)
@@ -146,7 +146,7 @@ fib_entry_src_action_deinit (fib_entry_t *fib_entry,
        fib_entry_src_vft[source].fesv_deinit(esrc);
     }
 
-    vec_free(esrc->fes_path_exts);
+    fib_path_ext_list_flush(&esrc->fes_path_exts);
     vec_del1(fib_entry->fe_srcs, index);
 }
 
@@ -188,7 +188,7 @@ fib_entry_src_action_cover_update (fib_entry_t *fib_entry,
 
 typedef struct fib_entry_src_collect_forwarding_ctx_t_
 {
-    load_balance_path_t * next_hops;
+    load_balance_path_t *next_hops;
     const fib_entry_t *fib_entry;
     const fib_entry_src_t *esrc;
     fib_forward_chain_type_t fct;
@@ -264,95 +264,46 @@ fib_entry_chain_type_fixup (const fib_entry_t *entry,
     return (dfct);
 }
 
-static int
-fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
-                                  fib_node_index_t path_index,
-                                  void *arg)
+static void
+fib_entry_src_get_path_forwarding (fib_node_index_t path_index,
+                                   fib_entry_src_collect_forwarding_ctx_t *ctx)
 {
-    fib_entry_src_collect_forwarding_ctx_t *ctx;
-    fib_path_ext_t *path_ext;
-    int have_path_ext;
-
-    ctx = arg;
-
-    /*
-     * if the path is not resolved, don't include it.
-     */
-    if (!fib_path_is_resolved(path_index))
-    {
-        return (!0);
-    }
-
-    if (fib_path_is_recursive_constrained(path_index))
-    {
-        ctx->n_recursive_constrained += 1;
-    }
+    load_balance_path_t *nh;
 
     /*
-     * get the matching path-extension for the path being visited.
+     * no extension => no out-going label for this path. that's OK
+     * in the case of an IP or EOS chain, but not for non-EOS
      */
-    have_path_ext = 0;
-    vec_foreach(path_ext, ctx->esrc->fes_path_exts)
-    {
-        if (path_ext->fpe_path_index == path_index)
-        {
-            have_path_ext = 1;
-            break;
-        }
-    }
-    
-    if (have_path_ext &&
-        fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0]))
+    switch (ctx->fct)
     {
+    case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
+    case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
+    case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
+    case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
         /*
-         * found a matching extension. stack it to obtain the forwarding
-         * info for this path.
+         * EOS traffic with no label to stack, we need the IP Adj
          */
-        ctx->next_hops =
-            fib_path_ext_stack(path_ext,
-                               ctx->fct,
-                               fib_entry_chain_type_fixup(ctx->fib_entry,
-                                                          ctx->fct),
-                               ctx->next_hops);
-    }
-    else
-    {
-        load_balance_path_t *nh;
+        vec_add2(ctx->next_hops, nh, 1);
 
-        /*
-         * no extension => no out-going label for this path. that's OK
-         * in the case of an IP or EOS chain, but not for non-EOS
-         */
-        switch (ctx->fct)
+        nh->path_index = path_index;
+        nh->path_weight = fib_path_get_weight(path_index);
+        fib_path_contribute_forwarding(path_index, ctx->fct, &nh->path_dpo);
+
+        break;
+    case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
+        if (fib_path_is_exclusive(path_index) ||
+            fib_path_is_deag(path_index))
         {
-        case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
-        case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
-        case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
-        case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
-            /*
-             * EOS traffic with no label to stack, we need the IP Adj
-             */
             vec_add2(ctx->next_hops, nh, 1);
 
             nh->path_index = path_index;
             nh->path_weight = fib_path_get_weight(path_index);
-            fib_path_contribute_forwarding(path_index, ctx->fct, &nh->path_dpo);
-
-            break;
-        case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
-           if (fib_path_is_exclusive(path_index) ||
-               fib_path_is_deag(path_index))
-           {
-               vec_add2(ctx->next_hops, nh, 1);
-
-               nh->path_index = path_index;
-               nh->path_weight = fib_path_get_weight(path_index);
-               fib_path_contribute_forwarding(path_index,
-                                              FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
-                                              &nh->path_dpo);
-           }
-            break;
-        case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
+            fib_path_contribute_forwarding(path_index,
+                                           FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
+                                           &nh->path_dpo);
+        }
+        break;
+    case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
         {
             /*
              * no label. we need a chain based on the payload. fixup.
@@ -371,14 +322,85 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
 
             break;
         }
-        case FIB_FORW_CHAIN_TYPE_ETHERNET:
-        case FIB_FORW_CHAIN_TYPE_NSH:
-           ASSERT(0);
-           break;
+    case FIB_FORW_CHAIN_TYPE_ETHERNET:
+    case FIB_FORW_CHAIN_TYPE_NSH:
+        ASSERT(0);
+        break;
+    }
+}
+
+static fib_path_list_walk_rc_t
+fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
+                                  fib_node_index_t path_index,
+                                  void *arg)
+{
+    fib_entry_src_collect_forwarding_ctx_t *ctx;
+    fib_path_ext_t *path_ext;
+
+    ctx = arg;
+
+    /*
+     * if the path is not resolved, don't include it.
+     */
+    if (!fib_path_is_resolved(path_index))
+    {
+        return (FIB_PATH_LIST_WALK_CONTINUE);
+    }
+
+    if (fib_path_is_recursive_constrained(path_index))
+    {
+        ctx->n_recursive_constrained += 1;
+    }
+
+    /*
+     * get the matching path-extension for the path being visited.
+     */
+    path_ext = fib_path_ext_list_find_by_path_index(&ctx->esrc->fes_path_exts,
+                                                    path_index);
+
+    if (NULL != path_ext)
+    {
+        switch (path_ext->fpe_type)
+        {
+        case FIB_PATH_EXT_MPLS:
+            if (fib_entry_src_valid_out_label(path_ext->fpe_label_stack[0]))
+            {
+                /*
+                 * found a matching extension. stack it to obtain the forwarding
+                 * info for this path.
+                 */
+                ctx->next_hops =
+                    fib_path_ext_stack(path_ext,
+                                       ctx->fct,
+                                       fib_entry_chain_type_fixup(ctx->fib_entry,
+                                                                  ctx->fct),
+                                       ctx->next_hops);
+            }
+            else
+            {
+                fib_entry_src_get_path_forwarding(path_index, ctx);
+            }
+            break;
+        case FIB_PATH_EXT_ADJ:
+            if (FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER & path_ext->fpe_adj_flags)
+            {
+                fib_entry_src_get_path_forwarding(path_index, ctx);
+            }
+            /*
+             * else
+             *  the path does not refine the cover, meaning that
+             *  the adjacency doesdoes not match the sub-net on the link.
+             *  So this path does not contribute forwarding.
+             */
+            break;
         }
     }
+    else
+    {
+        fib_entry_src_get_path_forwarding(path_index, ctx);
+    }
 
-    return (!0);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 void
@@ -1035,58 +1057,6 @@ fib_entry_flags_update (const fib_entry_t *fib_entry,
     }
 }
 
-/*
- * fib_entry_src_path_ext_add
- *
- * append a path extension to the entry's list
- */
-static void
-fib_entry_src_path_ext_append (fib_entry_src_t *esrc,
-                              const fib_route_path_t *rpath)
-{
-    if (NULL != rpath->frp_label_stack)
-    {
-       fib_path_ext_t *path_ext;
-
-       vec_add2(esrc->fes_path_exts, path_ext, 1);
-
-       fib_path_ext_init(path_ext, esrc->fes_pl, rpath);
-    }
-}
-
-/*
- * fib_entry_src_path_ext_insert
- *
- * insert, sorted, a path extension to the entry's list.
- * It's not strictly necessary in sort the path extensions, since each
- * extension has the path index to which it resolves. However, by being
- * sorted the load-balance produced has a deterministic order, not an order
- * based on the sequence of extension additions. this is a considerable benefit.
- */
-static void
-fib_entry_src_path_ext_insert (fib_entry_src_t *esrc,
-                              const fib_route_path_t *rpath)
-{
-    if (0 == vec_len(esrc->fes_path_exts))
-       return (fib_entry_src_path_ext_append(esrc, rpath));
-
-    if (NULL != rpath->frp_label_stack)
-    {
-       fib_path_ext_t path_ext;
-       int i = 0;
-
-       fib_path_ext_init(&path_ext, esrc->fes_pl, rpath);
-
-       while (i < vec_len(esrc->fes_path_exts) &&
-              (fib_path_ext_cmp(&esrc->fes_path_exts[i], rpath) < 0))
-       {
-           i++;
-       }
-
-       vec_insert_elts(esrc->fes_path_exts, &path_ext, 1, i);
-    }
-}
-
 /*
  * fib_entry_src_action_add
  *
@@ -1103,7 +1073,6 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry,
 {
     fib_node_index_t old_path_list, fib_entry_index;
     fib_path_list_flags_t pl_flags;
-    fib_path_ext_t *path_ext;
     fib_entry_src_t *esrc;
 
     /*
@@ -1140,18 +1109,6 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry,
     fib_entry_src_vft[source].fesv_path_add(esrc, fib_entry, pl_flags, rpath);
     fib_entry = fib_entry_get(fib_entry_index);
 
-    /*
-     * re-resolve all the path-extensions with the new path-list
-     */
-    vec_foreach(path_ext, esrc->fes_path_exts)
-    {
-       fib_path_ext_resolve(path_ext, esrc->fes_pl);
-    }
-    /*
-     * if the path has a label we need to add a path extension
-     */
-    fib_entry_src_path_ext_insert(esrc, rpath);
-
     fib_path_list_lock(esrc->fes_pl);
     fib_path_list_unlock(old_path_list);
 
@@ -1176,7 +1133,6 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
     fib_node_index_t old_path_list, fib_entry_index;
     fib_path_list_flags_t pl_flags;
     const fib_route_path_t *rpath;
-    fib_path_ext_t *path_ext;
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find(fib_entry, source, NULL);
@@ -1218,17 +1174,6 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
                                             pl_flags,
                                             rpaths);
 
-    vec_foreach(path_ext, esrc->fes_path_exts)
-    {
-       vec_free(path_ext->fpe_label_stack);
-    }
-    vec_free(esrc->fes_path_exts);
-
-    vec_foreach(rpath, rpaths)
-    {
-       fib_entry_src_path_ext_append(esrc, rpath);
-    }
-
     fib_entry = fib_entry_get(fib_entry_index);
 
     fib_path_list_lock(esrc->fes_pl);
@@ -1244,7 +1189,6 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry,
 {
     fib_path_list_flags_t pl_flags;
     fib_node_index_t old_path_list;
-    fib_path_ext_t *path_ext;
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find(fib_entry, source, NULL);
@@ -1266,29 +1210,6 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry,
     fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc);
 
     fib_entry_src_vft[source].fesv_path_remove(esrc, pl_flags, rpath);
-    /*
-     * find the matching path extension and remove it
-     */
-    vec_foreach(path_ext, esrc->fes_path_exts)
-    {
-       if (!fib_path_ext_cmp(path_ext, rpath))
-       {
-           /*
-            * delete the element moving the remaining elements down 1 position.
-            * this preserves the sorted order.
-            */
-           vec_free(path_ext->fpe_label_stack);
-           vec_delete(esrc->fes_path_exts, 1, (path_ext - esrc->fes_path_exts));
-           break;
-       }
-    }
-    /*
-     * re-resolve all the path-extensions with the new path-list
-     */
-    vec_foreach(path_ext, esrc->fes_path_exts)
-    {
-       fib_path_ext_resolve(path_ext, esrc->fes_pl);
-    }
 
     /*
      * lock the new path-list, unlock the old if it had one
index 9990223..9ea2b17 100644 (file)
 #include "fib_table.h"
 #include "fib_entry_cover.h"
 #include "fib_attached_export.h"
+#include "fib_path_ext.h"
 
 /**
- * Source initialisation Function 
+ * Source initialisation Function
  */
 static void
 fib_entry_src_adj_init (fib_entry_src_t *src)
@@ -30,13 +31,94 @@ fib_entry_src_adj_init (fib_entry_src_t *src)
     src->adj.fesa_sibling = FIB_NODE_INDEX_INVALID;
 }
 
+static void
+fib_entry_src_adj_path_add (fib_entry_src_t *src,
+                            const fib_entry_t *entry,
+                            fib_path_list_flags_t pl_flags,
+                            const fib_route_path_t *paths)
+{
+    const fib_route_path_t *rpath;
+
+    if (FIB_NODE_INDEX_INVALID == src->fes_pl)
+    {
+        src->fes_pl = fib_path_list_create(pl_flags, paths);
+    }
+    else
+    {
+        src->fes_pl = fib_path_list_copy_and_path_add(src->fes_pl,
+                                                      pl_flags,
+                                                      paths);
+    }
+
+    /*
+     * resolve the existing extensions
+     */
+    fib_path_ext_list_resolve(&src->fes_path_exts, src->fes_pl);
+
+    /*
+     * and new extensions
+     */
+    vec_foreach(rpath, paths)
+    {
+        fib_path_ext_list_insert(&src->fes_path_exts,
+                                 src->fes_pl,
+                                 FIB_PATH_EXT_ADJ,
+                                 rpath);
+    }
+}
+
+static void
+fib_entry_src_adj_path_remove (fib_entry_src_t *src,
+                               fib_path_list_flags_t pl_flags,
+                               const fib_route_path_t *rpaths)
+{
+    const fib_route_path_t *rpath;
+
+    if (FIB_NODE_INDEX_INVALID != src->fes_pl)
+    {
+        src->fes_pl = fib_path_list_copy_and_path_remove(src->fes_pl,
+                                                         pl_flags,
+                                                         rpaths);
+    }
+
+    /*
+     * remove the path-extension for the path
+     */
+    vec_foreach(rpath, rpaths)
+    {
+        fib_path_ext_list_remove(&src->fes_path_exts, FIB_PATH_EXT_ADJ, rpath);
+    };
+    /*
+     * resolve the remaining extensions
+     */
+    fib_path_ext_list_resolve(&src->fes_path_exts, src->fes_pl);
+}
+
 static void
 fib_entry_src_adj_path_swap (fib_entry_src_t *src,
-                            const fib_entry_t *entry,
-                            fib_path_list_flags_t pl_flags,
-                            const fib_route_path_t *paths)
+                             const fib_entry_t *entry,
+                             fib_path_list_flags_t pl_flags,
+                             const fib_route_path_t *paths)
 {
+    const fib_route_path_t *rpath;
+
+    /*
+     * flush all the old extensions before we create a brand new path-list
+     */
+    fib_path_ext_list_flush(&src->fes_path_exts);
+
     src->fes_pl = fib_path_list_create(pl_flags, paths);
+
+    /*
+     * and new extensions
+     */
+    vec_foreach(rpath, paths)
+    {
+        fib_path_ext_list_push_back(&src->fes_path_exts,
+                                    src->fes_pl,
+                                    FIB_PATH_EXT_ADJ,
+                                    rpath);
+    }
 }
 
 static void
@@ -45,14 +127,87 @@ fib_entry_src_adj_remove (fib_entry_src_t *src)
     src->fes_pl = FIB_NODE_INDEX_INVALID;
 }
 
+/*
+ * Add a path-extension indicating whether this path is resolved,
+ * because it passed the refinement check
+ */
+static void
+fib_enty_src_adj_update_path_ext (fib_entry_src_t *src,
+                                  fib_node_index_t path_index,
+                                  fib_path_ext_adj_flags_t flags)
+{
+    fib_path_ext_t *path_ext;
+
+    path_ext = fib_path_ext_list_find_by_path_index(&src->fes_path_exts,
+                                                    path_index);
+
+    if (NULL != path_ext)
+    {
+        path_ext->fpe_adj_flags = flags;
+    }
+    else
+    {
+        ASSERT(!"no path extension");
+    }
+}
+
+typedef struct fib_entry_src_path_list_walk_cxt_t_
+{
+    fib_entry_src_t *src;
+    u32 cover_itf;
+    fib_path_ext_adj_flags_t flags;
+} fib_entry_src_path_list_walk_cxt_t;
+
+static fib_path_list_walk_rc_t
+fib_entry_src_adj_path_list_walk (fib_node_index_t pl_index,
+                                  fib_node_index_t path_index,
+                                  void *arg)
+{
+    fib_entry_src_path_list_walk_cxt_t *ctx;
+    u32 adj_itf;
+
+    ctx = arg;
+    adj_itf = fib_path_get_resolving_interface(path_index);
+
+    if (ctx->cover_itf == adj_itf)
+    {
+        fib_enty_src_adj_update_path_ext(ctx->src, path_index,
+                                         FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER);
+        ctx->flags |= FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER;
+    }
+    else
+    {
+        /*
+         * if the interface the adj is on is unnumbered to the
+         * cover's, then allow that too.
+         */
+        vnet_sw_interface_t *swif;
+
+        swif = vnet_get_sw_interface (vnet_get_main(), adj_itf);
+
+        if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
+            ctx->cover_itf == swif->unnumbered_sw_if_index)
+        {
+            fib_enty_src_adj_update_path_ext(ctx->src, path_index,
+                                             FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER);
+            ctx->flags |= FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER;
+        }
+        else
+        {
+            fib_enty_src_adj_update_path_ext(ctx->src, path_index,
+                                             FIB_PATH_EXT_ADJ_FLAG_NONE);
+        }
+    }
+    return (FIB_PATH_LIST_WALK_CONTINUE);
+}
 
 /*
- * Source activate. 
+ * Source activate.
  * Called when the source is the new longer best source on the entry
  */
 static int
 fib_entry_src_adj_activate (fib_entry_src_t *src,
-                           const fib_entry_t *fib_entry)
+                            const fib_entry_t *fib_entry)
 {
     fib_entry_t *cover;
 
@@ -61,7 +216,7 @@ fib_entry_src_adj_activate (fib_entry_src_t *src,
      * there should always be a cover, though it may be the default route.
      */
     src->adj.fesa_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
-                                                     &fib_entry->fe_prefix);
+                                                      &fib_entry->fe_prefix);
 
     ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
     ASSERT(fib_entry_get_index(fib_entry) != src->adj.fesa_cover);
@@ -71,8 +226,8 @@ fib_entry_src_adj_activate (fib_entry_src_t *src,
     ASSERT(cover != fib_entry);
 
     src->adj.fesa_sibling =
-       fib_entry_cover_track(cover,
-                             fib_entry_get_index(fib_entry));
+        fib_entry_cover_track(cover,
+                              fib_entry_get_index(fib_entry));
 
     /*
      * if the cover is attached on the same interface as this adj source then
@@ -88,40 +243,31 @@ fib_entry_src_adj_activate (fib_entry_src_t *src,
      */
     if (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags_i(cover))
     {
-        u32 cover_itf = fib_entry_get_resolving_interface(src->adj.fesa_cover);
-        u32 adj_itf = fib_path_list_get_resolving_interface(src->fes_pl);
-
-        if (cover_itf == adj_itf)
-        {
-            return (1);
-        }
-        else
-        {
-            /*
-             * if the interface the adj is on is unnumbered to the
-             * cover's, then allow that too.
-             */
-            vnet_sw_interface_t *swif;
-
-            swif = vnet_get_sw_interface (vnet_get_main(), adj_itf);
-
-            if (swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
-                cover_itf == swif->unnumbered_sw_if_index)
-            {
-                return (1);
-            }
-        }
+        fib_entry_src_path_list_walk_cxt_t ctx = {
+            .cover_itf = fib_entry_get_resolving_interface(src->adj.fesa_cover),
+            .flags = FIB_PATH_EXT_ADJ_FLAG_NONE,
+            .src = src,
+        };
+
+        fib_path_list_walk(src->fes_pl,
+                           fib_entry_src_adj_path_list_walk,
+                           &ctx);
+
+        /*
+         * active the entry is one of the paths refines the cover.
+         */
+        return (FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER & ctx.flags);
     }
     return (0);
 }
 
 /*
- * Source Deactivate. 
+ * Source Deactivate.
  * Called when the source is no longer best source on the entry
  */
 static void
 fib_entry_src_adj_deactivate (fib_entry_src_t *src,
-                             const fib_entry_t *fib_entry)
+                              const fib_entry_t *fib_entry)
 {
     fib_entry_t *cover;
 
@@ -143,14 +289,14 @@ fib_entry_src_adj_deactivate (fib_entry_src_t *src,
 
 static u8*
 fib_entry_src_adj_format (fib_entry_src_t *src,
-                        u8* s)
+                         u8* s)
 {
     return (format(s, "cover:%d", src->adj.fesa_cover));
 }
 
 static void
 fib_entry_src_adj_installed (fib_entry_src_t *src,
-                            const fib_entry_t *fib_entry)
+                             const fib_entry_t *fib_entry)
 {
     /*
      * The adj source now rules! poke our cover to get exported
@@ -161,16 +307,16 @@ fib_entry_src_adj_installed (fib_entry_src_t *src,
     cover = fib_entry_get(src->adj.fesa_cover);
 
     fib_attached_export_covered_added(cover,
-                                     fib_entry_get_index(fib_entry));
+                                      fib_entry_get_index(fib_entry));
 }
 
 static fib_entry_src_cover_res_t
 fib_entry_src_adj_cover_change (fib_entry_src_t *src,
-                               const fib_entry_t *fib_entry)
+                                const fib_entry_t *fib_entry)
 {
     fib_entry_src_cover_res_t res = {
-       .install = !0,
-       .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
+        .install = !0,
+        .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
     };
 
     fib_entry_src_adj_deactivate(src, fib_entry);
@@ -178,10 +324,10 @@ fib_entry_src_adj_cover_change (fib_entry_src_t *src,
     res.install = fib_entry_src_adj_activate(src, fib_entry);
 
     if (res.install) {
-       /*
-        * ADJ fib can install
-        */
-       res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
+        /*
+         * ADJ fib can install
+         */
+        res.bw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE;
     }
 
     return (res);
@@ -196,12 +342,12 @@ fib_entry_src_adj_cover_update (fib_entry_src_t *src,
 {
     /*
      * the cover has updated, i.e. its forwarding or flags
-     * have changed. do'nt decativate/activate here, since this
+     * have changed. don't decativate/activate here, since this
      * prefix is updated during the covers walk.
      */
     fib_entry_src_cover_res_t res = {
-       .install = !0,
-       .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
+        .install = !0,
+        .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
     };
     fib_entry_t *cover;
 
@@ -217,6 +363,8 @@ fib_entry_src_adj_cover_update (fib_entry_src_t *src,
 const static fib_entry_src_vft_t adj_src_vft = {
     .fesv_init = fib_entry_src_adj_init,
     .fesv_path_swap = fib_entry_src_adj_path_swap,
+    .fesv_path_add = fib_entry_src_adj_path_add,
+    .fesv_path_remove = fib_entry_src_adj_path_remove,
     .fesv_remove = fib_entry_src_adj_remove,
     .fesv_activate = fib_entry_src_adj_activate,
     .fesv_deactivate = fib_entry_src_adj_deactivate,
index 19db881..f895886 100644 (file)
  * limitations under the License.
  */
 
-#include "fib_entry.h"
-#include "fib_entry_src.h"
-#include "fib_path_list.h"
+#include <vnet/fib/fib_entry.h>
+#include <vnet/fib/fib_entry_src.h>
+#include <vnet/fib/fib_path_list.h>
+#include <vnet/fib/fib_path_ext.h>
 
 /**
  * Source initialisation Function 
@@ -35,45 +36,94 @@ fib_entry_src_api_deinit (fib_entry_src_t *src)
 
 static void
 fib_entry_src_api_path_swap (fib_entry_src_t *src,
-                            const fib_entry_t *entry,
+                             const fib_entry_t *entry,
                             fib_path_list_flags_t pl_flags,
-                            const fib_route_path_t *paths)
+                            const fib_route_path_t *rpaths)
 {
+    const fib_route_path_t *rpath;
+
+    fib_path_ext_list_flush(&src->fes_path_exts);
+
     src->fes_pl = fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | pl_flags),
-                                      paths);
+                                      rpaths);
+
+    vec_foreach(rpath, rpaths)
+    {
+        if (NULL != rpath->frp_label_stack)
+        {
+            fib_path_ext_list_push_back(&src->fes_path_exts,
+                                        src->fes_pl,
+                                        FIB_PATH_EXT_MPLS,
+                                        rpath);
+        }
+    }
 }
 
 static void
 fib_entry_src_api_path_add (fib_entry_src_t *src,
                            const fib_entry_t *entry,
                            fib_path_list_flags_t pl_flags,
-                           const fib_route_path_t *paths)
+                           const fib_route_path_t *rpaths)
 {
+    const fib_route_path_t *rpath;
+
     if (FIB_NODE_INDEX_INVALID == src->fes_pl)
     {  
        src->fes_pl =
-           fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | pl_flags), paths);
+           fib_path_list_create((FIB_PATH_LIST_FLAG_SHARED | pl_flags), rpaths);
     }
     else
     {
        src->fes_pl =
            fib_path_list_copy_and_path_add(src->fes_pl,
                                            (FIB_PATH_LIST_FLAG_SHARED | pl_flags),
-                                           paths);
+                                           rpaths);
+    }
+
+    /*
+     * re-resolve all the path-extensions with the new path-list
+     */
+    fib_path_ext_list_resolve(&src->fes_path_exts, src->fes_pl);
+
+    /*
+     * if the path has a label we need to add a path extension
+     */
+    vec_foreach(rpath, rpaths)
+    {
+        if (NULL != rpath->frp_label_stack)
+        {
+            fib_path_ext_list_insert(&src->fes_path_exts,
+                                     src->fes_pl,
+                                     FIB_PATH_EXT_MPLS,
+                                     rpath);
+        }
     }
 }
 
 static void
 fib_entry_src_api_path_remove (fib_entry_src_t *src,
                               fib_path_list_flags_t pl_flags,
-                              const fib_route_path_t *paths)
+                              const fib_route_path_t *rpaths)
 {
+    const fib_route_path_t *rpath;
+
     if (FIB_NODE_INDEX_INVALID != src->fes_pl)
     {
        src->fes_pl =
            fib_path_list_copy_and_path_remove(src->fes_pl,
                                               (FIB_PATH_LIST_FLAG_SHARED | pl_flags),
-                                              paths);
+                                              rpaths);
+        /*
+         * remove the path-extension for the path
+         */
+        vec_foreach(rpath, rpaths)
+        {
+            fib_path_ext_list_remove(&src->fes_path_exts, FIB_PATH_EXT_MPLS, rpath);
+        };
+        /*
+         * resolve the remaining extensions
+         */
+        fib_path_ext_list_resolve(&src->fes_path_exts, src->fes_pl);
     }
 }
 
index b47d51f..255f0dd 100644 (file)
@@ -2084,7 +2084,7 @@ fib_path_is_looped (fib_node_index_t path_index)
     return (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP);
 }
 
-int
+fib_path_list_walk_rc_t
 fib_path_encode (fib_node_index_t path_list_index,
                 fib_node_index_t path_index,
                  void *ctx)
@@ -2095,7 +2095,7 @@ fib_path_encode (fib_node_index_t path_list_index,
 
     path = fib_path_get(path_index);
     if (!path)
-      return (0);
+      return (FIB_PATH_LIST_WALK_CONTINUE);
     vec_add2(*api_rpaths, api_rpath, 1);
     api_rpath->rpath.frp_weight = path->fp_weight;
     api_rpath->rpath.frp_proto = path->fp_nh_proto;
@@ -2124,7 +2124,7 @@ fib_path_encode (fib_node_index_t path_list_index,
       default:
         break;
       }
-    return (1);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 fib_protocol_t
index b6bf1e4..0b5e607 100644 (file)
@@ -170,8 +170,8 @@ extern u32 fib_path_get_resolving_interface(fib_node_index_t fib_entry_index);
 extern int fib_path_get_weight(fib_node_index_t path_index);
 
 extern void fib_path_module_init(void);
-extern int fib_path_encode(fib_node_index_t path_list_index,
-                           fib_node_index_t path_index,
-                          void *ctx);
+extern fib_path_list_walk_rc_t fib_path_encode(fib_node_index_t path_list_index,
+                                               fib_node_index_t path_index,
+                                               void *ctx);
 
 #endif
index 08293bc..45ab1f1 100644 (file)
@@ -24,6 +24,8 @@
 #include <vnet/fib/fib_path_list.h>
 #include <vnet/fib/fib_internal.h>
 
+const char *fib_path_ext_adj_flags_names[] = FIB_PATH_EXT_ADJ_ATTR_NAMES;
+
 u8 *
 format_fib_path_ext (u8 * s, va_list * args)
 {
@@ -32,13 +34,37 @@ format_fib_path_ext (u8 * s, va_list * args)
 
     path_ext = va_arg (*args, fib_path_ext_t *);
 
-    s = format(s, "path:%d labels:",
-              path_ext->fpe_path_index);
-    for (ii = 0; ii < vec_len(path_ext->fpe_path.frp_label_stack); ii++)
+    s = format(s, "path:%d ", path_ext->fpe_path_index);
+
+    switch (path_ext->fpe_type)
     {
-       s = format(s, "%U ",
-                  format_mpls_unicast_label,
-                  path_ext->fpe_path.frp_label_stack[ii]);
+    case FIB_PATH_EXT_MPLS:
+        s = format(s, "labels:",
+                   path_ext->fpe_path_index);
+        for (ii = 0; ii < vec_len(path_ext->fpe_path.frp_label_stack); ii++)
+        {
+            s = format(s, "%U ",
+                       format_mpls_unicast_label,
+                       path_ext->fpe_path.frp_label_stack[ii]);
+        }
+        break;
+    case FIB_PATH_EXT_ADJ: {
+        fib_path_ext_adj_attr_t attr;
+
+        s = format(s, "adj-flags:");
+        if (path_ext->fpe_adj_flags)
+        {
+            FOR_EACH_PATH_EXT_ADJ_ATTR(attr)
+            {
+                s = format(s, "%s", fib_path_ext_adj_flags_names[attr]);
+            }
+        }
+        else
+        {
+            s = format(s, "None");
+        }
+        break;
+    }
     }
     return (s);
 }
@@ -50,7 +76,7 @@ fib_path_ext_cmp (fib_path_ext_t *path_ext,
     return (fib_route_path_cmp(&path_ext->fpe_path, rpath));
 }
 
-static int
+static fib_path_list_walk_rc_t
 fib_path_ext_match (fib_node_index_t pl_index,
                    fib_node_index_t path_index,
                    void *ctx)
@@ -61,10 +87,9 @@ fib_path_ext_match (fib_node_index_t pl_index,
                                   &path_ext->fpe_path))
     {
        path_ext->fpe_path_index = path_index;
-       return (0);
+       return (FIB_PATH_LIST_WALK_STOP);
     }
-    // keep going
-    return (1);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 void
@@ -83,10 +108,13 @@ fib_path_ext_resolve (fib_path_ext_t *path_ext,
 void
 fib_path_ext_init (fib_path_ext_t *path_ext,
                   fib_node_index_t path_list_index,
+                   fib_path_ext_type_t ext_type,
                   const fib_route_path_t *rpath)
 {
     path_ext->fpe_path = *rpath;
     path_ext->fpe_path_index = FIB_NODE_INDEX_INVALID;
+    path_ext->fpe_adj_flags = FIB_PATH_EXT_ADJ_FLAG_NONE;
+    path_ext->fpe_type = ext_type;
 
     fib_path_ext_resolve(path_ext, path_list_index);
 }
@@ -229,3 +257,168 @@ fib_path_ext_stack (fib_path_ext_t *path_ext,
 
     return (nhs);
 }
+
+fib_path_ext_t *
+fib_path_ext_list_find (const fib_path_ext_list_t *list,
+                        fib_path_ext_type_t ext_type,
+                        const fib_route_path_t *rpath)
+{
+    fib_path_ext_t *path_ext;
+
+    vec_foreach(path_ext, list->fpel_exts)
+    {
+        if ((path_ext->fpe_type == ext_type) &&
+            !fib_path_ext_cmp(path_ext, rpath) )
+        {
+            return (path_ext);
+        }
+    }
+    return (NULL);
+}
+
+fib_path_ext_t *
+fib_path_ext_list_find_by_path_index (const fib_path_ext_list_t *list,
+                                      fib_node_index_t path_index)
+{
+    fib_path_ext_t *path_ext;
+
+    vec_foreach(path_ext, list->fpel_exts)
+    {
+        if (path_ext->fpe_path_index == path_index)
+        {
+            return (path_ext);
+        }
+    }
+    return (NULL);
+}
+
+
+fib_path_ext_t *
+fib_path_ext_list_push_back (fib_path_ext_list_t *list,
+                             fib_node_index_t path_list_index,
+                             fib_path_ext_type_t ext_type,
+                             const fib_route_path_t *rpath)
+{
+    fib_path_ext_t *path_ext;
+
+    path_ext = fib_path_ext_list_find(list, ext_type, rpath);
+
+    if (NULL == path_ext)
+    {
+        vec_add2(list->fpel_exts, path_ext, 1);
+        fib_path_ext_init(path_ext, path_list_index, ext_type, rpath);
+    }
+
+    return (path_ext);
+}
+
+/*
+ * insert, sorted, a path extension to the entry's list.
+ * It's not strictly necessary to sort the path extensions, since each
+ * extension has the path index to which it resolves. However, by being
+ * sorted the load-balance produced has a deterministic order, not an order
+ * based on the sequence of extension additions. this is a considerable benefit.
+ */
+fib_path_ext_t *
+fib_path_ext_list_insert (fib_path_ext_list_t *list,
+                          fib_node_index_t path_list_index,
+                          fib_path_ext_type_t ext_type,
+                          const fib_route_path_t *rpath)
+{
+    fib_path_ext_t new_path_ext, *path_ext;
+    int i = 0;
+
+    if (0 == fib_path_ext_list_length(list))
+    {
+        return (fib_path_ext_list_push_back(list, path_list_index,
+                                            ext_type, rpath));
+    }
+
+    fib_path_ext_init(&new_path_ext, path_list_index, ext_type, rpath);
+
+    vec_foreach(path_ext, list->fpel_exts)
+    {
+        if (fib_path_ext_cmp(path_ext, rpath) < 0)
+        {
+            i++;
+        }
+        else
+        {
+            break;
+        }
+    }
+    vec_insert_elts(list->fpel_exts, &new_path_ext, 1, i);
+
+    return (&(list->fpel_exts[i]));
+}
+
+void
+fib_path_ext_list_resolve (fib_path_ext_list_t *list,
+                           fib_node_index_t path_list_index)
+{
+    fib_path_ext_t *path_ext;
+
+    vec_foreach(path_ext, list->fpel_exts)
+    {
+        fib_path_ext_resolve(path_ext, path_list_index);
+    };
+}
+
+void
+fib_path_ext_list_remove (fib_path_ext_list_t *list,
+                          fib_path_ext_type_t ext_type,
+                          const fib_route_path_t *rpath)
+{
+    fib_path_ext_t *path_ext;
+
+    path_ext = fib_path_ext_list_find(list, ext_type, rpath);
+
+    if (NULL != path_ext)
+    {
+        /*
+         * delete the element moving the remaining elements down 1 position.
+         * this preserves the sorted order.
+         */
+        vec_free(path_ext->fpe_label_stack);
+        vec_delete(list->fpel_exts, 1, (path_ext - list->fpel_exts));
+    }
+}
+
+void
+fib_path_ext_list_flush (fib_path_ext_list_t *list)
+{
+    fib_path_ext_t *path_ext;
+
+    vec_foreach(path_ext, list->fpel_exts)
+    {
+        vec_free(path_ext->fpe_label_stack);
+    };
+    vec_free(list->fpel_exts);
+    list->fpel_exts = NULL;
+}
+
+u8*
+format_fib_path_ext_list (u8 * s, va_list * args)
+{
+    fib_path_ext_list_t *list;
+    fib_path_ext_t *path_ext;
+
+    list = va_arg (*args, fib_path_ext_list_t *);
+
+    if (fib_path_ext_list_length(list))
+    {
+        s = format(s, "    Extensions:");
+        vec_foreach(path_ext, list->fpel_exts)
+        {
+            s = format(s, "\n     %U", format_fib_path_ext, path_ext);
+        };
+    }
+
+    return (s);
+}
+
+int
+fib_path_ext_list_length (const fib_path_ext_list_t *list)
+{
+    return (vec_len(list->fpel_exts));
+}
index d617700..d1571a1 100644 (file)
 #include <vnet/fib/fib_types.h>
 #include <vnet/dpo/load_balance.h>
 
+/**
+ * A description of the type of path extension
+ */
+typedef enum fib_path_ext_type_t_
+{
+    /**
+     * An MPLS extension that maintains the path's outgoing labels,
+     */
+    FIB_PATH_EXT_MPLS,
+    /**
+     * A adj-source extension indicating the path's refinement criteria
+     * result
+     */
+    FIB_PATH_EXT_ADJ,
+} fib_path_ext_type_t;
+
+/**
+ * Flags present on an ADJ sourced path-extension
+ */
+typedef enum fib_path_ext_adj_attr_t_
+{
+    FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER,
+} fib_path_ext_adj_attr_t;
+
+typedef enum fib_path_ext_adj_flags_t_
+{
+    FIB_PATH_EXT_ADJ_FLAG_NONE = 0,
+    FIB_PATH_EXT_ADJ_FLAG_REFINES_COVER = (1 << FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER),
+} fib_path_ext_adj_flags_t;
+
+#define FIB_PATH_EXT_ADJ_ATTR_NAMES {                               \
+    [FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER] = "refines-cover",        \
+}
+
+#define FOR_EACH_PATH_EXT_ADJ_ATTR(_item)               \
+    for (_item = FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER;   \
+         _item <= FIB_PATH_EXT_ADJ_ATTR_REFINES_COVER;  \
+         _item++)
+
 /**
  * A path extension is a per-entry addition to the forwarding information
  * when packets are sent for that entry over that path.
  */
 typedef struct fib_path_ext_t_
 {
+    /**
+     * The type of path extension
+     */
+    fib_path_ext_type_t fpe_type;
+
     /**
      * A description of the path that is being extended.
      * This description is used to match this extension with the [changing]
@@ -40,21 +84,24 @@ typedef struct fib_path_ext_t_
     fib_route_path_t fpe_path;
 #define fpe_label_stack fpe_path.frp_label_stack
 
+    union {
+        /**
+         * For an ADJ type extension
+         *
+         * Flags describing the adj state
+         */
+        fib_path_ext_adj_flags_t fpe_adj_flags;
+    };
+
     /**
      * The index of the path. This is the global index, not the path's
      * position in the path-list.
      */
     fib_node_index_t fpe_path_index;
-} fib_path_ext_t;
-
-struct fib_entry_t_;
+} __attribute__ ((packed))  fib_path_ext_t;
 
 extern u8 * format_fib_path_ext(u8 * s, va_list * args);
 
-extern void fib_path_ext_init(fib_path_ext_t *path_ext,
-                             fib_node_index_t path_list_index,
-                             const fib_route_path_t *rpath);
-
 extern int fib_path_ext_cmp(fib_path_ext_t *path_ext,
                            const fib_route_path_t *rpath);
 
@@ -66,5 +113,32 @@ extern load_balance_path_t *fib_path_ext_stack(fib_path_ext_t *path_ext,
                                                fib_forward_chain_type_t imp_null_fct,
                                                load_balance_path_t *nhs);
 
+extern fib_path_ext_t * fib_path_ext_list_push_back (fib_path_ext_list_t *list,
+                                                     fib_node_index_t path_list_index,
+                                                     fib_path_ext_type_t ext_type,
+                                                     const fib_route_path_t *rpath);
+
+extern fib_path_ext_t * fib_path_ext_list_insert (fib_path_ext_list_t *list,
+                                                  fib_node_index_t path_list_index,
+                                                  fib_path_ext_type_t ext_type,
+                                                  const fib_route_path_t *rpath);
+
+extern u8* format_fib_path_ext_list (u8 * s, va_list * args);
+
+extern void fib_path_ext_list_remove (fib_path_ext_list_t *list,
+                                      fib_path_ext_type_t ext_type,
+                                      const fib_route_path_t *rpath);
+
+extern fib_path_ext_t * fib_path_ext_list_find (const fib_path_ext_list_t *list,
+                                                fib_path_ext_type_t ext_type,
+                                                const fib_route_path_t *rpath);
+extern fib_path_ext_t * fib_path_ext_list_find_by_path_index (const fib_path_ext_list_t *list,
+                                                              fib_node_index_t path_index);
+extern void fib_path_ext_list_resolve(fib_path_ext_list_t *list,
+                                      fib_node_index_t path_list_index);
+
+extern int fib_path_ext_list_length(const fib_path_ext_list_t *list);
+extern void fib_path_ext_list_flush(fib_path_ext_list_t *list);
+
 #endif
 
index 64917f9..3e4c333 100644 (file)
@@ -914,21 +914,32 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index,
      * If we find one then we can return the existing one and destroy the
      * new one just created.
      */
-    exist_path_list_index = fib_path_list_db_find(path_list);
-    if (FIB_NODE_INDEX_INVALID != exist_path_list_index)
+    if (path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED)
     {
-        fib_path_list_destroy(path_list);
+        exist_path_list_index = fib_path_list_db_find(path_list);
+        if (FIB_NODE_INDEX_INVALID != exist_path_list_index)
+        {
+            fib_path_list_destroy(path_list);
        
-        path_list_index = exist_path_list_index;
+            path_list_index = exist_path_list_index;
+        }
+        else
+        {
+            /*
+             * if there was not a matching path-list, then this
+             * new one will need inserting into the DB and resolving.
+             */
+            fib_path_list_db_insert(path_list_index);
+
+            path_list = fib_path_list_resolve(path_list);
+        }
     }
     else
     {
         /*
-         * if there was not a matching path-list, then this
-         * new one will need inserting into the DB and resolving.
+         * no shared path list requested. resolve and use the one
+         * just created.
          */
-        fib_path_list_db_insert(path_list_index);
-
         path_list = fib_path_list_resolve(path_list);
     }
 
@@ -1289,7 +1300,9 @@ fib_path_list_walk (fib_node_index_t path_list_index,
 
     vec_foreach(path_index, path_list->fpl_paths)
     {
-       if (!func(path_list_index, *path_index, ctx))
+       if (FIB_PATH_LIST_WALK_STOP == func(path_list_index,
+                                            *path_index,
+                                            ctx))
            break;
     }
 }
index 376cb72..b4b6985 100644 (file)
@@ -19,8 +19,8 @@
 #include <vlib/vlib.h>
 #include <vnet/adj/adj.h>
 
-#include "fib_node.h"
-#include "fib_path.h"
+#include <vnet/fib/fib_node.h>
+#include <vnet/fib/fib_path.h>
 
 /**
  * Enumeration of path-list flags.
@@ -161,9 +161,10 @@ extern u32 fib_path_list_find_rpath (fib_node_index_t path_list_index,
 /**
  * A callback function type for walking a path-list's paths
  */
-typedef int (*fib_path_list_walk_fn_t)(fib_node_index_t pl_index,
-                                      fib_node_index_t path_index,
-                                      void *ctx);
+typedef fib_path_list_walk_rc_t (*fib_path_list_walk_fn_t)(
+    fib_node_index_t pl_index,
+    fib_node_index_t path_index,
+    void *ctx);
 
 extern void fib_path_list_walk(fib_node_index_t pl_index,
                               fib_path_list_walk_fn_t func,
index 486e561..06aeda6 100644 (file)
@@ -846,7 +846,8 @@ fib_test_v4 (void)
             "Flags set on attached interface");
 
     ai = fib_entry_get_adj(fei);
-    FIB_TEST((FIB_NODE_INDEX_INVALID != ai), "attached interface route adj present");
+    FIB_TEST((FIB_NODE_INDEX_INVALID != ai),
+             "attached interface route adj present %d", ai);
     adj = adj_get(ai);
     FIB_TEST((IP_LOOKUP_NEXT_GLEAN == adj->lookup_next_index),
             "attached interface adj is glean");
@@ -1089,21 +1090,21 @@ fib_test_v4 (void)
     /*
      * add the adj fib
      */
-    fei = fib_table_entry_update_one_path(fib_index,
-                                          &pfx_10_10_10_1_s_32,
-                                          FIB_SOURCE_ADJ,
-                                          FIB_ENTRY_FLAG_ATTACHED,
-                                         FIB_PROTOCOL_IP4,
-                                          &pfx_10_10_10_1_s_32.fp_addr,
-                                          tm->hw[0]->sw_if_index,
-                                          ~0, // invalid fib index
-                                          1,
-                                          NULL,
-                                          FIB_ROUTE_PATH_FLAG_NONE);
+    fei = fib_table_entry_path_add(fib_index,
+                                   &pfx_10_10_10_1_s_32,
+                                   FIB_SOURCE_ADJ,
+                                   FIB_ENTRY_FLAG_ATTACHED,
+                                   FIB_PROTOCOL_IP4,
+                                   &pfx_10_10_10_1_s_32.fp_addr,
+                                   tm->hw[0]->sw_if_index,
+                                   ~0, // invalid fib index
+                                   1,
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
     FIB_TEST((FIB_ENTRY_FLAG_ATTACHED  == fib_entry_get_flags(fei)),
             "Flags set on adj-fib");
     ai = fib_entry_get_adj(fei);
-    FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj");
+    FIB_TEST((ai_01 == ai), "ADJ-FIB resolves via adj, %d", ai);
 
     fib_table_entry_path_remove(fib_index,
                                 &pfx_11_11_11_11_s_32,
@@ -1138,17 +1139,17 @@ fib_test_v4 (void)
              "adj nbr next-hop ok");
     FIB_TEST((ai_01 != ai_02), "ADJs are different");
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_10_10_10_2_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_10_10_10_2_s_32.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_10_10_10_2_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_10_10_10_2_s_32.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup(fib_index, &pfx_10_10_10_2_s_32);
     ai = fib_entry_get_adj(fei);
@@ -1644,13 +1645,13 @@ fib_test_v4 (void)
            .ip4.as_u32 = clib_host_to_net_u32(0x06060606),
        },
     };
-    fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_1 = {
+    fib_test_lb_bucket_t ip_o_10_10_10_1 = {
        .type = FT_LB_ADJ,
        .adj = {
            .adj = ai_01,
        },
     };
-    fib_test_lb_bucket_t ip_6_6_6_6_o_10_10_10_2 = {
+    fib_test_lb_bucket_t ip_o_10_10_10_2 = {
         .type = FT_LB_ADJ,
         .adj = {
             .adj = ai_02,
@@ -1678,7 +1679,7 @@ fib_test_v4 (void)
     FIB_TEST(fib_test_validate_entry(fei,
                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
                                     1,
-                                    &ip_6_6_6_6_o_10_10_10_1),
+                                    &ip_o_10_10_10_1),
             "6.6.6.6/32 via 10.10.10.1");
 
     fib_table_entry_path_add(fib_index,
@@ -1697,70 +1698,70 @@ fib_test_v4 (void)
     FIB_TEST(fib_test_validate_entry(fei,
                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
                                     64,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_1),
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_1),
             "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
 
     fib_table_entry_path_add(fib_index,
@@ -1779,71 +1780,71 @@ fib_test_v4 (void)
     FIB_TEST(fib_test_validate_entry(fei,
                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
                                     128,
-                                    &ip_6_6_6_6_o_10_10_10_1,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
+                                    &ip_o_10_10_10_1,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
                                     &ip_6_6_6_6_o_12_12_12_12,
                                     &ip_6_6_6_6_o_12_12_12_12,
                                     &ip_6_6_6_6_o_12_12_12_12,
@@ -1923,70 +1924,70 @@ fib_test_v4 (void)
     FIB_TEST(fib_test_validate_entry(fei,
                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
                                     64,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_2,
-                                    &ip_6_6_6_6_o_10_10_10_1),
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_2,
+                                    &ip_o_10_10_10_1),
             "6.6.6.6/32 via 10.10.10.1 and 10.10.10.2 in 63:1 ratio");
 
     fib_table_entry_path_remove(fib_index,
@@ -2003,7 +2004,7 @@ fib_test_v4 (void)
     FIB_TEST(fib_test_validate_entry(fei,
                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
                                     1,
-                                    &ip_6_6_6_6_o_10_10_10_1),
+                                    &ip_o_10_10_10_1),
             "6.6.6.6/32 via 10.10.10.1");
 
     fib_table_entry_delete(fib_index, &pfx_6_6_6_6_s_32, FIB_SOURCE_API);
@@ -3808,17 +3809,17 @@ fib_test_v4 (void)
        },
     };
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_12_10_10_2_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_12_10_10_2_s_32.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_12_10_10_2_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_12_10_10_2_s_32.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup_exact_match(fib_index, &pfx_12_10_10_2_s_32);
     dpo = fib_entry_contribute_ip_forwarding(fei);
@@ -3842,17 +3843,17 @@ fib_test_v4 (void)
        },
     };
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_10_10_10_127_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_10_10_10_127_s_32.fp_addr,
-                                   tm->hw[1]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_10_10_10_127_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_10_10_10_127_s_32.fp_addr,
+                             tm->hw[1]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_127_s_32);
     dpo = fib_entry_contribute_ip_forwarding(fei);
@@ -3862,6 +3863,134 @@ fib_test_v4 (void)
     fib_table_entry_delete(fib_index,
                           &pfx_10_10_10_127_s_32,
                           FIB_SOURCE_ADJ);
+
+    /*
+     * add a second path to an adj-fib
+     * this is a sumiluation of another ARP entry created
+     * on an interface on which the connected prefi does not exist.
+     * The second path fails refinement. Expect to forward through the
+     * first.
+     */
+    fib_prefix_t pfx_10_10_10_3_s_32 = {
+        .fp_len = 32,
+        .fp_proto = FIB_PROTOCOL_IP4,
+        .fp_addr = {
+            /* 10.10.10.3 */
+            .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a03),
+        },
+    };
+
+    ai_03 = adj_nbr_add_or_lock(FIB_PROTOCOL_IP4,
+                                VNET_LINK_IP4,
+                                &nh_10_10_10_3,
+                                tm->hw[0]->sw_if_index);
+
+    fib_test_lb_bucket_t ip_o_10_10_10_3 = {
+        .type = FT_LB_ADJ,
+        .adj = {
+            .adj = ai_03,
+        },
+    };
+    fei = fib_table_entry_path_add(fib_index,
+                                   &pfx_10_10_10_3_s_32,
+                                   FIB_SOURCE_ADJ,
+                                   FIB_ENTRY_FLAG_NONE,
+                                   FIB_PROTOCOL_IP4,
+                                   &nh_10_10_10_3,
+                                   tm->hw[0]->sw_if_index,
+                                   fib_index,
+                                   1,
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fei = fib_table_entry_path_add(fib_index,
+                                   &pfx_10_10_10_3_s_32,
+                                   FIB_SOURCE_ADJ,
+                                   FIB_ENTRY_FLAG_NONE,
+                                   FIB_PROTOCOL_IP4,
+                                   &nh_12_12_12_12,
+                                   tm->hw[1]->sw_if_index,
+                                   fib_index,
+                                   1,
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
+    FIB_TEST(fib_test_validate_entry(fei,
+                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+                                     1,
+                                     &ip_o_10_10_10_3),
+             "10.10.10.3 via 10.10.10.3/Eth0 only");
+
+    /*
+     * remove the path that refines the cover, should go unresolved
+     */
+    fib_table_entry_path_remove(fib_index,
+                                &pfx_10_10_10_3_s_32,
+                                FIB_SOURCE_ADJ,
+                                FIB_PROTOCOL_IP4,
+                                &nh_10_10_10_3,
+                                tm->hw[0]->sw_if_index,
+                                fib_index,
+                                1,
+                                FIB_ROUTE_PATH_FLAG_NONE);
+    dpo = fib_entry_contribute_ip_forwarding(fei);
+    FIB_TEST(!dpo_id_is_valid(dpo),
+             "wrong interface adj-fib fails refinement");
+
+    /*
+     * add back the path that refines the cover
+     */
+    fei = fib_table_entry_path_add(fib_index,
+                                   &pfx_10_10_10_3_s_32,
+                                   FIB_SOURCE_ADJ,
+                                   FIB_ENTRY_FLAG_NONE,
+                                   FIB_PROTOCOL_IP4,
+                                   &nh_10_10_10_3,
+                                   tm->hw[0]->sw_if_index,
+                                   fib_index,
+                                   1,
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
+    FIB_TEST(fib_test_validate_entry(fei,
+                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+                                     1,
+                                     &ip_o_10_10_10_3),
+             "10.10.10.3 via 10.10.10.3/Eth0 only");
+
+    /*
+     * remove the path that does not refine the cover
+     */
+    fib_table_entry_path_remove(fib_index,
+                                &pfx_10_10_10_3_s_32,
+                                FIB_SOURCE_ADJ,
+                                FIB_PROTOCOL_IP4,
+                                &nh_12_12_12_12,
+                                tm->hw[1]->sw_if_index,
+                                fib_index,
+                                1,
+                                FIB_ROUTE_PATH_FLAG_NONE);
+    FIB_TEST(fib_test_validate_entry(fei,
+                                     FIB_FORW_CHAIN_TYPE_UNICAST_IP4,
+                                     1,
+                                     &ip_o_10_10_10_3),
+             "10.10.10.3 via 10.10.10.3/Eth0 only");
+
+    /*
+     * remove the path that does refine, it's the last path, so
+     * the entry should be gone
+     */
+    fib_table_entry_path_remove(fib_index,
+                                &pfx_10_10_10_3_s_32,
+                                FIB_SOURCE_ADJ,
+                                FIB_PROTOCOL_IP4,
+                                &nh_10_10_10_3,
+                                tm->hw[0]->sw_if_index,
+                                fib_index,
+                                1,
+                                FIB_ROUTE_PATH_FLAG_NONE);
+    fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
+    FIB_TEST((fei == FIB_NODE_INDEX_INVALID), "10.10.10.3 gone");
+
+    adj_unlock(ai_03);
+
     /*
      * change the table's flow-hash config - expect the update to propagete to
      * the entries' load-balance objects
@@ -4283,17 +4412,17 @@ fib_test_v6 (void)
                                    &adj->sub_type.nbr.next_hop)),
              "adj nbr next-hop ok");
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_2001_1_2_s_128,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP6,
-                                   &pfx_2001_1_2_s_128.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0,
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_2001_1_2_s_128,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP6,
+                             &pfx_2001_1_2_s_128.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0,
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup(fib_index, &pfx_2001_1_2_s_128);
     ai = fib_entry_get_adj(fei);
@@ -4322,17 +4451,17 @@ fib_test_v6 (void)
              "adj nbr next-hop ok");
     FIB_TEST((ai_01 != ai_02), "ADJs are different");
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_2001_1_3_s_128,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP6,
-                                   &pfx_2001_1_3_s_128.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0,
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_2001_1_3_s_128,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP6,
+                             &pfx_2001_1_3_s_128.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0,
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup(fib_index, &pfx_2001_1_3_s_128);
     ai = fib_entry_get_adj(fei);
@@ -4957,17 +5086,17 @@ fib_test_ae (void)
     };
     fib_node_index_t ai;
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_10_10_10_1_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_10_10_10_1_s_32.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_10_10_10_1_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_10_10_10_1_s_32.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     fei = fib_table_lookup(fib_index, &pfx_10_10_10_1_s_32);
     FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib1 created");
@@ -5026,17 +5155,17 @@ fib_test_ae (void)
        },
     };
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_10_10_10_2_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_10_10_10_2_s_32.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_10_10_10_2_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_10_10_10_2_s_32.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
     fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_2_s_32);
     FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib2 present");
     ai = fib_entry_get_adj(fei);
@@ -5097,17 +5226,17 @@ fib_test_ae (void)
        },
     };
 
-    fib_table_entry_update_one_path(fib_index,
-                                   &pfx_10_10_10_3_s_32,
-                                   FIB_SOURCE_ADJ,
-                                   FIB_ENTRY_FLAG_ATTACHED,
-                                   FIB_PROTOCOL_IP4,
-                                   &pfx_10_10_10_3_s_32.fp_addr,
-                                   tm->hw[0]->sw_if_index,
-                                   ~0, // invalid fib index
-                                   1,
-                                   NULL,
-                                   FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(fib_index,
+                             &pfx_10_10_10_3_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &pfx_10_10_10_3_s_32.fp_addr,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
     fei = fib_table_lookup_exact_match(fib_index, &pfx_10_10_10_3_s_32);
     FIB_TEST((FIB_NODE_INDEX_INVALID != fei), "ADJ-fib3 present");
     ai = fib_entry_get_adj(fei);
@@ -7144,17 +7273,17 @@ fib_test_bfd (void)
     /*
      * source the entry via the ADJ fib
      */
-    fei = fib_table_entry_update_one_path(0,
-                                          &pfx_10_10_10_1_s_32,
-                                          FIB_SOURCE_ADJ,
-                                          FIB_ENTRY_FLAG_ATTACHED,
-                                          FIB_PROTOCOL_IP4,
-                                          &nh_10_10_10_1,
-                                          tm->hw[0]->sw_if_index,
-                                          ~0, // invalid fib index
-                                          1,
-                                          NULL,
-                                          FIB_ROUTE_PATH_FLAG_NONE);
+    fei = fib_table_entry_path_add(0,
+                                   &pfx_10_10_10_1_s_32,
+                                   FIB_SOURCE_ADJ,
+                                   FIB_ENTRY_FLAG_ATTACHED,
+                                   FIB_PROTOCOL_IP4,
+                                   &nh_10_10_10_1,
+                                   tm->hw[0]->sw_if_index,
+                                   ~0, // invalid fib index
+                                   1,
+                                   NULL,
+                                   FIB_ROUTE_PATH_FLAG_NONE);
 
     /*
      * Delete the BFD session. Expect the fib_entry to remain
@@ -7183,17 +7312,17 @@ fib_test_bfd (void)
         .fp_len = 32,
         .fp_proto = FIB_PROTOCOL_IP4,
     };
-    fib_table_entry_update_one_path(0,
-                                    &pfx_10_10_10_2_s_32,
-                                    FIB_SOURCE_ADJ,
-                                    FIB_ENTRY_FLAG_ATTACHED,
-                                    FIB_PROTOCOL_IP4,
-                                    &nh_10_10_10_2,
-                                    tm->hw[0]->sw_if_index,
-                                    ~0, // invalid fib index
-                                    1,
-                                    NULL,
-                                    FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(0,
+                             &pfx_10_10_10_2_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &nh_10_10_10_2,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
     /*
      * A BFD session for the new ADJ FIB
      */
@@ -7215,17 +7344,17 @@ fib_test_bfd (void)
      * then add it back
      */
     fib_table_entry_delete(0, &pfx_10_10_10_2_s_32, FIB_SOURCE_ADJ);
-    fib_table_entry_update_one_path(0,
-                                    &pfx_10_10_10_2_s_32,
-                                    FIB_SOURCE_ADJ,
-                                    FIB_ENTRY_FLAG_ATTACHED,
-                                    FIB_PROTOCOL_IP4,
-                                    &nh_10_10_10_2,
-                                    tm->hw[0]->sw_if_index,
-                                    ~0, // invalid fib index
-                                    1,
-                                    NULL,
-                                    FIB_ROUTE_PATH_FLAG_NONE);
+    fib_table_entry_path_add(0,
+                             &pfx_10_10_10_2_s_32,
+                             FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             FIB_PROTOCOL_IP4,
+                             &nh_10_10_10_2,
+                             tm->hw[0]->sw_if_index,
+                             ~0, // invalid fib index
+                             1,
+                             NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
 
     /*
      * Before adding a recursive via the BFD tracked ADJ-FIBs,
index 4cb73e8..60873c4 100644 (file)
@@ -400,4 +400,21 @@ typedef struct fib_route_path_encode_t_ {
     dpo_id_t dpo;
 } fib_route_path_encode_t;
 
+/**
+ * return code to control pat-hlist walk
+ */
+typedef enum fib_path_list_walk_rc_t_
+{
+    FIB_PATH_LIST_WALK_STOP,
+    FIB_PATH_LIST_WALK_CONTINUE,
+} fib_path_list_walk_rc_t;
+
+/**
+ * A list of path-extensions
+ */
+typedef struct fib_path_ext_list_t_
+{
+    struct fib_path_ext_t_ *fpel_exts;
+} fib_path_ext_list_t;
+
 #endif
index 4fd078d..e140c55 100644 (file)
@@ -630,12 +630,12 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
 
          fib_index = ip6_main.fib_index_by_sw_if_index[n->key.sw_if_index];
          n->fib_entry_index =
-           fib_table_entry_update_one_path (fib_index, &pfx,
-                                            FIB_SOURCE_ADJ,
-                                            FIB_ENTRY_FLAG_ATTACHED,
-                                            FIB_PROTOCOL_IP6, &pfx.fp_addr,
-                                            n->key.sw_if_index, ~0, 1, NULL,
-                                            FIB_ROUTE_PATH_FLAG_NONE);
+           fib_table_entry_path_add (fib_index, &pfx,
+                                     FIB_SOURCE_ADJ,
+                                     FIB_ENTRY_FLAG_ATTACHED,
+                                     FIB_PROTOCOL_IP6, &pfx.fp_addr,
+                                     n->key.sw_if_index, ~0, 1, NULL,
+                                     FIB_ROUTE_PATH_FLAG_NONE);
        }
       else
        {
index a937842..49792f0 100644 (file)
@@ -527,7 +527,7 @@ typedef struct mfib_entry_collect_forwarding_ctx_t_
     mfib_entry_src_t *msrc;
 } mfib_entry_collect_forwarding_ctx_t;
 
-static int
+static fib_path_list_walk_rc_t
 mfib_entry_src_collect_forwarding (fib_node_index_t pl_index,
                                    fib_node_index_t path_index,
                                    void *arg)
@@ -542,7 +542,7 @@ mfib_entry_src_collect_forwarding (fib_node_index_t pl_index,
      */
     if (!fib_path_is_resolved(path_index))
     {
-        return (!0);
+        return (FIB_PATH_LIST_WALK_CONTINUE);
     }
 
     /*
@@ -556,7 +556,7 @@ mfib_entry_src_collect_forwarding (fib_node_index_t pl_index,
     if (NULL != path_ext &&
         !(path_ext->mfpe_flags & MFIB_ITF_FLAG_FORWARD))
     {
-        return (!0);
+        return (FIB_PATH_LIST_WALK_CONTINUE);
     }
     
     switch (ctx->fct)
@@ -583,7 +583,7 @@ mfib_entry_src_collect_forwarding (fib_node_index_t pl_index,
         break;
     }
 
-    return (!0);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 static void
index 457d48e..d6e85e7 100644 (file)
@@ -99,14 +99,13 @@ typedef struct mpls_tunnel_collect_forwarding_ctx_t_
     fib_forward_chain_type_t fct;
 } mpls_tunnel_collect_forwarding_ctx_t;
 
-static int
+static fib_path_list_walk_rc_t
 mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
                                 fib_node_index_t path_index,
                                 void *arg)
 {
     mpls_tunnel_collect_forwarding_ctx_t *ctx;
     fib_path_ext_t *path_ext;
-    int have_path_ext;
 
     ctx = arg;
 
@@ -115,23 +114,16 @@ mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
      */
     if (!fib_path_is_resolved(path_index))
     {
-        return (!0);
+        return (FIB_PATH_LIST_WALK_CONTINUE);
     }
 
     /*
      * get the matching path-extension for the path being visited.
      */
-    have_path_ext = 0;
-    vec_foreach(path_ext, ctx->mt->mt_path_exts)
-    {
-        if (path_ext->fpe_path_index == path_index)
-        {
-            have_path_ext = 1;
-            break;
-        }
-    }
+    path_ext = fib_path_ext_list_find_by_path_index(&ctx->mt->mt_path_exts,
+                                                    path_index);
 
-    if (have_path_ext)
+    if (NULL != path_ext)
     {
         /*
          * found a matching extension. stack it to obtain the forwarding
@@ -149,7 +141,7 @@ mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
      *   There should be a path-extenios associated with each path
      */
 
-    return (!0);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 static void
@@ -648,58 +640,6 @@ vnet_mpls_tunnel_create (u8 l2_only,
     return (mt->mt_sw_if_index);
 }
 
-/*
- * mpls_tunnel_path_ext_add
- *
- * append a path extension to the entry's list
- */
-static void
-mpls_tunnel_path_ext_append (mpls_tunnel_t *mt,
-                             const fib_route_path_t *rpath)
-{
-    if (NULL != rpath->frp_label_stack)
-    {
-        fib_path_ext_t *path_ext;
-
-        vec_add2(mt->mt_path_exts, path_ext, 1);
-
-        fib_path_ext_init(path_ext, mt->mt_path_list, rpath);
-    }
-}
-
-/*
- * mpls_tunnel_path_ext_insert
- *
- * insert, sorted, a path extension to the entry's list.
- * It's not strictly necessary in sort the path extensions, since each
- * extension has the path index to which it resolves. However, by being
- * sorted the load-balance produced has a deterministic order, not an order
- * based on the sequence of extension additions. this is a considerable benefit.
- */
-static void
-mpls_tunnel_path_ext_insert (mpls_tunnel_t *mt,
-                             const fib_route_path_t *rpath)
-{
-    if (0 == vec_len(mt->mt_path_exts))
-        return (mpls_tunnel_path_ext_append(mt, rpath));
-
-    if (NULL != rpath->frp_label_stack)
-    {
-        fib_path_ext_t path_ext;
-        int i = 0;
-
-        fib_path_ext_init(&path_ext, mt->mt_path_list, rpath);
-
-        while (i < vec_len(mt->mt_path_exts) &&
-               (fib_path_ext_cmp(&mt->mt_path_exts[i], rpath) < 0))
-        {
-            i++;
-        }
-
-        vec_insert_elts(mt->mt_path_exts, &path_ext, 1, i);
-    }
-}
-
 void
 vnet_mpls_tunnel_path_add (u32 sw_if_index,
                            fib_route_path_t *rpaths)
@@ -727,7 +667,6 @@ vnet_mpls_tunnel_path_add (u32 sw_if_index,
     else
     {
         fib_node_index_t old_pl_index;
-        fib_path_ext_t *path_ext;
 
         old_pl_index = mt->mt_path_list;
 
@@ -744,12 +683,12 @@ vnet_mpls_tunnel_path_add (u32 sw_if_index,
         /*
          * re-resolve all the path-extensions with the new path-list
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            fib_path_ext_resolve(path_ext, mt->mt_path_list);
-        }
+        fib_path_ext_list_resolve(&mt->mt_path_exts, mt->mt_path_list);
     }
-    mpls_tunnel_path_ext_insert(mt, rpaths);
+    fib_path_ext_list_insert(&mt->mt_path_exts,
+                             mt->mt_path_list,
+                             FIB_PATH_EXT_MPLS,
+                             rpaths);
     mpls_tunnel_restack(mt);
 }
 
@@ -778,7 +717,6 @@ vnet_mpls_tunnel_path_remove (u32 sw_if_index,
     else
     {
         fib_node_index_t old_pl_index;
-        fib_path_ext_t *path_ext;
 
         old_pl_index = mt->mt_path_list;
 
@@ -805,27 +743,15 @@ vnet_mpls_tunnel_path_remove (u32 sw_if_index,
         /*
          * find the matching path extension and remove it
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            if (!fib_path_ext_cmp(path_ext, rpaths))
-            {
-                /*
-                 * delete the element moving the remaining elements down 1 position.
-                 * this preserves the sorted order.
-                 */
-                vec_free(path_ext->fpe_label_stack);
-                vec_delete(mt->mt_path_exts, 1,
-                           (path_ext - mt->mt_path_exts));
-                break;
-            }
-        }
-       /*
+        fib_path_ext_list_remove(&mt->mt_path_exts,
+                                  FIB_PATH_EXT_MPLS,
+                                  rpaths);
+
+        /*
          * re-resolve all the path-extensions with the new path-list
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            fib_path_ext_resolve(path_ext, mt->mt_path_list);
-        }
+        fib_path_ext_list_resolve(&mt->mt_path_exts,
+                                  mt->mt_path_list);
 
         mpls_tunnel_restack(mt);
    }
@@ -960,7 +886,6 @@ format_mpls_tunnel (u8 * s, va_list * args)
 {
     mpls_tunnel_t *mt = va_arg (*args, mpls_tunnel_t *);
     mpls_tunnel_attribute_t attr;
-    fib_path_ext_t *path_ext;
 
     s = format(s, "mpls_tunnel%d: sw_if_index:%d hw_if_index:%d",
                mt - mpls_tunnel_pool,
@@ -976,11 +901,7 @@ format_mpls_tunnel (u8 * s, va_list * args)
     }
     s = format(s, "\n via:\n");
     s = fib_path_list_format(mt->mt_path_list, s);
-    s = format(s, "    Extensions:");
-    vec_foreach(path_ext, mt->mt_path_exts)
-    {
-        s = format(s, "\n     %U", format_fib_path_ext, path_ext);
-    }
+    s = format(s, "%U", format_fib_path_ext_list, &mt->mt_path_exts);
     s = format(s, "\n");
 
     return (s);
index ec0729a..4cb0a86 100644 (file)
@@ -82,7 +82,7 @@ typedef struct mpls_tunnel_t_
     /**
      * A vector of path extensions o hold the label stack for each path
      */
-    fib_path_ext_t *mt_path_exts;
+    fib_path_ext_list_t mt_path_exts;
 
     /**
      * @brief Flag to indicate the tunnel is only for L2 traffic, that is