diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/ethernet/arp.c | 10 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry.c | 12 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry.h | 2 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry_src.c | 289 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry_src_adj.c | 242 | ||||
-rw-r--r-- | src/vnet/fib/fib_entry_src_api.c | 72 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.c | 6 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.h | 6 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_ext.c | 213 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_ext.h | 88 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_list.c | 31 | ||||
-rw-r--r-- | src/vnet/fib/fib_path_list.h | 11 | ||||
-rw-r--r-- | src/vnet/fib/fib_test.c | 791 | ||||
-rw-r--r-- | src/vnet/fib/fib_types.h | 17 | ||||
-rw-r--r-- | src/vnet/ip/ip6_neighbor.c | 12 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry.c | 8 | ||||
-rw-r--r-- | src/vnet/mpls/mpls_tunnel.c | 117 | ||||
-rw-r--r-- | src/vnet/mpls/mpls_tunnel.h | 2 |
18 files changed, 1194 insertions, 735 deletions
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index f44cb594dea..ad0c2c8ceab 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -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 { diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c index 29f5b35965d..cdebfbce0a9 100644 --- a/src/vnet/fib/fib_entry.c +++ b/src/vnet/fib/fib_entry.c @@ -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); } })); diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h index aa1000e04ec..5f6ff31297e 100644 --- a/src/vnet/fib/fib_entry.h +++ b/src/vnet/fib/fib_entry.h @@ -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 diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c index ab72565d903..8c5082846a8 100644 --- a/src/vnet/fib/fib_entry_src.c +++ b/src/vnet/fib/fib_entry_src.c @@ -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 @@ -1036,58 +1058,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 * * Adding a source can result in a new fib_entry being created, which @@ -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 diff --git a/src/vnet/fib/fib_entry_src_adj.c b/src/vnet/fib/fib_entry_src_adj.c index 9990223037a..9ea2b17e6b9 100644 --- a/src/vnet/fib/fib_entry_src_adj.c +++ b/src/vnet/fib/fib_entry_src_adj.c @@ -19,9 +19,10 @@ #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) @@ -31,12 +32,93 @@ fib_entry_src_adj_init (fib_entry_src_t *src) } 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, diff --git a/src/vnet/fib/fib_entry_src_api.c b/src/vnet/fib/fib_entry_src_api.c index 19db8819ede..f895886bc0e 100644 --- a/src/vnet/fib/fib_entry_src_api.c +++ b/src/vnet/fib/fib_entry_src_api.c @@ -13,9 +13,10 @@ * 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); } } diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c index b47d51f8d51..255f0dd18c6 100644 --- a/src/vnet/fib/fib_path.c +++ b/src/vnet/fib/fib_path.c @@ -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 diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h index b6bf1e4fa83..0b5e6072679 100644 --- a/src/vnet/fib/fib_path.h +++ b/src/vnet/fib/fib_path.h @@ -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 diff --git a/src/vnet/fib/fib_path_ext.c b/src/vnet/fib/fib_path_ext.c index 08293bcf175..45ab1f1498d 100644 --- a/src/vnet/fib/fib_path_ext.c +++ b/src/vnet/fib/fib_path_ext.c @@ -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)); +} diff --git a/src/vnet/fib/fib_path_ext.h b/src/vnet/fib/fib_path_ext.h index d617700d026..d1571a1b4ee 100644 --- a/src/vnet/fib/fib_path_ext.h +++ b/src/vnet/fib/fib_path_ext.h @@ -21,6 +21,45 @@ #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. * @@ -33,6 +72,11 @@ 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] * instance of a fib_path_t that is extended @@ -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 diff --git a/src/vnet/fib/fib_path_list.c b/src/vnet/fib/fib_path_list.c index 64917f95107..3e4c3333a08 100644 --- a/src/vnet/fib/fib_path_list.c +++ b/src/vnet/fib/fib_path_list.c @@ -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; } } diff --git a/src/vnet/fib/fib_path_list.h b/src/vnet/fib/fib_path_list.h index 376cb726dd6..b4b6985bd9a 100644 --- a/src/vnet/fib/fib_path_list.h +++ b/src/vnet/fib/fib_path_list.h @@ -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, diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c index 486e5616798..06aeda62354 100644 --- a/src/vnet/fib/fib_test.c +++ b/src/vnet/fib/fib_test.c @@ -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, diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index 4cb73e8a7a6..60873c4a9db 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -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 diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 4fd078dcf32..e140c55d428 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -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 { diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index a937842553c..49792f02ae4 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -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 diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c index 457d48eb6bf..d6e85e70b44 100644 --- a/src/vnet/mpls/mpls_tunnel.c +++ b/src/vnet/mpls/mpls_tunnel.c @@ -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); diff --git a/src/vnet/mpls/mpls_tunnel.h b/src/vnet/mpls/mpls_tunnel.h index ec0729a0f91..4cb0a860802 100644 --- a/src/vnet/mpls/mpls_tunnel.h +++ b/src/vnet/mpls/mpls_tunnel.h @@ -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 |