* String names for each source
*/
static const char *mfib_source_names[] = MFIB_SOURCE_NAMES;
+static const char *mfib_src_attribute_names[] = MFIB_ENTRY_SRC_ATTRIBUTES;
/*
* Pool for all fib_entries
format_mfib_itf_flags, path_ext->mfpe_flags));
}
+u8 *
+format_mfib_entry_src_flags (u8 *s, va_list *args)
+{
+ mfib_entry_src_attribute_t sattr;
+ mfib_entry_src_flags_t flag = va_arg(*args, int);
+
+ if (!flag)
+ {
+ return format(s, "none");
+ }
+
+ FOR_EACH_MFIB_SRC_ATTRIBUTE(sattr) {
+ if ((1 << sattr) & flag) {
+ s = format (s, "%s,", mfib_src_attribute_names[sattr]);
+ }
+ }
+
+ return (s);
+}
+
u8 *
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 locks:%d:",
+ s = format (s, " src:%s flags:%U locks:%d:",
mfib_source_names[msrc->mfes_src],
+ format_mfib_entry_src_flags, msrc->mfes_flags,
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);
+ s = format (s, " %U\n", format_mfib_entry_flags, msrc->mfes_route_flags);
if (FIB_NODE_INDEX_INVALID != msrc->mfes_pl)
{
s = fib_path_list_format(msrc->mfes_pl, s);
{
mfib_entry_src_t esrc = {
.mfes_pl = FIB_NODE_INDEX_INVALID,
- .mfes_flags = MFIB_ENTRY_FLAG_NONE,
+ .mfes_route_flags = MFIB_ENTRY_FLAG_NONE,
.mfes_src = source,
.mfes_cover = FIB_NODE_INDEX_INVALID,
.mfes_sibling = FIB_NODE_INDEX_INVALID,
static mfib_entry_src_t *
mfib_entry_src_find (const mfib_entry_t *mfib_entry,
- mfib_source_t source,
- u32 *index)
+ mfib_source_t source,
+ u32 *index)
{
mfib_entry_src_t *esrc;
msrc = mfib_entry_src_find_or_create(mfib_entry, source);
- msrc->mfes_flags = entry_flags;
+ msrc->mfes_route_flags = entry_flags;
msrc->mfes_rpf_id = rpf_id;
+ msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE;
return (msrc);
}
msrc = mfib_entry_src_update(mfib_entry, source, rpf_id, entry_flags);
msrc->mfes_ref_count++;
+ msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE;
return (msrc);
}
return (NULL != mfib_entry_src_find(mfib_entry, source, NULL));
}
+int
+mfib_entry_is_marked (fib_node_index_t mfib_entry_index,
+ mfib_source_t source)
+{
+ mfib_entry_t *mfib_entry;
+ mfib_entry_src_t *esrc;
+
+ mfib_entry = mfib_entry_get(mfib_entry_index);
+
+ esrc = mfib_entry_src_find(mfib_entry, source, NULL);
+
+ if (NULL == esrc)
+ {
+ return (0);
+ }
+ else
+ {
+ return (!!(esrc->mfes_flags & MFIB_ENTRY_SRC_FLAG_STALE));
+ }
+}
+
+void
+mfib_entry_mark (fib_node_index_t fib_entry_index,
+ mfib_source_t source)
+{
+ mfib_entry_t *mfib_entry;
+ mfib_entry_src_t *esrc;
+
+ mfib_entry = mfib_entry_get(fib_entry_index);
+
+ esrc = mfib_entry_src_find(mfib_entry, source, NULL);
+
+ if (NULL != esrc)
+ {
+ esrc->mfes_flags |= MFIB_ENTRY_SRC_FLAG_STALE;
+ }
+}
+
int
mfib_entry_is_host (fib_node_index_t mfib_entry_index)
{
* updates to recalculate forwarding.
*/
mfib_entry->mfe_pl = msrc->mfes_pl;
- mfib_entry->mfe_flags = msrc->mfes_flags;
+ mfib_entry->mfe_flags = msrc->mfes_route_flags;
mfib_entry->mfe_itfs = msrc->mfes_itfs;
mfib_entry->mfe_rpf_id = msrc->mfes_rpf_id;
{
/*
* for exclusive routes the source provided a replicate DPO
- * we we stashed inthe special path list with one path
+ * which we stashed in the special path list with one path,
* so we can stack directly on that.
*/
ASSERT(1 == vec_len(ctx.next_hops));
- dpo_stack(DPO_MFIB_ENTRY, dp,
- &mfib_entry->mfe_rep,
- &ctx.next_hops[0].path_dpo);
- dpo_reset(&ctx.next_hops[0].path_dpo);
- vec_free(ctx.next_hops);
+ if (NULL != ctx.next_hops)
+ {
+ dpo_stack(DPO_MFIB_ENTRY, dp,
+ &mfib_entry->mfe_rep,
+ &ctx.next_hops[0].path_dpo);
+ dpo_reset(&ctx.next_hops[0].path_dpo);
+ vec_free(ctx.next_hops);
+ }
+ else
+ {
+ dpo_stack(DPO_MFIB_ENTRY, dp,
+ &mfib_entry->mfe_rep,
+ drop_dpo_get(dp));
+ }
}
}
else
&bw_ctx);
}
-static fib_node_index_t
-mfib_entry_src_path_add (mfib_entry_src_t *msrc,
- const fib_route_path_t *rpath)
+static fib_node_index_t*
+mfib_entry_src_paths_add (mfib_entry_src_t *msrc,
+ const fib_route_path_t *rpaths)
{
- fib_node_index_t path_index;
- fib_route_path_t *rpaths;
+ ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_route_flags));
- ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags));
-
- /*
- * path-lists require a vector of paths
- */
- rpaths = NULL;
- vec_add1(rpaths, rpath[0]);
+ msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE;
if (FIB_NODE_INDEX_INVALID == msrc->mfes_pl)
{
fib_path_list_lock(msrc->mfes_pl);
}
- path_index = fib_path_list_path_add(msrc->mfes_pl, rpaths);
-
- vec_free(rpaths);
-
- return (path_index);
+ return (fib_path_list_paths_add(msrc->mfes_pl, rpaths));
}
-static fib_node_index_t
-mfib_entry_src_path_remove (mfib_entry_src_t *msrc,
- const fib_route_path_t *rpath)
+static fib_node_index_t*
+mfib_entry_src_paths_remove (mfib_entry_src_t *msrc,
+ const fib_route_path_t *rpaths)
{
- fib_node_index_t path_index;
- fib_route_path_t *rpaths;
-
- ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags));
-
- /*
- * path-lists require a vector of paths
- */
- rpaths = NULL;
- vec_add1(rpaths, rpath[0]);
+ ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_route_flags));
- path_index = fib_path_list_path_remove(msrc->mfes_pl, rpaths);
+ msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE;
- vec_free(rpaths);
-
- return (path_index);
+ return (fib_path_list_paths_remove(msrc->mfes_pl, rpaths));
}
static void
mfib_entry_src_ok_for_delete (const mfib_entry_src_t *msrc)
{
return ((INDEX_INVALID == msrc->mfes_cover &&
- MFIB_ENTRY_FLAG_NONE == msrc->mfes_flags &&
- 0 == fib_path_list_get_n_paths(msrc->mfes_pl)));
+ MFIB_ENTRY_FLAG_NONE == msrc->mfes_route_flags &&
+ 0 == fib_path_list_get_n_paths(msrc->mfes_pl)) &&
+ (0 == hash_elts(msrc->mfes_itfs)));
+
+ /* return ((MFIB_ENTRY_FLAG_NONE == msrc->mfes_route_flags) && */
+ /* (0 == fib_path_list_get_n_paths(msrc->mfes_pl)) && */
+ /* (0 == hash_elts(msrc->mfes_itfs))); */
}
hash_unset(msrc->mfes_itfs, sw_if_index);
}
+static int
+mfib_entry_path_itf_based (const fib_route_path_t *rpath)
+{
+ return (!(rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP) &&
+ ~0 != rpath->frp_sw_if_index);
+}
+
void
mfib_entry_path_update (fib_node_index_t mfib_entry_index,
mfib_source_t source,
- const fib_route_path_t *rpath,
- mfib_itf_flags_t itf_flags)
+ const fib_route_path_t *rpaths)
{
- fib_node_index_t path_index;
+ fib_node_index_t* path_indices, path_index;
+ const fib_route_path_t *rpath;
mfib_source_t current_best;
mfib_path_ext_t *path_ext;
mfib_entry_t *mfib_entry;
mfib_entry_src_t *msrc;
mfib_itf_flags_t old;
+ u32 ii;
mfib_entry = mfib_entry_get(mfib_entry_index);
ASSERT(NULL != mfib_entry);
* add the path to the path-list. If it's a duplicate we'll get
* back the original path.
*/
- path_index = mfib_entry_src_path_add(msrc, rpath);
+ path_indices = mfib_entry_src_paths_add(msrc, rpaths);
- /*
- * find the path extension for that path
- */
- path_ext = mfib_entry_path_ext_find(msrc->mfes_exts, path_index);
-
- if (NULL == path_ext)
- {
- old = MFIB_ITF_FLAG_NONE;
- path_ext = mfib_path_ext_add(msrc, path_index, itf_flags);
- }
- else
+ vec_foreach_index(ii, path_indices)
{
- old = path_ext->mfpe_flags;
- path_ext->mfpe_flags = itf_flags;
- }
+ path_index = path_indices[ii];
+ rpath = &rpaths[ii];
- /*
- * Has the path changed its contribution to the input interface set.
- * Which only paths with interfaces can do...
- */
- if (~0 != rpath[0].frp_sw_if_index)
- {
- mfib_itf_t *mfib_itf;
+ if (FIB_NODE_INDEX_INVALID == path_index)
+ continue;
+
+ /*
+ * find the path extension for that path
+ */
+ path_ext = mfib_entry_path_ext_find(msrc->mfes_exts, path_index);
- if (old != itf_flags)
+ if (NULL == path_ext)
{
- /*
- * change of flag contributions
- */
- mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
- rpath[0].frp_sw_if_index);
+ old = MFIB_ITF_FLAG_NONE;
+ path_ext = mfib_path_ext_add(msrc, path_index,
+ rpath->frp_mitf_flags);
+ }
+ else
+ {
+ old = path_ext->mfpe_flags;
+ path_ext->mfpe_flags = rpath->frp_mitf_flags;
+ }
- if (NULL == mfib_itf)
- {
- mfib_entry_itf_add(msrc,
- rpath[0].frp_sw_if_index,
- mfib_itf_create(path_index, itf_flags));
- }
- else
+ /*
+ * Has the path changed its contribution to the input interface set.
+ * Which only paths with interfaces can do...
+ */
+ if (mfib_entry_path_itf_based(rpath))
+ {
+ mfib_itf_t *mfib_itf;
+
+ if (old != rpath->frp_mitf_flags)
{
- if (mfib_itf_update(mfib_itf,
- path_index,
- itf_flags))
+ /*
+ * change of flag contributions
+ */
+ mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
+ rpath->frp_sw_if_index);
+
+ if (NULL == mfib_itf)
+ {
+ mfib_entry_itf_add(msrc,
+ rpath->frp_sw_if_index,
+ mfib_itf_create(path_index,
+ rpath->frp_mitf_flags));
+ }
+ else
{
- /*
- * no more interface flags on this path, remove
- * from the data-plane set
- */
- mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
+ if (mfib_itf_update(mfib_itf,
+ path_index,
+ rpath->frp_mitf_flags))
+ {
+ /*
+ * no more interface flags on this path, remove
+ * from the data-plane set
+ */
+ mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index);
+ }
}
}
}
}
+ vec_free(path_indices);
mfib_entry_recalculate_forwarding(mfib_entry, current_best);
}
int
mfib_entry_path_remove (fib_node_index_t mfib_entry_index,
mfib_source_t source,
- const fib_route_path_t *rpath)
+ const fib_route_path_t *rpaths)
{
- fib_node_index_t path_index;
+ fib_node_index_t path_index, *path_indices;
+ const fib_route_path_t *rpath;
mfib_source_t current_best;
mfib_entry_t *mfib_entry;
mfib_entry_src_t *msrc;
+ u32 ii;
mfib_entry = mfib_entry_get(mfib_entry_index);
ASSERT(NULL != mfib_entry);
}
/*
- * remove the path from the path-list. If it's not there we'll get
- * back invalid
+ * remove the paths from the path-list. If it's not there we'll get
+ * back an empty vector
*/
- path_index = mfib_entry_src_path_remove(msrc, rpath);
+ path_indices = mfib_entry_src_paths_remove(msrc, rpaths);
- if (FIB_NODE_INDEX_INVALID != path_index)
+ vec_foreach_index(ii, path_indices)
{
+ path_index = path_indices[ii];
+ rpath = &rpaths[ii];
+
+ if (FIB_NODE_INDEX_INVALID == path_index)
+ continue;
+
/*
* don't need the extension, nor the interface anymore
*/
mfib_path_ext_remove(msrc, path_index);
- if (~0 != rpath[0].frp_sw_if_index)
+ if (mfib_entry_path_itf_based(rpath))
{
mfib_itf_t *mfib_itf;
mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
- rpath[0].frp_sw_if_index);
+ rpath->frp_sw_if_index);
if (mfib_itf_update(mfib_itf,
path_index,
* no more interface flags on this path, remove
* from the data-plane set
*/
- mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
+ mfib_entry_itf_remove(msrc, rpath->frp_sw_if_index);
}
}
}
+ vec_free(path_indices);
if (mfib_entry_src_ok_for_delete(msrc))
- {
+ {
/*
* 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_recalculate_forwarding(mfib_entry, current_best);
mfib_entry_logger = vlib_log_register_class("mfib", "entry");
}
-void
-mfib_entry_encode (fib_node_index_t mfib_entry_index,
- fib_route_path_encode_t **api_rpaths)
+fib_route_path_t*
+mfib_entry_encode (fib_node_index_t mfib_entry_index)
{
+ fib_path_encode_ctx_t ctx = {
+ .rpaths = NULL,
+ };
mfib_entry_t *mfib_entry;
+ fib_route_path_t *rpath;
mfib_entry_src_t *bsrc;
mfib_entry = mfib_entry_get(mfib_entry_index);
fib_path_list_walk_w_ext(bsrc->mfes_pl,
NULL,
fib_path_encode,
- api_rpaths);
+ &ctx);
+ }
+
+ vec_foreach(rpath, ctx.rpaths)
+ {
+ mfib_itf_t *mfib_itf;
+
+ mfib_itf = mfib_entry_itf_find(bsrc->mfes_itfs,
+ rpath->frp_sw_if_index);
+ if (mfib_itf)
+ {
+ rpath->frp_mitf_flags = mfib_itf->mfi_flags;
+ }
}
+
+ return (ctx.rpaths);
}
const mfib_prefix_t *
/*
* caller does not want the local paths that the entry has
*/
- dpo_set(dpo, DPO_REPLICATE, rep->rep_proto,
+ dpo_proto_t rep_proto = rep->rep_proto;
+ dpo_set(dpo, DPO_REPLICATE, rep_proto,
replicate_dup(REPLICATE_FLAGS_NONE,
mfib_entry->mfe_rep.dpoi_index));
}