]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: process EVPN remote VTEP updates from the workqueue
authorMark Stapp <mjs@voltanet.io>
Tue, 20 Apr 2021 13:14:46 +0000 (09:14 -0400)
committerMark Stapp <mjs.ietf@gmail.com>
Mon, 19 Jul 2021 14:36:12 +0000 (10:36 -0400)
Move remote VTEP updates from immediate, inline processing
in their ZAPI message handlers to the main workqueue.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
zebra/rib.h
zebra/zapi_msg.c
zebra/zebra_rib.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h

index 669cc752481474812f778427629b271cf6fe312c..31d9dfd265a6f0e0f7db360320aaa0eb316ca9df 100644 (file)
@@ -470,6 +470,12 @@ int zebra_rib_queue_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
                                       uint8_t flags, uint32_t seq,
                                       struct in_addr vtep_ip,
                                       const esi_t *esi);
+/* Enqueue VXLAN remote vtep update for processing */
+int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
+                                     struct in_addr vtep_ip,
+                                     int flood_control);
+int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
+                                     struct in_addr vtep_ip);
 
 extern void meta_queue_free(struct meta_queue *mq);
 extern int zebra_rib_labeled_unicast(struct route_entry *re);
index 4ef4bc67225b97921ca2e7e287c1dd30d2af93c9..a53e38806227bd3673d26ce031ebbe94fd18c9ec 100644 (file)
@@ -3653,8 +3653,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni,
        [ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es,
        [ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es,
-       [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add,
-       [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del,
+       [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add_zapi,
+       [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del_zapi,
        [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add,
        [ZEBRA_REMOTE_MACIP_DEL] = zebra_vxlan_remote_macip_del,
        [ZEBRA_DUPLICATE_ADDR_DETECTION] = zebra_vxlan_dup_addr_detection,
index 5f12c3012dd6a879ed089dfbdb25e4bdf8052abe..c51dd759a6be619fe61bd665f4857ba177ae952c 100644 (file)
@@ -157,6 +157,7 @@ struct wq_evpn_wrapper {
 #define WQ_EVPN_WRAPPER_TYPE_VRFROUTE     0x01
 #define WQ_EVPN_WRAPPER_TYPE_REM_ES       0x02
 #define WQ_EVPN_WRAPPER_TYPE_REM_MACIP    0x03
+#define WQ_EVPN_WRAPPER_TYPE_REM_VTEP     0x04
 
 /* %pRN is already a printer for route_nodes that just prints the prefix */
 #ifdef _FRR_ATTRIBUTE_PRINTFRR
@@ -2384,8 +2385,16 @@ static void process_subq_evpn(struct listnode *lnode)
                else
                        zebra_evpn_rem_macip_del(w->vni, &w->macaddr, ipa_len,
                                                 &w->ip, w->vtep_ip);
+       } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_VTEP) {
+               if (w->add_p)
+                       zebra_vxlan_remote_vtep_add(w->vrf_id, w->vni,
+                                                   w->vtep_ip, w->flags);
+               else
+                       zebra_vxlan_remote_vtep_del(w->vrf_id, w->vni,
+                                                   w->vtep_ip);
        }
 
+
        XFREE(MTYPE_WQ_WRAPPER, w);
 }
 
@@ -2881,6 +2890,50 @@ int zebra_rib_queue_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
        return mq_add_handler(w, rib_meta_queue_evpn_add);
 }
 
+/*
+ * Enqueue remote VTEP address for processing
+ */
+int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
+                                     struct in_addr vtep_ip, int flood_control)
+{
+       struct wq_evpn_wrapper *w;
+
+       w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+       w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
+       w->add_p = true;
+       w->vrf_id = vrf_id;
+       w->vni = vni;
+       w->vtep_ip = vtep_ip;
+       w->flags = flood_control;
+
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+               zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
+                          &vtep_ip);
+
+       return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
+int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
+                                     struct in_addr vtep_ip)
+{
+       struct wq_evpn_wrapper *w;
+
+       w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
+
+       w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
+       w->add_p = false;
+       w->vrf_id = vrf_id;
+       w->vni = vni;
+       w->vtep_ip = vtep_ip;
+
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+               zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
+                          &vtep_ip);
+
+       return mq_add_handler(w, rib_meta_queue_evpn_add);
+}
+
 /* Clean up the EVPN meta-queue list */
 static void evpn_meta_queue_free(struct list *l)
 {
index 4b968312318250bc1d91bdbbb4cac2d77c1dc213..2b46929acbbd40f6902363195ead62fac516a541 100644 (file)
@@ -4199,27 +4199,23 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
 /*
  * Handle message from client to delete a remote VTEP for an EVPN.
  */
-void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
+void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
        unsigned short l = 0;
        vni_t vni;
        struct in_addr vtep_ip;
-       zebra_evpn_t *zevpn;
-       zebra_vtep_t *zvtep;
-       struct interface *ifp;
-       struct zebra_if *zif;
 
        if (!is_evpn_enabled()) {
                zlog_debug(
-                       "%s: EVPN is not enabled yet we have received a vtep del command",
+                       "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
                        __func__);
                return;
        }
 
        if (!EVPN_ENABLED(zvrf)) {
-               zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
-                         zvrf_id(zvrf));
+               zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
+                          zvrf_id(zvrf));
                return;
        }
 
@@ -4239,76 +4235,182 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
                l += 4;
 
                if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug("Recv VTEP_DEL %pI4 VNI %u from %s",
+                       zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
                                   &vtep_ip, vni,
                                   zebra_route_string(client->proto));
 
-               /* Locate VNI hash entry - expected to exist. */
-               zevpn = zebra_evpn_lookup(vni);
-               if (!zevpn) {
-                       if (IS_ZEBRA_DEBUG_VXLAN)
-                               zlog_debug(
-                                       "Failed to locate VNI hash upon remote VTEP DEL, VNI %u",
-                                       vni);
-                       continue;
-               }
+               /* Enqueue for processing */
+               zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf), vni, vtep_ip);
+       }
 
-               ifp = zevpn->vxlan_if;
-               if (!ifp) {
+stream_failure:
+       return;
+}
+
+/*
+ * Handle message from client to delete a remote VTEP for an EVPN.
+ */
+void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
+                                struct in_addr vtep_ip)
+{
+       zebra_evpn_t *zevpn;
+       zebra_vtep_t *zvtep;
+       struct interface *ifp;
+       struct zebra_if *zif;
+       struct zebra_vrf *zvrf;
+
+       if (!is_evpn_enabled()) {
+               zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
+                          __func__);
+               return;
+       }
+
+       zvrf = zebra_vrf_lookup_by_id(vrf_id);
+       if (!zvrf)
+               return;
+
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
+                          zvrf_id(zvrf));
+               return;
+       }
+
+       /* Locate VNI hash entry - expected to exist. */
+       zevpn = zebra_evpn_lookup(vni);
+       if (!zevpn) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
                        zlog_debug(
-                               "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
-                               zevpn->vni, zevpn);
-                       continue;
-               }
-               zif = ifp->info;
+                               "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
+                               vni);
+               return;
+       }
 
-               /* If down or not mapped to a bridge, we're done. */
-               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
-                       continue;
+       ifp = zevpn->vxlan_if;
+       if (!ifp) {
+               zlog_debug(
+                       "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
+                       zevpn->vni, zevpn);
+               return;
+       }
+       zif = ifp->info;
 
-               /* If the remote VTEP does not exist, there's nothing more to
-                * do.
-                * Otherwise, uninstall any remote MACs pointing to this VTEP
-                * and
-                * then, the VTEP entry itself and remove it.
-                */
-               zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
-               if (!zvtep)
-                       continue;
+       /* If down or not mapped to a bridge, we're done. */
+       if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+               return;
+
+       /* If the remote VTEP does not exist, there's nothing more to
+        * do.
+        * Otherwise, uninstall any remote MACs pointing to this VTEP
+        * and then, the VTEP entry itself and remove it.
+        */
+       zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
+       if (!zvtep)
+               return;
+
+       zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
+       zebra_evpn_vtep_del(zevpn, zvtep);
+}
+
+/*
+ * Handle message from client to add a remote VTEP for an EVPN.
+ */
+void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
+                                struct in_addr vtep_ip, int flood_control)
+{
+       zebra_evpn_t *zevpn;
+       struct interface *ifp;
+       struct zebra_if *zif;
+       zebra_vtep_t *zvtep;
+       struct zebra_vrf *zvrf;
 
-               zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
-               zebra_evpn_vtep_del(zevpn, zvtep);
+       if (!is_evpn_enabled()) {
+               zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
+                          __func__);
+               return;
        }
 
-stream_failure:
-       return;
+       zvrf = zebra_vrf_lookup_by_id(vrf_id);
+       if (!zvrf)
+               return;
+
+       if (!EVPN_ENABLED(zvrf)) {
+               zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
+                          zvrf_id(zvrf));
+               return;
+       }
+
+       /* Locate VNI hash entry - expected to exist. */
+       zevpn = zebra_evpn_lookup(vni);
+       if (!zevpn) {
+               flog_err(
+                       EC_ZEBRA_VTEP_ADD_FAILED,
+                       "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
+                       vni);
+               return;
+       }
+
+       ifp = zevpn->vxlan_if;
+       if (!ifp) {
+               flog_err(
+                       EC_ZEBRA_VTEP_ADD_FAILED,
+                       "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
+                       zevpn->vni, zevpn);
+               return;
+       }
+
+       zif = ifp->info;
+
+       /* If down or not mapped to a bridge, we're done. */
+       if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+               return;
+
+       zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
+       if (zvtep) {
+               /* If the remote VTEP already exists check if
+                * the flood mode has changed
+                */
+               if (zvtep->flood_control != flood_control) {
+                       if (zvtep->flood_control == VXLAN_FLOOD_DISABLED)
+                               /* old mode was head-end-replication but
+                                * is no longer; get rid of the HER fdb
+                                * entry installed before
+                                */
+                               zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
+                       zvtep->flood_control = flood_control;
+                       zebra_evpn_vtep_install(zevpn, zvtep);
+               }
+       } else {
+               zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, flood_control);
+               if (zvtep)
+                       zebra_evpn_vtep_install(zevpn, zvtep);
+               else
+                       flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
+                                "Failed to add remote VTEP, VNI %u zevpn %p",
+                                vni, zevpn);
+       }
 }
 
 /*
  * Handle message from client to add a remote VTEP for an EVPN.
  */
-void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
+void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
        unsigned short l = 0;
        vni_t vni;
        struct in_addr vtep_ip;
-       zebra_evpn_t *zevpn;
-       struct interface *ifp;
-       struct zebra_if *zif;
        int flood_control;
-       zebra_vtep_t *zvtep;
 
        if (!is_evpn_enabled()) {
                zlog_debug(
-                       "%s: EVPN not enabled yet we received a vtep_add zapi call",
+                       "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
                        __func__);
                return;
        }
 
        if (!EVPN_ENABLED(zvrf)) {
-               zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
-                         zvrf_id(zvrf));
+               zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
+                          zvrf_id(zvrf));
                return;
        }
 
@@ -4323,62 +4425,13 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
                l += IPV4_MAX_BYTELEN + 4;
 
                if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug("Recv VTEP_ADD %pI4 VNI %u flood %d from %s",
-                                       &vtep_ip, vni, flood_control,
-                                       zebra_route_string(client->proto));
-
-               /* Locate VNI hash entry - expected to exist. */
-               zevpn = zebra_evpn_lookup(vni);
-               if (!zevpn) {
-                       flog_err(
-                               EC_ZEBRA_VTEP_ADD_FAILED,
-                               "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
-                               vni);
-                       continue;
-               }
-
-               ifp = zevpn->vxlan_if;
-               if (!ifp) {
-                       flog_err(
-                               EC_ZEBRA_VTEP_ADD_FAILED,
-                               "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
-                               zevpn->vni, zevpn);
-                       continue;
-               }
-
-               zif = ifp->info;
-
-               /* If down or not mapped to a bridge, we're done. */
-               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
-                       continue;
+                       zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
+                                  &vtep_ip, vni, flood_control,
+                                  zebra_route_string(client->proto));
 
-               zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
-               if (zvtep) {
-                       /* If the remote VTEP already exists check if
-                        * the flood mode has changed
-                        */
-                       if (zvtep->flood_control != flood_control) {
-                               if (zvtep->flood_control
-                                               == VXLAN_FLOOD_DISABLED)
-                                       /* old mode was head-end-replication but
-                                        * is no longer; get rid of the HER fdb
-                                        * entry installed before
-                                        */
-                                       zebra_evpn_vtep_uninstall(zevpn,
-                                                                 &vtep_ip);
-                               zvtep->flood_control = flood_control;
-                               zebra_evpn_vtep_install(zevpn, zvtep);
-                       }
-               } else {
-                       zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip,
-                                                   flood_control);
-                       if (zvtep)
-                               zebra_evpn_vtep_install(zevpn, zvtep);
-                       else
-                               flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
-                                       "Failed to add remote VTEP, VNI %u zevpn %p",
-                                       vni, zevpn);
-               }
+               /* Enqueue for processing */
+               zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf), vni, vtep_ip,
+                                                 flood_control);
        }
 
 stream_failure:
@@ -4393,7 +4446,7 @@ stream_failure:
  *  3. vrr interface (MACVLAN) associated to a SVI
  * We advertise macip routes for an interface if it is associated to VxLan vlan
  */
-int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
+int zebra_vxlan_add_del_gw_macip(struct interface *ifp, const struct prefix *p,
                                 int add)
 {
        struct ipaddr ip;
index 24de8ff04ee1f814de96979b20fcfdab8333e597..915e987b6bbd8b57d1c899b2e2d33e89575030a5 100644 (file)
@@ -72,8 +72,12 @@ is_vxlan_flooding_head_end(void)
 /* ZAPI message handlers */
 extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS);
-extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS);
-extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS);
+extern void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS);
+void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
+                                struct in_addr vtep_ip, int flood_control);
+extern void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
+                                       struct in_addr vtep_ip);
 extern void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS);
@@ -157,8 +161,8 @@ extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json);
 extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json);
 extern void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
                                      json_object *json_vrfs);
-extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
-                                       int add);
+extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp,
+                                       const struct prefix *p, int add);
 extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
 extern int zebra_vxlan_svi_down(struct interface *ifp,
                                struct interface *link_if);