diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2021-05-09 19:29:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-09 19:29:45 +0200 |
commit | de10458d6ebf0f0a79a92546ab12451b2cf39267 (patch) | |
tree | 695d22f7cc10ffdcf0c42f3859b60da7258b1757 /lib | |
parent | Merge pull request #8642 from idryzhov/bgp-gr-no-oper (diff) | |
parent | tests: add unit test for nexthop comparisons (diff) | |
download | frr-de10458d6ebf0f0a79a92546ab12451b2cf39267.tar.xz frr-de10458d6ebf0f0a79a92546ab12451b2cf39267.zip |
Merge pull request #8380 from mjstapp/nexthop_cmp_basic
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nexthop.c | 102 | ||||
-rw-r--r-- | lib/nexthop.h | 5 |
2 files changed, 106 insertions, 1 deletions
diff --git a/lib/nexthop.c b/lib/nexthop.c index 843939814..0ac6c0ae1 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -62,7 +62,8 @@ static int _nexthop_labels_cmp(const struct nexthop *nh1, if (nhl1->num_labels < nhl2->num_labels) return -1; - return memcmp(nhl1->label, nhl2->label, nhl1->num_labels); + return memcmp(nhl1->label, nhl2->label, + (nhl1->num_labels * sizeof(mpls_label_t))); } int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1, @@ -203,6 +204,105 @@ int nexthop_cmp(const struct nexthop *next1, const struct nexthop *next2) } /* + * 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 */ const char *nexthop_type_to_str(enum nexthop_types_t nh_type) diff --git a/lib/nexthop.h b/lib/nexthop.h index f1ad195cf..d6ea83cf0 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); |