]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: use dataplane for vxlan remote mac programming
authorMark Stapp <mjs@voltanet.io>
Tue, 30 Jul 2019 15:54:07 +0000 (11:54 -0400)
committerMark Stapp <mjs@voltanet.io>
Fri, 2 Aug 2019 18:54:16 +0000 (14:54 -0400)
Move vxlan remote MAC install and uninstall to the async
dataplane.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/zebra_dplane.c
zebra/zebra_rib.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h

index 04576671fe54f085409b4759a04a4ee8ecb0574f..727d2d0c55ab5476a86d63719699502bc231343b 100644 (file)
@@ -41,7 +41,7 @@ extern "C" {
        ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
 
 /*
- * Update or delete a route, LSP, or pseudowire from the kernel,
+ * Update or delete a route, LSP, pseudowire, or vxlan MAC from the kernel,
  * using info from a dataplane context.
  */
 extern enum zebra_dplane_result kernel_route_update(
@@ -55,6 +55,8 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
 enum zebra_dplane_result kernel_address_update_ctx(
        struct zebra_dplane_ctx *ctx);
 
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx);
+
 extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
                               int llalen, ns_id_t ns_id);
 extern int kernel_interface_set_master(struct interface *master,
@@ -68,12 +70,6 @@ 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);
-extern int kernel_add_mac(struct interface *ifp, vlanid_t vid,
-                         struct ethaddr *mac, struct in_addr vtep_ip,
-                         bool sticky);
-extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
-                         struct ethaddr *mac, struct in_addr vtep_ip);
-
 extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
                            struct ethaddr *mac, uint8_t flags);
 extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
index b1d0c1e3a69ee78099ef8e276fbaa1dc76750bec..e48ed9ef8b7d32d43eb641dcfb9e9076e471fcaa 100644 (file)
@@ -2279,33 +2279,70 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
 
        return ret;
 }
-static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
-                                struct ethaddr *mac, struct in_addr vtep_ip,
-                                int cmd, bool sticky)
+
+/*
+ * Netlink-specific handler for MAC updates using dataplane context object.
+ */
+static enum zebra_dplane_result
+netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       struct zebra_ns *zns;
        struct {
                struct nlmsghdr n;
                struct ndmsg ndm;
                char buf[256];
        } req;
+       int ret;
        int dst_alen;
        struct zebra_if *zif;
        struct interface *br_if;
        struct zebra_if *br_zif;
-       char buf[ETHER_ADDR_STRLEN];
        int vid_present = 0;
        char vid_buf[20];
-       char dst_buf[30];
-       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+       struct zebra_ns *zns;
+       struct interface *ifp;
+       int cmd;
+       struct in_addr vtep_ip;
+       vlanid_t vid;
+
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
+               cmd = RTM_NEWNEIGH;
+       else
+               cmd = RTM_DELNEIGH;
+
+       /* Locate zebra ns and interface objects from context data */
+       zns = zebra_ns_lookup(dplane_ctx_get_ns(ctx)->ns_id);
+       if (zns == NULL) {
+               /* Nothing to be done */
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - zebra ns unknown",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  dplane_ctx_get_ifname(ctx),
+                                  dplane_ctx_get_ifindex(ctx));
+
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
+
+       ifp = if_lookup_by_index_per_ns(zns, dplane_ctx_get_ifindex(ctx));
+       if (ifp == NULL) {
+               /* Nothing to be done */
+               /* Nothing to be done */
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - interface unknown",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  dplane_ctx_get_ifname(ctx),
+                                  dplane_ctx_get_ifindex(ctx));
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
+
+       vid = dplane_ctx_mac_get_vlan(ctx);
 
-       zns = zvrf->zns;
        zif = ifp->info;
        if ((br_if = zif->brslave_info.br_if) == NULL) {
-               zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
-                          (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
-                          ifp->ifindex);
-               return -1;
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
+                                  (cmd == RTM_NEWNEIGH) ? "add" : "del",
+                                  ifp->name, ifp->ifindex);
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
        }
 
        memset(&req, 0, sizeof(req));
@@ -2319,16 +2356,19 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
        req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
        req.ndm.ndm_state = NUD_REACHABLE;
 
-       if (sticky)
+       if (dplane_ctx_mac_is_sticky(ctx))
                req.ndm.ndm_state |= NUD_NOARP;
        else
                req.ndm.ndm_flags |= NTF_EXT_LEARNED;
 
-       addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+       addattr_l(&req.n, sizeof(req), NDA_LLADDR,
+                 dplane_ctx_mac_get_addr(ctx), 6);
        req.ndm.ndm_ifindex = ifp->ifindex;
+
        dst_alen = 4; // TODO: hardcoded
+       vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
        addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
-       sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
+
        br_zif = (struct zebra_if *)br_if->info;
        if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
                addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
@@ -2337,16 +2377,29 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
        }
        addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
 
-       if (IS_ZEBRA_DEBUG_KERNEL)
+       if (IS_ZEBRA_DEBUG_KERNEL) {
+               char ipbuf[PREFIX_STRLEN];
+               char buf[ETHER_ADDR_STRLEN];
+               char dst_buf[PREFIX_STRLEN + 10];
+
+               inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
+               snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
+               prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
+
                zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
                           nl_msg_type_to_str(cmd),
                           nl_family_to_str(req.ndm.ndm_family), ifp->name,
                           ifp->ifindex, vid_present ? vid_buf : "",
-                          sticky ? "sticky " : "",
-                          prefix_mac2str(mac, buf, sizeof(buf)), dst_buf);
+                          dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
+                          buf, dst_buf);
+       }
 
-       return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
-                           0);
+       ret = netlink_talk_info(netlink_talk_filter, &req.n,
+                               dplane_ctx_get_ns(ctx), 0);
+       if (ret == 0)
+               return ZEBRA_DPLANE_REQUEST_SUCCESS;
+       else
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
 }
 
 /*
@@ -2759,17 +2812,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
                            0);
 }
 
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip, bool sticky)
-{
-       return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_NEWNEIGH,
-                                    sticky);
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0);
+       return netlink_macfdb_update_ctx(ctx);
 }
 
 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
index 8d8bdd0a6df839c09c31d89ff4b561ec722e1681..7e9a42a6177d0158429218d05607d6eb515bc8c0 100644 (file)
@@ -386,16 +386,12 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
        return 0;
 }
 
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip, bool sticky)
-{
-       return 0;
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
-                  struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object. No-op here for now.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
 {
-       return 0;
+       return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
 int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
index 5d99500397eb68bee5bac0923c962b294c33ec4a..4ba6b3e981bb69ddc96758bdf0695e663a7d59ab 100644 (file)
@@ -2114,6 +2114,16 @@ mac_update_internal(enum dplane_op_e op,
        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;
@@ -2560,7 +2570,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];
 
@@ -2581,6 +2590,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
        return res;
 }
 
+/*
+ * 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
  */
@@ -2635,6 +2672,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:
index 601970785ea0afa4de963eadee3cd55c59923b9a..fa8b5d400a7b92a89c2e5fc17cc2b54ef722c953 100644 (file)
@@ -3312,6 +3312,11 @@ static int rib_process_dplane_results(struct thread *thread)
                                dplane_ctx_fini(&ctx);
                                break;
 
+                       case DPLANE_OP_MAC_INSTALL:
+                       case DPLANE_OP_MAC_DELETE:
+                               zebra_vxlan_handle_result(ctx);
+                               break;
+
                        default:
                                /* Don't expect this: just return the struct? */
                                dplane_ctx_fini(&ctx);
index dff50ceef4de9d64008b6db1738fcd6ac9353e61..24cd88b91fe7063a9436557c7872b15e74a829b2 100644 (file)
@@ -3694,13 +3694,14 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
 }
 
 /*
- * Install remote MAC into the kernel.
+ * Install remote MAC into the forwarding plane.
  */
 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
 {
        struct zebra_if *zif;
        struct zebra_l2info_vxlan *vxl;
        bool sticky;
+       enum zebra_dplane_result res;
 
        if (!(mac->flags & ZEBRA_MAC_REMOTE))
                return 0;
@@ -3713,12 +3714,16 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
        sticky = !!CHECK_FLAG(mac->flags,
                         (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
 
-       return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
-                             mac->fwd_info.r_vtep_ip, sticky);
+       res = dplane_mac_add(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
+                            mac->fwd_info.r_vtep_ip, sticky);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
- * Uninstall remote MAC from the kernel.
+ * Uninstall remote MAC from the forwarding plane.
  */
 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
 {
@@ -3726,6 +3731,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
        struct zebra_l2info_vxlan *vxl;
        struct in_addr vtep_ip;
        struct interface *ifp;
+       enum zebra_dplane_result res;
 
        if (!(mac->flags & ZEBRA_MAC_REMOTE))
                return 0;
@@ -3744,7 +3750,11 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
        ifp = zvni->vxlan_if;
        vtep_ip = mac->fwd_info.r_vtep_ip;
 
-       return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+       res = dplane_mac_del(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
@@ -4431,12 +4441,13 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 }
 
 /*
- * Install remote RMAC into the kernel.
+ * Install remote RMAC into the forwarding plane.
  */
 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 {
        struct zebra_if *zif = NULL;
        struct zebra_l2info_vxlan *vxl = NULL;
+       enum zebra_dplane_result res;
 
        if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
            || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4448,18 +4459,23 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 
        vxl = &zif->l2info.vxl;
 
-       return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
-                             &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+       res = dplane_mac_add(zl3vni->vxlan_if, vxl->access_vlan,
+                            &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /*
- * Uninstall remote RMAC from the kernel.
+ * Uninstall remote RMAC from the forwarding plane.
  */
 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 {
        char buf[ETHER_ADDR_STRLEN];
        struct zebra_if *zif = NULL;
        struct zebra_l2info_vxlan *vxl = NULL;
+       enum zebra_dplane_result res;
 
        if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
            || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4479,8 +4495,12 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
 
        vxl = &zif->l2info.vxl;
 
-       return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
-                             &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+       res = dplane_mac_del(zl3vni->vxlan_if, vxl->access_vlan,
+                            &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+       if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+               return 0;
+       else
+               return -1;
 }
 
 /* handle rmac add */
@@ -9872,6 +9892,15 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client)
        return 0;
 }
 
+/*
+ * Handle results for vxlan dataplane operations.
+ */
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
+{
+       /* TODO -- anything other than freeing the context? */
+       dplane_ctx_fini(&ctx);
+}
+
 /* Cleanup BGP EVPN configuration upon client disconnect */
 extern void zebra_evpn_init(void)
 {
index c71953d6bb52bad0f847d2b0d6e12312adde4885..bb80ae1c9add110314d9ae2d45c9fa9fe9bc13d9 100644 (file)
@@ -35,6 +35,7 @@
 #include "lib/json.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zserv.h"
+#include "zebra/zebra_dplane.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -213,6 +214,8 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
 extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                                            struct zebra_vrf *zvrf,
                                            vni_t vni);
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx);
+
 extern void zebra_evpn_init(void);
 
 #ifdef __cplusplus