summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/nexthop.c9
-rw-r--r--lib/nexthop.h3
-rw-r--r--lib/nexthop_group.c25
-rw-r--r--lib/zclient.c88
-rw-r--r--lib/zebra.h1
5 files changed, 120 insertions, 6 deletions
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 0984c1a16..cf5bed3d6 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -65,9 +65,8 @@ static int _nexthop_labels_cmp(const struct nexthop *nh1,
return memcmp(nhl1->label, nhl2->label, nhl1->num_labels);
}
-static int _nexthop_g_addr_cmp(enum nexthop_types_t type,
- const union g_addr *addr1,
- const union g_addr *addr2)
+int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1,
+ const union g_addr *addr2)
{
int ret = 0;
@@ -92,13 +91,13 @@ static int _nexthop_g_addr_cmp(enum nexthop_types_t type,
static int _nexthop_gateway_cmp(const struct nexthop *nh1,
const struct nexthop *nh2)
{
- return _nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
+ return nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
}
static int _nexthop_source_cmp(const struct nexthop *nh1,
const struct nexthop *nh2)
{
- return _nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
+ return nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
}
static int _nexthop_cmp_no_labels(const struct nexthop *next1,
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 20401cd58..9dd5fc6fd 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -142,6 +142,9 @@ extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2);
extern bool nexthop_same_no_labels(const struct nexthop *nh1,
const struct nexthop *nh2);
extern int nexthop_cmp(const struct nexthop *nh1, const struct nexthop *nh2);
+extern int nexthop_g_addr_cmp(enum nexthop_types_t type,
+ const union g_addr *addr1,
+ const union g_addr *addr2);
extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
extern bool nexthop_labels_match(const struct nexthop *nh1,
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 5602018b3..abe2096ce 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -60,6 +60,16 @@ nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
return strcmp(nhgc1->name, nhgc2->name);
}
+static struct nexthop *nexthop_group_tail(const struct nexthop_group *nhg)
+{
+ struct nexthop *nexthop = nhg->nexthop;
+
+ while (nexthop && nexthop->next)
+ nexthop = nexthop->next;
+
+ return nexthop;
+}
+
uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg)
{
struct nexthop *nhop;
@@ -129,7 +139,20 @@ void _nexthop_add(struct nexthop **target, struct nexthop *nexthop)
void _nexthop_group_add_sorted(struct nexthop_group *nhg,
struct nexthop *nexthop)
{
- struct nexthop *position, *prev;
+ struct nexthop *position, *prev, *tail;
+
+ /* Try to just append to the end first
+ * This trust it is already sorted
+ */
+
+ tail = nexthop_group_tail(nhg);
+
+ if (tail && (nexthop_cmp(tail, nexthop) < 0)) {
+ tail->next = nexthop;
+ nexthop->prev = tail;
+
+ return;
+ }
for (position = nhg->nexthop, prev = NULL; position;
prev = position, position = position->next) {
diff --git a/lib/zclient.c b/lib/zclient.c
index 2d79d9b3c..f809704f8 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -766,6 +766,92 @@ int zclient_route_send(uint8_t cmd, struct zclient *zclient,
return zclient_send_message(zclient);
}
+static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1,
+ const struct zapi_nexthop *next2)
+{
+ if (next1->label_num > next2->label_num)
+ return 1;
+
+ if (next1->label_num < next2->label_num)
+ return -1;
+
+ return memcmp(next1->labels, next2->labels, next1->label_num);
+}
+
+static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
+ const struct zapi_nexthop *next2)
+{
+ int ret = 0;
+
+ if (next1->vrf_id < next2->vrf_id)
+ return -1;
+
+ if (next1->vrf_id > next2->vrf_id)
+ return 1;
+
+ if (next1->type < next2->type)
+ return -1;
+
+ if (next1->type > next2->type)
+ return 1;
+
+ switch (next1->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV6:
+ ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
+ &next2->gate);
+ if (ret != 0)
+ return ret;
+ break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ ret = nexthop_g_addr_cmp(next1->type, &next1->gate,
+ &next2->gate);
+ if (ret != 0)
+ return ret;
+ /* Intentional Fall-Through */
+ case NEXTHOP_TYPE_IFINDEX:
+ if (next1->ifindex < next2->ifindex)
+ return -1;
+
+ if (next1->ifindex > next2->ifindex)
+ return 1;
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ if (next1->bh_type < next2->bh_type)
+ return -1;
+
+ if (next1->bh_type > next2->bh_type)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+static int zapi_nexthop_cmp(const void *item1, const void *item2)
+{
+ int ret = 0;
+
+ const struct zapi_nexthop *next1 = item1;
+ const struct zapi_nexthop *next2 = item2;
+
+ ret = zapi_nexthop_cmp_no_labels(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = zapi_nexthop_labels_cmp(next1, next2);
+
+ return ret;
+}
+
+static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
+ uint16_t nexthop_num)
+{
+ qsort(nh_grp, nexthop_num, sizeof(struct zapi_nexthop),
+ &zapi_nexthop_cmp);
+}
+
int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
{
struct zapi_nexthop *api_nh;
@@ -821,6 +907,8 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
return -1;
}
+ zapi_nexthop_group_sort(api->nexthops, api->nexthop_num);
+
stream_putw(s, api->nexthop_num);
for (i = 0; i < api->nexthop_num; i++) {
diff --git a/lib/zebra.h b/lib/zebra.h
index 789a93a3c..b17ef700b 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -136,6 +136,7 @@ typedef unsigned char uint8_t;
#ifdef CRYPTO_OPENSSL
#include <openssl/evp.h>
+#include <openssl/hmac.h>
#endif
#include "openbsd-tree.h"