]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3134 from donaldsharp/bum_flooding
authorRuss White <russ@riw.us>
Fri, 12 Oct 2018 20:52:21 +0000 (16:52 -0400)
committerGitHub <noreply@github.com>
Fri, 12 Oct 2018 20:52:21 +0000 (16:52 -0400)
Bum flooding control for BGP and Zebra

14 files changed:
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_evpn_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.h
bgpd/subdir.am
lib/log.c
lib/vxlan.h
lib/zclient.h
zebra/zapi_msg.c
zebra/zebra_vrf.h
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h

index 259e6465c4bc40dcdcbf2175b2e5a48d879330b1..9e71f1855c1a5941a46e52e6649474bc18a8ba64 100644 (file)
@@ -2160,11 +2160,15 @@ static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
 
        /* Update and advertise the type-3 route (only one) followed by the
         * locally learnt type-2 routes (MACIP) - for this VNI.
+        *
+        * RT-3 only if doing head-end replication
         */
-       build_evpn_type3_prefix(&p, vpn->originator_ip);
-       ret = update_evpn_route(bgp, vpn, &p, 0, 0);
-       if (ret)
-               return ret;
+       if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+               build_evpn_type3_prefix(&p, vpn->originator_ip);
+               ret = update_evpn_route(bgp, vpn, &p, 0, 0);
+               if (ret)
+                       return ret;
+       }
 
        return update_all_type2_routes(bgp, vpn);
 }
@@ -3388,27 +3392,32 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
        /* Locate type-3 route for VNI in the per-VNI table and use its
         * attributes to create and advertise the type-3 route for this VNI
         * in the global table.
+        *
+        * RT-3 only if doing head-end replication
         */
-       build_evpn_type3_prefix(&p, vpn->originator_ip);
-       rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
-       if (!rn) /* unexpected */
-               return 0;
-       for (pi = rn->info; pi; pi = pi->next)
-               if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
-                   && pi->sub_type == BGP_ROUTE_STATIC)
-                       break;
-       if (!pi) /* unexpected */
-               return 0;
-       attr = pi->attr;
+       if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+               build_evpn_type3_prefix(&p, vpn->originator_ip);
+               rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+               if (!rn) /* unexpected */
+                       return 0;
+               for (pi = rn->info; pi; pi = pi->next)
+                       if (pi->peer == bgp->peer_self &&
+                           pi->type == ZEBRA_ROUTE_BGP
+                           && pi->sub_type == BGP_ROUTE_STATIC)
+                               break;
+               if (!pi) /* unexpected */
+                       return 0;
+               attr = pi->attr;
 
-       global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
-                                    (struct prefix *)&p, &vpn->prd);
-       update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, &pi, 0,
-                               mac_mobility_seqnum(attr));
+               global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
+                                            (struct prefix *)&p, &vpn->prd);
+               update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr,
+                                       1, &pi, 0, mac_mobility_seqnum(attr));
 
-       /* Schedule for processing and unlock node. */
-       bgp_process(bgp, global_rn, afi, safi);
-       bgp_unlock_node(global_rn);
+               /* Schedule for processing and unlock node. */
+               bgp_process(bgp, global_rn, afi, safi);
+               bgp_unlock_node(global_rn);
+       }
 
        /* Now, walk this VNI's route table and use the route and its attribute
         * to create and schedule route in global table.
@@ -3522,6 +3531,42 @@ static void withdraw_router_id_vni(struct hash_backet *backet, struct bgp *bgp)
        delete_withdraw_vni_routes(bgp, vpn);
 }
 
+/*
+ * Create RT-3 for a VNI and schedule for processing and advertisement.
+ * This is invoked upon flooding mode changing to head-end replication.
+ */
+static void create_advertise_type3(struct hash_backet *backet, void *data)
+{
+       struct bgpevpn *vpn = backet->data;
+       struct bgp *bgp = data;
+       struct prefix_evpn p;
+
+       if (!vpn || !is_vni_live(vpn))
+               return;
+
+       build_evpn_type3_prefix(&p, vpn->originator_ip);
+       if (update_evpn_route(bgp, vpn, &p, 0, 0))
+               flog_err(EC_BGP_EVPN_ROUTE_CREATE,
+                        "Type3 route creation failure for VNI %u", vpn->vni);
+}
+
+/*
+ * Delete RT-3 for a VNI and schedule for processing and withdrawal.
+ * This is invoked upon flooding mode changing to drop BUM packets.
+ */
+static void delete_withdraw_type3(struct hash_backet *backet, void *data)
+{
+       struct bgpevpn *vpn = backet->data;
+       struct bgp *bgp = data;
+       struct prefix_evpn p;
+
+       if (!vpn || !is_vni_live(vpn))
+               return;
+
+       build_evpn_type3_prefix(&p, vpn->originator_ip);
+       delete_evpn_route(bgp, vpn, &p);
+}
+
 /*
  * Process received EVPN type-2 route (advertise or withdraw).
  */
@@ -5481,13 +5526,19 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
        /* filter routes as nexthop database has changed */
        bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
 
-       /* Create EVPN type-3 route and schedule for processing. */
-       build_evpn_type3_prefix(&p, vpn->originator_ip);
-       if (update_evpn_route(bgp, vpn, &p, 0, 0)) {
-               flog_err(EC_BGP_EVPN_ROUTE_CREATE,
-                        "%u: Type3 route creation failure for VNI %u",
-                        bgp->vrf_id, vni);
-               return -1;
+       /*
+        * Create EVPN type-3 route and schedule for processing.
+        *
+        * RT-3 only if doing head-end replication
+        */
+       if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
+               build_evpn_type3_prefix(&p, vpn->originator_ip);
+               if (update_evpn_route(bgp, vpn, &p, 0, 0)) {
+                       flog_err(EC_BGP_EVPN_ROUTE_CREATE,
+                                "%u: Type3 route creation failure for VNI %u",
+                                bgp->vrf_id, vni);
+                       return -1;
+               }
        }
 
        /* If we have learnt and retained remote routes (VTEPs, MACs) for this
@@ -5585,6 +5636,26 @@ int bgp_evpn_local_es_add(struct bgp *bgp,
        return 0;
 }
 
+/*
+ * Handle change in setting for BUM handling. The supported values
+ * are head-end replication and dropping all BUM packets. Any change
+ * should be registered with zebra. Also, if doing head-end replication,
+ * need to advertise local VNIs as EVPN RT-3 wheras, if BUM packets are
+ * to be dropped, the RT-3s must be withdrawn.
+ */
+void bgp_evpn_flood_control_change(struct bgp *bgp)
+{
+       zlog_info("L2VPN EVPN BUM handling is %s",
+                 bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL ?
+                 "Flooding" : "Flooding Disabled");
+
+       bgp_zebra_vxlan_flood_control(bgp, bgp->vxlan_flood_ctrl);
+       if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL)
+               hash_iterate(bgp->vnihash, create_advertise_type3, bgp);
+       else if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
+               hash_iterate(bgp->vnihash, delete_withdraw_type3, bgp);
+}
+
 /*
  * Cleanup EVPN information on disable - Need to delete and withdraw
  * EVPN routes from peers.
@@ -5652,6 +5723,9 @@ void bgp_evpn_init(struct bgp *bgp)
        bgp->vrf_export_rtl->del = evpn_xxport_delete_ecomm;
        bgp->l2vnis = list_new();
        bgp->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
+
+       /* Default BUM handling is to do head-end replication. */
+       bgp->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
 }
 
 void bgp_evpn_vrf_delete(struct bgp *bgp_vrf)
index 968d5a0b3f0e86516e1777b4a800449909050e2c..8728fdcab7633278c0c3c1ff4076f67b72eec03a 100644 (file)
@@ -145,6 +145,7 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
                                 struct ipaddr *originator_ip);
 extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi,
                                 struct ipaddr *originator_ip);
+extern void bgp_evpn_flood_control_change(struct bgp *bgp);
 extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
 extern void bgp_evpn_cleanup(struct bgp *bgp);
 extern void bgp_evpn_init(struct bgp *bgp);
index 4e38d73146ed475a757792fb30156182b958e505..90c9db3dfe0420db7967063e3cd039fc61e2c93f 100644 (file)
@@ -2807,6 +2807,40 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
        }
 }
 
+#ifndef VTYSH_EXTRACT_PL
+#include "bgpd/bgp_evpn_vty_clippy.c"
+#endif
+
+DEFPY(bgp_evpn_flood_control,
+      bgp_evpn_flood_control_cmd,
+      "[no$no] flooding <disable$disable|head-end-replication$her>",
+      NO_STR
+      "Specify handling for BUM packets\n"
+      "Do not flood any BUM packets\n"
+      "Flood BUM packets using head-end replication\n")
+{
+       struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+       enum vxlan_flood_control flood_ctrl;
+
+       if (!bgp)
+               return CMD_WARNING;
+
+       if (disable && !no)
+               flood_ctrl = VXLAN_FLOOD_DISABLED;
+       else if (her || no)
+               flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
+       else
+               return CMD_WARNING;
+
+       if (bgp->vxlan_flood_ctrl == flood_ctrl)
+               return CMD_SUCCESS;
+
+       bgp->vxlan_flood_ctrl = flood_ctrl;
+       bgp_evpn_flood_control_change(bgp);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (bgp_evpn_advertise_default_gw_vni,
        bgp_evpn_advertise_default_gw_vni_cmd,
        "advertise-default-gw",
@@ -3210,6 +3244,12 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                        json_object_string_add(json, "advertiseAllVnis",
                                               is_evpn_enabled() ? "Enabled"
                                                                 : "Disabled");
+                       json_object_string_add(
+                               json, "flooding",
+                               bgp_def->vxlan_flood_ctrl
+                                               == VXLAN_FLOOD_HEAD_END_REPL
+                                       ? "Head-end replication"
+                                       : "Disabled");
                        json_object_int_add(json, "numVnis", num_vnis);
                        json_object_int_add(json, "numL2Vnis", num_l2vnis);
                        json_object_int_add(json, "numL3Vnis", num_l3vnis);
@@ -3219,6 +3259,11 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
                                                            : "Disabled");
                        vty_out(vty, "Advertise All VNI flag: %s\n",
                                is_evpn_enabled() ? "Enabled" : "Disabled");
+                       vty_out(vty, "BUM flooding: %s\n",
+                               bgp_def->vxlan_flood_ctrl
+                                               == VXLAN_FLOOD_HEAD_END_REPL
+                                       ? "Head-end replication"
+                                       : "Disabled");
                        vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
                        vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
                }
@@ -4874,6 +4919,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
        if (bgp->advertise_gw_macip)
                vty_out(vty, "  advertise-default-gw\n");
 
+       if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
+               vty_out(vty, "  flooding disable\n");
+
        if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
                       BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
                if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
@@ -4965,6 +5013,7 @@ void bgp_ethernetvpn_init(void)
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
        install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
        install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
+       install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
 
        /* test commands */
        install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
index e2bdf383506409ba73ba32c96f54b54139ec584c..b2148e52c62cca802574d84cc1f57a85bf7e2a3a 100644 (file)
@@ -1931,6 +1931,29 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
        return zclient_send_message(zclient);
 }
 
+int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
+                                 enum vxlan_flood_control flood_ctrl)
+{
+       struct stream *s;
+
+       /* Check socket. */
+       if (!zclient || zclient->sock < 0)
+               return 0;
+
+       /* Don't try to register if Zebra doesn't know of this instance. */
+       if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+               return 0;
+
+       s = zclient->obuf;
+       stream_reset(s);
+
+       zclient_create_header(s, ZEBRA_VXLAN_FLOOD_CONTROL, bgp->vrf_id);
+       stream_putc(s, flood_ctrl);
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return zclient_send_message(zclient);
+}
+
 int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
 {
        struct stream *s;
@@ -1948,6 +1971,10 @@ int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
 
        zclient_create_header(s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id);
        stream_putc(s, advertise);
+       /* Also inform current BUM handling setting. This is really
+        * relevant only when 'advertise' is set.
+        */
+       stream_putc(s, bgp->vxlan_flood_ctrl);
        stream_putw_at(s, 0, stream_get_endp(s));
 
        return zclient_send_message(zclient);
index 1118eaab24efd4f1899254054b6f3abead5d9e85..458730dd4345ab15b0640540027cf7f3d69ba4f1 100644 (file)
@@ -72,6 +72,8 @@ extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
                                      vni_t vni);
 extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
 extern int bgp_zebra_advertise_all_vni(struct bgp *, int);
+extern int bgp_zebra_vxlan_flood_control(struct bgp *bgp,
+                                        enum vxlan_flood_control flood_ctrl);
 
 extern int bgp_zebra_num_connects(void);
 
index 861435c036cb08eed7a5cbfe4c8e58fdb7fb0205..cef5394b09f2cc8741e1e7030480f84b1c4f5eab 100644 (file)
@@ -485,6 +485,11 @@ struct bgp {
        /* EVPN - use RFC 8365 to auto-derive RT */
        int advertise_autort_rfc8365;
 
+       /*
+        * Flooding mechanism for BUM packets for VxLAN-EVPN.
+        */
+       enum vxlan_flood_control vxlan_flood_ctrl;
+
        /* Hash table of Import RTs to EVIs */
        struct hash *import_rt_hash;
 
index 42913885675f3fedd63a1b9d897f053a5d12684d..83f55939ce4cc330c0b0507f55c1e116c0fa8ca5 100644 (file)
@@ -208,6 +208,8 @@ bgpd_bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
 bgpd_bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
 
+bgpd/bgp_evpn_vty_clippy.c: $(CLIPPY_DEPS)
+bgpd/bgp_evpn_vty.$(OBJEXT): bgpd/bgp_evpn_vty_clippy.c
 bgpd/bgp_vty_clippy.c: $(CLIPPY_DEPS)
 bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c
 bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
index 2d800baae142fb2371f76d211ca61b22914a8a8e..10cb2cd8a4d44c463a534978cf1eaf99800f6c60 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -980,6 +980,7 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_IPSET_DESTROY),
        DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD),
        DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE),
+       DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL),
 };
 #undef DESC_ENTRY
 
index ba3dbb05c885c99f3281154e2402af58cf592eb0..bcf8354539d982220cab64513d10bd62e08a7314 100644 (file)
 typedef uint32_t vni_t;
 #define VNI_MAX 16777215 /* (2^24 - 1) */
 
+/* Flooding mechanisms for BUM packets. */
+/* Currently supported mechanisms are head-end (ingress) replication
+ * (which is the default) and no flooding. Future options could be
+ * using PIM-SM, PIM-Bidir etc.
+ */
+enum vxlan_flood_control {
+       VXLAN_FLOOD_HEAD_END_REPL = 0,
+       VXLAN_FLOOD_DISABLED,
+};
 #endif /* __VXLAN_H__ */
index 54f3635901417d4b3842c582d161a1f95e5576e0..97ebb0811c26647acb64001d653ea6dd7b1d78d1 100644 (file)
@@ -155,6 +155,7 @@ typedef enum {
        ZEBRA_IPTABLE_ADD,
        ZEBRA_IPTABLE_DELETE,
        ZEBRA_IPTABLE_NOTIFY_OWNER,
+       ZEBRA_VXLAN_FLOOD_CONTROL,
 } zebra_message_types_t;
 
 struct redist_proto {
index c193a0c47a644423ea887a39ba59fd6bfc0a5bb6..149d2cb6a56c10943f44b080450fd26c628ebc80 100644 (file)
@@ -2439,6 +2439,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
        [ZEBRA_IPTABLE_ADD] = zread_iptable,
        [ZEBRA_IPTABLE_DELETE] = zread_iptable,
+       [ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
 };
 
 #if defined(HANDLE_ZAPI_FUZZING)
index 78f6331d03f749b9cb3d15e6cd66ba62eb05206e..a39d74b08b49955093ea4ef162be494a7fd12aaa 100644 (file)
@@ -22,6 +22,8 @@
 #if !defined(__ZEBRA_VRF_H__)
 #define __ZEBRA_VRF_H__
 
+#include "vxlan.h"
+
 #include <zebra/zebra_ns.h>
 #include <zebra/zebra_pw.h>
 #include <lib/vxlan.h>
@@ -123,6 +125,11 @@ struct zebra_vrf {
        /* l3-vni info */
        vni_t l3vni;
 
+       /*
+        * Flooding mechanism for BUM packets for VxLAN-EVPN.
+        */
+       enum vxlan_flood_control vxlan_flood_ctrl;
+
        /* Route Installs */
        uint64_t installs;
        uint64_t removals;
index f8417503ef126a563a2aa8b50374c86bbbd3e13e..5078eff59016fd6b7772e7bb894d220ef56f6d8e 100644 (file)
@@ -3097,7 +3097,9 @@ static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
  */
 static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
 {
-       return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
+       if (is_vxlan_flooding_head_end())
+               return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
+       return 0;
 }
 
 /*
@@ -3114,6 +3116,28 @@ static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
        return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
 }
 
+/*
+ * Install or uninstall flood entries in the kernel corresponding to
+ * remote VTEPs. This is invoked upon change to BUM handling.
+ */
+static void zvni_handle_flooding_remote_vteps(struct hash_backet *backet,
+                                             void *zvrf)
+{
+       zebra_vni_t *zvni;
+       zebra_vtep_t *zvtep;
+
+       zvni = (zebra_vni_t *)backet->data;
+       if (!zvni)
+               return;
+
+       for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
+               if (is_vxlan_flooding_head_end())
+                       zvni_vtep_install(zvni, &zvtep->vtep_ip);
+               else
+                       zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
+       }
+}
+
 /*
  * Cleanup VNI/VTEP and update kernel
  */
@@ -6897,6 +6921,46 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
        return 0;
 }
 
+/*
+ * Handle message from client to specify the flooding mechanism for
+ * BUM packets. The default is to do head-end (ingress) replication
+ * and the other supported option is to disable it. This applies to
+ * all BUM traffic and disabling it applies to both the transmit and
+ * receive direction.
+ */
+void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       enum vxlan_flood_control flood_ctrl;
+
+       if (zvrf_id(zvrf) != VRF_DEFAULT) {
+               zlog_err("EVPN flood control for non-default VRF %u",
+                        zvrf_id(zvrf));
+               return;
+       }
+
+       s = msg;
+       STREAM_GETC(s, flood_ctrl);
+
+       if (IS_ZEBRA_DEBUG_VXLAN)
+               zlog_debug("EVPN flood control %u, currently %u",
+                          flood_ctrl, zvrf->vxlan_flood_ctrl);
+
+       if (zvrf->vxlan_flood_ctrl == flood_ctrl)
+               return;
+
+       zvrf->vxlan_flood_ctrl = flood_ctrl;
+
+       /* Install or uninstall flood entries corresponding to
+        * remote VTEPs.
+        */
+       hash_iterate(zvrf->vni_table, zvni_handle_flooding_remote_vteps,
+                    zvrf);
+
+stream_failure:
+       return;
+}
+
 /*
  * Handle message from client to enable/disable advertisement of g/w macip
  * routes
@@ -7073,12 +7137,15 @@ stream_failure:
  * When enabled, the VNI hash table will be built and MAC FDB table read;
  * when disabled, the entries should be deleted and remote VTEPs and MACs
  * uninstalled from the kernel.
+ * This also informs the setting for BUM handling at the time this change
+ * occurs; it is relevant only when specifying "learn".
  */
 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
 {
        struct stream *s = NULL;
        int advertise = 0;
        struct zebra_ns *zns = NULL;
+       enum vxlan_flood_control flood_ctrl;
 
        if (zvrf_id(zvrf) != VRF_DEFAULT) {
                zlog_debug("EVPN VNI Adv for non-default VRF %u",
@@ -7088,17 +7155,22 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
 
        s = msg;
        STREAM_GETC(s, advertise);
+       STREAM_GETC(s, flood_ctrl);
 
        if (IS_ZEBRA_DEBUG_VXLAN)
-               zlog_debug("EVPN VNI Adv %s, currently %s",
+               zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
                           advertise ? "enabled" : "disabled",
-                          is_evpn_enabled() ? "enabled" : "disabled");
+                          is_evpn_enabled() ? "enabled" : "disabled",
+                          flood_ctrl);
 
        if (zvrf->advertise_all_vni == advertise)
                return;
 
        zvrf->advertise_all_vni = advertise;
        if (is_evpn_enabled()) {
+               /* Note BUM handling */
+               zvrf->vxlan_flood_ctrl = flood_ctrl;
+
                /* Build VNI hash table and inform BGP. */
                zvni_build_hash_table();
 
index a6c668785fb71baabc4dffe392c4f1828e343288..f03cd3d541ccf931a842018f0c7bcb5b0d0db40c 100644 (file)
@@ -44,6 +44,15 @@ static inline int is_evpn_enabled()
        return zvrf ? zvrf->advertise_all_vni : 0;
 }
 
+static inline int
+is_vxlan_flooding_head_end()
+{
+       struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+
+       if (!zvrf)
+               return 0;
+       return (zvrf->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL);
+}
 
 /* VxLAN interface change flags of interest. */
 #define ZEBRA_VXLIF_LOCAL_IP_CHANGE     0x1
@@ -57,6 +66,7 @@ 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_flood_control(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
 extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);