mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
Merge pull request #3134 from donaldsharp/bum_flooding
Bum flooding control for BGP and Zebra
This commit is contained in:
commit
5d3a8c513f
132
bgpd/bgp_evpn.c
132
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
|
/* Update and advertise the type-3 route (only one) followed by the
|
||||||
* locally learnt type-2 routes (MACIP) - for this VNI.
|
* 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);
|
if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
|
||||||
ret = update_evpn_route(bgp, vpn, &p, 0, 0);
|
build_evpn_type3_prefix(&p, vpn->originator_ip);
|
||||||
if (ret)
|
ret = update_evpn_route(bgp, vpn, &p, 0, 0);
|
||||||
return ret;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return update_all_type2_routes(bgp, vpn);
|
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
|
/* 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
|
* attributes to create and advertise the type-3 route for this VNI
|
||||||
* in the global table.
|
* in the global table.
|
||||||
|
*
|
||||||
|
* RT-3 only if doing head-end replication
|
||||||
*/
|
*/
|
||||||
build_evpn_type3_prefix(&p, vpn->originator_ip);
|
if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
|
||||||
rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
|
build_evpn_type3_prefix(&p, vpn->originator_ip);
|
||||||
if (!rn) /* unexpected */
|
rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
|
||||||
return 0;
|
if (!rn) /* unexpected */
|
||||||
for (pi = rn->info; pi; pi = pi->next)
|
return 0;
|
||||||
if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
|
for (pi = rn->info; pi; pi = pi->next)
|
||||||
&& pi->sub_type == BGP_ROUTE_STATIC)
|
if (pi->peer == bgp->peer_self &&
|
||||||
break;
|
pi->type == ZEBRA_ROUTE_BGP
|
||||||
if (!pi) /* unexpected */
|
&& pi->sub_type == BGP_ROUTE_STATIC)
|
||||||
return 0;
|
break;
|
||||||
attr = pi->attr;
|
if (!pi) /* unexpected */
|
||||||
|
return 0;
|
||||||
|
attr = pi->attr;
|
||||||
|
|
||||||
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
|
||||||
(struct prefix *)&p, &vpn->prd);
|
(struct prefix *)&p, &vpn->prd);
|
||||||
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, &pi, 0,
|
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr,
|
||||||
mac_mobility_seqnum(attr));
|
1, &pi, 0, mac_mobility_seqnum(attr));
|
||||||
|
|
||||||
/* Schedule for processing and unlock node. */
|
/* Schedule for processing and unlock node. */
|
||||||
bgp_process(bgp, global_rn, afi, safi);
|
bgp_process(bgp, global_rn, afi, safi);
|
||||||
bgp_unlock_node(global_rn);
|
bgp_unlock_node(global_rn);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now, walk this VNI's route table and use the route and its attribute
|
/* Now, walk this VNI's route table and use the route and its attribute
|
||||||
* to create and schedule route in global table.
|
* 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);
|
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).
|
* 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 */
|
/* filter routes as nexthop database has changed */
|
||||||
bgp_filter_evpn_routes_upon_martian_nh_change(bgp);
|
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);
|
* Create EVPN type-3 route and schedule for processing.
|
||||||
if (update_evpn_route(bgp, vpn, &p, 0, 0)) {
|
*
|
||||||
flog_err(EC_BGP_EVPN_ROUTE_CREATE,
|
* RT-3 only if doing head-end replication
|
||||||
"%u: Type3 route creation failure for VNI %u",
|
*/
|
||||||
bgp->vrf_id, vni);
|
if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) {
|
||||||
return -1;
|
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
|
/* 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;
|
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
|
* Cleanup EVPN information on disable - Need to delete and withdraw
|
||||||
* EVPN routes from peers.
|
* 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->vrf_export_rtl->del = evpn_xxport_delete_ecomm;
|
||||||
bgp->l2vnis = list_new();
|
bgp->l2vnis = list_new();
|
||||||
bgp->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp;
|
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)
|
void bgp_evpn_vrf_delete(struct bgp *bgp_vrf)
|
||||||
|
@ -145,6 +145,7 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
|
|||||||
struct ipaddr *originator_ip);
|
struct ipaddr *originator_ip);
|
||||||
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi,
|
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi,
|
||||||
struct ipaddr *originator_ip);
|
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_on_disable(struct bgp *bgp);
|
||||||
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
||||||
extern void bgp_evpn_init(struct bgp *bgp);
|
extern void bgp_evpn_init(struct bgp *bgp);
|
||||||
|
@ -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,
|
DEFUN (bgp_evpn_advertise_default_gw_vni,
|
||||||
bgp_evpn_advertise_default_gw_vni_cmd,
|
bgp_evpn_advertise_default_gw_vni_cmd,
|
||||||
"advertise-default-gw",
|
"advertise-default-gw",
|
||||||
@ -3210,6 +3244,12 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
|||||||
json_object_string_add(json, "advertiseAllVnis",
|
json_object_string_add(json, "advertiseAllVnis",
|
||||||
is_evpn_enabled() ? "Enabled"
|
is_evpn_enabled() ? "Enabled"
|
||||||
: "Disabled");
|
: "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, "numVnis", num_vnis);
|
||||||
json_object_int_add(json, "numL2Vnis", num_l2vnis);
|
json_object_int_add(json, "numL2Vnis", num_l2vnis);
|
||||||
json_object_int_add(json, "numL3Vnis", num_l3vnis);
|
json_object_int_add(json, "numL3Vnis", num_l3vnis);
|
||||||
@ -3219,6 +3259,11 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
|
|||||||
: "Disabled");
|
: "Disabled");
|
||||||
vty_out(vty, "Advertise All VNI flag: %s\n",
|
vty_out(vty, "Advertise All VNI flag: %s\n",
|
||||||
is_evpn_enabled() ? "Enabled" : "Disabled");
|
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 L2 VNIs: %u\n", num_l2vnis);
|
||||||
vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
|
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)
|
if (bgp->advertise_gw_macip)
|
||||||
vty_out(vty, " advertise-default-gw\n");
|
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],
|
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||||
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
|
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
|
||||||
if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
|
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, &no_bgp_evpn_advertise_type5_cmd);
|
||||||
install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_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, &no_bgp_evpn_default_originate_cmd);
|
||||||
|
install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
|
||||||
|
|
||||||
/* test commands */
|
/* test commands */
|
||||||
install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
|
install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
|
||||||
|
@ -1931,6 +1931,29 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni)
|
|||||||
return zclient_send_message(zclient);
|
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)
|
int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
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);
|
zclient_create_header(s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id);
|
||||||
stream_putc(s, advertise);
|
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));
|
stream_putw_at(s, 0, stream_get_endp(s));
|
||||||
|
|
||||||
return zclient_send_message(zclient);
|
return zclient_send_message(zclient);
|
||||||
|
@ -72,6 +72,8 @@ extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise,
|
|||||||
vni_t vni);
|
vni_t vni);
|
||||||
extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t);
|
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_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);
|
extern int bgp_zebra_num_connects(void);
|
||||||
|
|
||||||
|
@ -485,6 +485,11 @@ struct bgp {
|
|||||||
/* EVPN - use RFC 8365 to auto-derive RT */
|
/* EVPN - use RFC 8365 to auto-derive RT */
|
||||||
int advertise_autort_rfc8365;
|
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 */
|
/* Hash table of Import RTs to EVIs */
|
||||||
struct hash *import_rt_hash;
|
struct hash *import_rt_hash;
|
||||||
|
|
||||||
|
@ -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_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||||
bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
|
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_clippy.c: $(CLIPPY_DEPS)
|
||||||
bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c
|
bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c
|
||||||
bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
|
bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS)
|
||||||
|
@ -980,6 +980,7 @@ static const struct zebra_desc_table command_types[] = {
|
|||||||
DESC_ENTRY(ZEBRA_IPSET_DESTROY),
|
DESC_ENTRY(ZEBRA_IPSET_DESTROY),
|
||||||
DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD),
|
DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD),
|
||||||
DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE),
|
DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE),
|
||||||
|
DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL),
|
||||||
};
|
};
|
||||||
#undef DESC_ENTRY
|
#undef DESC_ENTRY
|
||||||
|
|
||||||
|
@ -26,4 +26,13 @@
|
|||||||
typedef uint32_t vni_t;
|
typedef uint32_t vni_t;
|
||||||
#define VNI_MAX 16777215 /* (2^24 - 1) */
|
#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__ */
|
#endif /* __VXLAN_H__ */
|
||||||
|
@ -155,6 +155,7 @@ typedef enum {
|
|||||||
ZEBRA_IPTABLE_ADD,
|
ZEBRA_IPTABLE_ADD,
|
||||||
ZEBRA_IPTABLE_DELETE,
|
ZEBRA_IPTABLE_DELETE,
|
||||||
ZEBRA_IPTABLE_NOTIFY_OWNER,
|
ZEBRA_IPTABLE_NOTIFY_OWNER,
|
||||||
|
ZEBRA_VXLAN_FLOOD_CONTROL,
|
||||||
} zebra_message_types_t;
|
} zebra_message_types_t;
|
||||||
|
|
||||||
struct redist_proto {
|
struct redist_proto {
|
||||||
|
@ -2439,6 +2439,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
|||||||
[ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
|
[ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
|
||||||
[ZEBRA_IPTABLE_ADD] = zread_iptable,
|
[ZEBRA_IPTABLE_ADD] = zread_iptable,
|
||||||
[ZEBRA_IPTABLE_DELETE] = zread_iptable,
|
[ZEBRA_IPTABLE_DELETE] = zread_iptable,
|
||||||
|
[ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HANDLE_ZAPI_FUZZING)
|
#if defined(HANDLE_ZAPI_FUZZING)
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#if !defined(__ZEBRA_VRF_H__)
|
#if !defined(__ZEBRA_VRF_H__)
|
||||||
#define __ZEBRA_VRF_H__
|
#define __ZEBRA_VRF_H__
|
||||||
|
|
||||||
|
#include "vxlan.h"
|
||||||
|
|
||||||
#include <zebra/zebra_ns.h>
|
#include <zebra/zebra_ns.h>
|
||||||
#include <zebra/zebra_pw.h>
|
#include <zebra/zebra_pw.h>
|
||||||
#include <lib/vxlan.h>
|
#include <lib/vxlan.h>
|
||||||
@ -123,6 +125,11 @@ struct zebra_vrf {
|
|||||||
/* l3-vni info */
|
/* l3-vni info */
|
||||||
vni_t l3vni;
|
vni_t l3vni;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flooding mechanism for BUM packets for VxLAN-EVPN.
|
||||||
|
*/
|
||||||
|
enum vxlan_flood_control vxlan_flood_ctrl;
|
||||||
|
|
||||||
/* Route Installs */
|
/* Route Installs */
|
||||||
uint64_t installs;
|
uint64_t installs;
|
||||||
uint64_t removals;
|
uint64_t removals;
|
||||||
|
@ -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)
|
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);
|
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
|
* Cleanup VNI/VTEP and update kernel
|
||||||
*/
|
*/
|
||||||
@ -6897,6 +6921,46 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
|
|||||||
return 0;
|
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
|
* Handle message from client to enable/disable advertisement of g/w macip
|
||||||
* routes
|
* routes
|
||||||
@ -7073,12 +7137,15 @@ stream_failure:
|
|||||||
* When enabled, the VNI hash table will be built and MAC FDB table read;
|
* 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
|
* when disabled, the entries should be deleted and remote VTEPs and MACs
|
||||||
* uninstalled from the kernel.
|
* 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)
|
void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
struct stream *s = NULL;
|
struct stream *s = NULL;
|
||||||
int advertise = 0;
|
int advertise = 0;
|
||||||
struct zebra_ns *zns = NULL;
|
struct zebra_ns *zns = NULL;
|
||||||
|
enum vxlan_flood_control flood_ctrl;
|
||||||
|
|
||||||
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
||||||
zlog_debug("EVPN VNI Adv for non-default VRF %u",
|
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;
|
s = msg;
|
||||||
STREAM_GETC(s, advertise);
|
STREAM_GETC(s, advertise);
|
||||||
|
STREAM_GETC(s, flood_ctrl);
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
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",
|
advertise ? "enabled" : "disabled",
|
||||||
is_evpn_enabled() ? "enabled" : "disabled");
|
is_evpn_enabled() ? "enabled" : "disabled",
|
||||||
|
flood_ctrl);
|
||||||
|
|
||||||
if (zvrf->advertise_all_vni == advertise)
|
if (zvrf->advertise_all_vni == advertise)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zvrf->advertise_all_vni = advertise;
|
zvrf->advertise_all_vni = advertise;
|
||||||
if (is_evpn_enabled()) {
|
if (is_evpn_enabled()) {
|
||||||
|
/* Note BUM handling */
|
||||||
|
zvrf->vxlan_flood_ctrl = flood_ctrl;
|
||||||
|
|
||||||
/* Build VNI hash table and inform BGP. */
|
/* Build VNI hash table and inform BGP. */
|
||||||
zvni_build_hash_table();
|
zvni_build_hash_table();
|
||||||
|
|
||||||
|
@ -44,6 +44,15 @@ static inline int is_evpn_enabled()
|
|||||||
return zvrf ? zvrf->advertise_all_vni : 0;
|
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. */
|
/* VxLAN interface change flags of interest. */
|
||||||
#define ZEBRA_VXLIF_LOCAL_IP_CHANGE 0x1
|
#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_macip_del(ZAPI_HANDLER_ARGS);
|
||||||
extern void zebra_vxlan_remote_vtep_add(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_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_subnet(ZAPI_HANDLER_ARGS);
|
||||||
extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
|
extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
|
||||||
extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
|
extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
|
||||||
|
Loading…
Reference in New Issue
Block a user