mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 18:04:03 +00:00
zebra: Create depends after initial lookup
Create any depends only after the initial hash lookup fails. Should reduce hashing cpu cycles significantly. Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
This commit is contained in:
parent
6e72876478
commit
6384cbcb0e
@ -439,48 +439,6 @@ static void zebra_nhg_process_grp(struct nexthop_group *nhg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
|
|
||||||
struct nexthop_group *nhg,
|
|
||||||
struct nhg_connected_tree_head *nhg_depends,
|
|
||||||
vrf_id_t vrf_id, afi_t afi, int type)
|
|
||||||
{
|
|
||||||
struct nhg_hash_entry lookup = {};
|
|
||||||
|
|
||||||
uint32_t old_id_counter = id_counter;
|
|
||||||
|
|
||||||
bool created = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If it has an id at this point, we must have gotten it from the kernel
|
|
||||||
*/
|
|
||||||
lookup.id = id ? id : ++id_counter;
|
|
||||||
|
|
||||||
lookup.afi = afi;
|
|
||||||
lookup.vrf_id = vrf_id;
|
|
||||||
lookup.type = type ? type : ZEBRA_ROUTE_NHG;
|
|
||||||
lookup.nhg = nhg;
|
|
||||||
|
|
||||||
if (nhg_depends)
|
|
||||||
lookup.nhg_depends = *nhg_depends;
|
|
||||||
|
|
||||||
if (id)
|
|
||||||
(*nhe) = zebra_nhg_lookup_id(id);
|
|
||||||
else
|
|
||||||
(*nhe) = hash_lookup(zrouter.nhgs, &lookup);
|
|
||||||
|
|
||||||
/* If it found an nhe in our tables, this new ID is unused */
|
|
||||||
if (*nhe)
|
|
||||||
id_counter = old_id_counter;
|
|
||||||
|
|
||||||
if (!(*nhe)) {
|
|
||||||
(*nhe) = hash_get(zrouter.nhgs, &lookup, zebra_nhg_hash_alloc);
|
|
||||||
created = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return created;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
|
static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
|
||||||
struct nexthop *nh, afi_t afi)
|
struct nexthop *nh, afi_t afi)
|
||||||
{
|
{
|
||||||
@ -493,30 +451,97 @@ static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
|
|||||||
depends_add(nhg_depends, depend);
|
depends_add(nhg_depends, depend);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find/create a single nexthop */
|
static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
|
||||||
static bool zebra_nhg_find_nexthop(struct nhg_hash_entry **nhe, uint32_t id,
|
struct nexthop_group *nhg,
|
||||||
struct nexthop *nh, afi_t afi, int type)
|
struct nhg_connected_tree_head *nhg_depends,
|
||||||
|
vrf_id_t vrf_id, afi_t afi, int type)
|
||||||
{
|
{
|
||||||
|
struct nhg_hash_entry lookup = {};
|
||||||
|
|
||||||
|
uint32_t old_id_counter = id_counter;
|
||||||
|
|
||||||
|
bool created = false;
|
||||||
|
bool recursive = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If it has an id at this point, we must have gotten it from the kernel
|
||||||
|
*/
|
||||||
|
lookup.id = id ? id : ++id_counter;
|
||||||
|
|
||||||
|
lookup.type = type ? type : ZEBRA_ROUTE_NHG;
|
||||||
|
lookup.nhg = nhg;
|
||||||
|
|
||||||
|
if (lookup.nhg->nexthop->next) {
|
||||||
|
/* Groups can have all vrfs and AF's in them */
|
||||||
|
lookup.afi = AFI_UNSPEC;
|
||||||
|
lookup.vrf_id = 0;
|
||||||
|
} else {
|
||||||
|
lookup.afi = afi;
|
||||||
|
lookup.vrf_id = vrf_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
(*nhe) = zebra_nhg_lookup_id(id);
|
||||||
|
else
|
||||||
|
(*nhe) = hash_lookup(zrouter.nhgs, &lookup);
|
||||||
|
|
||||||
|
/* If it found an nhe in our tables, this new ID is unused */
|
||||||
|
if (*nhe)
|
||||||
|
id_counter = old_id_counter;
|
||||||
|
|
||||||
|
if (!(*nhe)) {
|
||||||
|
/* Only hash/lookup the depends if the first lookup
|
||||||
|
* fails to find something. This should hopefully save a
|
||||||
|
* lot of cycles for larger ecmp sizes.
|
||||||
|
*/
|
||||||
|
if (nhg_depends)
|
||||||
|
/* If you don't want to hash on each nexthop in the
|
||||||
|
* nexthop group struct you can pass the depends
|
||||||
|
* directly. Kernel-side we do this since it just looks
|
||||||
|
* them up via IDs.
|
||||||
|
*/
|
||||||
|
lookup.nhg_depends = *nhg_depends;
|
||||||
|
else {
|
||||||
|
if (nhg->nexthop->next) {
|
||||||
|
nhg_connected_tree_init(&lookup.nhg_depends);
|
||||||
|
|
||||||
|
/* If its a group, create a dependency tree */
|
||||||
|
struct nexthop *nh = NULL;
|
||||||
|
|
||||||
|
for (nh = nhg->nexthop; nh; nh = nh->next)
|
||||||
|
depends_find_add(&lookup.nhg_depends,
|
||||||
|
nh, afi);
|
||||||
|
} else if (CHECK_FLAG(nhg->nexthop->flags,
|
||||||
|
NEXTHOP_FLAG_RECURSIVE)) {
|
||||||
|
nhg_connected_tree_init(&lookup.nhg_depends);
|
||||||
|
handle_recursive_depend(&lookup.nhg_depends,
|
||||||
|
nhg->nexthop->resolved,
|
||||||
|
afi);
|
||||||
|
recursive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*nhe) = hash_get(zrouter.nhgs, &lookup, zebra_nhg_hash_alloc);
|
||||||
|
created = true;
|
||||||
|
|
||||||
|
if (recursive)
|
||||||
|
SET_FLAG((*nhe)->flags, NEXTHOP_GROUP_RECURSIVE);
|
||||||
|
}
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find/create a single nexthop */
|
||||||
|
static struct nhg_hash_entry *
|
||||||
|
zebra_nhg_find_nexthop(uint32_t id, struct nexthop *nh, afi_t afi, int type)
|
||||||
|
{
|
||||||
|
struct nhg_hash_entry *nhe = NULL;
|
||||||
struct nexthop_group nhg = {};
|
struct nexthop_group nhg = {};
|
||||||
struct nhg_connected_tree_head nhg_depends = {};
|
|
||||||
bool created = true;
|
|
||||||
|
|
||||||
_nexthop_group_add_sorted(&nhg, nh);
|
_nexthop_group_add_sorted(&nhg, nh);
|
||||||
|
|
||||||
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) {
|
zebra_nhg_find(&nhe, id, &nhg, NULL, nh->vrf_id, afi, 0);
|
||||||
nhg_connected_tree_init(&nhg_depends);
|
|
||||||
handle_recursive_depend(&nhg_depends, nh->resolved, afi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zebra_nhg_find(nhe, id, &nhg, &nhg_depends, nh->vrf_id, afi, 0)) {
|
return nhe;
|
||||||
created = false;
|
|
||||||
depends_decrement_free(&nhg_depends);
|
|
||||||
} else {
|
|
||||||
if (zebra_nhg_depends_count(*nhe))
|
|
||||||
SET_FLAG((*nhe)->flags, NEXTHOP_GROUP_RECURSIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return created;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nhg_ctx *nhg_ctx_new()
|
static struct nhg_ctx *nhg_ctx_new()
|
||||||
@ -682,7 +707,7 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx)
|
|||||||
/* These got copied over in zebra_nhg_alloc() */
|
/* These got copied over in zebra_nhg_alloc() */
|
||||||
nexthop_group_free_delete(&nhg);
|
nexthop_group_free_delete(&nhg);
|
||||||
} else
|
} else
|
||||||
zebra_nhg_find_nexthop(&nhe, ctx->id, &ctx->u.nh, ctx->afi,
|
nhe = zebra_nhg_find_nexthop(ctx->id, &ctx->u.nh, ctx->afi,
|
||||||
ctx->type);
|
ctx->type);
|
||||||
|
|
||||||
if (nhe) {
|
if (nhe) {
|
||||||
@ -858,7 +883,7 @@ static struct nhg_hash_entry *depends_find(struct nexthop *nh, afi_t afi)
|
|||||||
lookup->next = NULL;
|
lookup->next = NULL;
|
||||||
lookup->prev = NULL;
|
lookup->prev = NULL;
|
||||||
|
|
||||||
zebra_nhg_find_nexthop(&nhe, 0, lookup, afi, 0);
|
nhe = zebra_nhg_find_nexthop(0, lookup, afi, 0);
|
||||||
|
|
||||||
nexthops_free(lookup);
|
nexthops_free(lookup);
|
||||||
|
|
||||||
@ -906,11 +931,7 @@ struct nhg_hash_entry *
|
|||||||
zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
|
zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
|
||||||
{
|
{
|
||||||
struct nhg_hash_entry *nhe = NULL;
|
struct nhg_hash_entry *nhe = NULL;
|
||||||
struct nhg_connected_tree_head nhg_depends = {};
|
|
||||||
bool recursive = false;
|
|
||||||
|
|
||||||
/* Defualt the nhe to the afi and vrf of the route */
|
|
||||||
afi_t nhg_afi = rt_afi;
|
|
||||||
vrf_id_t nhg_vrf_id = nhg->nexthop->vrf_id;
|
vrf_id_t nhg_vrf_id = nhg->nexthop->vrf_id;
|
||||||
|
|
||||||
if (!nhg) {
|
if (!nhg) {
|
||||||
@ -919,30 +940,7 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nhg->nexthop->next) {
|
zebra_nhg_find(&nhe, id, nhg, NULL, nhg_vrf_id, rt_afi, 0);
|
||||||
nhg_connected_tree_init(&nhg_depends);
|
|
||||||
|
|
||||||
/* If its a group, create a dependency tree */
|
|
||||||
struct nexthop *nh = NULL;
|
|
||||||
|
|
||||||
for (nh = nhg->nexthop; nh; nh = nh->next)
|
|
||||||
depends_find_add(&nhg_depends, nh, rt_afi);
|
|
||||||
|
|
||||||
/* change the afi/vrf_id since its a group */
|
|
||||||
nhg_afi = AFI_UNSPEC;
|
|
||||||
nhg_vrf_id = 0;
|
|
||||||
} else if (CHECK_FLAG(nhg->nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) {
|
|
||||||
nhg_connected_tree_init(&nhg_depends);
|
|
||||||
handle_recursive_depend(&nhg_depends, nhg->nexthop->resolved,
|
|
||||||
rt_afi);
|
|
||||||
recursive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zebra_nhg_find(&nhe, id, nhg, &nhg_depends, nhg_vrf_id, nhg_afi,
|
|
||||||
0))
|
|
||||||
depends_decrement_free(&nhg_depends);
|
|
||||||
else if (recursive)
|
|
||||||
SET_FLAG(nhe->flags, NEXTHOP_GROUP_RECURSIVE);
|
|
||||||
|
|
||||||
return nhe;
|
return nhe;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user