summaryrefslogtreecommitdiffstats
path: root/src/vnet/mfib
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/mfib')
-rw-r--r--src/vnet/mfib/mfib_entry.c90
-rw-r--r--src/vnet/mfib/mfib_entry.h5
-rw-r--r--src/vnet/mfib/mfib_table.c35
-rw-r--r--src/vnet/mfib/mfib_table.h32
-rw-r--r--src/vnet/mfib/mfib_test.c56
-rw-r--r--src/vnet/mfib/mfib_types.h14
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", \
}