]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_evpn_mh.c
Merge pull request #13450 from patrasar/mld_core
[mirror_frr.git] / zebra / zebra_evpn_mh.c
index 01ea9c5b9c924d4af15dba0bd64f9247ad3cf2e6..a5092c629ac7d32d29b1a6f10d0afcb71ba6aedb 100644 (file)
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Zebra EVPN multihoming code
  *
  * Copyright (C) 2019 Cumulus Networks, Inc.
  * Anuradha Karuppiah
- *
- * 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 "zebra/if_netlink.h"
 #include "zebra/zebra_errors.h"
 #include "zebra/zebra_l2.h"
+#include "zebra/zebra_l2_bridge_if.h"
 #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"
@@ -481,6 +471,7 @@ void zebra_evpn_update_all_es(struct zebra_evpn *zevpn)
        struct interface *vlan_if;
        struct interface *vxlan_if;
        struct zebra_if *vxlan_zif;
+       struct zebra_vxlan_vni *vni;
 
        /* the EVPN is now elgible as a base for EVPN-MH */
        if (zebra_evpn_send_to_client_ok(zevpn))
@@ -497,11 +488,15 @@ void zebra_evpn_update_all_es(struct zebra_evpn *zevpn)
                vxlan_zif = vxlan_if->info;
                if (if_is_operative(vxlan_if)
                    && vxlan_zif->brslave_info.br_if) {
-                       vlan_if = zvni_map_to_svi(
-                               vxlan_zif->l2info.vxl.access_vlan,
-                               vxlan_zif->brslave_info.br_if);
-                       if (vlan_if)
-                               zebra_evpn_acc_bd_svi_mac_add(vlan_if);
+                       vni = zebra_vxlan_if_vni_find(vxlan_zif, zevpn->vni);
+                       /* VLAN-VNI mappings may not exist */
+                       if (vni) {
+                               vlan_if = zvni_map_to_svi(
+                                       vni->access_vlan,
+                                       vxlan_zif->brslave_info.br_if);
+                               if (vlan_if)
+                                       zebra_evpn_acc_bd_svi_mac_add(vlan_if);
+                       }
                }
        }
 }
@@ -520,7 +515,7 @@ static unsigned int zebra_evpn_acc_vl_hash_keymake(const void *p)
 {
        const struct zebra_evpn_access_bd *acc_bd = p;
 
-       return jhash_1word(acc_bd->vid, 0);
+       return jhash_2words(acc_bd->vid, acc_bd->bridge_ifindex, 0);
 }
 
 /* Compare two VLAN based broadcast domains */
@@ -535,21 +530,31 @@ static bool zebra_evpn_acc_vl_cmp(const void *p1, const void *p2)
        if (acc_bd1 == NULL || acc_bd2 == NULL)
                return false;
 
-       return (acc_bd1->vid == acc_bd2->vid);
+       return ((acc_bd1->vid == acc_bd2->vid) &&
+               (acc_bd1->bridge_ifindex == acc_bd2->bridge_ifindex));
 }
 
 /* Lookup VLAN based broadcast domain */
-static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid)
+struct zebra_evpn_access_bd *
+zebra_evpn_acc_vl_find_index(vlanid_t vid, ifindex_t bridge_ifindex)
 {
        struct zebra_evpn_access_bd *acc_bd;
        struct zebra_evpn_access_bd tmp;
 
        tmp.vid = vid;
+       tmp.bridge_ifindex = bridge_ifindex;
        acc_bd = hash_lookup(zmh_info->evpn_vlan_table, &tmp);
 
        return acc_bd;
 }
 
+/* Lookup VLAN based broadcast domain */
+struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid,
+                                                   struct interface *br_if)
+{
+       return zebra_evpn_acc_vl_find_index(vid, br_if->ifindex);
+}
+
 /* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
  * mapping is added.
  */
@@ -560,11 +565,13 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
        struct interface *vlan_if;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d add", vid);
+               zlog_debug("access vlan %d bridge %s add", vid, br_if->name);
 
        acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd));
 
        acc_bd->vid = vid;
+       acc_bd->bridge_ifindex = br_if->ifindex;
+       acc_bd->bridge_zif = (struct zebra_if *)br_if->info;
 
        /* Initialize the mbr list */
        acc_bd->mbr_zifs = list_new();
@@ -573,14 +580,12 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
        (void)hash_get(zmh_info->evpn_vlan_table, acc_bd, hash_alloc_intern);
 
        /* check if an svi exists for the vlan */
-       if (br_if) {
-               vlan_if = zvni_map_to_svi(vid, br_if);
-               if (vlan_if) {
-                       if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-                               zlog_debug("vlan %d SVI %s set", vid,
-                                          vlan_if->name);
-                       acc_bd->vlan_zif = vlan_if->info;
-               }
+       vlan_if = zvni_map_to_svi(vid, br_if);
+       if (vlan_if) {
+               if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+                       zlog_debug("vlan %d bridge %s SVI %s set", vid,
+                                  br_if->name, vlan_if->name);
+               acc_bd->vlan_zif = vlan_if->info;
        }
        return acc_bd;
 }
@@ -621,16 +626,32 @@ static void zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd *acc_bd)
        if (!list_isempty(acc_bd->mbr_zifs) || acc_bd->vxlan_zif)
                return;
 
+       /* Remove this access_bd from bridge hash table */
+       zebra_l2_bridge_if_vlan_access_bd_deref(acc_bd);
+
        /* if there are no references free the EVI */
        zebra_evpn_acc_vl_free(acc_bd);
 }
 
+static struct zebra_evpn_access_bd *
+zebra_evpn_acc_bd_alloc_on_ref(vlanid_t vid, struct interface *br_if)
+{
+       struct zebra_evpn_access_bd *acc_bd = NULL;
+
+       assert(br_if && br_if->info);
+       acc_bd = zebra_evpn_acc_vl_new(vid, br_if);
+       if (acc_bd)
+               /* Add this access_bd to bridge hash table */
+               zebra_l2_bridge_if_vlan_access_bd_ref(acc_bd);
+
+       return acc_bd;
+}
+
 /* called when a SVI is goes up/down */
 void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
                               struct zebra_if *br_zif, bool is_up)
 {
        struct zebra_evpn_access_bd *acc_bd;
-       struct zebra_l2info_bridge *br;
        uint16_t vid;
        struct zebra_if *tmp_br_zif = br_zif;
 
@@ -641,20 +662,19 @@ void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
                tmp_br_zif = vlan_zif->link->info;
        }
 
-       br = &tmp_br_zif->l2info.br;
        /* ignore vlan unaware bridges */
-       if (!br->vlan_aware)
+       if (!IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(tmp_br_zif))
                return;
 
        vid = vlan_zif->l2info.vl.vid;
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       acc_bd = zebra_evpn_acc_vl_find(vid, tmp_br_zif->ifp);
        if (!acc_bd)
                return;
 
        if (is_up) {
                if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-                       zlog_debug("vlan %d SVI %s set", vid,
-                                  vlan_zif->ifp->name);
+                       zlog_debug("vlan %d bridge %s SVI %s set", vid,
+                                  tmp_br_zif->ifp->name, vlan_zif->ifp->name);
 
                acc_bd->vlan_zif = vlan_zif;
                if (acc_bd->zevpn)
@@ -662,7 +682,8 @@ void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
                                               acc_bd->zevpn);
        } else if (acc_bd->vlan_zif) {
                if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-                       zlog_debug("vlan %d SVI clear", vid);
+                       zlog_debug("vlan %d bridge %s SVI clear", vid,
+                                  tmp_br_zif->ifp->name);
                acc_bd->vlan_zif = NULL;
                if (acc_bd->zevpn && acc_bd->zevpn->mac_table)
                        zebra_evpn_mac_svi_del(vlan_zif->ifp, acc_bd->zevpn);
@@ -687,8 +708,9 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
        struct listnode *node;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d l2-vni %u set",
-                               acc_bd->vid, zevpn ? zevpn->vni : 0);
+               zlog_debug("access vlan %d bridge %s l2-vni %u set",
+                          acc_bd->vid, acc_bd->bridge_zif->ifp->name,
+                          zevpn ? zevpn->vni : 0);
 
        for (ALL_LIST_ELEMENTS_RO(acc_bd->mbr_zifs, node, zif)) {
                if (!zif->es_info.es)
@@ -711,33 +733,44 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
 }
 
 /* handle VLAN->VxLAN_IF association */
-void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)
+void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
+                          struct zebra_if *vxlan_zif)
 {
+       vni_t old_vni;
        struct zebra_evpn_access_bd *acc_bd;
-       struct zebra_if *old_vxlan_zif;
        struct zebra_evpn *old_zevpn;
+       struct interface *br_if;
 
        if (!vid)
                return;
 
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       if (!vni_id)
+               return;
+
+       br_if = vxlan_zif->brslave_info.br_if;
+
+       if (!br_if)
+               return;
+
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
        if (!acc_bd)
-               acc_bd = zebra_evpn_acc_vl_new(vid,
-                                              vxlan_zif->brslave_info.br_if);
+               acc_bd = zebra_evpn_acc_bd_alloc_on_ref(vid, br_if);
 
-       old_vxlan_zif = acc_bd->vxlan_zif;
-       acc_bd->vxlan_zif = vxlan_zif;
-       if (vxlan_zif == old_vxlan_zif)
+       old_vni = acc_bd->vni;
+
+       if (vni_id == old_vni)
                return;
 
+       acc_bd->vni = vni_id;
+       acc_bd->vxlan_zif = vxlan_zif;
+
        old_zevpn = acc_bd->zevpn;
-       acc_bd->zevpn = zebra_evpn_lookup(vxlan_zif->l2info.vxl.vni);
+       acc_bd->zevpn = zebra_evpn_lookup(vni_id);
        if (acc_bd->zevpn == old_zevpn)
                return;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d vni %u ref",
-                               acc_bd->vid, vxlan_zif->l2info.vxl.vni);
+               zlog_debug("access vlan %d vni %u ref", acc_bd->vid, vni_id);
 
        if (old_zevpn)
                zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
@@ -747,30 +780,66 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)
 }
 
 /* handle VLAN->VxLAN_IF deref */
-void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif)
+void zebra_evpn_vl_vxl_deref(uint16_t vid, vni_t vni_id,
+                            struct zebra_if *vxlan_zif)
 {
+       struct interface *br_if;
        struct zebra_evpn_access_bd *acc_bd;
 
        if (!vid)
                return;
 
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       if (!vni_id)
+               return;
+
+       br_if = vxlan_zif->brslave_info.br_if;
+       if (!br_if)
+               return;
+
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
        if (!acc_bd)
                return;
 
        /* clear vxlan_if only if it matches */
-       if (acc_bd->vxlan_zif != vxlan_zif)
+       if (acc_bd->vni != vni_id)
                return;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d vni %u deref",
-                               acc_bd->vid, vxlan_zif->l2info.vxl.vni);
+               zlog_debug("access vlan %d bridge %s vni %u deref", acc_bd->vid,
+                          br_if->name, vni_id);
 
        if (acc_bd->zevpn)
                zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, acc_bd->zevpn);
 
        acc_bd->zevpn = NULL;
        acc_bd->vxlan_zif = NULL;
+       acc_bd->vni = 0;
+
+       /* if there are no other references the access_bd can be freed */
+       zebra_evpn_acc_bd_free_on_deref(acc_bd);
+}
+
+/* handle BridgeIf<->AccessBD cleanup */
+void zebra_evpn_access_bd_bridge_cleanup(vlanid_t vid, struct interface *br_if,
+                                        struct zebra_evpn_access_bd *acc_bd)
+{
+       struct zebra_evpn *zevpn;
+
+       if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+               zlog_debug("access bd vlan %d bridge %s cleanup", acc_bd->vid,
+                          br_if->name);
+
+       zevpn = acc_bd->zevpn;
+       if (zevpn)
+               zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, zevpn);
+
+       /* cleanup resources maintained against the ES */
+       list_delete_all_node(acc_bd->mbr_zifs);
+
+       acc_bd->zevpn = NULL;
+       acc_bd->vxlan_zif = NULL;
+       acc_bd->vni = 0;
+       acc_bd->bridge_zif = NULL;
 
        /* if there are no other references the access_bd can be freed */
        zebra_evpn_acc_bd_free_on_deref(acc_bd);
@@ -780,15 +849,24 @@ void zebra_evpn_vl_vxl_deref(uint16_t vid, struct zebra_if *vxlan_zif)
 void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, struct zebra_evpn *zevpn,
                             bool set)
 {
-       struct zebra_l2info_vxlan *vxl;
+       struct zebra_vxlan_vni *vni;
        struct zebra_evpn_access_bd *acc_bd;
+       ifindex_t br_ifindex;
 
        if (!zif)
                return;
 
        /* locate access_bd associated with the vxlan device */
-       vxl = &zif->l2info.vxl;
-       acc_bd = zebra_evpn_acc_vl_find(vxl->access_vlan);
+       vni = zebra_vxlan_if_vni_find(zif, zevpn->vni);
+       if (!vni)
+               return;
+
+       /* Use the index as the pointer can be stale (deleted) */
+       br_ifindex = zif->brslave_info.bridge_ifindex;
+       if (!zif->brslave_info.br_if || br_ifindex == IFINDEX_INTERNAL)
+               return;
+
+       acc_bd = zebra_evpn_acc_vl_find_index(vni->access_vlan, br_ifindex);
        if (!acc_bd)
                return;
 
@@ -810,21 +888,26 @@ void zebra_evpn_vxl_evpn_set(struct zebra_if *zif, struct zebra_evpn *zevpn,
 /* handle addition of new VLAN members */
 void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
 {
+       struct interface *br_if;
        struct zebra_evpn_access_bd *acc_bd;
 
        if (!vid)
                return;
 
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       br_if = zif->brslave_info.br_if;
+       if (!br_if)
+               return;
+
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
        if (!acc_bd)
-               acc_bd = zebra_evpn_acc_vl_new(vid, zif->brslave_info.br_if);
+               acc_bd = zebra_evpn_acc_bd_alloc_on_ref(vid, br_if);
 
        if (listnode_lookup(acc_bd->mbr_zifs, zif))
                return;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d mbr %s ref",
-                               vid, zif->ifp->name);
+               zlog_debug("access vlan %d bridge %s mbr %s ref", vid,
+                          br_if->name, zif->ifp->name);
 
        listnode_add(acc_bd->mbr_zifs, zif);
        if (acc_bd->zevpn && zif->es_info.es)
@@ -834,13 +917,18 @@ void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
 /* handle deletion of VLAN members */
 void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
 {
+       struct interface *br_if;
        struct zebra_evpn_access_bd *acc_bd;
        struct listnode *node;
 
        if (!vid)
                return;
 
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       br_if = zif->brslave_info.br_if;
+       if (!br_if)
+               return;
+
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
        if (!acc_bd)
                return;
 
@@ -849,8 +937,8 @@ void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
                return;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d mbr %s deref",
-                               vid, zif->ifp->name);
+               zlog_debug("access vlan %d bridge %s mbr %s deref", vid,
+                          br_if->name, zif->ifp->name);
 
        list_delete_node(acc_bd->mbr_zifs, node);
 
@@ -917,14 +1005,19 @@ static void zebra_evpn_acc_vl_show_entry_detail(struct vty *vty,
        if (json) {
                zebra_evpn_acc_vl_json_fill(acc_bd, json, true);
        } else {
-               vty_out(vty, "VLAN: %u\n", acc_bd->vid);
+               vty_out(vty, "VLAN: %s.%u\n", acc_bd->bridge_zif->ifp->name,
+                       acc_bd->vid);
                vty_out(vty, " VxLAN Interface: %s\n",
                                acc_bd->vxlan_zif ?
                                acc_bd->vxlan_zif->ifp->name : "-");
                vty_out(vty, " SVI: %s\n",
                        acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-");
-               vty_out(vty, " L2-VNI: %d\n",
-                               acc_bd->zevpn ? acc_bd->zevpn->vni : 0);
+               if (acc_bd->zevpn)
+                       vty_out(vty, " L2-VNI: %d\n", acc_bd->zevpn->vni);
+               else {
+                       vty_out(vty, " L2-VNI: 0\n");
+                       vty_out(vty, " L3-VNI: %d\n", acc_bd->vni);
+               }
                vty_out(vty, " Member Count: %d\n",
                                listcount(acc_bd->mbr_zifs));
                vty_out(vty, " Members: \n");
@@ -940,7 +1033,8 @@ static void zebra_evpn_acc_vl_show_entry(struct vty *vty,
        if (json) {
                zebra_evpn_acc_vl_json_fill(acc_bd, json, false);
        } else {
-               vty_out(vty, "%-5u %-15s %-8d %-15s %u\n", acc_bd->vid,
+               vty_out(vty, "%-5s.%-5u %-15s %-8d %-15s %u\n",
+                       acc_bd->bridge_zif->ifp->name, acc_bd->vid,
                        acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-",
                        acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
                        acc_bd->vxlan_zif ? acc_bd->vxlan_zif->ifp->name : "-",
@@ -978,7 +1072,7 @@ void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
        wctx.detail = false;
 
        if (!uj)
-               vty_out(vty, "%-5s %-15s %-8s %-15s %s\n", "VLAN", "SVI",
+               vty_out(vty, "%-12s %-15s %-8s %-15s %s\n", "VLAN", "SVI",
                        "L2-VNI", "VXLAN-IF", "# Members");
 
        hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
@@ -1007,7 +1101,8 @@ void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj)
                vty_json(vty, json_array);
 }
 
-void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
+void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid,
+                               struct interface *br_if)
 {
        json_object *json = NULL;
        struct zebra_evpn_access_bd *acc_bd;
@@ -1015,12 +1110,13 @@ void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid)
        if (uj)
                json = json_object_new_object();
 
-       acc_bd = zebra_evpn_acc_vl_find(vid);
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
        if (acc_bd) {
                zebra_evpn_acc_vl_show_entry_detail(vty, acc_bd, json);
        } else {
                if (!json)
-                       vty_out(vty, "VLAN %u not present\n", vid);
+                       vty_out(vty, "VLAN %s.%u not present\n", br_if->name,
+                               vid);
        }
 
        if (uj)
@@ -1977,7 +2073,7 @@ static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es)
                return;
 
        bf_for_each_set_bit(zif->vlan_bitmap, vid, IF_VLAN_BITMAP_MAX) {
-               acc_bd = zebra_evpn_acc_vl_find(vid);
+               acc_bd = zebra_evpn_acc_vl_find(vid, zif->brslave_info.br_if);
                if (acc_bd->zevpn)
                        zebra_evpn_local_es_evi_add(es, acc_bd->zevpn);
        }
@@ -1986,9 +2082,10 @@ static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es)
 static void zebra_evpn_flush_local_mac(struct zebra_mac *mac,
                                       struct interface *ifp)
 {
+       vlanid_t vid;
        struct zebra_if *zif;
        struct interface *br_ifp;
-       vlanid_t vid;
+       struct zebra_vxlan_vni *vni;
 
        zif = ifp->info;
        br_ifp = zif->brslave_info.br_if;
@@ -1997,7 +2094,8 @@ static void zebra_evpn_flush_local_mac(struct zebra_mac *mac,
 
        if (mac->zevpn->vxlan_if) {
                zif = mac->zevpn->vxlan_if->info;
-               vid = zif->l2info.vxl.access_vlan;
+               vni = zebra_vxlan_if_vni_find(zif, mac->zevpn->vni);
+               vid = vni->access_vlan;
        } else {
                vid = 0;
        }
@@ -2111,11 +2209,11 @@ static void zebra_evpn_mh_advertise_svi_mac(void)
        zebra_evpn_acc_vl_adv_svi_mac_all();
 }
 
-static void zebra_evpn_es_df_delay_exp_cb(struct thread *t)
+static void zebra_evpn_es_df_delay_exp_cb(struct event *t)
 {
        struct zebra_evpn_es *es;
 
-       es = THREAD_ARG(t);
+       es = EVENT_ARG(t);
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
                zlog_debug("es %s df-delay expired", es->esi_str);
@@ -2179,9 +2277,9 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
 
        /* Start the DF delay timer on the local ES */
        if (!es->df_delay_timer)
-               thread_add_timer(zrouter.master, zebra_evpn_es_df_delay_exp_cb,
-                                es, ZEBRA_EVPN_MH_DF_DELAY_TIME,
-                                &es->df_delay_timer);
+               event_add_timer(zrouter.master, zebra_evpn_es_df_delay_exp_cb,
+                               es, ZEBRA_EVPN_MH_DF_DELAY_TIME,
+                               &es->df_delay_timer);
 
        /* See if the local VTEP can function as DF on the ES */
        if (!zebra_evpn_es_run_df_election(es, __func__)) {
@@ -2224,7 +2322,7 @@ static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp)
 
        es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
 
-       THREAD_OFF(es->df_delay_timer);
+       EVENT_OFF(es->df_delay_timer);
 
        /* clear EVPN protodown flags on the access port */
        zebra_evpn_mh_clear_protodown_es(es);
@@ -3049,7 +3147,7 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
        char alg_buf[EVPN_DF_ALG_STR_LEN];
        struct zebra_evpn_es_vtep *es_vtep;
        struct listnode *node;
-       char thread_buf[THREAD_TIMER_STRLEN];
+       char thread_buf[EVENT_TIMER_STRLEN];
 
        if (json) {
                json_object *json_vteps;
@@ -3067,6 +3165,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
                                json_array_string_add(json_flags, "local");
                        if (es->flags & ZEBRA_EVPNES_REMOTE)
                                json_array_string_add(json_flags, "remote");
+                       if (es->flags & ZEBRA_EVPNES_LOCAL &&
+                           !(es->flags & ZEBRA_EVPNES_NON_DF))
+                               json_array_string_add(json_flags, "df");
                        if (es->flags & ZEBRA_EVPNES_NON_DF)
                                json_array_string_add(json_flags, "nonDF");
                        if (es->flags & ZEBRA_EVPNES_BYPASS)
@@ -3091,9 +3192,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
                if (es->df_delay_timer)
                        json_object_string_add(
                                json, "dfDelayTimer",
-                               thread_timer_to_hhmmss(thread_buf,
-                                                      sizeof(thread_buf),
-                                                      es->df_delay_timer));
+                               event_timer_to_hhmmss(thread_buf,
+                                                     sizeof(thread_buf),
+                                                     es->df_delay_timer));
                json_object_int_add(json, "nexthopGroup", es->nhg_id);
                if (listcount(es->es_vtep_list)) {
                        json_vteps = json_object_new_array();
@@ -3136,9 +3237,9 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
                                                                  : "df");
                if (es->df_delay_timer)
                        vty_out(vty, " DF delay: %s\n",
-                               thread_timer_to_hhmmss(thread_buf,
-                                                      sizeof(thread_buf),
-                                                      es->df_delay_timer));
+                               event_timer_to_hhmmss(thread_buf,
+                                                     sizeof(thread_buf),
+                                                     es->df_delay_timer));
                vty_out(vty, " DF preference: %u\n", es->df_pref);
                vty_out(vty, " Nexthop group: %u\n", es->nhg_id);
                vty_out(vty, " VTEPs:\n");
@@ -3432,15 +3533,15 @@ DEFPY(zebra_evpn_mh_uplink, zebra_evpn_mh_uplink_cmd, "[no] evpn mh uplink",
 void zebra_evpn_mh_json(json_object *json)
 {
        json_object *json_array;
-       char thread_buf[THREAD_TIMER_STRLEN];
+       char thread_buf[EVENT_TIMER_STRLEN];
 
        json_object_int_add(json, "macHoldtime", zmh_info->mac_hold_time);
        json_object_int_add(json, "neighHoldtime", zmh_info->neigh_hold_time);
        json_object_int_add(json, "startupDelay", zmh_info->startup_delay_time);
        json_object_string_add(
                json, "startupDelayTimer",
-               thread_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
-                                      zmh_info->startup_delay_timer));
+               event_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
+                                     zmh_info->startup_delay_timer));
        json_object_int_add(json, "uplinkConfigCount",
                            zmh_info->uplink_cfg_cnt);
        json_object_int_add(json, "uplinkActiveCount",
@@ -3465,15 +3566,15 @@ void zebra_evpn_mh_json(json_object *json)
 void zebra_evpn_mh_print(struct vty *vty)
 {
        char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
-       char thread_buf[THREAD_TIMER_STRLEN];
+       char thread_buf[EVENT_TIMER_STRLEN];
 
        vty_out(vty, "EVPN MH:\n");
        vty_out(vty, "  mac-holdtime: %ds, neigh-holdtime: %ds\n",
                zmh_info->mac_hold_time, zmh_info->neigh_hold_time);
        vty_out(vty, "  startup-delay: %ds, start-delay-timer: %s\n",
                zmh_info->startup_delay_time,
-               thread_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
-                                      zmh_info->startup_delay_timer));
+               event_timer_to_hhmmss(thread_buf, sizeof(thread_buf),
+                                     zmh_info->startup_delay_timer));
        vty_out(vty, "  uplink-cfg-cnt: %u, uplink-active-cnt: %u\n",
                zmh_info->uplink_cfg_cnt, zmh_info->uplink_oper_up_cnt);
        if (zmh_info->protodown_rc)
@@ -3827,7 +3928,7 @@ void zebra_evpn_mh_uplink_oper_update(struct zebra_if *zif)
                                       new_protodown);
 }
 
-static void zebra_evpn_mh_startup_delay_exp_cb(struct thread *t)
+static void zebra_evpn_mh_startup_delay_exp_cb(struct event *t)
 {
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
                zlog_debug("startup-delay expired");
@@ -3841,7 +3942,7 @@ static void zebra_evpn_mh_startup_delay_timer_start(const char *rc)
        if (zmh_info->startup_delay_timer) {
                if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
                        zlog_debug("startup-delay timer cancelled");
-               THREAD_OFF(zmh_info->startup_delay_timer);
+               EVENT_OFF(zmh_info->startup_delay_timer);
        }
 
        if (zmh_info->startup_delay_time) {
@@ -3849,10 +3950,10 @@ static void zebra_evpn_mh_startup_delay_timer_start(const char *rc)
                        zlog_debug(
                                "startup-delay timer started for %d sec on %s",
                                zmh_info->startup_delay_time, rc);
-               thread_add_timer(zrouter.master,
-                                zebra_evpn_mh_startup_delay_exp_cb, NULL,
-                                zmh_info->startup_delay_time,
-                                &zmh_info->startup_delay_timer);
+               event_add_timer(zrouter.master,
+                               zebra_evpn_mh_startup_delay_exp_cb, NULL,
+                               zmh_info->startup_delay_time,
+                               &zmh_info->startup_delay_timer);
                zebra_evpn_mh_update_protodown(
                        ZEBRA_PROTODOWN_EVPN_STARTUP_DELAY, true /* set */);
        } else {