From fbac9605a798444d5845d8dfa179ccb92f33fc0f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Oct 2018 18:42:57 -0400 Subject: [PATCH 1/2] lib, zebra: Allow the specification of BUM flooding Allow the modification of whether or not we will allow BUM flooding on the vxlan bridge. To do this allow the upper level protocol to specify via the ZEBRA_VXLAN_FLOOD_CONTROL zapi message. If flooding is disabled then BUM traffic will not be forwarded to other VTEP's. Signed-off-by: Vivek Venkatraman Signed-off-by: Donald Sharp --- bgpd/bgp_zebra.c | 4 +++ lib/log.c | 1 + lib/vxlan.h | 9 ++++++ lib/zclient.h | 1 + zebra/zapi_msg.c | 1 + zebra/zebra_vrf.h | 7 ++++ zebra/zebra_vxlan.c | 78 +++++++++++++++++++++++++++++++++++++++++++-- zebra/zebra_vxlan.h | 10 ++++++ 8 files changed, 108 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index e2bdf38350..214d7e4d9c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1948,6 +1948,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, VXLAN_FLOOD_HEAD_END_REPL); stream_putw_at(s, 0, stream_get_endp(s)); return zclient_send_message(zclient); diff --git a/lib/log.c b/lib/log.c index 2d800baae1..10cb2cd8a4 100644 --- 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 diff --git a/lib/vxlan.h b/lib/vxlan.h index ba3dbb05c8..bcf8354539 100644 --- a/lib/vxlan.h +++ b/lib/vxlan.h @@ -26,4 +26,13 @@ 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__ */ diff --git a/lib/zclient.h b/lib/zclient.h index 54f3635901..97ebb0811c 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -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 { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index c193a0c47a..149d2cb6a5 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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) diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 78f6331d03..a39d74b08b 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -22,6 +22,8 @@ #if !defined(__ZEBRA_VRF_H__) #define __ZEBRA_VRF_H__ +#include "vxlan.h" + #include #include #include @@ -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; diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index f8417503ef..5078eff590 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -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(); diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index a6c668785f..f03cd3d541 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -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); From fd06964433e5a0152f69533d159837cab2749afe Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Oct 2018 19:20:12 -0400 Subject: [PATCH 2/2] bgpd: Add '[no] flood ' Add the '[no] flood ' command to the l2vpn evpn afi/safi sub commands for bgp. This command when entered as 'flood disable' will turn off type 3 route generation for the transmittal of the type 3 route necessary for BUM replication on the remote VTEP. Additionally it will turn off the BUM handling via the new zebra command, ZEBRA_VXLAN_FLOOD_CONTROL. Signed-off-by: Vivek Venkatraman Signed-off-by: Donald Sharp --- bgpd/bgp_evpn.c | 132 ++++++++++++++++++++++++++++++++++---------- bgpd/bgp_evpn.h | 1 + bgpd/bgp_evpn_vty.c | 49 ++++++++++++++++ bgpd/bgp_zebra.c | 25 ++++++++- bgpd/bgp_zebra.h | 2 + bgpd/bgpd.h | 5 ++ bgpd/subdir.am | 2 + 7 files changed, 186 insertions(+), 30 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 259e6465c4..9e71f1855c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -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) diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 968d5a0b3f..8728fdcab7 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -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); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 4e38d73146..90c9db3dfe 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -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 ", + 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); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 214d7e4d9c..b2148e52c6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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; @@ -1951,7 +1974,7 @@ int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise) /* Also inform current BUM handling setting. This is really * relevant only when 'advertise' is set. */ - stream_putc(s, VXLAN_FLOOD_HEAD_END_REPL); + stream_putc(s, bgp->vxlan_flood_ctrl); stream_putw_at(s, 0, stream_get_endp(s)); return zclient_send_message(zclient); diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 1118eaab24..458730dd43 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -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); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 861435c036..cef5394b09 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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; diff --git a/bgpd/subdir.am b/bgpd/subdir.am index 4291388567..83f55939ce 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -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)