]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: bridge flap handle vlan membership update
authorChirag Shah <chirag@nvidia.com>
Fri, 22 Mar 2024 20:25:18 +0000 (13:25 -0700)
committerChirag Shah <chirag@nvidia.com>
Fri, 3 May 2024 17:52:33 +0000 (10:52 -0700)
Upon bridge flap, the associated SVD case,
VLAN membership is not updated correctly.
When SVI comes up, the VNI could not associate
with it as bridge VLAN membership was not updated.

Ticket: #3821632

Testing:

Before fix:
-----------
tor-1:#ifdown br_l3vni ; sleep 1 ; ifup br_l3vni
tor-1:# vtysh -c 'show evpn vni 8888'
VNI: 8888
  Type: L3
  Tenant VRF: sym_1
  Vlan: 490
  Bridge: br_l3vni
  Local Vtep Ip: 27.0.0.9
  Vxlan-Intf: vxlan99
  SVI-If: None    <<<<<< SVI not found
  State: Down     <<<<<< status remained in down BGP is not informed
  VNI Filter: none
  System MAC: None
  Router MAC: None
  L2 VNIs: 1800 1801 1900 1901

After fix:
----------

tor-1:# ifdown br_l3vni; sleep 1; ifup br_l3vni
tor-1:# vtysh

Hello, this is FRRouting (version 8.4.3).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

tor-1# show evpn vni 8888
VNI: 8888
  Type: L3
  Tenant VRF: sym_1
  Vlan: 490
  Bridge: br_l3vni
  Local Vtep Ip: 27.0.0.9
  Vxlan-Intf: vxlan99
  SVI-If: vlan490_l3 <<<<<<
  State: Up          <<<<<<
  VNI Filter: none
  System MAC: 44:38:39:ff:ff:29
  Router MAC: 44:38:39:ff:ff:29
  L2 VNIs: 1800 1801 1900 1901

Signed-off-by: Chirag Shah <chirag@nvidia.com>
zebra/zebra_evpn_mh.c
zebra/zebra_evpn_mh.h
zebra/zebra_l2.c
zebra/zebra_vxlan_if.c

index 0d9d912f83669d560c33bff150bf3c1e2e571295..5c19d226b16aa6cb3a1af2a5ba4ae21a1911b02a 100644 (file)
@@ -563,8 +563,9 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
        struct zebra_evpn_access_bd *acc_bd;
        struct interface *vlan_if;
 
-       if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
-               zlog_debug("access vlan %d bridge %s add", vid, br_if->name);
+       if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+               zlog_debug("%s access vlan %d bridge %s add", __func__, vid,
+                          br_if->name);
 
        acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd));
 
@@ -582,8 +583,8 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *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 bridge %s SVI %s set", vid,
-                                  br_if->name, vlan_if->name);
+                       zlog_debug("%s vlan %d bridge %s SVI %s set", __func__,
+                                  vid, br_if->name, vlan_if->name);
                acc_bd->vlan_zif = vlan_if->info;
        }
        return acc_bd;
@@ -731,6 +732,29 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
        }
 }
 
+/* Lookup API for  VxLAN_IF's Bridge, VLAN in EVPN cache */
+int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, struct zebra_if *vxlan_zif)
+{
+       struct interface *br_if;
+       struct zebra_evpn_access_bd *acc_bd;
+
+       if (!vid)
+               return -1;
+
+       br_if = vxlan_zif->brslave_info.br_if;
+
+       if (!br_if)
+               return -1;
+
+       acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
+
+       if (!acc_bd)
+               return 0;
+
+       return 1;
+}
+
+
 /* handle VLAN->VxLAN_IF association */
 void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
                           struct zebra_if *vxlan_zif)
@@ -768,8 +792,9 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t 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, vni_id);
+       if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+               zlog_debug("%s bridge %s access vlan %d vni %u ref", __func__,
+                          br_if->name, acc_bd->vid, vni_id);
 
        if (old_zevpn)
                zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
index 34ef79f1558e95b083f317ded0317eaffe4fa826..f68e2eae60054b8446eb3e1be328ff9d65744d66 100644 (file)
@@ -378,7 +378,8 @@ extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
 extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
 extern struct zebra_evpn_es_evi *
 zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
-
+extern int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid,
+                                          struct zebra_if *vxlan_zif);
 void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi);
 
 void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac);
index 0f591810b926280fdd53422a113965f1bd8a4df9..240f674b0f55da630ff0e561745092a6c3d3b123 100644 (file)
@@ -384,7 +384,7 @@ void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
                return;
 
        old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan;
-       ;
+
        if (old_access_vlan == access_vlan)
                return;
 
index 3cc7e499bf6b90c7d567b740ca43036396190953..f4b859b861f333aeaac3be5d3a05f38d802c818b 100644 (file)
@@ -506,7 +506,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
        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)",
+                       zlog_debug("%s vxlan %s adding vni(%d, %d)", __func__,
                                   zif->ifp->name, vni->vni, vni->access_vlan);
 
                zebra_vxlan_if_vni_entry_add(zif, &vni_tmp);
@@ -521,17 +521,39 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
 
        if (old_vni->access_vlan != vni->access_vlan) {
                if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug(
-                               "vxlan %s updating vni(%d, %d) -> vni(%d, %d)",
-                               zif->ifp->name, old_vni->vni,
-                               old_vni->access_vlan, vni->vni,
-                               vni->access_vlan);
+                       zlog_debug("%s vxlan %s updating vni(%d, %d) -> vni(%d, %d)",
+                                  __func__, zif->ifp->name, old_vni->vni,
+                                  old_vni->access_vlan, vni->vni,
+                                  vni->access_vlan);
 
                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, ctx);
                zebra_vxlan_vni_free(old_vni);
+       } else {
+               int ret;
+
+               ret = zebra_evpn_vl_vxl_bridge_lookup(vni->access_vlan, zif);
+               /* Here ret value 0 implied bridge vlan mapping is not present
+                * repopulated. Ignore ret value 1 as it means vlan mapping is
+                * present in bridge table.
+                */
+               if (ret < 0) {
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug("%s vxlan %s vni %u has error accessing bridge table.",
+                                          __func__, zif->ifp->name, vni->vni);
+               } else if (ret == 0) {
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug("%s vxlan %s vni (%u, %u) not present in bridge table",
+                                          __func__, zif->ifp->name, vni->vni,
+                                          vni->access_vlan);
+                       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, ctx);
+                       zebra_vxlan_vni_free(old_vni);
+               }
        }
 
        return 0;
@@ -768,6 +790,7 @@ vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif,
        return vni->vni;
 }
 
+/* SVD VLAN-VNI mapping update */
 int zebra_vxlan_if_vni_table_add_update(struct interface *ifp,
                                        struct hash *vni_table)
 {