summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKishore Aramalla <karamalla@vmware.com>2019-06-19 23:45:21 +0200
committerKishore Aramalla <karamalla@vmware.com>2019-06-19 23:45:21 +0200
commit27627f9a11462f770b8e42a8acbe0e3f3abb54ef (patch)
treeaa10412e2f787bef4fc1ae4296d8ea294d496509
parentMerge pull request #4456 from opensourcerouting/workflow-update (diff)
downloadfrr-27627f9a11462f770b8e42a8acbe0e3f3abb54ef.tar.xz
frr-27627f9a11462f770b8e42a8acbe0e3f3abb54ef.zip
zebra: Clean up BGP EVPN configuration when the client, BGPD, goes down
When BGP daemon is down, Clean up its configuration state from zebra. When the BGP daemon is up again, it will push its configuration to zebra Delete the MAC and neighbor information received on the BGP session, while retaining the local MAC and local ARP entries. Signed-off-by: Kishore Aramalla karamalla@vmware.com
-rw-r--r--zebra/main.c4
-rw-r--r--zebra/zebra_vxlan.c227
-rw-r--r--zebra/zebra_vxlan.h1
3 files changed, 199 insertions, 33 deletions
diff --git a/zebra/main.c b/zebra/main.c
index 5797a5846..194710675 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -55,6 +55,7 @@
#include "zebra/zebra_netns_notify.h"
#include "zebra/zebra_rnh.h"
#include "zebra/zebra_pbr.h"
+#include "zebra/zebra_vxlan.h"
#if defined(HANDLE_NETLINK_FUZZING)
#include "zebra/kernel_netlink.h"
@@ -455,6 +456,9 @@ int main(int argc, char **argv)
/* RNH init */
zebra_rnh_init();
+ /* Config handler Init */
+ zebra_evpn_init();
+
/* Error init */
zebra_error_init();
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 077c1ff8f..626fa4e15 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -224,6 +224,9 @@ static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
struct in_addr mcast_grp);
static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg);
+static void zvni_send_mac_to_client(zebra_vni_t *zvn);
+static void zvni_send_neigh_to_client(zebra_vni_t *zvni);
+
/* Private functions */
static int host_rb_entry_compare(const struct host_rb_entry *hle1,
const struct host_rb_entry *hle2)
@@ -2869,6 +2872,16 @@ static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket *bucket,
/* Add primary SVI MAC*/
zvni = (zebra_vni_t *)bucket->data;
+ /* Global (Zvrf) advertise-default-gw is disabled,
+ * but zvni advertise-default-gw is enabled
+ */
+ if (zvni->advertise_gw_macip) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
+ zvni->vni);
+ return;
+ }
+
ifp = zvni->vxlan_if;
if (!ifp)
return;
@@ -2950,6 +2963,16 @@ static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket *bucket,
if (!zvni)
return;
+ /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
+ * enabled
+ */
+ if (zvni->advertise_svi_macip) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
+ zvni->vni);
+ return;
+ }
+
ifp = zvni->vxlan_if;
if (!ifp)
return;
@@ -4056,46 +4079,67 @@ static void zvni_build_hash_table(void)
ifp->name, ifp->ifindex, vni,
inet_ntoa(vxl->vtep_ip));
- /* VNI hash entry is not expected to exist. */
+ /* VNI hash entry is expected to exist, if the BGP process is killed */
zvni = zvni_lookup(vni);
if (zvni) {
zlog_debug(
"VNI hash already present for IF %s(%u) L2-VNI %u",
ifp->name, ifp->ifindex, vni);
- continue;
- }
- zvni = zvni_add(vni);
- if (!zvni) {
- zlog_debug(
- "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
- ifp->name, ifp->ifindex, vni);
- return;
- }
+ /*
+ * Inform BGP if intf is up and mapped to
+ * bridge.
+ */
+ if (if_is_operative(ifp) &&
+ zif->brslave_info.br_if)
+ zvni_send_add_to_client(zvni);
- if (zvni->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
- zvni->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
- zebra_vxlan_sg_deref(zvni->local_vtep_ip,
- zvni->mcast_grp);
- zebra_vxlan_sg_ref(vxl->vtep_ip,
- vxl->mcast_grp);
- zvni->local_vtep_ip = vxl->vtep_ip;
- zvni->mcast_grp = vxl->mcast_grp;
- }
- zvni->vxlan_if = ifp;
- vlan_if = zvni_map_to_svi(vxl->access_vlan,
- zif->brslave_info.br_if);
- if (vlan_if) {
- zvni->vrf_id = vlan_if->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
- if (zl3vni)
- listnode_add_sort(zl3vni->l2vnis, zvni);
- }
+ /* Send Local MAC-entries to client */
+ zvni_send_mac_to_client(zvni);
+
+ /* Send Loval Neighbor entries to client */
+ zvni_send_neigh_to_client(zvni);
+ } else {
+ zvni = zvni_add(vni);
+ if (!zvni) {
+ zlog_debug(
+ "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
+ ifp->name, ifp->ifindex, vni);
+ return;
+ }
+ if (zvni->local_vtep_ip.s_addr !=
+ vxl->vtep_ip.s_addr ||
+ zvni->mcast_grp.s_addr !=
+ vxl->mcast_grp.s_addr) {
+ zebra_vxlan_sg_deref(
+ zvni->local_vtep_ip,
+ zvni->mcast_grp);
+ zebra_vxlan_sg_ref(vxl->vtep_ip,
+ vxl->mcast_grp);
+ zvni->local_vtep_ip = vxl->vtep_ip;
+ zvni->mcast_grp = vxl->mcast_grp;
+ }
+ zvni->vxlan_if = ifp;
+ vlan_if = zvni_map_to_svi(vxl->access_vlan,
+ zif->brslave_info.br_if);
+ if (vlan_if) {
+ zvni->vrf_id = vlan_if->vrf_id;
+ zl3vni = zl3vni_from_vrf(
+ vlan_if->vrf_id);
+ if (zl3vni)
+ listnode_add_sort(
+ zl3vni->l2vnis, zvni);
+ }
- /* Inform BGP if intf is up and mapped to bridge. */
- if (if_is_operative(ifp) && zif->brslave_info.br_if)
- zvni_send_add_to_client(zvni);
+ /*
+ * Inform BGP if intf is up and mapped to
+ * bridge.
+ */
+ if (if_is_operative(ifp) &&
+ zif->brslave_info.br_if)
+ zvni_send_add_to_client(zvni);
+ }
}
}
}
@@ -8916,7 +8960,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
struct interface *ifp = NULL;
if (!EVPN_ENABLED(zvrf)) {
- zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
+ zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
zvrf_id(zvrf));
return;
}
@@ -8927,7 +8971,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
if (!vni) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("EVPN gateway macip Adv %s, currently %s",
+ zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
advertise ? "enabled" : "disabled",
advertise_gw_macip_enabled(NULL)
? "enabled"
@@ -9637,3 +9681,120 @@ static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg)
zebra_vxlan_sg_del(vxlan_sg);
}
+
+/************************** EVPN BGP config management ************************/
+/* Notify Local MACs to the clienti, skips GW MAC */
+static void zvni_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
+ void *arg)
+{
+ struct mac_walk_ctx *wctx = arg;
+ zebra_mac_t *zmac = bucket->data;
+
+ if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW))
+ return;
+
+ if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
+ zvni_mac_send_add_to_client(wctx->zvni->vni, &zmac->macaddr,
+ zmac->flags, zmac->loc_seq);
+}
+
+/* Iterator to Notify Local MACs of a L2VNI */
+static void zvni_send_mac_to_client(zebra_vni_t *zvni)
+{
+ struct mac_walk_ctx wctx;
+
+ if (!zvni->mac_table)
+ return;
+
+ memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+ wctx.zvni = zvni;
+
+ hash_iterate(zvni->mac_table, zvni_send_mac_hash_entry_to_client,
+ &wctx);
+}
+
+/* Notify Neighbor entries to the Client, skips the GW entry */
+static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket *bucket,
+ void *arg)
+{
+ struct mac_walk_ctx *wctx = arg;
+ zebra_neigh_t *zn = bucket->data;
+ zebra_mac_t *zmac = NULL;
+
+ if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_DEF_GW))
+ return;
+
+ if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_LOCAL) &&
+ IS_ZEBRA_NEIGH_ACTIVE(zn)) {
+ zmac = zvni_mac_lookup(wctx->zvni, &zn->emac);
+ if (!zmac)
+ return;
+
+ zvni_neigh_send_add_to_client(wctx->zvni->vni, &zn->ip,
+ &zn->emac, zn->flags,
+ zn->loc_seq);
+ }
+}
+
+/* Iterator of a specific L2VNI */
+static void zvni_send_neigh_to_client(zebra_vni_t *zvni)
+{
+ struct neigh_walk_ctx wctx;
+
+ memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
+ wctx.zvni = zvni;
+
+ hash_iterate(zvni->neigh_table, zvni_send_neigh_hash_entry_to_client,
+ &wctx);
+}
+
+static void zvni_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt)
+{
+ zebra_vni_t *zvni = NULL;
+
+ zvni = (zebra_vni_t *)bucket->data;
+ zvni->advertise_gw_macip = 0;
+ zvni->advertise_svi_macip = 0;
+ zvni->advertise_subnet = 0;
+
+ zvni_neigh_del_all(zvni, 0, 0,
+ DEL_REMOTE_NEIGH | DEL_REMOTE_NEIGH_FROM_VTEP);
+ zvni_mac_del_all(zvni, 0, 0,
+ DEL_REMOTE_MAC | DEL_REMOTE_MAC_FROM_VTEP);
+ zvni_vtep_del_all(zvni, 0);
+}
+
+/* Cleanup EVPN configuration of a specific VRF */
+static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
+{
+ zvrf->advertise_all_vni = 0;
+ zvrf->advertise_gw_macip = 0;
+ zvrf->advertise_svi_macip = 0;
+ zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
+
+ hash_iterate(zvrf->vni_table, zvni_evpn_cfg_cleanup, NULL);
+}
+
+/* Cleanup BGP EVPN configuration upon client disconnect */
+static int zebra_evpn_cfg_clean_up(struct zserv *client)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+
+ if (client->proto != ZEBRA_ROUTE_BGP)
+ return 0;
+
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+ zvrf = vrf->info;
+ if (zvrf)
+ zebra_evpn_vrf_cfg_cleanup(zvrf);
+ }
+
+ return 0;
+}
+
+/* Cleanup BGP EVPN configuration upon client disconnect */
+extern void zebra_evpn_init(void)
+{
+ hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
+}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index f752bdd69..6117567bc 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -212,6 +212,7 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni);
+extern void zebra_evpn_init(void);
#ifdef __cplusplus
}