diff options
author | Neale Ranns <nranns@cisco.com> | 2019-11-08 12:42:31 +0000 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2019-11-26 09:15:11 +0000 |
commit | 9db6ada779794779158163f6293b479ae7f6ad5e (patch) | |
tree | 53dd65975958b2d87b1cd312e612b45d7225e531 /src/vnet/mfib | |
parent | 0d3d4824a46205e776ff32c82be4cb514f459a5f (diff) |
fib: Table Replace
Type: feature
from the API doc, a table replace is:
"
The use-case is that, for some unspecified reason, the control plane
has a very different set of entries it wants in the table than VPP
currently has. The CP would thus like to 'replace' VPP's current table
only by specifying what the new set of entries shall be, i.e. it is not
going to delete anything that already eixts.
the CP delcartes the start of this procedure with this begin_replace
API Call, and when it has populated all the entries it wants, it calls
the below end_replace API. From this point on it is of coursce free
to add and delete entries as usual.
The underlying mechanism by which VPP implements this replace is
purposefully left unspecified.
"
In the FIB, the algorithm is implemented using mark and sweep.
Algorithm goes:
1) replace_begin: this marks all the entries in that table as 'stale'
2) download all the entries that should be in this table
- this clears the stale flag on those entries
3) signal the table converged: ip_table_replace_end
- this removes all entries that are still stale
this procedure can be used when an agent first connects to VPP,
as an alternative to dump and diff state reconciliation.
Change-Id: I168edec10cf7670866076b129ebfe6149ea8222e
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/mfib')
-rw-r--r-- | src/vnet/mfib/ip4_mfib.c | 5 | ||||
-rw-r--r-- | src/vnet/mfib/ip6_mfib.c | 9 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry.c | 88 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry.h | 2 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry_src.h | 49 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry_src_rr.c | 4 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_table.c | 99 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_table.h | 90 |
8 files changed, 321 insertions, 25 deletions
diff --git a/src/vnet/mfib/ip4_mfib.c b/src/vnet/mfib/ip4_mfib.c index 1d872f974fd..4da1be61113 100644 --- a/src/vnet/mfib/ip4_mfib.c +++ b/src/vnet/mfib/ip4_mfib.c @@ -506,9 +506,10 @@ ip4_show_mfib (vlib_main_t * vm, continue; } - vlib_cli_output (vm, "%U, fib_index %d", + vlib_cli_output (vm, "%U, fib_index:%d flags:%U", format_mfib_table_name, mfib->index, FIB_PROTOCOL_IP4, - mfib->index); + mfib->index, + format_mfib_table_flags, mfib_table->mft_flags); /* Show summary? */ if (! verbose) diff --git a/src/vnet/mfib/ip6_mfib.c b/src/vnet/mfib/ip6_mfib.c index 5b15c8d1736..690f4ed9dfd 100644 --- a/src/vnet/mfib/ip6_mfib.c +++ b/src/vnet/mfib/ip6_mfib.c @@ -562,14 +562,14 @@ typedef struct ip6_mfib_show_ctx_t_ { } ip6_mfib_show_ctx_t; -static int +static walk_rc_t ip6_mfib_table_collect_entries (fib_node_index_t mfei, void *arg) { ip6_mfib_show_ctx_t *ctx = arg; vec_add1(ctx->entries, mfei); - return (0); + return (WALK_CONTINUE); } static void @@ -609,7 +609,7 @@ typedef struct ip6_mfib_walk_ctx_t_ void *i6w_ctx; } ip6_mfib_walk_ctx_t; -static int +static void ip6_mfib_walk_cb (clib_bihash_kv_40_8_t * kvp, void *arg) { @@ -617,9 +617,8 @@ ip6_mfib_walk_cb (clib_bihash_kv_40_8_t * kvp, if ((kvp->key[4] >> 32) == ctx->i6w_mfib_index) { - return (ctx->i6w_fn(kvp->value, ctx->i6w_ctx)); + ctx->i6w_fn(kvp->value, ctx->i6w_ctx); } - return (FIB_TABLE_WALK_CONTINUE); } void diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index f169dc0886e..448e6c5e0a8 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -38,6 +38,7 @@ static mfib_path_ext_t *mfib_path_ext_pool; * 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 @@ -102,6 +103,26 @@ format_mfib_entry_path_ext (u8 * s, va_list * args) } 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) { fib_node_index_t fei, mfi; @@ -127,14 +148,15 @@ 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); @@ -201,7 +223,7 @@ mfib_entry_src_init (mfib_entry_t *mfib_entry, { 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, @@ -215,8 +237,8 @@ mfib_entry_src_init (mfib_entry_t *mfib_entry, 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; @@ -269,8 +291,9 @@ mfib_entry_src_update (mfib_entry_t *mfib_entry, 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); } @@ -286,6 +309,7 @@ mfib_entry_src_update_and_lock (mfib_entry_t *mfib_entry, 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); } @@ -332,6 +356,44 @@ mfib_entry_is_sourced (fib_node_index_t mfib_entry_index, } 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) { return (mfib_prefix_is_host(mfib_entry_get_prefix(mfib_entry_index))); @@ -578,7 +640,7 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, * 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; @@ -677,7 +739,9 @@ static fib_node_index_t* mfib_entry_src_paths_add (mfib_entry_src_t *msrc, const fib_route_path_t *rpaths) { - ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); + ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_route_flags)); + + msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE; if (FIB_NODE_INDEX_INVALID == msrc->mfes_pl) { @@ -694,7 +758,9 @@ static fib_node_index_t* mfib_entry_src_paths_remove (mfib_entry_src_t *msrc, const fib_route_path_t *rpaths) { - ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); + ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_route_flags)); + + msrc->mfes_flags &= ~MFIB_ENTRY_SRC_FLAG_STALE; return (fib_path_list_paths_remove(msrc->mfes_pl, rpaths)); } @@ -792,11 +858,11 @@ static int 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 && + 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_flags) && */ + /* 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))); */ } diff --git a/src/vnet/mfib/mfib_entry.h b/src/vnet/mfib/mfib_entry.h index 4a1121bc9d5..7087fe87a4d 100644 --- a/src/vnet/mfib/mfib_entry.h +++ b/src/vnet/mfib/mfib_entry.h @@ -161,6 +161,8 @@ extern u32 mfib_entry_get_fib_index(fib_node_index_t fib_entry_index); extern int mfib_entry_is_sourced(fib_node_index_t fib_entry_index, mfib_source_t source); extern int mfib_entry_is_host(fib_node_index_t fib_entry_index); +extern int mfib_entry_is_marked(fib_node_index_t fib_entry_index, mfib_source_t source); +extern void mfib_entry_mark(fib_node_index_t fib_entry_index, mfib_source_t source); extern u32 mfib_entry_get_stats_index(fib_node_index_t fib_entry_index); extern void mfib_entry_cover_changed(fib_node_index_t fib_entry_index); extern void mfib_entry_cover_updated(fib_node_index_t fib_entry_index); diff --git a/src/vnet/mfib/mfib_entry_src.h b/src/vnet/mfib/mfib_entry_src.h index 86752e071ec..b85c010779c 100644 --- a/src/vnet/mfib/mfib_entry_src.h +++ b/src/vnet/mfib/mfib_entry_src.h @@ -28,6 +28,48 @@ typedef struct mfib_path_ext_t_ } mfib_path_ext_t; /** + * Flags for the source data + */ +typedef enum mfib_entry_src_attribute_t_ { + /** + * Marker. Add new values after this one. + */ + MFIB_ENTRY_SRC_ATTRIBUTE_FIRST, + /** + * the source has been added to the entry + */ + MFIB_ENTRY_SRC_ATTRIBUTE_STALE = MFIB_ENTRY_SRC_ATTRIBUTE_FIRST, + /** + * Marker. add new entries before this one. + */ + MFIB_ENTRY_SRC_ATTRIBUTE_LAST = MFIB_ENTRY_SRC_ATTRIBUTE_STALE, +} mfib_entry_src_attribute_t; + + +#define MFIB_ENTRY_SRC_ATTRIBUTES { \ + [MFIB_ENTRY_SRC_ATTRIBUTE_STALE] = "stale", \ +} + +#define FOR_EACH_MFIB_SRC_ATTRIBUTE(_item) \ + for (_item = MFIB_ENTRY_SRC_ATTRIBUTE_FIRST; \ + _item <= MFIB_ENTRY_SRC_ATTRIBUTE_LAST; \ + _item++) + +typedef enum mfib_entry_src_flag_t_ { + MFIB_ENTRY_SRC_FLAG_NONE = 0, + MFIB_ENTRY_SRC_FLAG_STALE = (1 << MFIB_ENTRY_SRC_ATTRIBUTE_STALE), +} __attribute__ ((packed)) mfib_entry_src_flags_t; + +extern u8 * format_mfib_entry_src_flags(u8 *s, va_list *args); + +/* + * Keep the size of the flags field to 2 bytes, so it + * can be placed next to the 2 bytes reference count + */ +STATIC_ASSERT (sizeof(mfib_entry_src_flags_t) <= 2, + "FIB entry flags field size too big"); + +/** * The source of an MFIB entry */ typedef struct mfib_entry_src_t_ @@ -40,7 +82,12 @@ typedef struct mfib_entry_src_t_ /** * Route flags */ - mfib_entry_flags_t mfes_flags; + mfib_entry_flags_t mfes_route_flags; + + /** + * Source flags + */ + mfib_entry_src_flags_t mfes_flags; /** * The reference count on the entry. this is a u32 diff --git a/src/vnet/mfib/mfib_entry_src_rr.c b/src/vnet/mfib/mfib_entry_src_rr.c index 4512f74a9f5..a6a1e0d8aa5 100644 --- a/src/vnet/mfib/mfib_entry_src_rr.c +++ b/src/vnet/mfib/mfib_entry_src_rr.c @@ -62,7 +62,7 @@ mfib_entry_src_rr_activiate (mfib_entry_t *mfib_entry, msrc->mfes_pl = csrc->mfes_pl; fib_path_list_lock(msrc->mfes_pl); - msrc->mfes_flags = csrc->mfes_flags; + msrc->mfes_route_flags = csrc->mfes_route_flags; msrc->mfes_itfs = csrc->mfes_itfs; msrc->mfes_exts = csrc->mfes_exts; msrc->mfes_rpf_id = csrc->mfes_rpf_id; @@ -91,7 +91,7 @@ mfib_entry_src_rr_cover_update (mfib_entry_t *mfib_entry, cover = mfib_entry_get(msrc->mfes_cover); - msrc->mfes_flags = cover->mfe_flags; + msrc->mfes_route_flags = cover->mfe_flags; msrc->mfes_itfs = cover->mfe_itfs; msrc->mfes_rpf_id = cover->mfe_rpf_id; diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c index 504333a2474..a6a82774794 100644 --- a/src/vnet/mfib/mfib_table.c +++ b/src/vnet/mfib/mfib_table.c @@ -24,6 +24,8 @@ #include <vnet/mfib/mfib_entry_cover.h> #include <vnet/mfib/mfib_signal.h> +const static char * mfib_table_flags_strings[] = MFIB_TABLE_ATTRIBUTES; + mfib_table_t * mfib_table_get (fib_node_index_t index, fib_protocol_t proto) @@ -643,7 +645,7 @@ typedef struct mfib_table_flush_ctx_t_ mfib_source_t mftf_source; } mfib_table_flush_ctx_t; -static int +static walk_rc_t mfib_table_flush_cb (fib_node_index_t mfib_entry_index, void *arg) { @@ -653,7 +655,7 @@ mfib_table_flush_cb (fib_node_index_t mfib_entry_index, { vec_add1(ctx->mftf_entries, mfib_entry_index); } - return (1); + return (WALK_CONTINUE); } void @@ -679,6 +681,79 @@ mfib_table_flush (u32 mfib_index, vec_free(ctx.mftf_entries); } +static walk_rc_t +mfib_table_mark_cb (fib_node_index_t fib_entry_index, + void *arg) +{ + mfib_table_flush_ctx_t *ctx = arg; + + if (mfib_entry_is_sourced(fib_entry_index, ctx->mftf_source)) + { + mfib_entry_mark(fib_entry_index, ctx->mftf_source); + } + return (WALK_CONTINUE); +} + +void +mfib_table_mark (u32 fib_index, + fib_protocol_t proto, + mfib_source_t source) +{ + mfib_table_flush_ctx_t ctx = { + .mftf_source = source, + }; + mfib_table_t *mfib_table; + + mfib_table = mfib_table_get(fib_index, proto); + + mfib_table->mft_epoch++; + mfib_table->mft_flags |= MFIB_TABLE_FLAG_RESYNC; + + mfib_table_walk(fib_index, proto, + mfib_table_mark_cb, + &ctx); +} + +static walk_rc_t +mfib_table_sweep_cb (fib_node_index_t fib_entry_index, + void *arg) +{ + mfib_table_flush_ctx_t *ctx = arg; + + if (mfib_entry_is_marked(fib_entry_index, ctx->mftf_source)) + { + vec_add1(ctx->mftf_entries, fib_entry_index); + } + return (WALK_CONTINUE); +} + +void +mfib_table_sweep (u32 fib_index, + fib_protocol_t proto, + mfib_source_t source) +{ + mfib_table_flush_ctx_t ctx = { + .mftf_source = source, + }; + fib_node_index_t *fib_entry_index; + mfib_table_t *mfib_table; + + mfib_table = mfib_table_get(fib_index, proto); + + mfib_table->mft_flags &= ~MFIB_TABLE_FLAG_RESYNC; + + mfib_table_walk(fib_index, proto, + mfib_table_sweep_cb, + &ctx); + + vec_foreach(fib_entry_index, ctx.mftf_entries) + { + mfib_table_entry_delete_index(*fib_entry_index, source); + } + + vec_free(ctx.mftf_entries); +} + static void mfib_table_destroy (mfib_table_t *mfib_table) { @@ -770,6 +845,26 @@ mfib_table_walk (u32 fib_index, } u8* +format_mfib_table_flags (u8 *s, va_list *args) +{ + mfib_table_flags_t flags = va_arg(*args, int); + mfib_table_attribute_t attr; + + if (!flags) + { + return format(s, "none"); + } + + FOR_EACH_MFIB_TABLE_ATTRIBUTE(attr) { + if (1 << attr & flags) { + s = format(s, "%s", mfib_table_flags_strings[attr]); + } + } + + return (s); +} + +u8* format_mfib_table_name (u8* s, va_list *ap) { fib_node_index_t fib_index = va_arg(*ap, fib_node_index_t); diff --git a/src/vnet/mfib/mfib_table.h b/src/vnet/mfib/mfib_table.h index 47461375a10..d6b6dc3845d 100644 --- a/src/vnet/mfib/mfib_table.h +++ b/src/vnet/mfib/mfib_table.h @@ -29,6 +29,42 @@ #define MFIB_TABLE_TOTAL_LOCKS MFIB_N_SOURCES /** + * Flags for the source data + */ +typedef enum mfib_table_attribute_t_ { + /** + * Marker. Add new values after this one. + */ + MFIB_TABLE_ATTRIBUTE_FIRST, + /** + * the table is currently resync-ing + */ + MFIB_TABLE_ATTRIBUTE_RESYNC = MFIB_TABLE_ATTRIBUTE_FIRST, + /** + * Marker. add new entries before this one. + */ + MFIB_TABLE_ATTRIBUTE_LAST = MFIB_TABLE_ATTRIBUTE_RESYNC, +} mfib_table_attribute_t; + +#define MFIB_TABLE_ATTRIBUTE_MAX (MFIB_TABLE_ATTRIBUTE_LAST+1) + +#define MFIB_TABLE_ATTRIBUTES { \ + [MFIB_TABLE_ATTRIBUTE_RESYNC] = "resync", \ +} + +#define FOR_EACH_MFIB_TABLE_ATTRIBUTE(_item) \ + for (_item = MFIB_TABLE_ATTRIBUTE_FIRST; \ + _item < MFIB_TABLE_ATTRIBUTE_MAX; \ + _item++) + +typedef enum mfib_table_flags_t_ { + MFIB_TABLE_FLAG_NONE = 0, + MFIB_TABLE_FLAG_RESYNC = (1 << MFIB_TABLE_ATTRIBUTE_RESYNC), +} __attribute__ ((packed)) mfib_table_flags_t; + +extern u8* format_mfib_table_flags(u8 *s, va_list *args); + +/** * @brief * A protocol Independent IP multicast FIB table */ @@ -56,6 +92,11 @@ typedef struct mfib_table_t_ fib_protocol_t mft_proto; /** + * table falgs + */ + mfib_table_flags_t mft_flags; + + /** * number of locks on the table */ u16 mft_locks[MFIB_TABLE_N_LOCKS]; @@ -66,6 +107,11 @@ typedef struct mfib_table_t_ u32 mft_table_id; /** + * resync epoch + */ + u32 mft_epoch; + + /** * Index into FIB vector. */ fib_node_index_t mft_index; @@ -282,6 +328,46 @@ extern void mfib_table_flush(u32 fib_index, /** * @brief + * Resync all entries from a table for the source + * this is the mark part of the mark and sweep algorithm. + * All entries in this FIB that are sourced by 'source' are marked + * as stale. + * + * @param fib_index + * The index of the FIB + * + * @paran proto + * The protocol of the entries in the table + * + * @param source + * the source to flush + */ +extern void mfib_table_mark(u32 fib_index, + fib_protocol_t proto, + mfib_source_t source); + +/** + * @brief + * Signal that the table has converged, i.e. all updates are complete. + * this is the sweep part of the mark and sweep algorithm. + * All entries in this FIB that are sourced by 'source' and marked + * as stale are flushed. + * + * @param fib_index + * The index of the FIB + * + * @paran proto + * The protocol of the entries in the table + * + * @param source + * the source to flush + */ +extern void mfib_table_sweep(u32 fib_index, + fib_protocol_t proto, + mfib_source_t source); + +/** + * @brief * Get the index of the FIB bound to the interface * * @paran proto @@ -465,8 +551,8 @@ extern mfib_table_t *mfib_table_get(fib_node_index_t index, /** * @brief Call back function when walking entries in a FIB table */ -typedef int (*mfib_table_walk_fn_t)(fib_node_index_t fei, - void *ctx); +typedef walk_rc_t (*mfib_table_walk_fn_t)(fib_node_index_t fei, + void *ctx); /** * @brief Walk all entries in a FIB table |