summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--isisd/isis_tlvs.c18
-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
-rw-r--r--zebra/rt.h4
-rw-r--r--zebra/rt_netlink.c49
-rw-r--r--zebra/rt_socket.c10
-rw-r--r--zebra/zebra_dplane.c65
-rw-r--r--zebra/zebra_dplane.h15
-rw-r--r--zebra/zebra_rib.c2
-rw-r--r--zebra/zebra_vxlan.c16
13 files changed, 243 insertions, 62 deletions
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 488dfedae..ee253c7a3 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -22,7 +22,9 @@
*/
#include <zebra.h>
+#ifdef CRYPTO_INTERNAL
#include "md5.h"
+#endif
#include "memory.h"
#include "stream.h"
#include "sbuf.h"
@@ -2770,8 +2772,16 @@ static void update_auth_hmac_md5(struct isis_auth *auth, struct stream *s,
safe_auth_md5(s, &checksum, &rem_lifetime);
memset(STREAM_DATA(s) + auth->offset, 0, 16);
+#ifdef CRYPTO_OPENSSL
+ uint8_t *result = (uint8_t *)HMAC(EVP_md5(), auth->passwd,
+ auth->plength, STREAM_DATA(s),
+ stream_get_endp(s), NULL, NULL);
+
+ memcpy(digest, result, 16);
+#elif CRYPTO_INTERNAL
hmac_md5(STREAM_DATA(s), stream_get_endp(s), auth->passwd,
auth->plength, digest);
+#endif
memcpy(auth->value, digest, 16);
memcpy(STREAM_DATA(s) + auth->offset, digest, 16);
@@ -3310,8 +3320,16 @@ static bool auth_validator_hmac_md5(struct isis_passwd *passwd,
safe_auth_md5(stream, &checksum, &rem_lifetime);
memset(STREAM_DATA(stream) + auth->offset, 0, 16);
+#ifdef CRYPTO_OPENSSL
+ uint8_t *result = (uint8_t *)HMAC(EVP_md5(), passwd->passwd,
+ passwd->len, STREAM_DATA(stream),
+ stream_get_endp(stream), NULL, NULL);
+
+ memcpy(digest, result, 16);
+#elif CRYPTO_INTERNAL
hmac_md5(STREAM_DATA(stream), stream_get_endp(stream), passwd->passwd,
passwd->len, digest);
+#endif
memcpy(STREAM_DATA(stream) + auth->offset, auth->value, 16);
bool rv = !memcmp(digest, auth->value, 16);
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"
diff --git a/zebra/rt.h b/zebra/rt.h
index 73708bd30..59b42fed1 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -68,10 +68,6 @@ extern int mpls_kernel_init(void);
extern uint32_t kernel_get_speed(struct interface *ifp);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
-extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
- struct in_addr *vtep_ip);
-extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
- struct in_addr *vtep_ip);
/*
* Southbound Initialization routines to get initial starting
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 98d1dbbbc..5edcf9bb8 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1927,19 +1927,17 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
* Add remote VTEP to the flood list for this VxLAN interface (VNI). This
* is done by adding an FDB entry with a MAC of 00:00:00:00:00:00.
*/
-static int netlink_vxlan_flood_list_update(struct interface *ifp,
- struct in_addr *vtep_ip, int cmd)
+static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
+ int cmd)
{
- struct zebra_ns *zns;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
uint8_t dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ const struct ipaddr *addr;
- zns = zvrf->zns;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
@@ -1953,39 +1951,14 @@ static int netlink_vxlan_flood_list_update(struct interface *ifp,
addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
- req.ndm.ndm_ifindex = ifp->ifindex;
- addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4);
-
- return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
- 0);
-}
-
-/*
- * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves
- * adding
- * a "flood" MAC FDB entry.
- */
-int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
-{
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
- inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
+ req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
- return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH);
-}
+ addr = dplane_ctx_neigh_get_ipaddr(ctx);
-/*
- * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves
- * deleting the "flood" MAC FDB entry.
- */
-int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
-{
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Uninstall %s from flood list for VNI %u intf %s(%u)",
- inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex);
+ addattr_l(&req.n, sizeof(req), NDA_DST, &(addr->ipaddr_v4), 4);
- return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH);
+ return netlink_talk_info(netlink_talk_filter, &req.n,
+ dplane_ctx_get_ns(ctx), 0);
}
#ifndef NDA_RTA
@@ -2883,6 +2856,12 @@ enum zebra_dplane_result kernel_neigh_update_ctx(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NEIGH_DELETE:
ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH);
break;
+ case DPLANE_OP_VTEP_ADD:
+ ret = netlink_vxlan_flood_update_ctx(ctx, RTM_NEWNEIGH);
+ break;
+ case DPLANE_OP_VTEP_DELETE:
+ ret = netlink_vxlan_flood_update_ctx(ctx, RTM_DELNEIGH);
+ break;
default:
break;
}
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index f8ce71713..dc0f29bdb 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -382,16 +382,6 @@ extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute)
return 0;
}
-int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
-{
- return 0;
-}
-
-int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
-{
- return 0;
-}
-
/*
* Update MAC, using dataplane context object. No-op here for now.
*/
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 569ccfb0b..2bf541617 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -148,7 +148,7 @@ struct dplane_intf_info {
};
/*
- * MAC address info for the dataplane.
+ * EVPN MAC address info for the dataplane.
*/
struct dplane_mac_info {
vlanid_t vid;
@@ -508,6 +508,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
case DPLANE_OP_NEIGH_INSTALL:
case DPLANE_OP_NEIGH_UPDATE:
case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
case DPLANE_OP_NONE:
break;
}
@@ -684,6 +686,12 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_NEIGH_DELETE:
ret = "NEIGH_DELETE";
break;
+ case DPLANE_OP_VTEP_ADD:
+ ret = "VTEP_ADD";
+ break;
+ case DPLANE_OP_VTEP_DELETE:
+ ret = "VTEP_DELETE";
+ break;
}
return ret;
@@ -2243,7 +2251,7 @@ enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp,
const struct ipaddr *ip,
const struct ethaddr *mac)
{
- enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ enum zebra_dplane_result result;
result = neigh_update_internal(DPLANE_OP_NEIGH_UPDATE,
ifp, mac, ip, 0, DPLANE_NUD_PROBE);
@@ -2257,7 +2265,7 @@ enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp,
enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp,
const struct ipaddr *ip)
{
- enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ enum zebra_dplane_result result;
result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE,
ifp, NULL, ip, 0, 0);
@@ -2266,6 +2274,55 @@ enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp,
}
/*
+ * Enqueue evpn VTEP add for the dataplane.
+ */
+enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
+ const struct in_addr *ip,
+ vni_t vni)
+{
+ enum zebra_dplane_result result;
+ struct ethaddr mac = { {0, 0, 0, 0, 0, 0} };
+ struct ipaddr addr;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Install %s into flood list for VNI %u intf %s(%u)",
+ inet_ntoa(*ip), vni, ifp->name, ifp->ifindex);
+
+ SET_IPADDR_V4(&addr);
+ addr.ipaddr_v4 = *ip;
+
+ result = neigh_update_internal(DPLANE_OP_VTEP_ADD,
+ ifp, &mac, &addr, 0, 0);
+
+ return result;
+}
+
+/*
+ * Enqueue evpn VTEP add for the dataplane.
+ */
+enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
+ const struct in_addr *ip,
+ vni_t vni)
+{
+ enum zebra_dplane_result result;
+ struct ethaddr mac = { {0, 0, 0, 0, 0, 0} };
+ struct ipaddr addr;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Uninstall %s from flood list for VNI %u intf %s(%u)",
+ inet_ntoa(*ip), vni, ifp->name, ifp->ifindex);
+
+ SET_IPADDR_V4(&addr);
+ addr.ipaddr_v4 = *ip;
+
+ result = neigh_update_internal(DPLANE_OP_VTEP_DELETE,
+ ifp, &mac, &addr, 0, 0);
+
+ return result;
+}
+
+/*
* Common helper api for evpn neighbor updates
*/
static enum zebra_dplane_result
@@ -2910,6 +2967,8 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
case DPLANE_OP_NEIGH_INSTALL:
case DPLANE_OP_NEIGH_UPDATE:
case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
res = kernel_dplane_neigh_update(ctx);
break;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index fab241a57..31f0fc98b 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -134,6 +134,10 @@ enum dplane_op_e {
DPLANE_OP_NEIGH_INSTALL,
DPLANE_OP_NEIGH_UPDATE,
DPLANE_OP_NEIGH_DELETE,
+
+ /* EVPN VTEP updates */
+ DPLANE_OP_VTEP_ADD,
+ DPLANE_OP_VTEP_DELETE,
};
/*
@@ -421,6 +425,17 @@ enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp,
enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp,
const struct ipaddr *ip);
+/*
+ * Enqueue evpn VTEP updates for the dataplane.
+ */
+enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
+ const struct in_addr *ip,
+ vni_t vni);
+enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
+ const struct in_addr *ip,
+ vni_t vni);
+
+
/* Retrieve the limit on the number of pending, unprocessed updates. */
uint32_t dplane_get_in_queue_limit(void);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index b85784f59..157c67fa6 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3280,6 +3280,8 @@ static int rib_process_dplane_results(struct thread *thread)
case DPLANE_OP_NEIGH_INSTALL:
case DPLANE_OP_NEIGH_UPDATE:
case DPLANE_OP_NEIGH_DELETE:
+ case DPLANE_OP_VTEP_ADD:
+ case DPLANE_OP_VTEP_DELETE:
case DPLANE_OP_NONE:
/* Don't expect this: just return the struct? */
dplane_ctx_fini(&ctx);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index b8dfe999d..bb8b61e7e 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -4290,9 +4290,13 @@ static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
static int zvni_vtep_install(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
{
if (is_vxlan_flooding_head_end() &&
- (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL))
- return kernel_add_vtep(zvni->vni, zvni->vxlan_if,
- &zvtep->vtep_ip);
+ (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) {
+ if (ZEBRA_DPLANE_REQUEST_FAILURE ==
+ dplane_vtep_add(zvni->vxlan_if,
+ &zvtep->vtep_ip, zvni->vni))
+ return -1;
+ }
+
return 0;
}
@@ -4307,7 +4311,11 @@ static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
return -1;
}
- return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
+ if (ZEBRA_DPLANE_REQUEST_FAILURE ==
+ dplane_vtep_delete(zvni->vxlan_if, vtep_ip, zvni->vni))
+ return -1;
+
+ return 0;
}
/*