diff options
author | Neale Ranns <nranns@cisco.com> | 2017-02-02 02:18:18 -0800 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2017-02-02 14:27:13 +0000 |
commit | a9374df5f351d25e968f5f90a827796203cbafdd (patch) | |
tree | 7876e45e388ebc739722777c1cadcf666dda6439 /src/vnet/mfib | |
parent | ed0e49c51841e84c72a5bb2c6d538ee779b734d4 (diff) |
Fix SR multicast post mfib commit
1 - use the SR policy to construct the replicate DPO. Each bucket therein is a SR tunnel.
2 - install a special mfib entry that links via this replicate
3 - forwarding is now mfib-lookup -> replicate -> sr_rewrite (per-tunnel)
no need for a separate sr_replicate node.
4 - Stack the sr tunnel on the forwarding DPO of the first-hop FIB entry.
no need for a second lookup post SR encap.
5 - fix some path-list lock leaks in the MFIB entry.
Change-Id: I20de96ea4c4be4fae252625bde159d9c435c8315
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/mfib')
-rw-r--r-- | src/vnet/mfib/mfib_entry.c | 90 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_entry.h | 5 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_table.c | 35 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_table.h | 32 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_test.c | 56 | ||||
-rw-r--r-- | src/vnet/mfib/mfib_types.h | 14 |
6 files changed, 210 insertions, 22 deletions
diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index 479ce5f1442..5170080c4ca 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -292,6 +292,7 @@ mfib_entry_src_flush (mfib_entry_src_t *msrc) ({ mfib_itf_delete(mfib_itf_get(mfii)); })); + fib_path_list_unlock(msrc->mfes_pl); } static void @@ -474,37 +475,60 @@ mfib_entry_src_collect_forwarding (fib_node_index_t pl_index, static void mfib_entry_stack (mfib_entry_t *mfib_entry) { - mfib_entry_collect_forwarding_ctx_t ctx = { - .next_hops = NULL, - .fct = mfib_entry_get_default_chain_type(mfib_entry), - }; dpo_proto_t dp; dp = fib_proto_to_dpo(mfib_entry_get_proto(mfib_entry)); if (FIB_NODE_INDEX_INVALID != mfib_entry->mfe_parent) { + mfib_entry_collect_forwarding_ctx_t ctx = { + .next_hops = NULL, + .fct = mfib_entry_get_default_chain_type(mfib_entry), + }; + fib_path_list_walk(mfib_entry->mfe_parent, mfib_entry_src_collect_forwarding, &ctx); - if (!dpo_id_is_valid(&mfib_entry->mfe_rep) || - dpo_is_drop(&mfib_entry->mfe_rep)) + if (!(MFIB_ENTRY_FLAG_EXCLUSIVE & mfib_entry->mfe_flags)) { - dpo_id_t tmp_dpo = DPO_INVALID; + /* + * each path contirbutes a next-hop. form a replicate + * from those choices. + */ + if (!dpo_id_is_valid(&mfib_entry->mfe_rep) || + dpo_is_drop(&mfib_entry->mfe_rep)) + { + dpo_id_t tmp_dpo = DPO_INVALID; - dpo_set(&tmp_dpo, - DPO_REPLICATE, dp, - replicate_create(0, dp)); + dpo_set(&tmp_dpo, + DPO_REPLICATE, dp, + replicate_create(0, dp)); + + dpo_stack(DPO_MFIB_ENTRY, dp, + &mfib_entry->mfe_rep, + &tmp_dpo); + + dpo_reset(&tmp_dpo); + } + replicate_multipath_update(&mfib_entry->mfe_rep, + ctx.next_hops); + } + else + { + /* + * for exclusive routes the source provided a replicate DPO + * we we stashed inthe 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, - &tmp_dpo); - - dpo_reset(&tmp_dpo); + &ctx.next_hops[0].path_dpo); + dpo_reset(&ctx.next_hops[0].path_dpo); + vec_free(ctx.next_hops); } - replicate_multipath_update(&mfib_entry->mfe_rep, - ctx.next_hops); } else { @@ -521,6 +545,8 @@ mfib_entry_forwarding_path_add (mfib_entry_src_t *msrc, fib_node_index_t old_pl_index; fib_route_path_t *rpaths; + ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); + /* * path-lists require a vector of paths */ @@ -555,6 +581,8 @@ mfib_entry_forwarding_path_remove (mfib_entry_src_t *msrc, fib_node_index_t old_pl_index; fib_route_path_t *rpaths; + ASSERT(!(MFIB_ENTRY_FLAG_EXCLUSIVE & msrc->mfes_flags)); + /* * path-lists require a vector of paths */ @@ -650,7 +678,8 @@ mfib_entry_src_ok_for_delete (const mfib_entry_src_t *msrc) int mfib_entry_update (fib_node_index_t mfib_entry_index, mfib_source_t source, - mfib_entry_flags_t entry_flags) + mfib_entry_flags_t entry_flags, + index_t repi) { mfib_entry_t *mfib_entry; mfib_entry_src_t *msrc; @@ -659,6 +688,35 @@ mfib_entry_update (fib_node_index_t mfib_entry_index, msrc = mfib_entry_src_find_or_create(mfib_entry, source); msrc->mfes_flags = entry_flags; + 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; + fib_protocol_t fp; + dpo_id_t dpo = DPO_INVALID; + + fp = mfib_entry_get_proto(mfib_entry); + old_pl_index = msrc->mfes_pl; + + dpo_set(&dpo, DPO_REPLICATE, + fib_proto_to_dpo(fp), + repi); + + msrc->mfes_pl = + fib_path_list_create_special(fp, + FIB_PATH_LIST_FLAG_EXCLUSIVE, + &dpo); + + dpo_reset(&dpo); + fib_path_list_lock(msrc->mfes_pl); + fib_path_list_unlock(old_pl_index); + } + if (mfib_entry_src_ok_for_delete(msrc)) { /* diff --git a/src/vnet/mfib/mfib_entry.h b/src/vnet/mfib/mfib_entry.h index cc5d5326ef6..36fc73e1670 100644 --- a/src/vnet/mfib/mfib_entry.h +++ b/src/vnet/mfib/mfib_entry.h @@ -65,7 +65,7 @@ typedef struct mfib_entry_t_ { CLIB_CACHE_LINE_ALIGN_MARK(cacheline1); /** - * The Replicate used for forwarding. + * The Replicate DPO used for forwarding. */ dpo_id_t mfe_rep; @@ -94,7 +94,8 @@ extern fib_node_index_t mfib_entry_create(u32 fib_index, extern int mfib_entry_update(fib_node_index_t fib_entry_index, mfib_source_t source, - mfib_entry_flags_t entry_flags); + mfib_entry_flags_t entry_flags, + index_t rep_dpo); extern void mfib_entry_path_update(fib_node_index_t fib_entry_index, mfib_source_t source, diff --git a/src/vnet/mfib/mfib_table.c b/src/vnet/mfib/mfib_table.c index e4c0936d6c9..b4e855ff071 100644 --- a/src/vnet/mfib/mfib_table.c +++ b/src/vnet/mfib/mfib_table.c @@ -195,7 +195,10 @@ mfib_table_entry_update (u32 fib_index, { mfib_entry_lock(mfib_entry_index); - if (mfib_entry_update(mfib_entry_index, source, entry_flags)) + if (mfib_entry_update(mfib_entry_index, + source, + entry_flags, + INDEX_INVALID)) { /* * this update means we can now remove the entry. @@ -283,6 +286,36 @@ mfib_table_entry_path_remove (u32 fib_index, } } +fib_node_index_t +mfib_table_entry_special_add (u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + mfib_entry_flags_t entry_flags, + index_t rep_dpo) +{ + fib_node_index_t mfib_entry_index; + mfib_table_t *mfib_table; + + mfib_table = mfib_table_get(fib_index, prefix->fp_proto); + mfib_entry_index = mfib_table_lookup_exact_match_i(mfib_table, prefix); + + if (FIB_NODE_INDEX_INVALID == mfib_entry_index) + { + mfib_entry_index = mfib_entry_create(fib_index, + source, + prefix, + MFIB_ENTRY_FLAG_NONE); + + mfib_table_entry_insert(mfib_table, prefix, mfib_entry_index); + } + + mfib_entry_update(mfib_entry_index, source, + (MFIB_ENTRY_FLAG_EXCLUSIVE | entry_flags), + rep_dpo); + + return (mfib_entry_index); +} + static void mfib_table_entry_delete_i (u32 fib_index, fib_node_index_t mfib_entry_index, diff --git a/src/vnet/mfib/mfib_table.h b/src/vnet/mfib/mfib_table.h index 4faa69ee999..4c51b70fd72 100644 --- a/src/vnet/mfib/mfib_table.h +++ b/src/vnet/mfib/mfib_table.h @@ -18,6 +18,7 @@ #include <vnet/ip/ip.h> #include <vnet/adj/adj.h> +#include <vnet/dpo/replicate_dpo.h> #include <vnet/mfib/mfib_types.h> @@ -214,6 +215,37 @@ extern void mfib_table_entry_delete_index(fib_node_index_t entry_index, /** * @brief + * Add a 'special' entry to the mFIB that links to the DPO passed + * A special entry is an entry that the FIB is not expect to resolve + * via the usual mechanisms (i.e. recurisve or neighbour adj DB lookup). + * Instead the client/source provides the index of a replicate DPO to link to. + * + * @param fib_index + * The index of the FIB + * + * @param prefix + * The prefix to add + * + * @param source + * The ID of the client/source adding the entry. + * + * @param flags + * Flags for the entry. + * + * @param rep_dpo + * The replicate DPO index to link to. + * + * @return + * the index of the fib_entry_t that is created (or existed already). + */ +extern fib_node_index_t mfib_table_entry_special_add(u32 fib_index, + const mfib_prefix_t *prefix, + mfib_source_t source, + mfib_entry_flags_t flags, + index_t rep_dpo); + +/** + * @brief * Flush all entries from a table for the source * * @param fib_index diff --git a/src/vnet/mfib/mfib_test.c b/src/vnet/mfib/mfib_test.c index 8082a6bb606..36a303e844d 100644 --- a/src/vnet/mfib/mfib_test.c +++ b/src/vnet/mfib/mfib_test.c @@ -19,6 +19,7 @@ #include <vnet/mfib/mfib_entry.h> #include <vnet/mfib/mfib_signal.h> #include <vnet/mfib/ip6_mfib.h> +#include <vnet/fib/fib_path_list.h> #include <vnet/dpo/replicate_dpo.h> #include <vnet/adj/adj_mcast.h> @@ -337,7 +338,7 @@ mfib_test_i (fib_protocol_t PROTO, const mfib_prefix_t *pfx_star_g_slash_m) { fib_node_index_t mfei, mfei_dflt, mfei_no_f, mfei_s_g, mfei_g_1, mfei_g_2, mfei_g_3, mfei_g_m; - u32 fib_index, n_entries, n_itfs, n_reps; + u32 fib_index, n_entries, n_itfs, n_reps, n_pls; fib_node_index_t ai_1, ai_2, ai_3; test_main_t *tm; @@ -347,6 +348,7 @@ mfib_test_i (fib_protocol_t PROTO, n_entries = pool_elts(mfib_entry_pool); n_itfs = pool_elts(mfib_itf_pool); n_reps = pool_elts(replicate_pool); + n_pls = fib_path_list_pool_size(); tm = &test_main; ai_1 = adj_mcast_add_or_lock(PROTO, @@ -1024,6 +1026,54 @@ mfib_test_i (fib_protocol_t PROTO, format_mfib_prefix, pfx_star_g_slash_m); /* + * Add a prefix as a special/exclusive route + */ + dpo_id_t td = DPO_INVALID; + index_t repi = replicate_create(1, fib_proto_to_dpo(PROTO)); + + dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_2); + replicate_set_bucket(repi, 0, &td); + + mfei = mfib_table_entry_special_add(fib_index, + pfx_star_g_3, + MFIB_SOURCE_SRv6, + MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF, + repi); + MFIB_TEST(mfib_test_entry(mfei, + (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF | + MFIB_ENTRY_FLAG_EXCLUSIVE), + 1, + DPO_ADJACENCY_MCAST, ai_2), + "%U exclusive replicate OK", + format_mfib_prefix, pfx_star_g_3); + + /* + * update a special/exclusive route + */ + index_t repi2 = replicate_create(1, fib_proto_to_dpo(PROTO)); + + dpo_set(&td, DPO_ADJACENCY_MCAST, fib_proto_to_dpo(PROTO), ai_1); + replicate_set_bucket(repi2, 0, &td); + + mfei = mfib_table_entry_special_add(fib_index, + pfx_star_g_3, + MFIB_SOURCE_SRv6, + MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF, + repi2); + MFIB_TEST(mfib_test_entry(mfei, + (MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF | + MFIB_ENTRY_FLAG_EXCLUSIVE), + 1, + DPO_ADJACENCY_MCAST, ai_1), + "%U exclusive update replicate OK", + format_mfib_prefix, pfx_star_g_3); + + mfib_table_entry_delete(fib_index, + pfx_star_g_3, + MFIB_SOURCE_SRv6); + dpo_reset(&td); + + /* * Unlock the table - it's the last lock so should be gone thereafter */ mfib_table_unlock(fib_index, PROTO); @@ -1040,6 +1090,8 @@ mfib_test_i (fib_protocol_t PROTO, * test we've leaked no resources */ MFIB_TEST(0 == adj_mcast_db_size(), "%d MCAST adjs", adj_mcast_db_size()); + MFIB_TEST(n_pls == fib_path_list_pool_size(), "%d=%d path-lists", + n_pls, fib_path_list_pool_size()); MFIB_TEST(n_reps == pool_elts(replicate_pool), "%d=%d replicates", n_reps, pool_elts(replicate_pool)); MFIB_TEST(n_entries == pool_elts(mfib_entry_pool), @@ -1214,7 +1266,7 @@ mfib_test (vlib_main_t * vm, VLIB_CLI_COMMAND (test_fib_command, static) = { .path = "test mfib", - .short_help = "fib unit tests - DO NOT RUN ON A LIVE SYSTEM", + .short_help = "mfib unit tests - DO NOT RUN ON A LIVE SYSTEM", .function = mfib_test, }; diff --git a/src/vnet/mfib/mfib_types.h b/src/vnet/mfib/mfib_types.h index 37898a07b00..fe53aa6807a 100644 --- a/src/vnet/mfib/mfib_types.h +++ b/src/vnet/mfib/mfib_types.h @@ -68,6 +68,13 @@ typedef enum mfib_entry_attribute_t_ * Use with extreme caution */ MFIB_ENTRY_ACCEPT_ALL_ITF, + /** + * Exclusive - like its unicast counterpart. the source has provided + * the forwarding DPO directly. The entry therefore does not resolve + * paths via a path-list + */ + MFIB_ENTRY_EXCLUSIVE, + MFIB_ENTRY_INHERIT_ACCEPT, MFIB_ENTRY_ATTRIBUTE_LAST = MFIB_ENTRY_INHERIT_ACCEPT, } mfib_entry_attribute_t; @@ -83,6 +90,7 @@ typedef enum mfib_entry_attribute_t_ [MFIB_ENTRY_DROP] = "D", \ [MFIB_ENTRY_ACCEPT_ALL_ITF] = "AA", \ [MFIB_ENTRY_INHERIT_ACCEPT] = "IA", \ + [MFIB_ENTRY_EXCLUSIVE] = "E", \ } #define MFIB_ENTRY_NAMES_LONG { \ @@ -91,6 +99,7 @@ typedef enum mfib_entry_attribute_t_ [MFIB_ENTRY_DROP] = "Drop", \ [MFIB_ENTRY_ACCEPT_ALL_ITF] = "Accept-all-itf", \ [MFIB_ENTRY_INHERIT_ACCEPT] = "Inherit-Accept", \ + [MFIB_ENTRY_EXCLUSIVE] = "Exclusive", \ } typedef enum mfib_entry_flags_t_ @@ -99,8 +108,9 @@ typedef enum mfib_entry_flags_t_ MFIB_ENTRY_FLAG_SIGNAL = (1 << MFIB_ENTRY_SIGNAL), MFIB_ENTRY_FLAG_DROP = (1 << MFIB_ENTRY_DROP), MFIB_ENTRY_FLAG_CONNECTED = (1 << MFIB_ENTRY_CONNECTED), - MFIB_ENTRY_FLAG_INHERIT_ACCEPT = (1 << MFIB_ENTRY_INHERIT_ACCEPT), MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF = (1 << MFIB_ENTRY_ACCEPT_ALL_ITF), + MFIB_ENTRY_FLAG_EXCLUSIVE = (1 << MFIB_ENTRY_EXCLUSIVE), + MFIB_ENTRY_FLAG_INHERIT_ACCEPT = (1 << MFIB_ENTRY_INHERIT_ACCEPT), } mfib_entry_flags_t; typedef enum mfib_itf_attribute_t_ @@ -155,6 +165,7 @@ typedef enum mfib_source_t_ MFIB_SOURCE_CLI, MFIB_SOURCE_VXLAN, MFIB_SOURCE_DHCP, + MFIB_SOURCE_SRv6, MFIB_SOURCE_DEFAULT_ROUTE, } mfib_source_t; @@ -164,6 +175,7 @@ typedef enum mfib_source_t_ [MFIB_SOURCE_CLI] = "CLI", \ [MFIB_SOURCE_DHCP] = "DHCP", \ [MFIB_SOURCE_VXLAN] = "VXLAN", \ + [MFIB_SOURCE_SRv6] = "SRv6", \ [MFIB_SOURCE_DEFAULT_ROUTE] = "Default Route", \ } |