IP mcast: allow unicast address as a next-hop
Change-Id: I5e679f2601e37688f2768620479dc2efb7d19ca3 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
committed by
Damjan Marion
parent
167d458cba
commit
e821ab100a
@@ -2323,6 +2323,8 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
|
||||
case FIB_FORW_CHAIN_TYPE_ETHERNET:
|
||||
case FIB_FORW_CHAIN_TYPE_NSH:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
{
|
||||
adj_index_t ai;
|
||||
|
||||
@@ -2338,8 +2340,6 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
|
||||
|
||||
break;
|
||||
}
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
|
||||
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
|
||||
case FIB_FORW_CHAIN_TYPE_BIER:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -446,6 +446,7 @@ autoreply define ip_mroute_add_del
|
||||
u8 is_local;
|
||||
u8 grp_address[16];
|
||||
u8 src_address[16];
|
||||
u8 nh_address[16];
|
||||
};
|
||||
|
||||
/** \brief Dump IP multicast fib table
|
||||
|
||||
@@ -1208,13 +1208,15 @@ mroute_add_del_handler (u8 is_add,
|
||||
dpo_proto_t nh_proto,
|
||||
u32 entry_flags,
|
||||
fib_rpf_id_t rpf_id,
|
||||
u32 next_hop_sw_if_index, u32 itf_flags, u32 bier_imp)
|
||||
u32 next_hop_sw_if_index,
|
||||
ip46_address_t * nh, u32 itf_flags, u32 bier_imp)
|
||||
{
|
||||
stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
|
||||
|
||||
fib_route_path_t path = {
|
||||
.frp_sw_if_index = next_hop_sw_if_index,
|
||||
.frp_proto = nh_proto,
|
||||
.frp_addr = *nh,
|
||||
};
|
||||
|
||||
if (is_local)
|
||||
@@ -1253,6 +1255,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
|
||||
{
|
||||
fib_protocol_t fproto;
|
||||
dpo_proto_t nh_proto;
|
||||
ip46_address_t nh;
|
||||
u32 fib_index;
|
||||
int rv;
|
||||
|
||||
@@ -1277,6 +1280,8 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
|
||||
sizeof (pfx.fp_grp_addr.ip4));
|
||||
clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
|
||||
sizeof (pfx.fp_src_addr.ip4));
|
||||
memset (&nh.ip6, 0, sizeof (nh.ip6));
|
||||
clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1284,6 +1289,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
|
||||
sizeof (pfx.fp_grp_addr.ip6));
|
||||
clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
|
||||
sizeof (pfx.fp_src_addr.ip6));
|
||||
clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6));
|
||||
}
|
||||
|
||||
return (mroute_add_del_handler (mp->is_add,
|
||||
@@ -1293,6 +1299,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
|
||||
ntohl (mp->entry_flags),
|
||||
ntohl (mp->rpf_id),
|
||||
ntohl (mp->next_hop_sw_if_index),
|
||||
&nh,
|
||||
ntohl (mp->itf_flags),
|
||||
ntohl (mp->bier_imp)));
|
||||
}
|
||||
|
||||
+17
-1
@@ -899,14 +899,30 @@ vnet_ip_mroute_cmd (vlib_main_t * vm,
|
||||
pfx.fp_proto = FIB_PROTOCOL_IP6;
|
||||
pfx.fp_len = 128;
|
||||
}
|
||||
else if (unformat (line_input, "via %U",
|
||||
else if (unformat (line_input, "via %U %U",
|
||||
unformat_ip4_address, &rpath.frp_addr.ip4,
|
||||
unformat_vnet_sw_interface, vnm,
|
||||
&rpath.frp_sw_if_index))
|
||||
{
|
||||
rpath.frp_weight = 1;
|
||||
}
|
||||
else if (unformat (line_input, "via %U %U",
|
||||
unformat_ip6_address, &rpath.frp_addr.ip6,
|
||||
unformat_vnet_sw_interface, vnm,
|
||||
&rpath.frp_sw_if_index))
|
||||
{
|
||||
rpath.frp_weight = 1;
|
||||
}
|
||||
else if (unformat (line_input, "via %U",
|
||||
unformat_vnet_sw_interface, vnm,
|
||||
&rpath.frp_sw_if_index))
|
||||
{
|
||||
memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
|
||||
rpath.frp_weight = 1;
|
||||
}
|
||||
else if (unformat (line_input, "via local"))
|
||||
{
|
||||
memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
|
||||
rpath.frp_sw_if_index = ~0;
|
||||
rpath.frp_weight = 1;
|
||||
rpath.frp_flags |= FIB_ROUTE_PATH_LOCAL;
|
||||
|
||||
+39
-27
@@ -217,7 +217,10 @@ format_mfib_entry (u8 * s, va_list * args)
|
||||
({
|
||||
s = format(s, "\n %U", format_mfib_itf, mfi);
|
||||
}));
|
||||
s = format(s, "\n RPF-ID:%d", mfib_entry->mfe_rpf_id);
|
||||
if (MFIB_RPF_ID_NONE != mfib_entry->mfe_rpf_id)
|
||||
{
|
||||
s = format(s, "\n RPF-ID:%d", mfib_entry->mfe_rpf_id);
|
||||
}
|
||||
s = format(s, "\n %U-chain\n %U",
|
||||
format_fib_forw_chain_type,
|
||||
mfib_entry_get_default_chain_type(mfib_entry),
|
||||
@@ -835,9 +838,9 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index,
|
||||
{
|
||||
fib_node_index_t path_index;
|
||||
mfib_path_ext_t *path_ext;
|
||||
mfib_itf_flags_t old, new;
|
||||
mfib_entry_t *mfib_entry;
|
||||
mfib_entry_src_t *msrc;
|
||||
mfib_itf_flags_t old;
|
||||
|
||||
mfib_entry = mfib_entry_get(mfib_entry_index);
|
||||
ASSERT(NULL != mfib_entry);
|
||||
@@ -873,37 +876,32 @@ mfib_entry_path_update (fib_node_index_t mfib_entry_index,
|
||||
{
|
||||
mfib_itf_t *mfib_itf;
|
||||
|
||||
new = itf_flags;
|
||||
|
||||
if (old != new)
|
||||
if (old != itf_flags)
|
||||
{
|
||||
if (MFIB_ITF_FLAG_NONE == new)
|
||||
/*
|
||||
* change of flag contributions
|
||||
*/
|
||||
mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
|
||||
rpath[0].frp_sw_if_index);
|
||||
|
||||
if (NULL == mfib_itf)
|
||||
{
|
||||
/*
|
||||
* no more interface flags on this path, remove
|
||||
* from the data-plane set
|
||||
*/
|
||||
mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
|
||||
}
|
||||
else if (MFIB_ITF_FLAG_NONE == old)
|
||||
{
|
||||
/*
|
||||
* This interface is now contributing
|
||||
*/
|
||||
mfib_entry_itf_add(msrc,
|
||||
rpath[0].frp_sw_if_index,
|
||||
mfib_itf_create(rpath[0].frp_sw_if_index,
|
||||
itf_flags));
|
||||
mfib_itf_create(path_index, itf_flags));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* change of flag contributions
|
||||
*/
|
||||
mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
|
||||
rpath[0].frp_sw_if_index);
|
||||
/* Seen by packets inflight */
|
||||
mfib_itf->mfi_flags = new;
|
||||
if (mfib_itf_update(mfib_itf,
|
||||
path_index,
|
||||
itf_flags))
|
||||
{
|
||||
/*
|
||||
* no more interface flags on this path, remove
|
||||
* from the data-plane set
|
||||
*/
|
||||
mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -952,7 +950,21 @@ mfib_entry_path_remove (fib_node_index_t mfib_entry_index,
|
||||
mfib_path_ext_remove(msrc, path_index);
|
||||
if (~0 != rpath[0].frp_sw_if_index)
|
||||
{
|
||||
mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
|
||||
mfib_itf_t *mfib_itf;
|
||||
|
||||
mfib_itf = mfib_entry_itf_find(msrc->mfes_itfs,
|
||||
rpath[0].frp_sw_if_index);
|
||||
|
||||
if (mfib_itf_update(mfib_itf,
|
||||
path_index,
|
||||
MFIB_ITF_FLAG_NONE))
|
||||
{
|
||||
/*
|
||||
* no more interface flags on this path, remove
|
||||
* from the data-plane set
|
||||
*/
|
||||
mfib_entry_itf_remove(msrc, rpath[0].frp_sw_if_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
|
||||
#include <vnet/mfib/mfib_itf.h>
|
||||
#include <vnet/mfib/mfib_signal.h>
|
||||
#include <vnet/fib/fib_path.h>
|
||||
|
||||
mfib_itf_t *mfib_itf_pool;
|
||||
|
||||
index_t
|
||||
mfib_itf_create (u32 sw_if_index,
|
||||
mfib_itf_create (fib_node_index_t path_index,
|
||||
mfib_itf_flags_t mfi_flags)
|
||||
{
|
||||
mfib_itf_t *mfib_itf;
|
||||
@@ -29,16 +30,89 @@ mfib_itf_create (u32 sw_if_index,
|
||||
pool_get_aligned(mfib_itf_pool, mfib_itf,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
mfib_itf->mfi_sw_if_index = sw_if_index;
|
||||
mfib_itf->mfi_flags = mfi_flags;
|
||||
mfib_itf->mfi_sw_if_index = fib_path_get_resolving_interface(path_index);
|
||||
mfib_itf->mfi_si = INDEX_INVALID;
|
||||
|
||||
/*
|
||||
* add the path index to the per-path hash
|
||||
*/
|
||||
mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash, path_index, mfi_flags);
|
||||
|
||||
/*
|
||||
* the combined flags from all the paths is from just the one contributor
|
||||
*/
|
||||
mfib_itf->mfi_flags = mfi_flags;
|
||||
|
||||
return (mfib_itf - mfib_itf_pool);
|
||||
}
|
||||
|
||||
static mfib_itf_flags_t
|
||||
mfib_itf_mk_flags (const mfib_itf_t *mfib_itf)
|
||||
{
|
||||
mfib_itf_flags_t combined_flags, flags;
|
||||
fib_node_index_t *path_index;
|
||||
|
||||
combined_flags = MFIB_ITF_FLAG_NONE;
|
||||
|
||||
hash_foreach(path_index, flags, mfib_itf->mfi_hash,
|
||||
{
|
||||
combined_flags |= flags;
|
||||
});
|
||||
|
||||
return (combined_flags);
|
||||
}
|
||||
|
||||
int
|
||||
mfib_itf_update (mfib_itf_t *mfib_itf,
|
||||
fib_node_index_t path_index,
|
||||
mfib_itf_flags_t mfi_flags)
|
||||
{
|
||||
/*
|
||||
* add or remove the path index to the per-path hash
|
||||
*/
|
||||
if (MFIB_ITF_FLAG_NONE == mfi_flags)
|
||||
{
|
||||
hash_unset(mfib_itf->mfi_hash, path_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfib_itf->mfi_hash = hash_set(mfib_itf->mfi_hash,
|
||||
path_index,
|
||||
mfi_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* re-generate the combined flags from all the paths.
|
||||
*/
|
||||
mfib_itf->mfi_flags = mfib_itf_mk_flags(mfib_itf);
|
||||
|
||||
/*
|
||||
* The interface can be removed if there are no more flags
|
||||
*/
|
||||
return (MFIB_ITF_FLAG_NONE == mfib_itf->mfi_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
mfib_itf_hash_flush (mfib_itf_t *mfi)
|
||||
{
|
||||
fib_node_index_t path_index, *path_indexp, *all = NULL;
|
||||
mfib_itf_flags_t flags;
|
||||
|
||||
hash_foreach(path_index, flags, mfi->mfi_hash,
|
||||
{
|
||||
vec_add1(all, path_index);
|
||||
});
|
||||
|
||||
vec_foreach(path_indexp, all)
|
||||
{
|
||||
hash_unset(mfi->mfi_hash, *path_indexp);
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
mfib_itf_delete (mfib_itf_t *mfi)
|
||||
{
|
||||
mfib_itf_hash_flush(mfi);
|
||||
mfib_signal_remove_itf(mfi);
|
||||
pool_put(mfib_itf_pool, mfi);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
typedef struct mfib_itf_t_
|
||||
{
|
||||
/**
|
||||
* @brief Falags on the entry
|
||||
* @brief Forwarding Flags on the entry - checked in the data-path
|
||||
*/
|
||||
mfib_itf_flags_t mfi_flags;
|
||||
|
||||
@@ -38,22 +38,43 @@ typedef struct mfib_itf_t_
|
||||
* The index of the signal in the pending list
|
||||
*/
|
||||
u32 mfi_si;
|
||||
|
||||
/**
|
||||
* A hash table of path-inidices that are contributing flags to this interface.
|
||||
* Since paths with next-hops can be on the same interface and each of those
|
||||
* paths can contribute different flags, we need to maintain the flag
|
||||
* contribution from each path, and use a combination for forwarding.
|
||||
*/
|
||||
uword *mfi_hash;
|
||||
} mfib_itf_t;
|
||||
|
||||
/**
|
||||
* update an interface from a path.
|
||||
* returns 1 if the entry is removed, i.e. has no flags left, as a result
|
||||
* of the update.
|
||||
*/
|
||||
extern int mfib_itf_update(mfib_itf_t *itf,
|
||||
fib_node_index_t path_index,
|
||||
mfib_itf_flags_t mfi_flags);
|
||||
|
||||
extern index_t mfib_itf_create(u32 sw_if_index,
|
||||
extern index_t mfib_itf_create(fib_node_index_t path_index,
|
||||
mfib_itf_flags_t mfi_flags);
|
||||
extern void mfib_itf_delete(mfib_itf_t *mfi);
|
||||
|
||||
extern void mfib_itf_delete(mfib_itf_t *itf);
|
||||
|
||||
extern u8 *format_mfib_itf(u8 * s, va_list * args);
|
||||
|
||||
extern mfib_itf_t *mfib_itf_pool;
|
||||
|
||||
/**
|
||||
* Get the MFIB interface representation
|
||||
*/
|
||||
static inline mfib_itf_t *
|
||||
mfib_itf_get (index_t mi)
|
||||
{
|
||||
return (pool_elt_at_index(mfib_itf_pool, mi));
|
||||
}
|
||||
|
||||
static inline index_t
|
||||
mfib_itf_get_index (const mfib_itf_t *mfi)
|
||||
{
|
||||
|
||||
+139
-5
@@ -347,11 +347,14 @@ mfib_test_i (fib_protocol_t PROTO,
|
||||
const mfib_prefix_t *pfx_star_g_1,
|
||||
const mfib_prefix_t *pfx_star_g_2,
|
||||
const mfib_prefix_t *pfx_star_g_3,
|
||||
const mfib_prefix_t *pfx_star_g_slash_m)
|
||||
const mfib_prefix_t *pfx_star_g_slash_m,
|
||||
const fib_prefix_t *pfx_itf,
|
||||
const ip46_address_t *addr_nbr1,
|
||||
const ip46_address_t *addr_nbr2)
|
||||
{
|
||||
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, n_pls;
|
||||
fib_node_index_t ai_1, ai_2, ai_3;
|
||||
fib_node_index_t ai_1, ai_2, ai_3, ai_nbr1, ai_nbr2;
|
||||
test_main_t *tm;
|
||||
int res;
|
||||
|
||||
@@ -374,12 +377,33 @@ mfib_test_i (fib_protocol_t PROTO,
|
||||
ai_3 = adj_mcast_add_or_lock(PROTO,
|
||||
LINKT,
|
||||
tm->hw[3]->sw_if_index);
|
||||
ai_nbr1 = adj_nbr_add_or_lock(PROTO,
|
||||
LINKT,
|
||||
addr_nbr1,
|
||||
tm->hw[0]->sw_if_index);
|
||||
ai_nbr2 = adj_nbr_add_or_lock(PROTO,
|
||||
LINKT,
|
||||
addr_nbr2,
|
||||
tm->hw[0]->sw_if_index);
|
||||
|
||||
MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
|
||||
|
||||
/* Find or create FIB table 11 */
|
||||
fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
|
||||
|
||||
fib_table_entry_update_one_path(0,
|
||||
pfx_itf,
|
||||
FIB_SOURCE_INTERFACE,
|
||||
(FIB_ENTRY_FLAG_CONNECTED |
|
||||
FIB_ENTRY_FLAG_ATTACHED),
|
||||
DPO_PROTO_IP4,
|
||||
NULL,
|
||||
tm->hw[0]->sw_if_index,
|
||||
~0, // invalid fib index
|
||||
1, // weight
|
||||
NULL,
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
|
||||
mfib_prefix_t pfx_dft = {
|
||||
.fp_len = 0,
|
||||
.fp_proto = PROTO,
|
||||
@@ -1042,6 +1066,69 @@ mfib_test_i (fib_protocol_t PROTO,
|
||||
"%U Gone",
|
||||
format_mfib_prefix, pfx_star_g_slash_m);
|
||||
|
||||
/*
|
||||
* Entries with paths via unicast next-hops
|
||||
*/
|
||||
fib_route_path_t path_via_nbr1 = {
|
||||
.frp_proto = fib_proto_to_dpo(PROTO),
|
||||
.frp_addr = *addr_nbr1,
|
||||
.frp_sw_if_index = tm->hw[0]->sw_if_index,
|
||||
.frp_fib_index = ~0,
|
||||
.frp_weight = 0,
|
||||
.frp_flags = 0,
|
||||
};
|
||||
fib_route_path_t path_via_nbr2 = {
|
||||
.frp_proto = fib_proto_to_dpo(PROTO),
|
||||
.frp_addr = *addr_nbr2,
|
||||
.frp_sw_if_index = tm->hw[0]->sw_if_index,
|
||||
.frp_fib_index = ~0,
|
||||
.frp_weight = 0,
|
||||
.frp_flags = 0,
|
||||
};
|
||||
|
||||
mfei_g_1 = mfib_table_entry_path_update(fib_index,
|
||||
pfx_star_g_1,
|
||||
MFIB_SOURCE_API,
|
||||
&path_via_nbr1,
|
||||
(MFIB_ITF_FLAG_FORWARD));
|
||||
mfei_g_1 = mfib_table_entry_path_update(fib_index,
|
||||
pfx_star_g_1,
|
||||
MFIB_SOURCE_API,
|
||||
&path_via_nbr2,
|
||||
(MFIB_ITF_FLAG_FORWARD));
|
||||
MFIB_TEST(!mfib_test_entry(mfei_g_1,
|
||||
MFIB_ENTRY_FLAG_NONE,
|
||||
2,
|
||||
DPO_ADJACENCY_INCOMPLETE, ai_nbr1,
|
||||
DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
|
||||
"%U replicate OK",
|
||||
format_mfib_prefix, pfx_star_g_1);
|
||||
MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
|
||||
MFIB_ITF_FLAG_FORWARD));
|
||||
|
||||
mfib_table_entry_path_remove(fib_index,
|
||||
pfx_star_g_1,
|
||||
MFIB_SOURCE_API,
|
||||
&path_via_nbr1);
|
||||
|
||||
MFIB_TEST(!mfib_test_entry(mfei_g_1,
|
||||
MFIB_ENTRY_FLAG_NONE,
|
||||
1,
|
||||
DPO_ADJACENCY_INCOMPLETE, ai_nbr2),
|
||||
"%U replicate OK",
|
||||
format_mfib_prefix, pfx_star_g_1);
|
||||
MFIB_TEST_NS(!mfib_test_entry_itf(mfei_g_1, tm->hw[0]->sw_if_index,
|
||||
MFIB_ITF_FLAG_FORWARD));
|
||||
|
||||
mfib_table_entry_path_remove(fib_index,
|
||||
pfx_star_g_1,
|
||||
MFIB_SOURCE_API,
|
||||
&path_via_nbr2);
|
||||
mfei = mfib_table_lookup_exact_match(fib_index, pfx_star_g_1);
|
||||
MFIB_TEST(FIB_NODE_INDEX_INVALID == mfei,
|
||||
"%U Gone",
|
||||
format_mfib_prefix, pfx_star_g_1);
|
||||
|
||||
/*
|
||||
* Add a prefix as a special/exclusive route
|
||||
*/
|
||||
@@ -1216,6 +1303,8 @@ mfib_test_i (fib_protocol_t PROTO,
|
||||
adj_unlock(ai_1);
|
||||
adj_unlock(ai_2);
|
||||
adj_unlock(ai_3);
|
||||
adj_unlock(ai_nbr1);
|
||||
adj_unlock(ai_nbr2);
|
||||
|
||||
/*
|
||||
* MPLS disable the interface
|
||||
@@ -1225,6 +1314,11 @@ mfib_test_i (fib_protocol_t PROTO,
|
||||
0, 0);
|
||||
mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
|
||||
|
||||
/*
|
||||
* remove the connected
|
||||
*/
|
||||
fib_table_entry_delete(0, pfx_itf, FIB_SOURCE_INTERFACE);
|
||||
|
||||
/*
|
||||
* test we've leaked no resources
|
||||
*/
|
||||
@@ -1303,7 +1397,19 @@ mfib_test_v4 (void)
|
||||
.ip4.as_u32 = 0,
|
||||
},
|
||||
};
|
||||
|
||||
const fib_prefix_t pfx_itf = {
|
||||
.fp_len = 24,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
.fp_addr = {
|
||||
.ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0a),
|
||||
},
|
||||
};
|
||||
const ip46_address_t nbr1 = {
|
||||
.ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0b),
|
||||
};
|
||||
const ip46_address_t nbr2 = {
|
||||
.ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a0c),
|
||||
};
|
||||
return (mfib_test_i(FIB_PROTOCOL_IP4,
|
||||
VNET_LINK_IP4,
|
||||
&pfx_224_s_8,
|
||||
@@ -1311,7 +1417,10 @@ mfib_test_v4 (void)
|
||||
&pfx_239_1_1_1,
|
||||
&pfx_239_1_1_2,
|
||||
&pfx_239_1_1_3,
|
||||
&pfx_239));
|
||||
&pfx_239,
|
||||
&pfx_itf,
|
||||
&nbr1,
|
||||
&nbr2));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1371,6 +1480,22 @@ mfib_test_v6 (void)
|
||||
.ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000000),
|
||||
},
|
||||
};
|
||||
const fib_prefix_t pfx_itf = {
|
||||
.fp_len = 64,
|
||||
.fp_proto = FIB_PROTOCOL_IP6,
|
||||
.fp_addr = {
|
||||
.ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
|
||||
.ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000001),
|
||||
},
|
||||
};
|
||||
const ip46_address_t nbr1 = {
|
||||
.ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
|
||||
.ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000002),
|
||||
};
|
||||
const ip46_address_t nbr2 = {
|
||||
.ip6.as_u64[0] = clib_host_to_net_u64(0x2001000000000000),
|
||||
.ip6.as_u64[1] = clib_host_to_net_u64(0x0000000000000003),
|
||||
};
|
||||
|
||||
return (mfib_test_i(FIB_PROTOCOL_IP6,
|
||||
VNET_LINK_IP6,
|
||||
@@ -1379,7 +1504,10 @@ mfib_test_v6 (void)
|
||||
&pfx_ff_1,
|
||||
&pfx_ff_2,
|
||||
&pfx_ff_3,
|
||||
&pfx_ff));
|
||||
&pfx_ff,
|
||||
&pfx_itf,
|
||||
&nbr1,
|
||||
&nbr2));
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
@@ -1391,6 +1519,12 @@ mfib_test (vlib_main_t * vm,
|
||||
|
||||
res += mfib_test_mk_intf(4);
|
||||
res += mfib_test_v4();
|
||||
|
||||
if (res)
|
||||
{
|
||||
return clib_error_return(0, "MFIB Unit Test Failed");
|
||||
}
|
||||
|
||||
res += mfib_test_v6();
|
||||
|
||||
if (res)
|
||||
|
||||
+50
-3
@@ -111,7 +111,7 @@ class TestIPMcast(VppTestCase):
|
||||
capture.remove(p)
|
||||
return capture
|
||||
|
||||
def verify_capture_ip4(self, rx_if, sent):
|
||||
def verify_capture_ip4(self, rx_if, sent, dst_mac=None):
|
||||
rxd = rx_if.get_capture(len(sent))
|
||||
|
||||
try:
|
||||
@@ -129,8 +129,11 @@ class TestIPMcast(VppTestCase):
|
||||
tx_ip = tx[IP]
|
||||
rx_ip = rx[IP]
|
||||
|
||||
if dst_mac is None:
|
||||
dst_mac = getmacbyip(rx_ip.dst)
|
||||
|
||||
# check the MAC address on the RX'd packet is correctly formed
|
||||
self.assertEqual(eth.dst, getmacbyip(rx_ip.dst))
|
||||
self.assertEqual(eth.dst, dst_mac)
|
||||
|
||||
self.assertEqual(rx_ip.src, tx_ip.src)
|
||||
self.assertEqual(rx_ip.dst, tx_ip.dst)
|
||||
@@ -225,6 +228,26 @@ class TestIPMcast(VppTestCase):
|
||||
MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)])
|
||||
route_1_1_1_1_232_1_1_1.add_vpp_config()
|
||||
|
||||
#
|
||||
# An (S,G).
|
||||
# one accepting interface, pg0, 2 forwarding interfaces
|
||||
# that use unicast next-hops
|
||||
#
|
||||
route_1_1_1_1_232_1_1_2 = VppIpMRoute(
|
||||
self,
|
||||
"1.1.1.1",
|
||||
"232.1.1.2", 64,
|
||||
MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
|
||||
[VppMRoutePath(self.pg0.sw_if_index,
|
||||
MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
|
||||
VppMRoutePath(self.pg1.sw_if_index,
|
||||
MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
|
||||
nh=self.pg1.remote_ip4),
|
||||
VppMRoutePath(self.pg2.sw_if_index,
|
||||
MRouteItfFlags.MFIB_ITF_FLAG_FORWARD,
|
||||
nh=self.pg2.remote_ip4)])
|
||||
route_1_1_1_1_232_1_1_2.add_vpp_config()
|
||||
|
||||
#
|
||||
# An (*,G/m).
|
||||
# one accepting interface, pg0, 1 forwarding interfaces
|
||||
@@ -283,6 +306,26 @@ class TestIPMcast(VppTestCase):
|
||||
self.pg3.assert_nothing_captured(
|
||||
remark="IP multicast packets forwarded on PG3")
|
||||
|
||||
#
|
||||
# a stream to the unicast next-hops
|
||||
#
|
||||
self.vapi.cli("clear trace")
|
||||
tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "232.1.1.2")
|
||||
self.pg0.add_stream(tx)
|
||||
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
# We expect replications on Pg1->7
|
||||
self.verify_capture_ip4(self.pg1, tx, dst_mac=self.pg1.remote_mac)
|
||||
self.verify_capture_ip4(self.pg2, tx, dst_mac=self.pg2.remote_mac)
|
||||
|
||||
# no replications on Pg0 nor pg3
|
||||
self.pg0.assert_nothing_captured(
|
||||
remark="IP multicast packets forwarded on PG0")
|
||||
self.pg3.assert_nothing_captured(
|
||||
remark="IP multicast packets forwarded on PG3")
|
||||
|
||||
#
|
||||
# a stream that matches the route for (*,232.0.0.0/8)
|
||||
# Send packets with the 9th bit set so we test the correct clearing
|
||||
@@ -316,7 +359,7 @@ class TestIPMcast(VppTestCase):
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
# We expect replications on Pg1, 2, 3.
|
||||
# We expect replications on Pg1->7
|
||||
self.verify_capture_ip4(self.pg1, tx)
|
||||
self.verify_capture_ip4(self.pg2, tx)
|
||||
self.verify_capture_ip4(self.pg3, tx)
|
||||
@@ -325,6 +368,10 @@ class TestIPMcast(VppTestCase):
|
||||
self.verify_capture_ip4(self.pg6, tx)
|
||||
self.verify_capture_ip4(self.pg7, tx)
|
||||
|
||||
# no replications on Pg0
|
||||
self.pg0.assert_nothing_captured(
|
||||
remark="IP multicast packets forwarded on PG0")
|
||||
|
||||
def test_ip6_mcast(self):
|
||||
""" IPv6 Multicast Replication """
|
||||
|
||||
|
||||
+11
-4
@@ -185,12 +185,14 @@ class VppRoutePath(object):
|
||||
class VppMRoutePath(VppRoutePath):
|
||||
|
||||
def __init__(self, nh_sw_if_index, flags,
|
||||
nh=None,
|
||||
proto=DpoProto.DPO_PROTO_IP4,
|
||||
bier_imp=0):
|
||||
super(VppMRoutePath, self).__init__(
|
||||
"::" if proto is DpoProto.DPO_PROTO_IP6 else "0.0.0.0",
|
||||
nh_sw_if_index,
|
||||
proto=proto)
|
||||
if not nh:
|
||||
nh = "::" if proto is DpoProto.DPO_PROTO_IP6 else "0.0.0.0"
|
||||
super(VppMRoutePath, self).__init__(nh,
|
||||
nh_sw_if_index,
|
||||
proto=proto)
|
||||
self.nh_i_flags = flags
|
||||
self.bier_imp = bier_imp
|
||||
|
||||
@@ -337,6 +339,7 @@ class VppIpMRoute(VppObject):
|
||||
self.e_flags,
|
||||
path.proto,
|
||||
path.nh_itf,
|
||||
path.nh_addr,
|
||||
path.nh_i_flags,
|
||||
bier_imp=path.bier_imp,
|
||||
rpf_id=self.rpf_id,
|
||||
@@ -352,6 +355,7 @@ class VppIpMRoute(VppObject):
|
||||
self.e_flags,
|
||||
path.proto,
|
||||
path.nh_itf,
|
||||
path.nh_addr,
|
||||
path.nh_i_flags,
|
||||
table_id=self.table_id,
|
||||
bier_imp=path.bier_imp,
|
||||
@@ -366,6 +370,7 @@ class VppIpMRoute(VppObject):
|
||||
self.e_flags,
|
||||
0,
|
||||
0xffffffff,
|
||||
"",
|
||||
0,
|
||||
table_id=self.table_id,
|
||||
is_ipv6=self.is_ip6)
|
||||
@@ -378,6 +383,7 @@ class VppIpMRoute(VppObject):
|
||||
self.e_flags,
|
||||
0,
|
||||
0xffffffff,
|
||||
"",
|
||||
0,
|
||||
rpf_id=self.rpf_id,
|
||||
table_id=self.table_id,
|
||||
@@ -394,6 +400,7 @@ class VppIpMRoute(VppObject):
|
||||
self.e_flags,
|
||||
path.proto,
|
||||
path.nh_itf,
|
||||
path.nh_addr,
|
||||
path.nh_i_flags,
|
||||
table_id=self.table_id,
|
||||
is_ipv6=self.is_ip6)
|
||||
|
||||
@@ -2300,6 +2300,7 @@ class VppPapiProvider(object):
|
||||
e_flags,
|
||||
next_hop_afi,
|
||||
next_hop_sw_if_index,
|
||||
next_hop_address,
|
||||
i_flags,
|
||||
bier_imp=0,
|
||||
rpf_id=0,
|
||||
@@ -2324,7 +2325,8 @@ class VppPapiProvider(object):
|
||||
'next_hop_afi': next_hop_afi,
|
||||
'grp_address_length': grp_address_length,
|
||||
'grp_address': grp_address,
|
||||
'src_address': src_address})
|
||||
'src_address': src_address,
|
||||
'nh_address': next_hop_address})
|
||||
|
||||
def mfib_signal_dump(self):
|
||||
return self.api(self.papi.mfib_signal_dump, {})
|
||||
|
||||
Reference in New Issue
Block a user