diff options
| -rw-r--r-- | zebra/zebra_nhg.c | 128 |
1 files changed, 63 insertions, 65 deletions
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 9e54753bf0..b343778bf3 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -439,6 +439,17 @@ static void zebra_nhg_process_grp(struct nexthop_group *nhg, } } +static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends, + struct nexthop *nh, afi_t afi) +{ + struct nhg_hash_entry *depend = NULL; + struct nexthop_group resolved_ng = {}; + + _nexthop_group_add_sorted(&resolved_ng, nh); + + depend = zebra_nhg_rib_find(0, &resolved_ng, afi); + depends_add(nhg_depends, depend); +} static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id, struct nexthop_group *nhg, @@ -450,19 +461,24 @@ static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id, 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.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 (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); @@ -474,49 +490,58 @@ static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id, 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; } -static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends, - struct nexthop *nh, afi_t afi) -{ - struct nhg_hash_entry *depend = NULL; - struct nexthop_group resolved_ng = {}; - - _nexthop_group_add_sorted(&resolved_ng, nh); - - depend = zebra_nhg_rib_find(0, &resolved_ng, afi); - depends_add(nhg_depends, depend); -} - /* Find/create a single nexthop */ -static bool zebra_nhg_find_nexthop(struct nhg_hash_entry **nhe, uint32_t id, - struct nexthop *nh, afi_t afi, int type) +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 nhg_connected_tree_head nhg_depends = {}; - bool created = true; _nexthop_group_add_sorted(&nhg, nh); - if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) { - nhg_connected_tree_init(&nhg_depends); - handle_recursive_depend(&nhg_depends, nh->resolved, afi); - } + zebra_nhg_find(&nhe, id, &nhg, NULL, nh->vrf_id, afi, 0); - if (!zebra_nhg_find(nhe, id, &nhg, &nhg_depends, nh->vrf_id, afi, 0)) { - created = false; - depends_decrement_free(&nhg_depends); - } else { - if (zebra_nhg_depends_count(*nhe)) - SET_FLAG((*nhe)->flags, NEXTHOP_GROUP_RECURSIVE); - } - - return created; + return nhe; } static struct nhg_ctx *nhg_ctx_new() @@ -682,8 +707,8 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx) /* These got copied over in zebra_nhg_alloc() */ nexthop_group_free_delete(&nhg); } else - zebra_nhg_find_nexthop(&nhe, ctx->id, &ctx->u.nh, ctx->afi, - ctx->type); + nhe = zebra_nhg_find_nexthop(ctx->id, &ctx->u.nh, ctx->afi, + ctx->type); if (nhe) { if (ctx->id != nhe->id) { @@ -858,7 +883,7 @@ static struct nhg_hash_entry *depends_find(struct nexthop *nh, afi_t afi) lookup->next = 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); @@ -906,11 +931,7 @@ struct nhg_hash_entry * zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi) { 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; if (!nhg) { @@ -919,30 +940,7 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi) return NULL; } - if (nhg->nexthop->next) { - 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); + zebra_nhg_find(&nhe, id, nhg, NULL, nhg_vrf_id, rt_afi, 0); return nhe; } |
