diff --git a/lib/nexthop.c b/lib/nexthop.c index d2ab70e209..e23f8b0792 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -34,6 +34,7 @@ #include "jhash.h" #include "printfrr.h" #include "vrf.h" +#include "nexthop_group.h" DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") @@ -565,8 +566,9 @@ uint32_t nexthop_hash(const struct nexthop *nexthop) return key; } -void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, - struct nexthop *rparent) +void nexthop_copy_no_recurse(struct nexthop *copy, + const struct nexthop *nexthop, + struct nexthop *rparent) { copy->vrf_id = nexthop->vrf_id; copy->ifindex = nexthop->ifindex; @@ -583,6 +585,28 @@ void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, &nexthop->nh_label->label[0]); } +void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, + struct nexthop *rparent) +{ + nexthop_copy_no_recurse(copy, nexthop, rparent); + + /* Bit of a special case here, we need to handle the case + * of a nexthop resolving to agroup. Hence, we need to + * use a nexthop_group API. + */ + if (CHECK_FLAG(copy->flags, NEXTHOP_FLAG_RECURSIVE)) + copy_nexthops(©->resolved, nexthop->resolved, copy); +} + +struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, + struct nexthop *rparent) +{ + struct nexthop *new = nexthop_new(); + + nexthop_copy_no_recurse(new, nexthop, rparent); + return new; +} + struct nexthop *nexthop_dup(const struct nexthop *nexthop, struct nexthop *rparent) { diff --git a/lib/nexthop.h b/lib/nexthop.h index 040b643a84..cb5efe00cc 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -187,9 +187,16 @@ extern unsigned int nexthop_level(struct nexthop *nexthop); /* Copies to an already allocated nexthop struct */ extern void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, struct nexthop *rparent); +/* Copies to an already allocated nexthop struct, not including recurse info */ +extern void nexthop_copy_no_recurse(struct nexthop *copy, + const struct nexthop *nexthop, + struct nexthop *rparent); /* Duplicates a nexthop and returns the newly allocated nexthop */ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, struct nexthop *rparent); +/* Duplicates a nexthop and returns the newly allocated nexthop */ +extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop, + struct nexthop *rparent); #ifdef __cplusplus } diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 0051cba625..0f1a87cf6e 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -363,10 +363,6 @@ void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh, for (nh1 = nh; nh1; nh1 = nh1->next) { nexthop = nexthop_dup(nh1, rparent); _nexthop_add(tnh, nexthop); - - if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) - copy_nexthops(&nexthop->resolved, nh1->resolved, - nexthop); } } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 2be9238ee8..2a76fa61e9 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1054,18 +1054,7 @@ static struct nhg_hash_entry *depends_find_recursive(const struct nexthop *nh, struct nhg_hash_entry *nhe; struct nexthop *lookup = NULL; - /* - * We need to copy its resolved nexthop if its recursively - * resolved so that has to be handled with allocs/frees since - * it could resolve to a group of unknown size. - */ - copy_nexthops(&lookup, nh, NULL); - - /* Make it a single, recursive nexthop */ - nexthops_free(lookup->next); - nexthops_free(lookup->prev); - lookup->next = NULL; - lookup->prev = NULL; + lookup = nexthop_dup(nh, NULL); nhe = zebra_nhg_find_nexthop(0, lookup, afi, 0); @@ -1083,7 +1072,7 @@ static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh, /* Capture a snapshot of this single nh; it might be part of a list, * so we need to make a standalone copy. */ - nexthop_copy(&lookup, nh, NULL); + nexthop_copy_no_recurse(&lookup, nh, NULL); nhe = zebra_nhg_find_nexthop(0, &lookup, afi, 0);