From 338ec3b86723f19bc43df9899e345811ad5f80d0 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Mon, 29 Mar 2021 16:09:40 -0400 Subject: [PATCH] lib: add basic nexthop comparison api Add a simpler, more limited nexthop comparison function. This compares a few key attributes, such as vrf, gateway, labels. Signed-off-by: Mark Stapp --- lib/nexthop.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/nexthop.h | 5 +++ 2 files changed, 104 insertions(+) diff --git a/lib/nexthop.c b/lib/nexthop.c index 6b15442a87..0ac6c0ae1b 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -203,6 +203,105 @@ int nexthop_cmp(const struct nexthop *next1, const struct nexthop *next2) return ret; } +/* + * More-limited comparison function used to detect duplicate + * nexthops. This is used in places where we don't need the full + * comparison of 'nexthop_cmp()'. + */ +int nexthop_cmp_basic(const struct nexthop *nh1, + const struct nexthop *nh2) +{ + int ret = 0; + const struct mpls_label_stack *nhl1 = NULL; + const struct mpls_label_stack *nhl2 = NULL; + + if (nh1 == NULL && nh2 == NULL) + return 0; + + if (nh1 && !nh2) + return 1; + + if (!nh1 && nh2) + return -1; + + if (nh1->vrf_id < nh2->vrf_id) + return -1; + + if (nh1->vrf_id > nh2->vrf_id) + return 1; + + if (nh1->type < nh2->type) + return -1; + + if (nh1->type > nh2->type) + return 1; + + if (nh1->weight < nh2->weight) + return -1; + + if (nh1->weight > nh2->weight) + return 1; + + switch (nh1->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: + ret = nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate); + if (ret != 0) + return ret; + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: + ret = nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate); + if (ret != 0) + return ret; + /* Intentional Fall-Through */ + case NEXTHOP_TYPE_IFINDEX: + if (nh1->ifindex < nh2->ifindex) + return -1; + + if (nh1->ifindex > nh2->ifindex) + return 1; + break; + case NEXTHOP_TYPE_BLACKHOLE: + if (nh1->bh_type < nh2->bh_type) + return -1; + + if (nh1->bh_type > nh2->bh_type) + return 1; + break; + } + + /* Compare source addr */ + ret = nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src); + if (ret != 0) + goto done; + + nhl1 = nh1->nh_label; + nhl2 = nh2->nh_label; + + /* No labels is a match */ + if (!nhl1 && !nhl2) + return 0; + + if (nhl1 && !nhl2) + return 1; + + if (nhl2 && !nhl1) + return -1; + + if (nhl1->num_labels > nhl2->num_labels) + return 1; + + if (nhl1->num_labels < nhl2->num_labels) + return -1; + + ret = memcmp(nhl1->label, nhl2->label, + (nhl1->num_labels * sizeof(mpls_label_t))); + +done: + return ret; +} + /* * nexthop_type_to_str */ diff --git a/lib/nexthop.h b/lib/nexthop.h index f1ad195cf4..d6ea83cf06 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -207,6 +207,11 @@ extern int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1, const union g_addr *addr2); +/* More-limited comparison function used to detect duplicate nexthops. + * Returns -1, 0, 1 + */ +int nexthop_cmp_basic(const struct nexthop *nh1, const struct nexthop *nh2); + extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type); extern bool nexthop_labels_match(const struct nexthop *nh1, const struct nexthop *nh2); -- 2.39.5