From 7597ac7b4d478c6bc47b109752b2ed515c7986b7 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Fri, 26 Jul 2019 12:10:03 -0400 Subject: [PATCH] zebra: initial dplane support for MAC updates Initial data struct and api changes to support EVPN MAC updates via the dataplane subsystem (no handlers yet). Signed-off-by: Mark Stapp --- zebra/zebra_dplane.c | 142 +++++++++++++++++++++++++++++++++++++++++++ zebra/zebra_dplane.h | 26 ++++++++ 2 files changed, 168 insertions(+) diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index bb60600f3a..5d99500397 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -147,6 +147,17 @@ struct dplane_intf_info { 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 @@ -192,6 +203,7 @@ struct zebra_dplane_ctx { 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 */ @@ -306,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 */ @@ -346,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 @@ -464,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; } @@ -624,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; @@ -1177,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 */ @@ -2011,6 +2065,94 @@ static enum zebra_dplane_result intf_addr_update_internal( 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' */ diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 01a23b0881..912fda45d3 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -25,6 +25,7 @@ #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" @@ -124,6 +125,10 @@ enum dplane_op_e { /* 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 */ @@ -291,6 +296,14 @@ const struct prefix *dplane_ctx_get_intf_dest( 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); @@ -352,6 +365,19 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp, 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); -- 2.39.5