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 <vivek@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2018-10-04 18:42:57 -04:00
parent eaae6204a9
commit fbac9605a7
8 changed files with 108 additions and 3 deletions

View File

@ -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);

View File

@ -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

View File

@ -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__ */

View 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 {

View 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)

View 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;

View 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();

View 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);