summaryrefslogtreecommitdiff
path: root/zebra/zebra_dplane.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_dplane.c')
-rw-r--r--zebra/zebra_dplane.c303
1 files changed, 251 insertions, 52 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index c90e027f02..512a9b4021 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -109,8 +109,6 @@ struct dplane_route_info {
* Pseudowire info for the dataplane
*/
struct dplane_pw_info {
- char ifname[IF_NAMESIZE];
- ifindex_t ifindex;
int type;
int af;
int status;
@@ -130,16 +128,13 @@ struct dplane_pw_info {
*/
struct dplane_intf_info {
- char ifname[INTERFACE_NAMSIZ];
- ifindex_t ifindex;
-
uint32_t metric;
uint32_t flags;
#define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */
#define DPLANE_INTF_SECONDARY (1 << 1)
#define DPLANE_INTF_BROADCAST (1 << 2)
-#define DPLANE_INTF_HAS_DEST (1 << 3)
+#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED
#define DPLANE_INTF_HAS_LABEL (1 << 4)
/* Interface address/prefix */
@@ -153,6 +148,17 @@ struct dplane_intf_info {
};
/*
+ * MAC address info for the dataplane.
+ */
+struct dplane_mac_info {
+ vlanid_t vid;
+ struct ethaddr mac;
+ struct in_addr vtep_ip;
+ bool is_sticky;
+
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -188,12 +194,16 @@ struct zebra_dplane_ctx {
vrf_id_t zd_vrf_id;
uint32_t zd_table_id;
+ char zd_ifname[INTERFACE_NAMSIZ];
+ ifindex_t zd_ifindex;
+
/* Support info for different kinds of updates */
union {
struct dplane_route_info rinfo;
zebra_lsp_t lsp;
struct dplane_pw_info pw;
struct dplane_intf_info intf;
+ struct dplane_mac_info macinfo;
} u;
/* Namespace info, used especially for netlink kernel communication */
@@ -273,8 +283,8 @@ static struct zebra_dplane_globals {
/* Sentinel for end of shutdown */
volatile bool dg_run;
- /* Route-update context queue inbound to the dataplane */
- TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q;
+ /* Update context queue inbound to the dataplane */
+ TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
/* Ordered list of providers */
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
@@ -308,6 +318,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_intf_addrs_in;
_Atomic uint32_t dg_intf_addr_errors;
+ _Atomic uint32_t dg_macs_in;
+ _Atomic uint32_t dg_mac_errors;
+
_Atomic uint32_t dg_update_yields;
/* Dataplane pthread */
@@ -348,6 +361,10 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
static enum zebra_dplane_result intf_addr_update_internal(
const struct interface *ifp, const struct connected *ifc,
enum dplane_op_e op);
+static enum zebra_dplane_result mac_update_internal(
+ enum dplane_op_e op, const struct interface *ifp,
+ vlanid_t vid, const struct ethaddr *mac,
+ struct in_addr vtep_ip, bool sticky);
/*
* Public APIs
@@ -466,6 +483,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
}
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
case DPLANE_OP_NONE:
break;
}
@@ -626,6 +645,12 @@ const char *dplane_op2str(enum dplane_op_e op)
ret = "ADDR_UNINSTALL";
break;
+ case DPLANE_OP_MAC_INSTALL:
+ ret = "MAC_INSTALL";
+ break;
+ case DPLANE_OP_MAC_DELETE:
+ ret = "MAC_DELETE";
+ break;
}
return ret;
@@ -744,6 +769,19 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx,
ctx->zd_notif_provider = id;
}
+const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ifname;
+}
+
+ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ifindex;
+}
void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
{
@@ -1030,13 +1068,6 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.num_ecmp;
}
-const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.pw.ifname;
-}
-
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1104,20 +1135,6 @@ dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
}
/* Accessors for interface information */
-const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.intf.ifname;
-}
-
-ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.intf.ifindex;
-}
-
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1187,6 +1204,33 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx)
return ctx->u.intf.label;
}
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.vid;
+}
+
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.is_sticky;
+}
+
+const struct ethaddr *dplane_ctx_mac_get_addr(
+ const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return &(ctx->u.macinfo.mac);
+}
+
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+ const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return &(ctx->u.macinfo.vtep_ip);
+}
+
/*
* End of dplane context accessors
*/
@@ -1422,10 +1466,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
/* This name appears to be c-string, so we use string copy. */
- strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+ strlcpy(ctx->zd_ifname, pw->ifname, sizeof(ctx->zd_ifname));
ctx->zd_vrf_id = pw->vrf_id;
- ctx->u.pw.ifindex = pw->ifindex;
+ ctx->zd_ifindex = pw->ifindex;
ctx->u.pw.type = pw->type;
ctx->u.pw.af = pw->af;
ctx->u.pw.local_label = pw->local_label;
@@ -1467,10 +1511,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
}
/*
- * Enqueue a new route update,
+ * Enqueue a new update,
* and ensure an event is active for the dataplane pthread.
*/
-static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
+static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
{
int ret = EINVAL;
uint32_t high, curr;
@@ -1478,7 +1522,7 @@ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
/* Enqueue for processing by the dataplane pthread */
DPLANE_LOCK();
{
- TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx,
+ TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
zd_q_entries);
}
DPLANE_UNLOCK();
@@ -1558,7 +1602,7 @@ dplane_route_update_internal(struct route_node *rn,
}
/* Enqueue context for processing */
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
}
/* Update counter */
@@ -1724,7 +1768,7 @@ dplane_route_notif_update(struct route_node *rn,
dplane_ctx_set_notif_provider(new_ctx,
dplane_ctx_get_notif_provider(ctx));
- dplane_route_enqueue(new_ctx);
+ dplane_update_enqueue(new_ctx);
ret = ZEBRA_DPLANE_REQUEST_QUEUED;
@@ -1791,7 +1835,7 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
ctx,
dplane_ctx_get_notif_provider(notif_ctx));
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1842,7 +1886,7 @@ static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
if (ret != AOK)
goto done;
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1876,7 +1920,7 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
if (ret != AOK)
goto done;
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1967,8 +2011,8 @@ static enum zebra_dplane_result intf_addr_update_internal(
/* Init the interface-addr-specific area */
memset(&ctx->u.intf, 0, sizeof(ctx->u.intf));
- strlcpy(ctx->u.intf.ifname, ifp->name, sizeof(ctx->u.intf.ifname));
- ctx->u.intf.ifindex = ifp->ifindex;
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+ ctx->zd_ifindex = ifp->ifindex;
ctx->u.intf.prefix = *(ifc->address);
if (if_is_broadcast(ifp))
@@ -1978,9 +2022,6 @@ static enum zebra_dplane_result intf_addr_update_internal(
ctx->u.intf.dest_prefix = *(ifc->destination);
ctx->u.intf.flags |=
(DPLANE_INTF_CONNECTED | DPLANE_INTF_HAS_DEST);
- } else if (ifc->destination) {
- ctx->u.intf.dest_prefix = *(ifc->destination);
- ctx->u.intf.flags |= DPLANE_INTF_HAS_DEST;
}
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
@@ -2003,7 +2044,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
}
}
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
/* Increment counter */
atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1,
@@ -2022,6 +2063,104 @@ static enum zebra_dplane_result intf_addr_update_internal(
}
/*
+ * Enqueue vxlan/evpn mac add (or update).
+ */
+enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip,
+ bool sticky)
+{
+ enum zebra_dplane_result result;
+
+ /* Use common helper api */
+ result = mac_update_internal(DPLANE_OP_MAC_INSTALL, ifp, vid,
+ mac, vtep_ip, sticky);
+ return result;
+}
+
+/*
+ * Enqueue vxlan/evpn mac delete.
+ */
+enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip)
+{
+ enum zebra_dplane_result result;
+
+ /* Use common helper api */
+ result = mac_update_internal(DPLANE_OP_MAC_DELETE, ifp, vid, mac,
+ vtep_ip, false);
+ return result;
+}
+
+/*
+ * Common helper api for MAC address/vxlan updates
+ */
+static enum zebra_dplane_result
+mac_update_internal(enum dplane_op_e op,
+ const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip,
+ bool sticky)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ int ret;
+ struct zebra_dplane_ctx *ctx = NULL;
+ struct zebra_ns *zns;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
+
+ zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s",
+ dplane_op2str(op),
+ prefix_mac2str(mac, buf1, sizeof(buf1)),
+ ifp->name,
+ inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2)));
+ }
+
+ ctx = dplane_ctx_alloc();
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+ ctx->zd_vrf_id = ifp->vrf_id;
+
+ zns = zebra_ns_lookup(ifp->vrf_id);
+ dplane_ctx_ns_init(ctx, zns, false);
+
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+ ctx->zd_ifindex = ifp->ifindex;
+
+ /* Init the mac-specific data area */
+ memset(&ctx->u.macinfo, 0, sizeof(ctx->u.macinfo));
+
+ ctx->u.macinfo.vtep_ip = vtep_ip;
+ ctx->u.macinfo.mac = *mac;
+ ctx->u.macinfo.vid = vid;
+ ctx->u.macinfo.is_sticky = sticky;
+
+ /* Enqueue for processing on the dplane pthread */
+ ret = dplane_update_enqueue(ctx);
+
+ /* Increment counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_macs_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ /* Error counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, 1,
+ memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+/*
* Handler for 'show dplane'
*/
int dplane_show_helper(struct vty *vty, bool detailed)
@@ -2054,7 +2193,35 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit);
vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued);
vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max);
- vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
+ vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_lsps_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_lsp_errors,
+ memory_order_relaxed);
+ vty_out(vty, "LSP updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "LSP update errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_pws_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_pw_errors,
+ memory_order_relaxed);
+ vty_out(vty, "PW updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "PW update errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_intf_addrs_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_intf_addr_errors,
+ memory_order_relaxed);
+ vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_macs_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_mac_errors,
+ memory_order_relaxed);
+ vty_out(vty, "EVPN MAC updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "EVPN MAC errors: %"PRIu64"\n", errs);
return CMD_SUCCESS;
}
@@ -2374,7 +2541,7 @@ kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
- dplane_ctx_get_pw_ifname(ctx),
+ dplane_ctx_get_ifname(ctx),
dplane_op2str(ctx->zd_op),
dplane_ctx_get_pw_af(ctx),
dplane_ctx_get_pw_local_label(ctx),
@@ -2428,7 +2595,6 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
{
enum zebra_dplane_result res;
-
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
char dest_str[PREFIX_STRLEN];
@@ -2450,6 +2616,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
}
/*
+ * Handler for kernel-facing MAC address updates
+ */
+static enum zebra_dplane_result
+kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx)
+{
+ enum zebra_dplane_result res;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ char buf[ETHER_ADDR_STRLEN];
+
+ prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf,
+ sizeof(buf));
+
+ zlog_debug("Dplane %s, mac %s, ifindex %u",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ buf, dplane_ctx_get_ifindex(ctx));
+ }
+
+ res = kernel_mac_update_ctx(ctx);
+
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors,
+ 1, memory_order_relaxed);
+
+ return res;
+}
+
+/*
* Kernel provider callback
*/
static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
@@ -2503,6 +2697,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
res = kernel_dplane_address_update(ctx);
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ res = kernel_dplane_mac_update(ctx);
+ break;
+
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -2682,7 +2881,7 @@ static bool dplane_work_pending(void)
*/
DPLANE_LOCK();
{
- ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+ ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
}
DPLANE_UNLOCK();
@@ -2810,9 +3009,9 @@ static int dplane_thread_loop(struct thread *event)
/* Move new work from incoming list to temp list */
for (counter = 0; counter < limit; counter++) {
- ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+ ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
if (ctx) {
- TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, ctx,
+ TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
zd_q_entries);
ctx->zd_provider = prov->dp_id;
@@ -2997,7 +3196,7 @@ static void zebra_dplane_init_internal(void)
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
- TAILQ_INIT(&zdplane_info.dg_route_ctx_q);
+ TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
TAILQ_INIT(&zdplane_info.dg_providers_q);
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;