]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Create depends after initial lookup
authorStephen Worley <sworley@cumulusnetworks.com>
Mon, 26 Aug 2019 21:09:31 +0000 (17:09 -0400)
committerStephen Worley <sworley@cumulusnetworks.com>
Fri, 25 Oct 2019 15:13:42 +0000 (11:13 -0400)
Create any depends only after the initial hash lookup
fails. Should reduce hashing cpu cycles significantly.

Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
zebra/zebra_nhg.c

index 9e54753bf01e9cdfa2ccdb980c90dca0e4f1ff4a..b343778bf3a601e921957684b9c6fcdc37b0e8d8 100644 (file)
@@ -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;
 }