summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_vxlan_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_vxlan_if.c')
-rw-r--r--zebra/zebra_vxlan_if.c71
1 files changed, 41 insertions, 30 deletions
diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c
index 57fdc1953..31cef767d 100644
--- a/zebra/zebra_vxlan_if.c
+++ b/zebra/zebra_vxlan_if.c
@@ -175,9 +175,11 @@ static int zebra_vxlan_if_del_vni(struct interface *ifp,
static int zebra_vxlan_if_update_vni(struct interface *ifp,
struct zebra_vxlan_vni *vnip,
- uint16_t chgflags)
+ struct zebra_vxlan_if_update_ctx *ctx)
{
vni_t vni;
+ uint16_t chgflags;
+ vlanid_t access_vlan;
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
struct zebra_evpn *zevpn;
@@ -193,6 +195,7 @@ static int zebra_vxlan_if_update_vni(struct interface *ifp,
assert(zif);
vxl = &zif->l2info.vxl;
vni = vnip->vni;
+ chgflags = ctx->chgflags;
zl3vni = zl3vni_lookup(vni);
if (zl3vni) {
@@ -299,8 +302,12 @@ static int zebra_vxlan_if_update_vni(struct interface *ifp,
/* Remove all existing local neigh and MACs for this VNI
* (including from BGP)
*/
+ access_vlan = vnip->access_vlan;
+ vnip->access_vlan = ctx->old_vni.access_vlan;
zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
+ zebra_evpn_rem_mac_uninstall_all(zevpn);
+ vnip->access_vlan = access_vlan;
}
if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
@@ -347,15 +354,11 @@ static int zebra_vxlan_if_update_vni(struct interface *ifp,
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);
+ zebra_evpn_rem_mac_install_all(zevpn);
memset(&n_wctx, 0, sizeof(n_wctx));
n_wctx.zevpn = zevpn;
@@ -493,15 +496,15 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
struct zebra_vxlan_vni *vni,
void *ctxt)
{
- struct hash *old_vni_table;
struct zebra_vxlan_vni vni_tmp;
+ struct zebra_vxlan_if_update_ctx *ctx;
struct zebra_vxlan_vni *old_vni = NULL;
- old_vni_table = (struct hash *)ctxt;
+ ctx = (struct zebra_vxlan_if_update_ctx *)ctxt;
memcpy(&vni_tmp, vni, sizeof(*vni));
- old_vni = hash_release(old_vni_table, &vni_tmp);
- if (!old_vni) {
+ if ((hashcount(ctx->old_vni_table) == 0) ||
+ !(old_vni = hash_release(ctx->old_vni_table, &vni_tmp))) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("vxlan %s adding vni(%d, %d)",
zif->ifp->name, vni->vni, vni->access_vlan);
@@ -510,6 +513,9 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
return 0;
}
+ ctx->old_vni = *old_vni;
+ ctx->chgflags = ZEBRA_VXLIF_VLAN_CHANGE;
+
/* copy mcast group from old_vni as thats not being changed here */
vni->mcast_grp = old_vni->mcast_grp;
@@ -524,8 +530,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni,
zif);
zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
- zebra_vxlan_if_update_vni(zif->ifp, vni,
- ZEBRA_VXLIF_VLAN_CHANGE);
+ zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
zebra_vxlan_vni_free(old_vni);
}
@@ -536,10 +541,10 @@ static int zebra_vxlan_if_vni_entry_update_callback(struct zebra_if *zif,
struct zebra_vxlan_vni *vni,
void *ctxt)
{
- uint16_t *chgflags;
+ struct zebra_vxlan_if_update_ctx *ctx;
- chgflags = (uint16_t *)ctxt;
- return zebra_vxlan_if_update_vni(zif->ifp, vni, *chgflags);
+ ctx = (struct zebra_vxlan_if_update_ctx *)ctxt;
+ return zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
}
static int zebra_vxlan_if_vni_entry_del_callback(struct zebra_if *zif,
@@ -770,31 +775,32 @@ int zebra_vxlan_if_vni_table_add_update(struct interface *ifp,
struct hash *vni_table)
{
struct zebra_if *zif;
- struct hash *old_vni_table = NULL;
struct zebra_vxlan_vni_info *vni_info;
+ struct zebra_vxlan_if_update_ctx ctx;
zif = (struct zebra_if *)ifp->info;
vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
- old_vni_table = vni_info->vni_table;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.old_vni_table = vni_info->vni_table;
vni_info->vni_table = vni_table;
- zebra_vxlan_if_vni_iterate(zif, zebra_vxlan_if_add_update_vni,
- old_vni_table);
+ zebra_vxlan_if_vni_iterate(zif, zebra_vxlan_if_add_update_vni, &ctx);
/* release kernel deleted vnis */
- if (old_vni_table) {
- if (hashcount(old_vni_table)) {
+ if (ctx.old_vni_table) {
+ if (hashcount(ctx.old_vni_table)) {
/* UGLY HACK: Put back the old table so that delete of
* MACs goes through and then flip back.
*/
- vni_info->vni_table = old_vni_table;
- hash_iterate(old_vni_table, zebra_vxlan_if_vni_clean,
- zif);
+ vni_info->vni_table = ctx.old_vni_table;
+ hash_iterate(ctx.old_vni_table,
+ zebra_vxlan_if_vni_clean, zif);
vni_info->vni_table = vni_table;
}
- zebra_vxlan_vni_table_destroy(old_vni_table);
+ zebra_vxlan_vni_table_destroy(ctx.old_vni_table);
+ ctx.old_vni_table = NULL;
}
return 0;
@@ -805,6 +811,7 @@ int zebra_vxlan_if_vni_mcast_group_update(struct interface *ifp, vni_t vni_id,
{
struct zebra_if *zif;
struct zebra_vxlan_vni *vni;
+ struct zebra_vxlan_if_update_ctx ctx;
zif = (struct zebra_if *)ifp->info;
@@ -815,13 +822,16 @@ int zebra_vxlan_if_vni_mcast_group_update(struct interface *ifp, vni_t vni_id,
if (!vni)
return 0;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.old_vni.mcast_grp = vni->mcast_grp;
+ ctx.chgflags = ZEBRA_VXLIF_MCAST_GRP_CHANGE;
+
if (mcast_group)
vni->mcast_grp = *mcast_group;
else
memset(&vni->mcast_grp, 0, sizeof(vni->mcast_grp));
- return zebra_vxlan_if_update_vni(ifp, vni,
- ZEBRA_VXLIF_MCAST_GRP_CHANGE);
+ return zebra_vxlan_if_update_vni(ifp, vni, &ctx);
}
int zebra_vxlan_if_vni_down(struct interface *ifp, struct zebra_vxlan_vni *vnip)
@@ -1061,7 +1071,8 @@ int zebra_vxlan_if_del(struct interface *ifp)
/*
* Handle VxLAN interface update - change to tunnel IP, master or VLAN.
*/
-int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
+int zebra_vxlan_if_update(struct interface *ifp,
+ struct zebra_vxlan_if_update_ctx *ctx)
{
struct zebra_if *zif;
struct zebra_vxlan_vni_info *vni_info;
@@ -1071,11 +1082,11 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
- return zebra_vxlan_if_update_vni(ifp, &vni_info->vni, chgflags);
+ return zebra_vxlan_if_update_vni(ifp, &vni_info->vni, ctx);
}
zebra_vxlan_if_vni_iterate(
- zif, zebra_vxlan_if_vni_entry_update_callback, &chgflags);
+ zif, zebra_vxlan_if_vni_entry_update_callback, ctx);
return 0;
}