diff options
Diffstat (limited to 'src/vnet/mfib/mfib_entry.c')
-rw-r--r-- | src/vnet/mfib/mfib_entry.c | 423 |
1 files changed, 300 insertions, 123 deletions
diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index 90b223e3c25..51d775dd295 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -16,7 +16,10 @@ #include <vlib/vlib.h> #include <vnet/mfib/mfib_entry.h> +#include <vnet/mfib/mfib_entry_src.h> +#include <vnet/mfib/mfib_entry_cover.h> #include <vnet/fib/fib_path_list.h> +#include <vnet/fib/fib_walk.h> #include <vnet/dpo/drop_dpo.h> #include <vnet/dpo/replicate_dpo.h> @@ -27,66 +30,6 @@ vlib_log_class_t mfib_entry_logger; /** - * Debug macro - */ -#define MFIB_ENTRY_DBG(_e, _fmt, _args...) \ -{ \ - vlib_log_debug(mfib_entry_logger, \ - "e:[%d:%U]: " _fmt, \ - mfib_entry_get_index(_e), \ - format_mfib_prefix, \ - &_e->mfe_prefix, \ - ##_args); \ -} - -/** - * MFIB extensions to each path - */ -typedef struct mfib_path_ext_t_ -{ - mfib_itf_flags_t mfpe_flags; - fib_node_index_t mfpe_path; -} mfib_path_ext_t; - -/** - * The source of an MFIB entry - */ -typedef struct mfib_entry_src_t_ -{ - /** - * Which source this is - */ - mfib_source_t mfes_src; - - /** - * Route flags - */ - mfib_entry_flags_t mfes_flags; - - /** - * The path-list of forwarding interfaces - */ - fib_node_index_t mfes_pl; - - /** - * RPF-ID - */ - fib_rpf_id_t mfes_rpf_id; - - /** - * Hash table of path extensions - */ - mfib_path_ext_t *mfes_exts; - - /** - * The hash table of all interfaces. - * This is forwarding time information derived from the paths - * and their extensions. - */ - mfib_itf_t *mfes_itfs; -} mfib_entry_src_t; - -/** * Pool of path extensions */ static mfib_path_ext_t *mfib_path_ext_pool; @@ -184,8 +127,14 @@ format_mfib_entry (u8 * s, va_list * args) s = format (s, " locks:%d\n", mfib_entry->mfe_node.fn_locks); vec_foreach(msrc, mfib_entry->mfe_srcs) { - s = format (s, " src:%s", mfib_source_names[msrc->mfes_src]); - s = format (s, ": %U\n", format_mfib_entry_flags, msrc->mfes_flags); + s = format (s, " src:%s locks:%d:", + mfib_source_names[msrc->mfes_src], + msrc->mfes_ref_count); + if (msrc->mfes_cover != FIB_NODE_INDEX_INVALID) + { + s = format (s, " cover:%d", msrc->mfes_cover); + } + s = format (s, " %U\n", format_mfib_entry_flags, msrc->mfes_flags); if (FIB_NODE_INDEX_INVALID != msrc->mfes_pl) { s = fib_path_list_format(msrc->mfes_pl, s); @@ -254,6 +203,9 @@ mfib_entry_src_init (mfib_entry_t *mfib_entry, .mfes_pl = FIB_NODE_INDEX_INVALID, .mfes_flags = MFIB_ENTRY_FLAG_NONE, .mfes_src = source, + .mfes_cover = FIB_NODE_INDEX_INVALID, + .mfes_sibling = FIB_NODE_INDEX_INVALID, + .mfes_ref_count = 1, }; vec_add1(mfib_entry->mfe_srcs, esrc); @@ -294,19 +246,51 @@ static mfib_entry_src_t * mfib_entry_src_find_or_create (mfib_entry_t *mfib_entry, mfib_source_t source) { - mfib_entry_src_t *esrc; + mfib_entry_src_t *msrc; - esrc = mfib_entry_src_find(mfib_entry, source, NULL); + msrc = mfib_entry_src_find(mfib_entry, source, NULL); - if (NULL == esrc) + if (NULL == msrc) { mfib_entry_src_init(mfib_entry, source); + msrc = mfib_entry_src_find(mfib_entry, source, NULL); } - return (mfib_entry_src_find(mfib_entry, source, NULL)); + return (msrc); +} + +static mfib_entry_src_t * +mfib_entry_src_update (mfib_entry_t *mfib_entry, + mfib_source_t source, + fib_rpf_id_t rpf_id, + mfib_entry_flags_t entry_flags) +{ + mfib_entry_src_t *msrc; + + msrc = mfib_entry_src_find_or_create(mfib_entry, source); + + msrc->mfes_flags = entry_flags; + msrc->mfes_rpf_id = rpf_id; + + return (msrc); } -static mfib_entry_src_t* +static mfib_entry_src_t * +mfib_entry_src_update_and_lock (mfib_entry_t *mfib_entry, + mfib_source_t source, + fib_rpf_id_t rpf_id, + mfib_entry_flags_t entry_flags) +{ + mfib_entry_src_t *msrc; + + msrc = mfib_entry_src_update(mfib_entry, source, rpf_id, entry_flags); + + msrc->mfes_ref_count++; + + return (msrc); +} + +mfib_entry_src_t* mfib_entry_get_best_src (const mfib_entry_t *mfib_entry) { mfib_entry_src_t *bsrc; @@ -326,6 +310,16 @@ mfib_entry_get_best_src (const mfib_entry_t *mfib_entry) return (bsrc); } +static mfib_source_t +mfib_entry_get_best_source (const mfib_entry_t *mfib_entry) +{ + mfib_entry_src_t *bsrc; + + bsrc = mfib_entry_get_best_src(mfib_entry); + + return (bsrc->mfes_src); +} + int mfib_entry_is_sourced (fib_node_index_t mfib_entry_index, mfib_source_t source) @@ -337,6 +331,13 @@ mfib_entry_is_sourced (fib_node_index_t mfib_entry_index, return (NULL != mfib_entry_src_find(mfib_entry, source, NULL)); } +int +mfib_entry_is_host (fib_node_index_t mfib_entry_index) +{ + return (mfib_prefix_is_host(mfib_entry_get_prefix(mfib_entry_index))); +} + + static void mfib_entry_src_flush (mfib_entry_src_t *msrc) { @@ -364,8 +365,19 @@ mfib_entry_src_remove (mfib_entry_t *mfib_entry, if (NULL != msrc) { - mfib_entry_src_flush(msrc); - vec_del1(mfib_entry->mfe_srcs, index); + ASSERT(0 != msrc->mfes_ref_count); + msrc->mfes_ref_count--; + + if (0 == msrc->mfes_ref_count) + { + mfib_entry_src_deactivate(mfib_entry, msrc); + mfib_entry_src_flush(msrc); + + vec_del1(mfib_entry->mfe_srcs, index); + if (vec_len (mfib_entry->mfe_srcs) > 1) + vec_sort_with_function(mfib_entry->mfe_srcs, + mfib_entry_src_cmp_for_sort); + } } } @@ -552,8 +564,7 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, mfib_entry->mfe_sibling); } - if (NULL != msrc && - FIB_NODE_INDEX_INVALID != msrc->mfes_pl) + if (NULL != msrc) { mfib_entry_collect_forwarding_ctx_t ctx = { .next_hops = NULL, @@ -561,10 +572,27 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, .msrc = msrc, }; - fib_path_list_walk(msrc->mfes_pl, - mfib_entry_src_collect_forwarding, - &ctx); + /* + * link the entry to the path-list. + * The entry needs to be a child so that we receive the back-walk + * updates to recalculate forwarding. + */ + mfib_entry->mfe_pl = msrc->mfes_pl; + mfib_entry->mfe_flags = msrc->mfes_flags; + mfib_entry->mfe_itfs = msrc->mfes_itfs; + mfib_entry->mfe_rpf_id = msrc->mfes_rpf_id; + if (FIB_NODE_INDEX_INVALID != mfib_entry->mfe_pl) + { + mfib_entry->mfe_sibling = + fib_path_list_child_add(mfib_entry->mfe_pl, + FIB_NODE_TYPE_MFIB_ENTRY, + mfib_entry_get_index(mfib_entry)); + + fib_path_list_walk(mfib_entry->mfe_pl, + mfib_entry_src_collect_forwarding, + &ctx); + } if (!(MFIB_ENTRY_FLAG_EXCLUSIVE & mfib_entry->mfe_flags)) { if (NULL == ctx.next_hops) @@ -616,17 +644,6 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, dpo_reset(&ctx.next_hops[0].path_dpo); vec_free(ctx.next_hops); } - - /* - * link the entry to the path-list. - * The entry needs to be a child so that we receive the back-walk - * updates to recalculate forwarding. - */ - mfib_entry->mfe_pl = msrc->mfes_pl; - mfib_entry->mfe_sibling = - fib_path_list_child_add(mfib_entry->mfe_pl, - FIB_NODE_TYPE_MFIB_ENTRY, - mfib_entry_get_index(mfib_entry)); } else { @@ -634,6 +651,17 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, &mfib_entry->mfe_rep, drop_dpo_get(dp)); } + + /* + * time for walkies fido. + */ + fib_node_back_walk_ctx_t bw_ctx = { + .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE, + }; + + fib_walk_sync(FIB_NODE_TYPE_MFIB_ENTRY, + mfib_entry_get_index(mfib_entry), + &bw_ctx); } static fib_node_index_t @@ -689,23 +717,36 @@ mfib_entry_src_path_remove (mfib_entry_src_t *msrc, } static void -mfib_entry_recalculate_forwarding (mfib_entry_t *mfib_entry) +mfib_entry_recalculate_forwarding (mfib_entry_t *mfib_entry, + mfib_source_t old_best) { - mfib_entry_src_t *bsrc; + mfib_entry_src_t *bsrc, *osrc; /* * copy the forwarding data from the bast source */ bsrc = mfib_entry_get_best_src(mfib_entry); + osrc = mfib_entry_src_find(mfib_entry, old_best, NULL); if (NULL != bsrc) { - mfib_entry->mfe_flags = bsrc->mfes_flags; - mfib_entry->mfe_itfs = bsrc->mfes_itfs; - mfib_entry->mfe_rpf_id = bsrc->mfes_rpf_id; + if (bsrc->mfes_src != old_best) + { + /* + * we are changing from one source to another + * deactivate the old, and activate the new + */ + mfib_entry_src_deactivate(mfib_entry, osrc); + mfib_entry_src_activate(mfib_entry, bsrc); + } + } + else + { + mfib_entry_src_deactivate(mfib_entry, osrc); } mfib_entry_stack(mfib_entry, bsrc); + mfib_entry_cover_update_notify(mfib_entry); } @@ -714,7 +755,8 @@ mfib_entry_create (u32 fib_index, mfib_source_t source, const mfib_prefix_t *prefix, fib_rpf_id_t rpf_id, - mfib_entry_flags_t entry_flags) + mfib_entry_flags_t entry_flags, + index_t repi) { fib_node_index_t mfib_entry_index; mfib_entry_t *mfib_entry; @@ -722,11 +764,37 @@ mfib_entry_create (u32 fib_index, mfib_entry = mfib_entry_alloc(fib_index, prefix, &mfib_entry_index); - msrc = mfib_entry_src_find_or_create(mfib_entry, source); - msrc->mfes_flags = entry_flags; - msrc->mfes_rpf_id = rpf_id; + msrc = mfib_entry_src_update(mfib_entry, source, + rpf_id, entry_flags); - mfib_entry_recalculate_forwarding(mfib_entry); + if (INDEX_INVALID != repi) + { + /* + * The source is providing its own replicate DPO. + * Create a sepcial path-list to manage it, that way + * this entry and the source are equivalent to a normal + * entry + */ + fib_node_index_t old_pl_index; + dpo_proto_t dp; + dpo_id_t dpo = DPO_INVALID; + + dp = fib_proto_to_dpo(mfib_entry_get_proto(mfib_entry)); + old_pl_index = msrc->mfes_pl; + + dpo_set(&dpo, DPO_REPLICATE, dp, repi); + + msrc->mfes_pl = + fib_path_list_create_special(dp, + FIB_PATH_LIST_FLAG_EXCLUSIVE, + &dpo); + + dpo_reset(&dpo); + fib_path_list_lock(msrc->mfes_pl); + fib_path_list_unlock(old_pl_index); + } + + mfib_entry_recalculate_forwarding(mfib_entry, MFIB_SOURCE_NONE); return (mfib_entry_index); } @@ -740,25 +808,18 @@ mfib_entry_ok_for_delete (mfib_entry_t *mfib_entry) static int mfib_entry_src_ok_for_delete (const mfib_entry_src_t *msrc) { - return ((MFIB_ENTRY_FLAG_NONE == msrc->mfes_flags && + return ((INDEX_INVALID == msrc->mfes_cover && + MFIB_ENTRY_FLAG_NONE == msrc->mfes_flags && 0 == fib_path_list_get_n_paths(msrc->mfes_pl))); } -int -mfib_entry_update (fib_node_index_t mfib_entry_index, - mfib_source_t source, - mfib_entry_flags_t entry_flags, - fib_rpf_id_t rpf_id, - index_t repi) -{ - mfib_entry_t *mfib_entry; - mfib_entry_src_t *msrc; - - mfib_entry = mfib_entry_get(mfib_entry_index); - msrc = mfib_entry_src_find_or_create(mfib_entry, source); - msrc->mfes_flags = entry_flags; - msrc->mfes_rpf_id = rpf_id; +static void +mfib_entry_update_i (mfib_entry_t *mfib_entry, + mfib_entry_src_t *msrc, + mfib_source_t current_best, + index_t repi) +{ if (INDEX_INVALID != repi) { /* @@ -792,10 +853,50 @@ mfib_entry_update (fib_node_index_t mfib_entry_index, * this source has no interfaces and no flags. * it has nothing left to give - remove it */ - mfib_entry_src_remove(mfib_entry, source); + mfib_entry_src_remove(mfib_entry, msrc->mfes_src); } - mfib_entry_recalculate_forwarding(mfib_entry); + mfib_entry_recalculate_forwarding(mfib_entry, current_best); +} + +int +mfib_entry_special_add (fib_node_index_t mfib_entry_index, + mfib_source_t source, + mfib_entry_flags_t entry_flags, + fib_rpf_id_t rpf_id, + index_t repi) +{ + mfib_source_t current_best; + mfib_entry_t *mfib_entry; + mfib_entry_src_t *msrc; + + mfib_entry = mfib_entry_get(mfib_entry_index); + current_best = mfib_entry_get_best_source(mfib_entry); + + msrc = mfib_entry_src_update_and_lock(mfib_entry, source, rpf_id, + entry_flags); + + mfib_entry_update_i(mfib_entry, msrc, current_best, repi); + + return (mfib_entry_ok_for_delete(mfib_entry)); +} + +int +mfib_entry_update (fib_node_index_t mfib_entry_index, + mfib_source_t source, + mfib_entry_flags_t entry_flags, + fib_rpf_id_t rpf_id, + index_t repi) +{ + mfib_source_t current_best; + mfib_entry_t *mfib_entry; + mfib_entry_src_t *msrc; + + mfib_entry = mfib_entry_get(mfib_entry_index); + current_best = mfib_entry_get_best_source(mfib_entry); + msrc = mfib_entry_src_update(mfib_entry, source, rpf_id, entry_flags); + + mfib_entry_update_i(mfib_entry, msrc, current_best, repi); return (mfib_entry_ok_for_delete(mfib_entry)); } @@ -828,6 +929,7 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, mfib_itf_flags_t itf_flags) { fib_node_index_t path_index; + mfib_source_t current_best; mfib_path_ext_t *path_ext; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; @@ -835,6 +937,7 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, mfib_entry = mfib_entry_get(mfib_entry_index); ASSERT(NULL != mfib_entry); + current_best = mfib_entry_get_best_source(mfib_entry); msrc = mfib_entry_src_find_or_create(mfib_entry, source); /* @@ -897,7 +1000,7 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index, } } - mfib_entry_recalculate_forwarding(mfib_entry); + mfib_entry_recalculate_forwarding(mfib_entry, current_best); } /* @@ -912,11 +1015,13 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, const fib_route_path_t *rpath) { fib_node_index_t path_index; + mfib_source_t current_best; mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; mfib_entry = mfib_entry_get(mfib_entry_index); ASSERT(NULL != mfib_entry); + current_best = mfib_entry_get_best_source(mfib_entry); msrc = mfib_entry_src_find(mfib_entry, source, NULL); if (NULL == msrc) @@ -968,7 +1073,7 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index, mfib_entry_src_remove(mfib_entry, source); } - mfib_entry_recalculate_forwarding(mfib_entry); + mfib_entry_recalculate_forwarding(mfib_entry, current_best); return (mfib_entry_ok_for_delete(mfib_entry)); } @@ -982,12 +1087,14 @@ int mfib_entry_delete (fib_node_index_t mfib_entry_index, mfib_source_t source) { + mfib_source_t current_best; mfib_entry_t *mfib_entry; mfib_entry = mfib_entry_get(mfib_entry_index); + current_best = mfib_entry_get_best_source(mfib_entry); mfib_entry_src_remove(mfib_entry, source); - mfib_entry_recalculate_forwarding(mfib_entry); + mfib_entry_recalculate_forwarding(mfib_entry, current_best); return (mfib_entry_ok_for_delete(mfib_entry)); } @@ -1116,7 +1223,11 @@ static fib_node_back_walk_rc_t mfib_entry_back_walk_notify (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { - mfib_entry_recalculate_forwarding(mfib_entry_from_fib_node(node)); + mfib_entry_t *mfib_entry; + + mfib_entry = mfib_entry_from_fib_node(node); + mfib_entry_recalculate_forwarding(mfib_entry, + mfib_entry_get_best_source(mfib_entry)); return (FIB_NODE_BACK_WALK_CONTINUE); } @@ -1219,15 +1330,14 @@ mfib_entry_encode (fib_node_index_t mfib_entry_index, } } - -void -mfib_entry_get_prefix (fib_node_index_t mfib_entry_index, - mfib_prefix_t *pfx) +const mfib_prefix_t * +mfib_entry_get_prefix (fib_node_index_t mfib_entry_index) { mfib_entry_t *mfib_entry; mfib_entry = mfib_entry_get(mfib_entry_index); - *pfx = mfib_entry->mfe_prefix; + + return (&mfib_entry->mfe_prefix); } u32 @@ -1253,6 +1363,7 @@ mfib_entry_contribute_ip_forwarding (fib_node_index_t mfib_entry_index) void mfib_entry_contribute_forwarding (fib_node_index_t mfib_entry_index, fib_forward_chain_type_t type, + mfib_entry_fwd_flags_t flags, dpo_id_t *dpo) { /* @@ -1267,9 +1378,26 @@ mfib_entry_contribute_forwarding (fib_node_index_t mfib_entry_index, dp = fib_proto_to_dpo(mfib_entry->mfe_prefix.fp_proto); - if (type == fib_forw_chain_type_from_dpo_proto(dp)) + if (type == mfib_forw_chain_type_from_dpo_proto(dp)) { - dpo_copy(dpo, &mfib_entry->mfe_rep); + replicate_t * rep; + + rep = replicate_get(mfib_entry->mfe_rep.dpoi_index); + + if ((rep->rep_flags & REPLICATE_FLAGS_HAS_LOCAL) && + (flags & MFIB_ENTRY_FWD_FLAG_NO_LOCAL)) + { + /* + * caller does not want the local paths that the entry has + */ + dpo_set(dpo, DPO_REPLICATE, rep->rep_proto, + replicate_dup(REPLICATE_FLAGS_NONE, + mfib_entry->mfe_rep.dpoi_index)); + } + else + { + dpo_copy(dpo, &mfib_entry->mfe_rep); + } } else { @@ -1277,6 +1405,55 @@ mfib_entry_contribute_forwarding (fib_node_index_t mfib_entry_index, } } +/* + * fib_entry_cover_changed + * + * this entry is tracking its cover and that cover has changed. + */ +void +mfib_entry_cover_changed (fib_node_index_t mfib_entry_index) +{ + mfib_entry_t *mfib_entry; + mfib_entry_src_t *msrc; + mfib_src_res_t res; + + mfib_entry = mfib_entry_get(mfib_entry_index); + msrc = mfib_entry_get_best_src(mfib_entry); + + res = mfib_entry_src_cover_change(mfib_entry, msrc); + + if (MFIB_SRC_REEVALUATE == res) + { + mfib_entry_recalculate_forwarding(mfib_entry, msrc->mfes_src); + } + MFIB_ENTRY_DBG(mfib_entry, "cover-changed"); +} + +/* + * mfib_entry_cover_updated + * + * this entry is tracking its cover and that cover has been updated + * (i.e. its forwarding information has changed). + */ +void +mfib_entry_cover_updated (fib_node_index_t mfib_entry_index) +{ + mfib_entry_t *mfib_entry; + mfib_entry_src_t *msrc; + mfib_src_res_t res; + + mfib_entry = mfib_entry_get(mfib_entry_index); + msrc = mfib_entry_get_best_src(mfib_entry); + + res = mfib_entry_src_cover_update(mfib_entry, msrc); + + if (MFIB_SRC_REEVALUATE == res) + { + mfib_entry_recalculate_forwarding(mfib_entry, msrc->mfes_src); + } + MFIB_ENTRY_DBG(mfib_entry, "cover-updated"); +} + u32 mfib_entry_pool_size (void) { |