return tmp_if;
}
+/*
+ * Uninstall MAC hash entry - called upon access VLAN change.
+ */
+static void zebra_evpn_uninstall_mac_hash(struct hash_bucket *bucket,
+ void *ctxt)
+{
+ struct zebra_mac *mac;
+ struct mac_walk_ctx *wctx = ctxt;
+
+ mac = (struct zebra_mac *)bucket->data;
+
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
+ zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac, false);
+}
+
/*
* Install MAC hash entry - called upon access VLAN change.
*/
-void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt)
+static void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt)
{
struct zebra_mac *mac;
struct mac_walk_ctx *wctx = ctxt;
zebra_evpn_rem_mac_install(wctx->zevpn, mac, false);
}
+/*
+ * Uninstall remote MAC entries for this EVPN.
+ */
+void zebra_evpn_rem_mac_uninstall_all(struct zebra_evpn *zevpn)
+{
+ struct mac_walk_ctx wctx;
+
+ if (!zevpn->mac_table)
+ return;
+
+ memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+ wctx.zevpn = zevpn;
+ wctx.uninstall = 1;
+ wctx.upd_client = 0;
+ wctx.flags = ZEBRA_MAC_REMOTE;
+
+ hash_iterate(zevpn->mac_table, zebra_evpn_uninstall_mac_hash, &wctx);
+}
+
+/*
+ * Install remote MAC entries for this EVPN.
+ */
+void zebra_evpn_rem_mac_install_all(struct zebra_evpn *zevpn)
+{
+ struct mac_walk_ctx wctx;
+
+ if (!zevpn->mac_table)
+ return;
+
+ memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+ wctx.zevpn = zevpn;
+ wctx.uninstall = 0;
+ wctx.upd_client = 0;
+ wctx.flags = ZEBRA_MAC_REMOTE;
+
+ hash_iterate(zevpn->mac_table, zebra_evpn_install_mac_hash, &wctx);
+}
+
/*
* Read and populate local MACs and neighbors corresponding to this EVPN.
*/
struct interface *br_if);
struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if,
struct interface *svi_if);
-void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt);
+void zebra_evpn_rem_mac_install_all(struct zebra_evpn *zevpn);
+void zebra_evpn_rem_mac_uninstall_all(struct zebra_evpn *zevpn);
void zebra_evpn_read_mac_neigh(struct zebra_evpn *zevpn, struct interface *ifp);
unsigned int zebra_evpn_hash_keymake(const void *p);
bool zebra_evpn_hash_cmp(const void *p1, const void *p2);
struct zebra_l2info_vxlan *vxlan_info, int add)
{
struct zebra_if *zif;
- struct in_addr old_vtep_ip;
uint16_t chgflags = 0;
+ struct zebra_vxlan_if_update_ctx ctx;
zif = ifp->info;
assert(zif);
return;
}
- old_vtep_ip = zif->l2info.vxl.vtep_ip;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.old_vtep_ip = zif->l2info.vxl.vtep_ip;
- if (!IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip)) {
+ if (!IPV4_ADDR_SAME(&ctx.old_vtep_ip, &vxlan_info->vtep_ip)) {
chgflags |= ZEBRA_VXLIF_LOCAL_IP_CHANGE;
zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip;
}
if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
+ ctx.old_vni = vxlan_info->vni_info.vni;
if (!IPV4_ADDR_SAME(&zif->l2info.vxl.vni_info.vni.mcast_grp,
&vxlan_info->vni_info.vni.mcast_grp)) {
chgflags |= ZEBRA_VXLIF_MCAST_GRP_CHANGE;
}
}
- if (chgflags)
- zebra_vxlan_if_update(ifp, chgflags);
+ if (chgflags) {
+ ctx.chgflags = chgflags;
+ zebra_vxlan_if_update(ifp, &ctx);
+ }
}
/*
struct zebra_if *zif;
vlanid_t old_access_vlan;
struct zebra_vxlan_vni *vni;
+ struct zebra_vxlan_if_update_ctx ctx;
zif = ifp->info;
if (old_access_vlan == access_vlan)
return;
+ memset(&ctx, 0, sizeof(ctx));
vni = zebra_vxlan_if_vni_find(zif, 0);
+ ctx.old_vni = *vni;
+ ctx.chgflags = ZEBRA_VXLIF_VLAN_CHANGE;
vni->access_vlan = access_vlan;
zebra_evpn_vl_vxl_deref(old_access_vlan, vni->vni, zif);
zebra_evpn_vl_vxl_ref(access_vlan, vni->vni, zif);
- zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_VLAN_CHANGE);
+ zebra_vxlan_if_update(ifp, &ctx);
}
/*
ifindex_t old_bridge_ifindex;
ns_id_t old_ns_id;
struct zebra_vrf *zvrf;
+ struct zebra_vxlan_if_update_ctx ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
zif = ifp->info;
assert(zif);
if (zif->zif_type == ZEBRA_IF_VXLAN
&& chgflags != ZEBRA_BRIDGE_NO_ACTION) {
- if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE)
- zebra_vxlan_if_update(ifp,
- ZEBRA_VXLIF_MASTER_MAC_CHANGE);
- if (chgflags & ZEBRA_BRIDGE_MASTER_UP)
- zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
+ if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) {
+ ctx.chgflags = ZEBRA_VXLIF_MASTER_MAC_CHANGE;
+ zebra_vxlan_if_update(ifp, &ctx);
+ }
+ if (chgflags & ZEBRA_BRIDGE_MASTER_UP) {
+ ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE;
+ zebra_vxlan_if_update(ifp, &ctx);
+ }
}
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
old_ns_id = zif->brslave_info.ns_id;
old_ns_id == zif->brslave_info.ns_id)
return;
+ ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE;
+
+
zif->brslave_info.ns_id = ns_id;
zif->brslave_info.bridge_ifindex = bridge_ifindex;
/* Set up or remove link with master */
zebra_l2_map_slave_to_bridge(&zif->brslave_info, zvrf->zns);
/* In the case of VxLAN, invoke the handler for EVPN. */
if (zif->zif_type == ZEBRA_IF_VXLAN)
- zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
+ zebra_vxlan_if_update(ifp, &ctx);
if (zif->es_info.es)
zebra_evpn_es_local_br_port_update(zif);
} else if (old_bridge_ifindex != IFINDEX_INTERNAL) {
* to unmapping the interface from the bridge.
*/
if (zif->zif_type == ZEBRA_IF_VXLAN)
- zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);
+ zebra_vxlan_if_update(ifp, &ctx);
if (zif->es_info.es)
zebra_evpn_es_local_br_port_update(zif);
zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
struct zebra_vxlan_vni *vni;
};
+struct zebra_vxlan_if_update_ctx {
+ uint16_t chgflags;
+ struct in_addr old_vtep_ip;
+ struct zebra_vxlan_vni old_vni;
+ struct hash *old_vni_table;
+};
+
struct zebra_vxlan_if_ctx {
/* input */
struct zebra_if *zif;
extern int zebra_vxlan_if_up(struct interface *ifp);
extern int zebra_vxlan_if_down(struct interface *ifp);
extern int zebra_vxlan_if_add(struct interface *ifp);
-extern int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags);
+extern int zebra_vxlan_if_update(struct interface *ifp,
+ struct zebra_vxlan_if_update_ctx *ctx);
extern int zebra_vxlan_if_del(struct interface *ifp);
extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
char *err, int err_str_sz,
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;
assert(zif);
vxl = &zif->l2info.vxl;
vni = vnip->vni;
+ chgflags = ctx->chgflags;
zl3vni = zl3vni_lookup(vni);
if (zl3vni) {
/* 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 ||
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;
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);
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;
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);
}
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,
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;
{
struct zebra_if *zif;
struct zebra_vxlan_vni *vni;
+ struct zebra_vxlan_if_update_ctx ctx;
zif = (struct zebra_if *)ifp->info;
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)
/*
* 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;
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;
}
extern int zebra_vxlan_if_vni_update(struct interface *ifp,
struct zebra_vxlan_vni *vni,
uint16_t chgflags);
-extern int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags);
+extern int zebra_vxlan_if_update(struct interface *ifp,
+ struct zebra_vxlan_if_update_ctx *ctx);
extern int zebra_vxlan_if_vni_add(struct interface *ifp,
struct zebra_vxlan_vni *vni);
extern int zebra_vxlan_if_add(struct interface *ifp);