summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSharath Ramamurthy <sramamurthy@nvidia.com>2021-07-27 13:40:48 +0530
committerStephen Worley <sworley@nvidia.com>2023-02-13 18:12:04 -0500
commit0adeb5fdf46fe23a85924d04f2f02ee0be3cce6a (patch)
treeaa5d70622d9f3a621a1669dce5d5ca0c188c1bc1
parentb95ce8fadbceea40639224d59bfcc0a2679f5604 (diff)
zebra: vxlan interface refactoring changes
This change refactors the zebra_vxlan_if related functionality to a new zebra_vxlan_if.c file. zebra_vxlan_if_up/down, zebra_vxlan_if_add/update/del is moved zebra_vxlan_if.c Signed-off-by: Sharath Ramamurthy <sramamurthy@nvidia.com>
-rw-r--r--zebra/subdir.am1
-rw-r--r--zebra/zebra_evpn.c2
-rw-r--r--zebra/zebra_evpn_mac.c2
-rw-r--r--zebra/zebra_evpn_mh.c2
-rw-r--r--zebra/zebra_evpn_neigh.c2
-rw-r--r--zebra/zebra_l2.c5
-rw-r--r--zebra/zebra_nb_state.c1
-rw-r--r--zebra/zebra_vxlan.c505
-rw-r--r--zebra/zebra_vxlan_if.c554
-rw-r--r--zebra/zebra_vxlan_if.h55
-rw-r--r--zebra/zebra_vxlan_private.h2
11 files changed, 621 insertions, 510 deletions
diff --git a/zebra/subdir.am b/zebra/subdir.am
index 5c4a87b934..104980218d 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -105,6 +105,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_vrf.c \
zebra/zebra_vty.c \
zebra/zebra_vxlan.c \
+ zebra/zebra_vxlan_if.c \
zebra/zebra_evpn_mh.c \
zebra/zebra_neigh.c \
zebra/zserv.c \
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index 0bf6039693..6f2765284b 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -47,10 +47,10 @@
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_evpn.h"
#include "zebra/zebra_evpn_mac.h"
#include "zebra/zebra_evpn_neigh.h"
-#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_evpn_vxlan.h"
#include "zebra/zebra_router.h"
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 4babbe97cd..801403c11c 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -36,6 +36,8 @@
#include "zebra/zebra_router.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
#include "zebra/zebra_evpn.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_evpn_mac.h"
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 9d672ab51d..a2a0952165 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -44,9 +44,9 @@
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_evpn.h"
#include "zebra/zebra_evpn_mac.h"
-#include "zebra/zebra_vxlan_private.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_nhg.h"
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 684720bb4d..4c7f393fa1 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -36,6 +36,8 @@
#include "zebra/rt.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
#include "zebra/zebra_evpn.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_evpn_neigh.h"
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 550b819428..e1de9a147a 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -43,6 +43,7 @@
#include "zebra/interface.h"
#include "zebra/zebra_l2.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
#include "zebra/zebra_evpn_mh.h"
/* definitions */
@@ -349,8 +350,6 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp,
if (add) {
memcpy(&zif->l2info.vxl, vxlan_info, sizeof(*vxlan_info));
- zebra_evpn_vl_vxl_ref(zif->l2info.vxl.vni_info.vni.access_vlan,
- zif->l2info.vxl.vni_info.vni.vni, zif);
zebra_vxlan_if_add(ifp);
return;
}
@@ -415,8 +414,6 @@ void zebra_l2_vxlanif_del(struct interface *ifp)
zif = ifp->info;
assert(zif);
- zebra_evpn_vl_vxl_deref(zif->l2info.vxl.vni_info.vni.access_vlan,
- zif->l2info.vxl.vni_info.vni.vni, zif);
zebra_vxlan_if_del(ifp);
}
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index 0c0bd56383..45b9d440a6 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -26,6 +26,7 @@
#include "zebra/debug.h"
#include "printfrr.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
/*
* XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/up-count
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 79f696c97d..28ffafec5a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -907,7 +907,7 @@ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
return tmp_if;
}
-static int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
+int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
{
zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);
@@ -4797,509 +4797,6 @@ void zebra_vxlan_macvlan_up(struct interface *ifp)
}
}
-/*
- * Handle VxLAN interface down
- */
-int zebra_vxlan_if_down(struct interface *ifp)
-{
- vni_t vni;
- struct zebra_if *zif = NULL;
- struct zebra_l3vni *zl3vni = NULL;
- struct zebra_evpn *zevpn;
- struct zebra_vxlan_vni *vnip;
-
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
- zif = ifp->info;
- assert(zif);
- vnip = zebra_vxlan_if_vni_find(zif, 0);
- vni = vnip->vni;
-
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
- /* process-if-down for l3-vni */
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
- ifp->ifindex, vni);
-
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
- } else {
- /* process if-down for l2-vni */
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
- ifp->ifindex, vni);
-
- /* Locate hash entry; it is expected to exist. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- zlog_debug(
- "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
- ifp->name, ifp->ifindex, vni);
- return -1;
- }
-
- assert(zevpn->vxlan_if == ifp);
-
- /* remove from l3-vni list */
- zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
- if (zl3vni)
- listnode_delete(zl3vni->l2vnis, zevpn);
-
- /* Delete this VNI from BGP. */
- zebra_evpn_send_del_to_client(zevpn);
-
- /* Free up all neighbors and MACs, if any. */
- zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
- zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
-
- /* Free up all remote VTEPs, if any. */
- zebra_evpn_vtep_del_all(zevpn, 1);
- }
- return 0;
-}
-
-/*
- * Handle VxLAN interface up - update BGP if required.
- */
-int zebra_vxlan_if_up(struct interface *ifp)
-{
- vni_t vni;
- struct zebra_if *zif = NULL;
- struct zebra_evpn *zevpn = NULL;
- struct zebra_l3vni *zl3vni = NULL;
- struct zebra_vxlan_vni *vnip;
-
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
- zif = ifp->info;
- assert(zif);
- vnip = zebra_vxlan_if_vni_find(zif, 0);
- vni = vnip->vni;
-
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
- /* we need to associate with SVI, if any, we can associate with
- * svi-if only after association with vxlan-intf is complete
- */
- zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
- zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
- , ifp->name, ifp->ifindex, vni,
- zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
- zl3vni->mac_vlan_if ?
- zl3vni->mac_vlan_if->name : "NIL");
-
- if (is_l3vni_oper_up(zl3vni))
- zebra_vxlan_process_l3vni_oper_up(zl3vni);
- } else {
- /* Handle L2-VNI add */
- struct interface *vlan_if = NULL;
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
- ifp->ifindex, vni);
-
- /* Locate hash entry; it is expected to exist. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- zlog_debug(
- "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
- ifp->name, ifp->ifindex, vni);
- return -1;
- }
-
- assert(zevpn->vxlan_if == ifp);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
- if (vlan_if) {
- zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
- if (zl3vni)
- listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
- }
-
- /* If part of a bridge, inform BGP about this VNI. */
- /* Also, read and populate local MACs and neighbors. */
- if (zif->brslave_info.br_if) {
- zebra_evpn_send_add_to_client(zevpn);
- zebra_evpn_read_mac_neigh(zevpn, ifp);
- }
- }
-
- return 0;
-}
-
-/*
- * Handle VxLAN interface delete. Locate and remove entry in hash table
- * and update BGP, if required.
- */
-int zebra_vxlan_if_del(struct interface *ifp)
-{
- vni_t vni;
- struct zebra_if *zif = NULL;
- struct zebra_evpn *zevpn = NULL;
- struct zebra_l3vni *zl3vni = NULL;
- struct zebra_vxlan_vni *vnip;
-
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
- zif = ifp->info;
- assert(zif);
- vnip = zebra_vxlan_if_vni_find(zif, 0);
- vni = vnip->vni;
-
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
- ifp->ifindex);
-
- /* process oper-down for l3-vni */
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
-
- /* remove the association with vxlan_if */
- memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
- zl3vni->vxlan_if = NULL;
- } else {
-
- /* process if-del for l2-vni*/
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
- ifp->ifindex);
-
- /* Locate hash entry; it is expected to exist. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- zlog_debug(
- "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
- ifp->name, ifp->ifindex, vni);
- return 0;
- }
-
- /* remove from l3-vni list */
- zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
- if (zl3vni)
- listnode_delete(zl3vni->l2vnis, zevpn);
- /* Delete VNI from BGP. */
- zebra_evpn_send_del_to_client(zevpn);
-
- /* Free up all neighbors and MAC, if any. */
- zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
- zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
-
- /* Free up all remote VTEPs, if any. */
- zebra_evpn_vtep_del_all(zevpn, 0);
-
- /* Delete the hash entry. */
- if (zebra_evpn_vxlan_del(zevpn)) {
- flog_err(EC_ZEBRA_VNI_DEL_FAILED,
- "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
- zevpn, ifp->name, ifp->ifindex, zevpn->vni);
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
- */
-int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
-{
- vni_t vni;
- struct zebra_if *zif = NULL;
- struct zebra_l2info_vxlan *vxl = NULL;
- struct zebra_evpn *zevpn = NULL;
- struct zebra_l3vni *zl3vni = NULL;
- struct interface *vlan_if = NULL;
- struct zebra_vxlan_vni *vnip;
-
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
- zif = ifp->info;
- assert(zif);
- vnip = zebra_vxlan_if_vni_find(zif, 0);
- vni = vnip->vni;
-
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
- vni, ifp->name, ifp->ifindex, vnip->access_vlan,
- &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
- chgflags);
-
- /* Removed from bridge? Cleanup and return */
- if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
- && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
- return 0;
- }
-
- if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
- && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
- zebra_vxlan_process_l3vni_oper_up(zl3vni);
- return 0;
- }
-
- /* access-vlan change - process oper down, associate with new
- * svi_if and then process oper up again
- */
- if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
- if (if_is_operative(ifp)) {
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
- zl3vni->svi_if = NULL;
- zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
- zl3vni->mac_vlan_if =
- zl3vni_map_to_mac_vlan_if(zl3vni);
- zl3vni->local_vtep_ip = vxl->vtep_ip;
- if (is_l3vni_oper_up(zl3vni))
- zebra_vxlan_process_l3vni_oper_up(
- zl3vni);
- }
- }
-
- /*
- * local-ip change - process oper down, associate with new
- * local-ip and then process oper up again
- */
- if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
- if (if_is_operative(ifp)) {
- zebra_vxlan_process_l3vni_oper_down(zl3vni);
- zl3vni->local_vtep_ip = vxl->vtep_ip;
- if (is_l3vni_oper_up(zl3vni))
- zebra_vxlan_process_l3vni_oper_up(
- zl3vni);
- }
- }
-
- /* Update local tunnel IP. */
- zl3vni->local_vtep_ip = vxl->vtep_ip;
-
- /* if we have a valid new master, process l3-vni oper up */
- if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
- if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
- zebra_vxlan_process_l3vni_oper_up(zl3vni);
- }
- } else {
-
- /* Update VNI hash. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn) {
- zlog_debug(
- "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
- ifp->name, ifp->ifindex, vni);
- return -1;
- }
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
- vni, ifp->name, ifp->ifindex, vnip->access_vlan,
- &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
- chgflags);
-
- /* Removed from bridge? Cleanup and return */
- if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
- && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
- /* Delete from client, remove all remote VTEPs */
- /* Also, free up all MACs and neighbors. */
- zevpn->svi_if = NULL;
- zebra_evpn_send_del_to_client(zevpn);
- zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
- zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
- zebra_evpn_vtep_del_all(zevpn, 1);
- return 0;
- }
-
- /* Handle other changes. */
- if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
- /* Remove all existing local neigh and MACs for this VNI
- * (including from BGP)
- */
- zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
- zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
- }
-
- if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr
- || zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
- zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
- zevpn->mcast_grp);
- zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
- zevpn->local_vtep_ip = vxl->vtep_ip;
- zevpn->mcast_grp = vnip->mcast_grp;
- /* on local vtep-ip check if ES orig-ip
- * needs to be updated
- */
- zebra_evpn_es_set_base_evpn(zevpn);
- }
- zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
- if (vlan_if) {
- zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
- if (zl3vni)
- listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
- }
-
- /* Take further actions needed.
- * Note that if we are here, there is a change of interest.
- */
- /* If down or not mapped to a bridge, we're done. */
- if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- return 0;
-
- /* Inform BGP, if there is a change of interest. */
- if (chgflags &
- (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE |
- ZEBRA_VXLIF_MCAST_GRP_CHANGE | ZEBRA_VXLIF_VLAN_CHANGE))
- zebra_evpn_send_add_to_client(zevpn);
-
- /* If there is a valid new master or a VLAN mapping change,
- * read and populate local MACs and neighbors.
- * Also, reinstall any remote MACs and neighbors
- * for this VNI (based on new VLAN).
- */
- if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
- zebra_evpn_read_mac_neigh(zevpn, ifp);
- else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
- struct mac_walk_ctx m_wctx;
- struct neigh_walk_ctx n_wctx;
-
- zebra_evpn_read_mac_neigh(zevpn, ifp);
-
- memset(&m_wctx, 0, sizeof(m_wctx));
- m_wctx.zevpn = zevpn;
- hash_iterate(zevpn->mac_table,
- zebra_evpn_install_mac_hash, &m_wctx);
-
- memset(&n_wctx, 0, sizeof(n_wctx));
- n_wctx.zevpn = zevpn;
- hash_iterate(zevpn->neigh_table,
- zebra_evpn_install_neigh_hash, &n_wctx);
- }
- }
-
- return 0;
-}
-
-/*
- * Handle VxLAN interface add.
- */
-int zebra_vxlan_if_add(struct interface *ifp)
-{
- vni_t vni;
- struct zebra_if *zif = NULL;
- struct zebra_l2info_vxlan *vxl = NULL;
- struct zebra_evpn *zevpn = NULL;
- struct zebra_l3vni *zl3vni = NULL;
- struct zebra_vxlan_vni *vnip;
-
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
- zif = ifp->info;
- assert(zif);
- vnip = zebra_vxlan_if_vni_find(zif, 0);
- vni = vnip->vni;
-
- zl3vni = zl3vni_lookup(vni);
- if (zl3vni) {
-
- /* process if-add for l3-vni*/
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
- vni, ifp->name, ifp->ifindex, vnip->access_vlan,
- &vxl->vtep_ip,
- zif->brslave_info.bridge_ifindex);
-
- /* associate with vxlan_if */
- zl3vni->local_vtep_ip = vxl->vtep_ip;
- zl3vni->vxlan_if = ifp;
-
- /* Associate with SVI, if any. We can associate with svi-if only
- * after association with vxlan_if is complete */
- zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
-
- zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
-
- if (is_l3vni_oper_up(zl3vni))
- zebra_vxlan_process_l3vni_oper_up(zl3vni);
- } else {
-
- /* process if-add for l2-vni */
- struct interface *vlan_if = NULL;
-
- /* Create or update EVPN hash. */
- zevpn = zebra_evpn_lookup(vni);
- if (!zevpn)
- zevpn = zebra_evpn_add(vni);
-
- if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr
- || zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
- zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
- zevpn->mcast_grp);
- zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
- zevpn->local_vtep_ip = vxl->vtep_ip;
- zevpn->mcast_grp = vnip->mcast_grp;
- /* on local vtep-ip check if ES orig-ip
- * needs to be updated
- */
- zebra_evpn_es_set_base_evpn(zevpn);
- }
- zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
- if (vlan_if) {
- zevpn->svi_if = vlan_if;
- zevpn->vrf_id = vlan_if->vrf->vrf_id;
- zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
- if (zl3vni)
- listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
- }
-
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
- vni,
- vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
- ifp->name, ifp->ifindex, vnip->access_vlan,
- &vxl->vtep_ip, &vnip->mcast_grp,
- zif->brslave_info.bridge_ifindex);
-
- /* If down or not mapped to a bridge, we're done. */
- if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
- return 0;
-
- /* Inform BGP */
- zebra_evpn_send_add_to_client(zevpn);
-
- /* Read and populate local MACs and neighbors */
- zebra_evpn_read_mac_neigh(zevpn, ifp);
- }
-
- return 0;
-}
-
int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
char *err, int err_str_sz, int filter,
int add)
diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c
new file mode 100644
index 0000000000..eb01547fcc
--- /dev/null
+++ b/zebra/zebra_vxlan_if.c
@@ -0,0 +1,554 @@
+/*
+ * Zebra EVPN for VxLAN interface handling
+ *
+ * Copyright (C) 2020 Cumulus Networks, Inc.
+ * Vivek Venkatraman, Stephen Worley, Sharath Ramamurthy
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <zebra.h>
+
+#include "hash.h"
+#include "if.h"
+#include "jhash.h"
+#include "linklist.h"
+#include "log.h"
+#include "memory.h"
+#include "prefix.h"
+#include "stream.h"
+#include "table.h"
+#include "vlan.h"
+#include "vxlan.h"
+#ifdef GNU_LINUX
+#include <linux/neighbour.h>
+#endif
+
+#include "zebra/zebra_router.h"
+#include "zebra/debug.h"
+#include "zebra/interface.h"
+#include "zebra/rib.h"
+#include "zebra/rt.h"
+#include "zebra/rt_netlink.h"
+#include "zebra/zebra_errors.h"
+#include "zebra/zebra_l2.h"
+#include "zebra/zebra_ns.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
+#include "zebra/zebra_evpn.h"
+#include "zebra/zebra_evpn_mac.h"
+#include "zebra/zebra_evpn_neigh.h"
+#include "zebra/zebra_vxlan_private.h"
+#include "zebra/zebra_evpn_mh.h"
+#include "zebra/zebra_evpn_vxlan.h"
+#include "zebra/zebra_router.h"
+
+/*
+ * Handle VxLAN interface down
+ */
+int zebra_vxlan_if_down(struct interface *ifp)
+{
+ vni_t vni;
+ struct zebra_if *zif = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
+ struct zebra_evpn *zevpn;
+ struct zebra_vxlan_vni *vnip;
+
+ /* Check if EVPN is enabled. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ zif = ifp->info;
+ assert(zif);
+ vnip = zebra_vxlan_if_vni_find(zif, 0);
+ vni = vnip->vni;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni) {
+ /* process-if-down for l3-vni */
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
+ ifp->ifindex, vni);
+
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ } else {
+ /* process if-down for l2-vni */
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
+ ifp->ifindex, vni);
+
+ /* Locate hash entry; it is expected to exist. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ zlog_debug(
+ "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
+ ifp->name, ifp->ifindex, vni);
+ return -1;
+ }
+
+ assert(zevpn->vxlan_if == ifp);
+
+ /* remove from l3-vni list */
+ zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
+ if (zl3vni)
+ listnode_delete(zl3vni->l2vnis, zevpn);
+
+ /* Delete this VNI from BGP. */
+ zebra_evpn_send_del_to_client(zevpn);
+
+ /* Free up all neighbors and MACs, if any. */
+ zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
+ zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
+
+ /* Free up all remote VTEPs, if any. */
+ zebra_evpn_vtep_del_all(zevpn, 1);
+ }
+ return 0;
+}
+
+/*
+ * Handle VxLAN interface up - update BGP if required.
+ */
+int zebra_vxlan_if_up(struct interface *ifp)
+{
+ vni_t vni;
+ struct zebra_if *zif = NULL;
+ struct zebra_evpn *zevpn = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
+ struct zebra_vxlan_vni *vnip;
+
+ /* Check if EVPN is enabled. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ zif = ifp->info;
+ assert(zif);
+ vnip = zebra_vxlan_if_vni_find(zif, 0);
+ vni = vnip->vni;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni) {
+ /* we need to associate with SVI, if any, we can associate with
+ * svi-if only after association with vxlan-intf is complete
+ */
+ zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
+ zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s",
+ ifp->name, ifp->ifindex, vni,
+ zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
+ zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
+ : "NIL");
+
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ } else {
+ /* Handle L2-VNI add */
+ struct interface *vlan_if = NULL;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
+ ifp->ifindex, vni);
+
+ /* Locate hash entry; it is expected to exist. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ zlog_debug(
+ "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
+ ifp->name, ifp->ifindex, vni);
+ return -1;
+ }
+
+ assert(zevpn->vxlan_if == ifp);
+ vlan_if = zvni_map_to_svi(vnip->access_vlan,
+ zif->brslave_info.br_if);
+ if (vlan_if) {
+ zevpn->svi_if = vlan_if;
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
+ zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
+ if (zl3vni)
+ listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
+ }
+
+ /* If part of a bridge, inform BGP about this VNI. */
+ /* Also, read and populate local MACs and neighbors. */
+ if (zif->brslave_info.br_if) {
+ zebra_evpn_send_add_to_client(zevpn);
+ zebra_evpn_read_mac_neigh(zevpn, ifp);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Handle VxLAN interface delete. Locate and remove entry in hash table
+ * and update BGP, if required.
+ */
+int zebra_vxlan_if_del(struct interface *ifp)
+{
+ vni_t vni;
+ struct zebra_if *zif = NULL;
+ struct zebra_evpn *zevpn = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
+ struct zebra_vxlan_vni *vnip;
+
+ /* Check if EVPN is enabled. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ zif = ifp->info;
+ assert(zif);
+ vnip = zebra_vxlan_if_vni_find(zif, 0);
+ vni = vnip->vni;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni) {
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
+ ifp->ifindex);
+
+ /* process oper-down for l3-vni */
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+
+ /* remove the association with vxlan_if */
+ memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
+ zl3vni->vxlan_if = NULL;
+ } else {
+
+ /* process if-del for l2-vni*/
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
+ ifp->ifindex);
+
+ /* Locate hash entry; it is expected to exist. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ zlog_debug(
+ "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
+ ifp->name, ifp->ifindex, vni);
+ return 0;
+ }
+
+ /* remove from l3-vni list */
+ zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
+ if (zl3vni)
+ listnode_delete(zl3vni->l2vnis, zevpn);
+ /* Delete VNI from BGP. */
+ zebra_evpn_send_del_to_client(zevpn);
+
+ /* Free up all neighbors and MAC, if any. */
+ zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
+ zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
+
+ /* Free up all remote VTEPs, if any. */
+ zebra_evpn_vtep_del_all(zevpn, 0);
+
+ /* Delete the hash entry. */
+ if (zebra_evpn_vxlan_del(zevpn)) {
+ flog_err(EC_ZEBRA_VNI_DEL_FAILED,
+ "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
+ zevpn, ifp->name, ifp->ifindex, zevpn->vni);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
+ */
+int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
+{
+ vni_t vni;
+ struct zebra_if *zif = NULL;
+ struct zebra_l2info_vxlan *vxl = NULL;
+ struct zebra_evpn *zevpn = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
+ struct interface *vlan_if = NULL;
+ struct zebra_vxlan_vni *vnip;
+
+ /* Check if EVPN is enabled. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ zif = ifp->info;
+ assert(zif);
+ vnip = zebra_vxlan_if_vni_find(zif, 0);
+ vni = vnip->vni;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni) {
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
+ vni, ifp->name, ifp->ifindex, vnip->access_vlan,
+ &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
+ chgflags);
+
+ /* Removed from bridge? Cleanup and return */
+ if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
+ && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ return 0;
+ }
+
+ if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
+ && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ return 0;
+ }
+
+ /* access-vlan change - process oper down, associate with new
+ * svi_if and then process oper up again
+ */
+ if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
+ if (if_is_operative(ifp)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ zl3vni->svi_if = NULL;
+ zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
+ zl3vni->mac_vlan_if =
+ zl3vni_map_to_mac_vlan_if(zl3vni);
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(
+ zl3vni);
+ }
+ }
+
+ /*
+ * local-ip change - process oper down, associate with new
+ * local-ip and then process oper up again
+ */
+ if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
+ if (if_is_operative(ifp)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(
+ zl3vni);
+ }
+ }
+
+ /* Update local tunnel IP. */
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+
+ /* if we have a valid new master, process l3-vni oper up */
+ if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
+ if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ }
+ } else {
+
+ /* Update VNI hash. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn) {
+ zlog_debug(
+ "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
+ ifp->name, ifp->ifindex, vni);
+ return -1;
+ }
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
+ vni, ifp->name, ifp->ifindex, vnip->access_vlan,
+ &vxl->vtep_ip, zif->brslave_info.bridge_ifindex,
+ chgflags);
+
+ /* Removed from bridge? Cleanup and return */
+ if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
+ && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
+ /* Delete from client, remove all remote VTEPs */
+ /* Also, free up all MACs and neighbors. */
+ zevpn->svi_if = NULL;
+ zebra_evpn_send_del_to_client(zevpn);
+ zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
+ zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
+ zebra_evpn_vtep_del_all(zevpn, 1);
+ return 0;
+ }
+
+ /* Handle other changes. */
+ if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
+ /* Remove all existing local neigh and MACs for this VNI
+ * (including from BGP)
+ */
+ zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
+ zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
+ }
+
+ if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr
+ || zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
+ zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
+ zevpn->mcast_grp);
+ zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
+ zevpn->local_vtep_ip = vxl->vtep_ip;
+ zevpn->mcast_grp = vnip->mcast_grp;
+ /* on local vtep-ip check if ES orig-ip
+ * needs to be updated
+ */
+ zebra_evpn_es_set_base_evpn(zevpn);
+ }
+ zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
+ vlan_if = zvni_map_to_svi(vnip->access_vlan,
+ zif->brslave_info.br_if);
+ if (vlan_if)
+ zevpn->svi_if = vlan_if;
+
+ /* Take further actions needed.
+ * Note that if we are here, there is a change of interest.
+ */
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return 0;
+
+ /* Inform BGP, if there is a change of interest. */
+ if (chgflags &
+ (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE |
+ ZEBRA_VXLIF_MCAST_GRP_CHANGE | ZEBRA_VXLIF_VLAN_CHANGE))
+ zebra_evpn_send_add_to_client(zevpn);
+
+ /* If there is a valid new master or a VLAN mapping change,
+ * read and populate local MACs and neighbors.
+ * Also, reinstall any remote MACs and neighbors
+ * for this VNI (based on new VLAN).
+ */
+ if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
+ zebra_evpn_read_mac_neigh(zevpn, ifp);
+ else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
+ struct mac_walk_ctx m_wctx;
+ struct neigh_walk_ctx n_wctx;
+
+ zebra_evpn_read_mac_neigh(zevpn, ifp);
+
+ memset(&m_wctx, 0, sizeof(m_wctx));
+ m_wctx.zevpn = zevpn;
+ hash_iterate(zevpn->mac_table,
+ zebra_evpn_install_mac_hash, &m_wctx);
+
+ memset(&n_wctx, 0, sizeof(n_wctx));
+ n_wctx.zevpn = zevpn;
+ hash_iterate(zevpn->neigh_table,
+ zebra_evpn_install_neigh_hash, &n_wctx);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Handle VxLAN interface add.
+ */
+int zebra_vxlan_if_add(struct interface *ifp)
+{
+ vni_t vni;
+ struct zebra_if *zif = NULL;
+ struct zebra_l2info_vxlan *vxl = NULL;
+ struct zebra_evpn *zevpn = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
+ struct zebra_vxlan_vni *vnip;
+
+ /* Check if EVPN is enabled. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ zif = ifp->info;
+ assert(zif);
+ vnip = zebra_vxlan_if_vni_find(zif, 0);
+ vni = vnip->vni;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni) {
+
+ /* process if-add for l3-vni*/
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
+ vni, ifp->name, ifp->ifindex, vnip->access_vlan,
+ &vxl->vtep_ip,
+ zif->brslave_info.bridge_ifindex);
+
+ /* associate with vxlan_if */
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
+ zl3vni->vxlan_if = ifp;
+
+ /* Associate with SVI, if any. We can associate with svi-if only
+ * after association with vxlan_if is complete */
+ zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
+
+ zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
+
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ } else {
+
+ /* process if-add for l2-vni */
+ struct interface *vlan_if = NULL;
+
+ /* Create or update EVPN hash. */
+ zevpn = zebra_evpn_lookup(vni);
+ if (!zevpn)
+ zevpn = zebra_evpn_add(vni);
+
+ if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr
+ || zevpn->mcast_grp.s_addr != vnip->mcast_grp.s_addr) {
+ zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
+ zevpn->mcast_grp);
+ zebra_vxlan_sg_ref(vxl->vtep_ip, vnip->mcast_grp);
+ zevpn->local_vtep_ip = vxl->vtep_ip;
+ zevpn->mcast_grp = vnip->mcast_grp;
+ /* on local vtep-ip check if ES orig-ip
+ * needs to be updated
+ */
+ zebra_evpn_es_set_base_evpn(zevpn);
+ }
+ zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
+ vlan_if = zvni_map_to_svi(vnip->access_vlan,
+ zif->brslave_info.br_if);
+ if (vlan_if) {
+ zevpn->svi_if = vlan_if;
+ zevpn->vrf_id = vlan_if->vrf->vrf_id;
+ zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
+ if (zl3vni)
+ listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
+ }
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
+ vni,
+ vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
+ ifp->name, ifp->ifindex, vnip->access_vlan,
+ &vxl->vtep_ip, &vnip->mcast_grp,
+ zif->brslave_info.bridge_ifindex);
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return 0;
+
+ /* Inform BGP */
+ zebra_evpn_send_add_to_client(zevpn);
+
+ /* Read and populate local MACs and neighbors */
+ zebra_evpn_read_mac_neigh(zevpn, ifp);
+ }
+
+ return 0;
+}
diff --git a/zebra/zebra_vxlan_if.h b/zebra/zebra_vxlan_if.h
new file mode 100644
index 0000000000..721e2b87ad
--- /dev/null
+++ b/zebra/zebra_vxlan_if.h
@@ -0,0 +1,55 @@
+/*
+ * Zebra VxLAN (EVPN) Data structures and definitions
+ * These are public definitions referenced by other files.
+ * Copyright (C) 2021 Cumulus Networks, Inc.
+ * Sharath Ramamurthy
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_VXLAN_IF_H
+#define _ZEBRA_VXLAN_IF_H
+
+#include <zebra.h>
+#include <zebra/zebra_router.h>
+
+#include "linklist.h"
+#include "if.h"
+#include "vlan.h"
+#include "vxlan.h"
+
+#include "lib/json.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/zserv.h"
+#include "zebra/zebra_dplane.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int zebra_vxlan_if_down(struct interface *ifp);
+extern int zebra_vxlan_if_up(struct interface *ifp);
+extern int zebra_vxlan_if_del(struct interface *ifp);
+extern int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags);
+extern int zebra_vxlan_if_add(struct interface *ifp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZEBRA_VXLAN_IF_H */
diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h
index 9161348b16..6da45b214e 100644
--- a/zebra/zebra_vxlan_private.h
+++ b/zebra/zebra_vxlan_private.h
@@ -29,6 +29,7 @@
#include "if.h"
#include "linklist.h"
#include "zebra_vxlan.h"
+#include "zebra_vxlan_if.h"
#include "zebra_evpn.h"
#include "zebra_evpn_mac.h"
@@ -266,5 +267,6 @@ extern void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
struct in_addr mcast_grp);
extern void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
extern void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
+extern int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn);
#endif /* _ZEBRA_VXLAN_PRIVATE_H */