Merge pull request #5600 from sworleys/NHG-Depend-Crash

zebra: can't improve efficiency for recursive depends
This commit is contained in:
Mark Stapp 2020-01-15 16:31:55 -05:00 committed by GitHub
commit d26e2d9be4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 13 deletions

View file

@ -34,6 +34,7 @@
#include "jhash.h" #include "jhash.h"
#include "printfrr.h" #include "printfrr.h"
#include "vrf.h" #include "vrf.h"
#include "nexthop_group.h"
DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
@ -565,8 +566,9 @@ uint32_t nexthop_hash(const struct nexthop *nexthop)
return key; return key;
} }
void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, void nexthop_copy_no_recurse(struct nexthop *copy,
struct nexthop *rparent) const struct nexthop *nexthop,
struct nexthop *rparent)
{ {
copy->vrf_id = nexthop->vrf_id; copy->vrf_id = nexthop->vrf_id;
copy->ifindex = nexthop->ifindex; copy->ifindex = nexthop->ifindex;
@ -583,6 +585,28 @@ void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop,
&nexthop->nh_label->label[0]); &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(&copy->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 *nexthop_dup(const struct nexthop *nexthop,
struct nexthop *rparent) struct nexthop *rparent)
{ {

View file

@ -187,9 +187,16 @@ extern unsigned int nexthop_level(struct nexthop *nexthop);
/* Copies to an already allocated nexthop struct */ /* Copies to an already allocated nexthop struct */
extern void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, extern void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop,
struct nexthop *rparent); 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 */ /* Duplicates a nexthop and returns the newly allocated nexthop */
extern struct nexthop *nexthop_dup(const struct nexthop *nexthop, extern struct nexthop *nexthop_dup(const struct nexthop *nexthop,
struct nexthop *rparent); 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 #ifdef __cplusplus
} }

View file

@ -364,10 +364,6 @@ void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh,
for (nh1 = nh; nh1; nh1 = nh1->next) { for (nh1 = nh; nh1; nh1 = nh1->next) {
nexthop = nexthop_dup(nh1, rparent); nexthop = nexthop_dup(nh1, rparent);
_nexthop_add(tnh, nexthop); _nexthop_add(tnh, nexthop);
if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
copy_nexthops(&nexthop->resolved, nh1->resolved,
nexthop);
} }
} }

View file

@ -1048,25 +1048,55 @@ int zebra_nhg_kernel_del(uint32_t id)
} }
/* Some dependency helper functions */ /* Some dependency helper functions */
static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi) static struct nhg_hash_entry *depends_find_recursive(const struct nexthop *nh,
afi_t afi)
{ {
struct nexthop lookup; struct nhg_hash_entry *nhe;
struct nhg_hash_entry *nhe = NULL; struct nexthop *lookup = NULL;
if (!nh) lookup = nexthop_dup(nh, NULL);
goto done;
nhe = zebra_nhg_find_nexthop(0, lookup, afi, 0);
nexthops_free(lookup);
return nhe;
}
static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh,
afi_t afi)
{
struct nhg_hash_entry *nhe;
struct nexthop lookup = {};
/* Capture a snapshot of this single nh; it might be part of a list, /* Capture a snapshot of this single nh; it might be part of a list,
* so we need to make a standalone copy. * so we need to make a standalone copy.
*/ */
memset(&lookup, 0, sizeof(lookup)); nexthop_copy_no_recurse(&lookup, nh, NULL);
nexthop_copy(&lookup, nh, NULL);
nhe = zebra_nhg_find_nexthop(0, &lookup, afi, 0); nhe = zebra_nhg_find_nexthop(0, &lookup, afi, 0);
/* The copy may have allocated labels; free them if necessary. */ /* The copy may have allocated labels; free them if necessary. */
nexthop_del_labels(&lookup); nexthop_del_labels(&lookup);
return nhe;
}
static struct nhg_hash_entry *depends_find(const struct nexthop *nh, afi_t afi)
{
struct nhg_hash_entry *nhe = NULL;
if (!nh)
goto done;
/* We are separating these functions out to increase handling speed
* in the non-recursive case (by not alloc/freeing)
*/
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
nhe = depends_find_recursive(nh, afi);
else
nhe = depends_find_singleton(nh, afi);
done: done:
return nhe; return nhe;
} }