summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2021-05-09 19:29:45 +0200
committerGitHub <noreply@github.com>2021-05-09 19:29:45 +0200
commitde10458d6ebf0f0a79a92546ab12451b2cf39267 (patch)
tree695d22f7cc10ffdcf0c42f3859b60da7258b1757 /lib
parentMerge pull request #8642 from idryzhov/bgp-gr-no-oper (diff)
parenttests: add unit test for nexthop comparisons (diff)
downloadfrr-de10458d6ebf0f0a79a92546ab12451b2cf39267.tar.xz
frr-de10458d6ebf0f0a79a92546ab12451b2cf39267.zip
Merge pull request #8380 from mjstapp/nexthop_cmp_basic
Diffstat (limited to 'lib')
-rw-r--r--lib/nexthop.c102
-rw-r--r--lib/nexthop.h5
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);