fib: improve ipv6 fib scaling
VPP IPv6 FIB relies on 2 bihash for all its VRFs: 1 for control plane and one for data plane. Because of that, control plane VRF walks time grows with the number of VRFs as it has to go through all the VRFs. In order to improve control plane performance with large number of VRFs, the control plane data structure is changed from a global bihash to a per-VRF hashtable, similarly to IPv4. Contrary to IPv4, there is only 1 hashtable per VRF and not 1 hashtable per prefix-length per VRF, which is a compromise between memory consumption and single VRF scaling. Type: improvement Change-Id: Ib738a44adb88e46c95c4c62c853ee1f1392c7187 Signed-off-by: Benoît Ganne <bganne@cisco.com>
This commit is contained in:

committed by
Neale Ranns

parent
ff570d3d07
commit
23c489660b
File diff suppressed because it is too large
Load Diff
@ -26,36 +26,15 @@
|
||||
#include <vppinfra/bihash_template.h>
|
||||
|
||||
/*
|
||||
* Default size of the ip6 fib hash table
|
||||
* Default size of the ip6 fib forwarding hash table
|
||||
*/
|
||||
#define IP6_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
|
||||
#define IP6_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20)
|
||||
|
||||
/**
|
||||
* Enumeration of the FIB table instance types
|
||||
* A representation the forwarding IP6 table
|
||||
*/
|
||||
typedef enum ip6_fib_table_instance_type_t_
|
||||
{
|
||||
/**
|
||||
* This table stores the routes that are used to forward traffic.
|
||||
* The key is the prefix, the result the adjacency to forward on.
|
||||
*/
|
||||
IP6_FIB_TABLE_FWDING,
|
||||
/**
|
||||
* The table that stores ALL routes learned by the DP.
|
||||
* Some of these routes may not be ready to install in forwarding
|
||||
* at a given time.
|
||||
* The key in this table is the prefix, the result is the fib_entry_t
|
||||
*/
|
||||
IP6_FIB_TABLE_NON_FWDING,
|
||||
} ip6_fib_table_instance_type_t;
|
||||
|
||||
#define IP6_FIB_NUM_TABLES (IP6_FIB_TABLE_NON_FWDING+1)
|
||||
|
||||
/**
|
||||
* A representation of a single IP6 table
|
||||
*/
|
||||
typedef struct ip6_fib_table_instance_t_
|
||||
typedef struct ip6_fib_fwding_table_instance_t_
|
||||
{
|
||||
/* The hash table */
|
||||
clib_bihash_24_8_t ip6_hash;
|
||||
@ -64,12 +43,12 @@ typedef struct ip6_fib_table_instance_t_
|
||||
uword *non_empty_dst_address_length_bitmap;
|
||||
u8 *prefix_lengths_in_search_order;
|
||||
i32 dst_address_length_refcounts[129];
|
||||
} ip6_fib_table_instance_t;
|
||||
} ip6_fib_fwding_table_instance_t;
|
||||
|
||||
/**
|
||||
* The two FIB tables; fwding and non-fwding
|
||||
*/
|
||||
extern ip6_fib_table_instance_t ip6_fib_table[IP6_FIB_NUM_TABLES];
|
||||
extern ip6_fib_fwding_table_instance_t ip6_fib_fwding_table;
|
||||
|
||||
extern fib_node_index_t ip6_fib_table_lookup(u32 fib_index,
|
||||
const ip6_address_t *addr,
|
||||
@ -115,13 +94,13 @@ always_inline u32
|
||||
ip6_fib_table_fwding_lookup (u32 fib_index,
|
||||
const ip6_address_t * dst)
|
||||
{
|
||||
ip6_fib_table_instance_t *table;
|
||||
ip6_fib_fwding_table_instance_t *table;
|
||||
clib_bihash_kv_24_8_t kv, value;
|
||||
int i, len;
|
||||
int rv;
|
||||
u64 fib;
|
||||
|
||||
table = &ip6_fib_table[IP6_FIB_TABLE_FWDING];
|
||||
table = &ip6_fib_fwding_table;
|
||||
len = vec_len (table->prefix_lengths_in_search_order);
|
||||
|
||||
kv.key[0] = dst->as_u64[0];
|
||||
@ -230,6 +209,7 @@ u32 ip6_fib_index_from_table_id (u32 table_id)
|
||||
}
|
||||
|
||||
extern u32 ip6_fib_table_get_index_for_sw_if_index(u32 sw_if_index);
|
||||
extern void ip6_fib_table_show (vlib_main_t *vm, fib_table_t *fib_table, int summary);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -68,6 +68,11 @@ typedef struct
|
||||
|
||||
/* Index into FIB vector. */
|
||||
u32 index;
|
||||
|
||||
/**
|
||||
* The hash table DB
|
||||
*/
|
||||
uword *fib_entry_by_dst_address;
|
||||
} ip6_fib_t;
|
||||
|
||||
typedef struct ip6_mfib_t
|
||||
|
@ -144,17 +144,20 @@ ip6_ll_table_entry_delete (const ip6_ll_prefix_t * ilp)
|
||||
fib_node_index_t ip6_ll_entry_index;
|
||||
u32 fib_index;
|
||||
|
||||
ip6_ll_entry_index = ip6_ll_table_lookup_exact_match (ilp);
|
||||
fib_index = ip6_ll_fib_get (ilp->ilp_sw_if_index);
|
||||
if (~0 == fib_index)
|
||||
return;
|
||||
|
||||
if (FIB_NODE_INDEX_INVALID != ip6_ll_entry_index)
|
||||
fib_table_entry_delete_index (ip6_ll_entry_index, FIB_SOURCE_IP6_ND);
|
||||
ip6_ll_entry_index = ip6_ll_table_lookup_exact_match (ilp);
|
||||
if (FIB_NODE_INDEX_INVALID == ip6_ll_entry_index)
|
||||
return;
|
||||
|
||||
fib_table_entry_delete_index (ip6_ll_entry_index, FIB_SOURCE_IP6_ND);
|
||||
|
||||
/*
|
||||
* if there are no ND sourced prefixes left, then we can clean up this FIB
|
||||
*/
|
||||
fib_index = ip6_ll_fib_get (ilp->ilp_sw_if_index);
|
||||
if (~0 != fib_index &&
|
||||
0 == fib_table_get_num_entries (fib_index, FIB_PROTOCOL_IP6,
|
||||
if (0 == fib_table_get_num_entries (fib_index, FIB_PROTOCOL_IP6,
|
||||
FIB_SOURCE_IP6_ND))
|
||||
{
|
||||
fib_table_unlock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_IP6_ND);
|
||||
@ -208,33 +211,10 @@ ip6_ll_table_show_all (vlib_main_t * vm, u32 fib_index)
|
||||
vec_free (ctx.entries);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 fib_index;
|
||||
u64 count_by_prefix_length[129];
|
||||
} count_routes_in_fib_at_prefix_length_arg_t;
|
||||
|
||||
static int
|
||||
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;
|
||||
int mask_width;
|
||||
|
||||
if ((kvp->key[2] >> 32) != ap->fib_index)
|
||||
return (BIHASH_WALK_CONTINUE);
|
||||
|
||||
mask_width = kvp->key[2] & 0xFF;
|
||||
|
||||
ap->count_by_prefix_length[mask_width]++;
|
||||
|
||||
return (BIHASH_WALK_CONTINUE);
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
ip6_ll_show_fib (vlib_main_t * vm,
|
||||
unformat_input_t * input, vlib_cli_command_t * cmd)
|
||||
{
|
||||
count_routes_in_fib_at_prefix_length_arg_t _ca, *ca = &_ca;
|
||||
fib_table_t *fib_table;
|
||||
int verbose, matching;
|
||||
ip6_address_t matching_address;
|
||||
@ -272,9 +252,6 @@ ip6_ll_show_fib (vlib_main_t * vm,
|
||||
|
||||
vec_foreach_index (sw_if_index, ip6_ll_table.ilt_fibs)
|
||||
{
|
||||
fib_source_t source;
|
||||
u8 *s = NULL;
|
||||
|
||||
fib_index = ip6_ll_table.ilt_fibs[sw_if_index];
|
||||
if (~0 == fib_index)
|
||||
continue;
|
||||
@ -284,44 +261,9 @@ ip6_ll_show_fib (vlib_main_t * vm,
|
||||
if (!(fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL))
|
||||
continue;
|
||||
|
||||
s = format (s, "%U, fib_index:%d, locks:[",
|
||||
format_fib_table_name, fib_index,
|
||||
FIB_PROTOCOL_IP6, fib_index);
|
||||
vec_foreach_index (source, fib_table->ft_locks)
|
||||
{
|
||||
if (0 != fib_table->ft_locks[source])
|
||||
{
|
||||
s = format (s, "%U:%d, ",
|
||||
format_fib_source, source, fib_table->ft_locks[source]);
|
||||
}
|
||||
}
|
||||
s = format (s, "]");
|
||||
vlib_cli_output (vm, "%v", s);
|
||||
vec_free (s);
|
||||
|
||||
/* Show summary? */
|
||||
ip6_fib_table_show (vm, fib_table, !verbose);
|
||||
if (!verbose)
|
||||
{
|
||||
clib_bihash_24_8_t *h =
|
||||
&ip6_fib_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;
|
||||
|
||||
clib_bihash_foreach_key_value_pair_24_8
|
||||
(h, count_routes_in_fib_at_prefix_length, ca);
|
||||
|
||||
for (len = 128; len >= 0; len--)
|
||||
{
|
||||
if (ca->count_by_prefix_length[len])
|
||||
vlib_cli_output (vm, "%=20d%=16lld",
|
||||
len, ca->count_by_prefix_length[len]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
|
||||
if (!matching)
|
||||
{
|
||||
|
Reference in New Issue
Block a user