mfei = mfib_table_lookup(fib_index,
pfx_star_g_1);
MFIB_TEST(mfei == mfei_g_1,
- "%U found via LP match",
+ "[e:%d a:%d] %U found via LP match",
+ mfei, mfei_g_1,
format_mfib_prefix, pfx_star_g_1);
MFIB_TEST(!mfib_test_entry(mfei,
/*
* Find the (*,G/m)
*/
- MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
+ MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
ip6_mfib_get(fib_index),
&src,
&pfx_star_g_slash_m->fp_grp_addr.ip6)),
ip6_address_t tmp = pfx_star_g_slash_m->fp_grp_addr.ip6;
tmp.as_u8[15] = 0xff;
- MFIB_TEST((mfei_g_m == ip6_mfib_table_lookup2(
+ MFIB_TEST((mfei_g_m == ip6_mfib_table_fwd_lookup(
ip6_mfib_get(fib_index),
&pfx_s_g->fp_src_addr.ip6,
&tmp)),
/*
* Find the (S,G).
*/
- mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
- &pfx_s_g->fp_src_addr.ip6,
- &pfx_s_g->fp_grp_addr.ip6);
+ mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
+ &pfx_s_g->fp_src_addr.ip6,
+ &pfx_s_g->fp_grp_addr.ip6);
MFIB_TEST((mfei_s_g == mfei),
"%U found via DP LPM: %d",
format_mfib_prefix, pfx_s_g, mfei);
/*
* Find the 3 (*,G) s
*/
- mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
- &src,
- &pfx_star_g_1->fp_grp_addr.ip6);
+ mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
+ &src,
+ &pfx_star_g_1->fp_grp_addr.ip6);
MFIB_TEST((mfei_g_1 == mfei),
"%U found via DP LPM: %d",
format_mfib_prefix, pfx_star_g_1, mfei);
- mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
- &src,
- &pfx_star_g_2->fp_grp_addr.ip6);
+ mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
+ &src,
+ &pfx_star_g_2->fp_grp_addr.ip6);
MFIB_TEST((mfei_g_2 == mfei),
"%U found via DP LPM: %d",
format_mfib_prefix, pfx_star_g_2, mfei);
- mfei = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index),
- &src,
- &pfx_star_g_3->fp_grp_addr.ip6);
+ mfei = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index),
+ &src,
+ &pfx_star_g_3->fp_grp_addr.ip6);
MFIB_TEST((mfei_g_3 == mfei),
"%U found via DP LPM: %d",
format_mfib_prefix, pfx_star_g_3, mfei);
#include <vnet/ethernet/arp_packet.h>
#include <vnet/fib/fib_walk.h>
+#include <vppinfra/bihash_24_8.h>
+
/*
* Vector Hash tables of neighbour (traditional) adjacencies
* Key: interface(for the vector index), address (and its proto),
ip6_header_t * ip0;
ip0 = vlib_buffer_get_current (b0);
- mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0),
- &ip0->src_address,
- &ip0->dst_address);
+ mfei0 = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index0),
+ &ip0->src_address,
+ &ip0->dst_address);
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
lookup_trace_t *tr = vlib_add_trace (vm, node,
#include <vnet/fib/fib_table.h>
#include <vnet/dpo/ip6_ll_dpo.h>
+#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_template.c>
+
static void
vnet_ip6_fib_init (u32 fib_index)
{
u32 len)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv, value;
+ clib_bihash_kv_24_8_t kv, value;
int i, n_p, rv;
u64 fib;
kv.key[1] &= mask->as_u64[1];
kv.key[2] = fib | dst_address_length;
- rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
+ rv = clib_bihash_search_inline_2_24_8(&table->ip6_hash, &kv, &value);
if (rv == 0)
return value.value;
}
u32 len)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv, value;
+ clib_bihash_kv_24_8_t kv, value;
ip6_address_t *mask;
u64 fib;
int rv;
kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
kv.key[2] = fib | len;
- rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
+ rv = clib_bihash_search_inline_2_24_8(&table->ip6_hash, &kv, &value);
if (rv == 0)
return value.value;
u32 len)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv;
+ clib_bihash_kv_24_8_t kv;
ip6_address_t *mask;
u64 fib;
kv.key[1] = addr->as_u64[1] & mask->as_u64[1];
kv.key[2] = fib | len;
- BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 0);
+ clib_bihash_add_del_24_8(&table->ip6_hash, &kv, 0);
/* refcount accounting */
ASSERT (table->dst_address_length_refcounts[len] > 0);
fib_node_index_t fib_entry_index)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv;
+ clib_bihash_kv_24_8_t kv;
ip6_address_t *mask;
u64 fib;
kv.key[2] = fib | len;
kv.value = fib_entry_index;
- BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 1);
+ clib_bihash_add_del_24_8(&table->ip6_hash, &kv, 1);
table->dst_address_length_refcounts[len]++;
const dpo_id_t *dpo)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv;
+ clib_bihash_kv_24_8_t kv;
ip6_address_t *mask;
u64 fib;
kv.key[2] = fib | len;
kv.value = dpo->dpoi_index;
- BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 1);
+ clib_bihash_add_del_24_8(&table->ip6_hash, &kv, 1);
table->dst_address_length_refcounts[len]++;
const dpo_id_t *dpo)
{
ip6_fib_table_instance_t *table;
- BVT(clib_bihash_kv) kv;
+ clib_bihash_kv_24_8_t kv;
ip6_address_t *mask;
u64 fib;
kv.key[2] = fib | len;
kv.value = dpo->dpoi_index;
- BV(clib_bihash_add_del)(&table->ip6_hash, &kv, 0);
+ clib_bihash_add_del_24_8(&table->ip6_hash, &kv, 0);
/* refcount accounting */
ASSERT (table->dst_address_length_refcounts[len] > 0);
.i6w_sub_trees = NULL,
};
- BV(clib_bihash_foreach_key_value_pair)(
+ clib_bihash_foreach_key_value_pair_24_8(
&ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
ip6_fib_walk_cb,
&ctx);
.i6w_root = *root,
};
- BV(clib_bihash_foreach_key_value_pair)(
+ clib_bihash_foreach_key_value_pair_24_8(
&ip6_main.ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
ip6_fib_walk_cb,
&ctx);
} count_routes_in_fib_at_prefix_length_arg_t;
static void
-count_routes_in_fib_at_prefix_length (BVT(clib_bihash_kv) * kvp,
+count_routes_in_fib_at_prefix_length (clib_bihash_kv_24_8_t * kvp,
void *arg)
{
count_routes_in_fib_at_prefix_length_arg_t * ap = arg;
/* Show summary? */
if (! verbose)
{
- BVT(clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash;
+ clib_bihash_24_8_t * h = &im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash;
int len;
vlib_cli_output (vm, "%=20s%=16s", "Prefix length", "Count");
clib_memset (ca, 0, sizeof(*ca));
ca->fib_index = fib->index;
- BV(clib_bihash_foreach_key_value_pair)
+ clib_bihash_foreach_key_value_pair_24_8
(h, count_routes_in_fib_at_prefix_length, ca);
for (len = 128; len >= 0; len--)
const ip6_address_t * dst)
{
ip6_fib_table_instance_t *table;
+ clib_bihash_kv_24_8_t kv, value;
int i, len;
int rv;
- BVT(clib_bihash_kv) kv, value;
u64 fib;
table = &ip6_main.ip6_table[IP6_FIB_TABLE_FWDING];
kv.key[1] &= mask->as_u64[1];
kv.key[2] = fib | dst_address_length;
- rv = BV(clib_bihash_search_inline_2)(&table->ip6_hash, &kv, &value);
+ rv = clib_bihash_search_inline_2_24_8(&table->ip6_hash, &kv, &value);
if (rv == 0)
return value.value;
}
#include <vnet/ip/lookup.h>
#include <stdbool.h>
#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_40_8.h>
#include <vppinfra/bihash_template.h>
#include <vnet/util/radix.h>
#include <vnet/util/throttle.h>
typedef struct ip6_mfib_t
{
+ /* required for pool_get_aligned. */
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
+
/* Table ID (hash key) for this FIB. */
u32 table_id;
/* Index into FIB vector. */
u32 index;
-
- /*
- * Pointer to the top of a radix tree.
- * This cannot be realloc'd, hence it cannot be inlined with this table
- */
- struct radix_node_head *rhead;
} ip6_mfib_t;
struct ip6_main_t;
typedef struct ip6_fib_table_instance_t_
{
/* The hash table */
- BVT (clib_bihash) ip6_hash;
+ clib_bihash_24_8_t ip6_hash;
/* bitmap / refcounts / vector of mask widths to search */
uword *non_empty_dst_address_length_bitmap;
i32 dst_address_length_refcounts[129];
} ip6_fib_table_instance_t;
+/**
+ * A represenation of a single IP6 mfib table
+ */
+typedef struct ip6_mfib_table_instance_t_
+{
+ /* The hash table */
+ clib_bihash_40_8_t ip6_mhash;
+
+ /* bitmap / refcounts / vector of mask widths to search */
+ uword *non_empty_dst_address_length_bitmap;
+ u16 *prefix_lengths_in_search_order;
+ i32 dst_address_length_refcounts[257];
+} ip6_mfib_table_instance_t;
+
typedef struct ip6_main_t
{
/**
*/
ip6_fib_table_instance_t ip6_table[IP6_FIB_NUM_TABLES];
+ /**
+ * the single MFIB table
+ */
+ ip6_mfib_table_instance_t ip6_mtable;
+
ip_lookup_main_t lookup_main;
/* Pool of FIBs. */
if (im->lookup_table_size == 0)
im->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE;
- BV (clib_bihash_init) (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash),
+ clib_bihash_init_24_8 (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash),
"ip6 FIB fwding table",
im->lookup_table_nbuckets, im->lookup_table_size);
- BV (clib_bihash_init) (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
+ clib_bihash_init_24_8 (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
"ip6 FIB non-fwding table",
im->lookup_table_nbuckets, im->lookup_table_size);
+ clib_bihash_init_40_8 (&im->ip6_mtable.ip6_mhash,
+ "ip6 mFIB table",
+ im->lookup_table_nbuckets, im->lookup_table_size);
/* Create FIB with index 0 and table id of 0. */
fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
/* Show summary? */
if (!verbose)
{
- BVT (clib_bihash) * h =
+ clib_bihash_24_8_t *h =
&im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash;
int len;
clib_memset (ca, 0, sizeof (*ca));
ca->fib_index = fib_index;
- BV (clib_bihash_foreach_key_value_pair)
+ clib_bihash_foreach_key_value_pair_24_8
(h, count_routes_in_fib_at_prefix_length, ca);
for (len = 128; len >= 0; len--)
}
}
- for (mask_len = 32; mask_len >= 0; mask_len--)
+ for (mask_len = (len == 64 ? 32 : len); mask_len >= 0; mask_len--)
{
hash = mfib->fib_entry_by_dst_address[mask_len];
IP4_MFIB_MK_GRP_KEY(grp, mask_len, key);
#include <vnet/mfib/mfib_entry.h>
#include <vnet/fib/ip6_fib.h>
-/**
- * The number of bytes in an address/ask key in the radix tree
- * First byte is the length in bytes.
- */
-#define IP6_MFIB_KEY_LEN 33
-
/**
* Key and mask for radix
*/
-typedef struct ip6_mfib_key_t_
-{
- u8 key[IP6_MFIB_KEY_LEN];
- u8 mask[IP6_MFIB_KEY_LEN];
-} ip6_mfib_key_t;
-
-/**
- * An object that is inserted into the radix tree.
- * Since it's in the tree and has pointers, it cannot realloc and so cannot
- * come from a vlib pool.
- */
-typedef struct ip6_mfib_node_t_
-{
- struct radix_node i6mn_nodes[2];
- ip6_mfib_key_t i6mn_key;
- index_t i6mn_entry;
-} ip6_mfib_node_t;
+typedef clib_bihash_kv_40_8_t ip6_mfib_key_t;
static const mfib_prefix_t all_zeros = {
/* (*,*) */
mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP6, src);
- mfib_table->v6.rhead =
- clib_mem_alloc_aligned (sizeof(*mfib_table->v6.rhead),
- CLIB_CACHE_LINE_BYTES);
- rn_inithead0(mfib_table->v6.rhead, 8);
-
/*
* add the special entries into the new FIB
*/
ASSERT(~0 != mfib_table->mft_table_id);
hash_unset (ip6_main.mfib_index_by_table_id, mfib_table->mft_table_id);
- clib_mem_free(mfib_table->v6.rhead);
pool_put(ip6_main.mfibs, mfib_table);
}
return (ip6_main.mfib_index_by_sw_if_index[sw_if_index]);
}
-#define IP6_MFIB_MK_KEY(_grp, _src, _key) \
-{ \
- (_key)->key[0] = 33; \
- memcpy((_key)->key+1, _grp, 16); \
- memcpy((_key)->key+17, _src, 16); \
-}
+#define IPV6_MFIB_GRP_LEN(_len) \
+ (_len > 128 ? 128 : _len)
-#define IP6_MFIB_MK_KEY_MASK(_grp, _src, _len, _key) \
-{ \
- IP6_MFIB_MK_KEY(_grp, _src, _key); \
- \
- (_key)->mask[0] = 33; \
- if (_len <= 128) \
- { \
- memcpy((_key)->mask+1, &ip6_main.fib_masks[_len], 16); \
- clib_memset((_key)->mask+17, 0, 16); \
- } \
- else \
- { \
- ASSERT(_len == 256); \
- memcpy((_key)->mask+1, &ip6_main.fib_masks[128], 16); \
- memcpy((_key)->mask+17, &ip6_main.fib_masks[128], 16); \
- } \
+#define IP6_MFIB_MK_KEY(_mfib, _grp, _src, _len, _key) \
+{ \
+ _key.key[0] = (_grp->as_u64[0] & \
+ ip6_main.fib_masks[IPV6_MFIB_GRP_LEN(_len)].as_u64[0]); \
+ _key.key[1] = (_grp->as_u64[1] & \
+ ip6_main.fib_masks[IPV6_MFIB_GRP_LEN(_len)].as_u64[1]); \
+ if (_len == 256) { \
+ _key.key[2] = _src->as_u64[0]; \
+ _key.key[3] = _src->as_u64[1]; \
+ } else { \
+ _key.key[2] = 0; \
+ _key.key[3] = 0; \
+ } \
+ _key.key[4] = _mfib->index; \
+ _key.key[4] = (_key.key[4] << 32) | len; \
}
/*
const ip6_address_t *src,
u32 len)
{
- ip6_mfib_node_t *i6mn;
- ip6_mfib_key_t key;
-
- IP6_MFIB_MK_KEY_MASK(grp, src, len, &key);
+ ip6_mfib_key_t key, value;
+ int rv;
- i6mn = (ip6_mfib_node_t*) rn_lookup(key.key, key.mask,
- (struct radix_node_head *)mfib->rhead);
+ IP6_MFIB_MK_KEY(mfib, grp, src, len, key);
- if (NULL == i6mn)
- {
- return (INDEX_INVALID);
- }
+ rv = clib_bihash_search_inline_2_40_8(&ip6_main.ip6_mtable.ip6_mhash,
+ &key, &value);
+ if (rv == 0)
+ return value.value;
- return (i6mn->i6mn_entry);
+ return (FIB_NODE_INDEX_INVALID);
}
/*
* ip6_fib_table_lookup
*
- * Longest prefix match
+ * Longest prefix match for the forwarding plane (no mask given)
*/
fib_node_index_t
-ip6_mfib_table_lookup (const ip6_mfib_t *mfib,
- const ip6_address_t *src,
- const ip6_address_t *grp,
- u32 len)
+ip6_mfib_table_fwd_lookup (const ip6_mfib_t *mfib,
+ const ip6_address_t *src,
+ const ip6_address_t *grp)
{
- ip6_mfib_node_t *i6mn;
- ip6_mfib_key_t key;
+ ip6_mfib_table_instance_t *table;
+ ip6_mfib_key_t key, value;
+ int i, n, len;
+ int rv;
+
+ table = &ip6_main.ip6_mtable;
+ n = vec_len (table->prefix_lengths_in_search_order);
- IP6_MFIB_MK_KEY_MASK(grp, src, len, &key);
+ for (i = 0; i < n; i++)
+ {
+ len = table->prefix_lengths_in_search_order[i];
- i6mn = (ip6_mfib_node_t*) rn_search_m(key.key,
- mfib->rhead->rnh_treetop,
- key.mask);
+ ASSERT(len >= 0 && len <= 256);
+ IP6_MFIB_MK_KEY(mfib, grp, src, len, key);
- ASSERT(NULL != i6mn);
+ rv = clib_bihash_search_inline_2_40_8(&table->ip6_mhash, &key, &value);
+ if (rv == 0)
+ return value.value;
+ }
- return (i6mn->i6mn_entry);
+ return (FIB_NODE_INDEX_INVALID);
}
/*
* ip6_fib_table_lookup
*
- * Longest prefix match no mask
+ * Longest prefix match
*/
fib_node_index_t
-ip6_mfib_table_lookup2 (const ip6_mfib_t *mfib,
- const ip6_address_t *src,
- const ip6_address_t *grp)
+ip6_mfib_table_lookup (const ip6_mfib_t *mfib,
+ const ip6_address_t *src,
+ const ip6_address_t *grp,
+ u32 len)
{
- ip6_mfib_node_t *i6mn;
- ip6_mfib_key_t key;
+ ip6_mfib_table_instance_t *table;
+ ip6_mfib_key_t key, value;
+ int i, n, rv;
+
+ table = &ip6_main.ip6_mtable;
+ n = vec_len (table->prefix_lengths_in_search_order);
+
+ /*
+ * start search from a mask length same length or shorter.
+ * we don't want matches longer than the mask passed
+ */
+ i = 0;
+ while (i < n && table->prefix_lengths_in_search_order[i] > len)
+ {
+ i++;
+ }
- IP6_MFIB_MK_KEY(grp, src, &key);
+ for (; i < n; i++)
+ {
+ len = table->prefix_lengths_in_search_order[i];
- i6mn = (ip6_mfib_node_t*) rn_match(key.key,
- (struct radix_node_head *)mfib->rhead); // const cast
+ ASSERT(len >= 0 && len <= 256);
+ IP6_MFIB_MK_KEY(mfib, grp, src, len, key);
- ASSERT(NULL != i6mn);
+ rv = clib_bihash_search_inline_2_40_8(&table->ip6_mhash, &key, &value);
+ if (rv == 0)
+ return value.value;
+ }
- return (i6mn->i6mn_entry);
+ return (FIB_NODE_INDEX_INVALID);
+}
+
+static void
+compute_prefix_lengths_in_search_order (ip6_mfib_table_instance_t *table)
+{
+ int i;
+ vec_reset_length (table->prefix_lengths_in_search_order);
+ /* Note: bitmap reversed so this is in fact a longest prefix match */
+ clib_bitmap_foreach (i, table->non_empty_dst_address_length_bitmap,
+ ({
+ vec_add1(table->prefix_lengths_in_search_order, (256 - i));
+ }));
}
void
u32 len,
fib_node_index_t mfib_entry_index)
{
- ip6_mfib_node_t *i6mn = clib_mem_alloc(sizeof(*i6mn));
+ ip6_mfib_table_instance_t *table;
+ ip6_mfib_key_t key;
- clib_memset(i6mn->i6mn_nodes, 0, sizeof(i6mn->i6mn_nodes));
+ table = &ip6_main.ip6_mtable;
+ IP6_MFIB_MK_KEY(mfib, grp, src, len, key);
+ key.value = mfib_entry_index;
- IP6_MFIB_MK_KEY_MASK(grp, src, len, &i6mn->i6mn_key);
- i6mn->i6mn_entry = mfib_entry_index;
+ clib_bihash_add_del_40_8(&table->ip6_mhash, &key, 1);
- if (NULL == rn_addroute(i6mn->i6mn_key.key,
- i6mn->i6mn_key.mask,
- mfib->rhead,
- i6mn->i6mn_nodes))
+ if (0 == table->dst_address_length_refcounts[len]++)
{
- ASSERT(0);
+ table->non_empty_dst_address_length_bitmap =
+ clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
+ 256 - len, 1);
+ compute_prefix_lengths_in_search_order (table);
}
}
const ip6_address_t *src,
u32 len)
{
- ip6_mfib_node_t *i6mn;
+ ip6_mfib_table_instance_t *table;
ip6_mfib_key_t key;
- IP6_MFIB_MK_KEY_MASK(grp, src, len, &key);
+ IP6_MFIB_MK_KEY(mfib, grp, src, len, key);
- i6mn = (ip6_mfib_node_t*) rn_delete(key.key, key.mask, mfib->rhead);
+ table = &ip6_main.ip6_mtable;
+ clib_bihash_add_del_40_8(&table->ip6_mhash, &key, 0);
- clib_mem_free(i6mn);
+ ASSERT (table->dst_address_length_refcounts[len] > 0);
+ if (--table->dst_address_length_refcounts[len] == 0)
+ {
+ table->non_empty_dst_address_length_bitmap =
+ clib_bitmap_set (table->non_empty_dst_address_length_bitmap,
+ 256 - len, 0);
+ compute_prefix_lengths_in_search_order (table);
+ }
}
static clib_error_t *
vec_free(ctx.entries);
}
-typedef struct ip6_mfib_radix_walk_ctx_t_
+/**
+ * @brief Context when walking the IPv6 table. Since all VRFs are in the
+ * same hash table, we need to filter only those we need as we walk
+ */
+typedef struct ip6_mfib_walk_ctx_t_
{
- mfib_table_walk_fn_t user_fn;
- void *user_ctx;
-} ip6_mfib_radix_walk_ctx_t;
+ u32 i6w_mfib_index;
+ mfib_table_walk_fn_t i6w_fn;
+ void *i6w_ctx;
+} ip6_mfib_walk_ctx_t;
static int
-ip6_mfib_table_radix_walk (struct radix_node *rn,
- void *arg)
+ip6_mfib_walk_cb (clib_bihash_kv_40_8_t * kvp,
+ void *arg)
{
- ip6_mfib_radix_walk_ctx_t *ctx = arg;
- ip6_mfib_node_t *i6mn;
-
- i6mn = (ip6_mfib_node_t*) rn;
-
- ctx->user_fn(i6mn->i6mn_entry, ctx->user_ctx);
+ ip6_mfib_walk_ctx_t *ctx = arg;
- return (0);
+ if ((kvp->key[4] >> 32) == ctx->i6w_mfib_index)
+ {
+ return (ctx->i6w_fn(kvp->value, ctx->i6w_ctx));
+ }
+ return (FIB_TABLE_WALK_CONTINUE);
}
void
ip6_mfib_table_walk (ip6_mfib_t *mfib,
mfib_table_walk_fn_t fn,
- void *ctx)
+ void *arg)
{
- ip6_mfib_radix_walk_ctx_t rn_ctx = {
- .user_fn = fn,
- .user_ctx = ctx,
+ ip6_mfib_walk_ctx_t ctx = {
+ .i6w_mfib_index = mfib->index,
+ .i6w_fn = fn,
+ .i6w_ctx = arg,
};
- rn_walktree(mfib->rhead,
- ip6_mfib_table_radix_walk,
- &rn_ctx);
+ clib_bihash_foreach_key_value_pair_40_8(
+ &ip6_main.ip6_mtable.ip6_mhash,
+ ip6_mfib_walk_cb,
+ &ctx);
}
static clib_error_t *
const ip6_address_t *src,
const ip6_address_t *grp,
u32 len);
+extern fib_node_index_t ip6_mfib_table_fwd_lookup(const ip6_mfib_t *fib,
+ const ip6_address_t *src,
+ const ip6_address_t *grp);
extern fib_node_index_t ip6_mfib_table_lookup_exact_match(const ip6_mfib_t *fib,
const ip6_address_t *grp,
const ip6_address_t *src,
fib_index0 = vec_elt (ip6_main.mfib_index_by_sw_if_index,
vnet_buffer(p0)->sw_if_index[VLIB_RX]);
ip0 = vlib_buffer_get_current (p0);
- mfei0 = ip6_mfib_table_lookup2(ip6_mfib_get(fib_index0),
- &ip0->src_address,
- &ip0->dst_address);
+ mfei0 = ip6_mfib_table_fwd_lookup(ip6_mfib_get(fib_index0),
+ &ip0->src_address,
+ &ip0->dst_address);
}
vnet_buffer (p0)->ip.adj_index[VLIB_TX] = mfei0;
u32 items_this_message;
vl_api_ip6_fib_counter_t *ctrp = 0;
u32 start_at_fib_index = 0;
- BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
+ clib_bihash_24_8_t *h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
add_routes_in_fib_arg_t _a, *a = &_a;
int i;
if (clib_setjmp (&sm->jmp_buf, 0) == 0)
{
start_at_fib_index = fib - im6->fibs;
- BV (clib_bihash_foreach_key_value_pair) (h, add_routes_in_fib, a);
+ clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a);
}
else
{
faulthandler; python_version < '3.3' # # BSD License (2 clause)
flake8 # MIT
ipaddress; python_version < '3.3' # PSF
+parameterized>=0.6.1 # BSD
pexpect # ISC
psutil # BSD
pycodestyle # MIT (Expat license) https://pypi.org/project/pycodestyle/
import socket
import unittest
+from parameterized import parameterized
import scapy.layers.inet6 as inet6
from scapy.contrib.mpls import MPLS
from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_RS, \
class TestIP6Input(VppTestCase):
- """ IPv6 Input Exceptions """
+ """ IPv6 Input Exception Test Cases """
def setUp(self):
super(TestIP6Input, self).setUp()
i.unconfig_ip6()
i.admin_down()
- def test_ip_input(self):
- """ IP6 Input Exceptions """
-
- #
- # bad version - this is dropped
- #
- p_version = (Ether(src=self.pg0.remote_mac,
- dst=self.pg0.local_mac) /
- IPv6(src=self.pg0.remote_ip6,
- dst=self.pg1.remote_ip6,
- version=3) /
- inet6.UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, p_version * 65,
- "funky version")
-
+ def test_ip_input_icmp_reply(self):
+ """ IP6 Input Exception - Return ICMP (3,0) """
#
- # hop limit - IMCP replies
+ # hop limit - ICMP replies
#
p_version = (Ether(src=self.pg0.remote_mac,
dst=self.pg0.local_mac) /
rx = self.send_and_expect(self.pg0, p_version * 65, self.pg0)
rx = rx[0]
icmp = rx[ICMPv6TimeExceeded]
- self.assertEqual(icmp.type, 3)
+
# 0: "hop limit exceeded in transit",
- self.assertEqual(icmp.code, 0)
+ self.assertEqual((icmp.type, icmp.code), (3, 0))
+
+ icmpv6_data = '\x0a' * 18
+ all_0s = "::"
+ all_1s = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
+
+ @parameterized.expand([
+ # Name, src, dst, l4proto, msg, timeout
+ ("src='iface', dst='iface'", None, None,
+ inet6.UDP(sport=1234, dport=1234), "funky version", None),
+ ("src='All 0's', dst='iface'", all_0s, None,
+ ICMPv6EchoRequest(id=0xb, seq=5, data=icmpv6_data), None, 0.1),
+ ("src='iface', dst='All 0's'", None, all_0s,
+ ICMPv6EchoRequest(id=0xb, seq=5, data=icmpv6_data), None, 0.1),
+ ("src='All 1's', dst='iface'", all_1s, None,
+ ICMPv6EchoRequest(id=0xb, seq=5, data=icmpv6_data), None, 0.1),
+ ("src='iface', dst='All 1's'", None, all_1s,
+ ICMPv6EchoRequest(id=0xb, seq=5, data=icmpv6_data), None, 0.1),
+ ("src='All 1's', dst='All 1's'", all_1s, all_1s,
+ ICMPv6EchoRequest(id=0xb, seq=5, data=icmpv6_data), None, 0.1),
+
+ ])
+ def test_ip_input_no_replies(self, name, src, dst, l4, msg, timeout):
+
+ self._testMethodDoc = 'IPv6 Input Exception - %s' % name
+
+ p_version = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IPv6(src=src or self.pg0.remote_ip6,
+ dst=dst or self.pg1.remote_ip6,
+ version=3) /
+ l4 /
+ Raw('\xa5' * 100))
+
+ self.send_and_assert_no_replies(self.pg0, p_version * 65,
+ remark=msg or "",
+ timeout=timeout)
if __name__ == '__main__':