char label_buf[32];
};
+/*
+ * 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
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 */
_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 */
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
}
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
case DPLANE_OP_NONE:
break;
}
ret = "ADDR_UNINSTALL";
break;
+ case DPLANE_OP_MAC_INSTALL:
+ ret = "MAC_INSTALL";
+ break;
+ case DPLANE_OP_MAC_DELETE:
+ ret = "MAC_DELETE";
+ break;
}
return ret;
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
*/
return result;
}
+/*
+ * 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;
+
+ 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'
*/
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
#include "lib/queue.h"
+#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
/* Interface address update */
DPLANE_OP_ADDR_INSTALL,
DPLANE_OP_ADDR_UNINSTALL,
+
+ /* MAC address update */
+ DPLANE_OP_MAC_INSTALL,
+ DPLANE_OP_MAC_DELETE,
};
/* Enable system route notifications */
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx);
+const struct ethaddr *dplane_ctx_mac_get_addr(
+ const struct zebra_dplane_ctx *ctx);
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+ const struct zebra_dplane_ctx *ctx);
+
/* Namespace info - esp. for netlink communication */
const struct zebra_dplane_info *dplane_ctx_get_ns(
const struct zebra_dplane_ctx *ctx);
enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
const struct connected *ifc);
+/*
+ * Enqueue evpn mac operations for the dataplane.
+ */
+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 dplane_mac_del(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip);
/* Retrieve the limit on the number of pending, unprocessed updates. */
uint32_t dplane_get_in_queue_limit(void);