summaryrefslogtreecommitdiff
path: root/zebra/zebra_evpn_mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_evpn_mac.c')
-rw-r--r--zebra/zebra_evpn_mac.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index e38766bc6b..46d789bc34 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -1141,14 +1141,6 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
sizeof(mac_buf)));
}
- /* If the MAC is freed before the neigh we will end up
- * with a stale pointer against the neigh
- */
- if (!list_isempty(mac->neigh_list))
- zlog_warn("%s: MAC %pEA flags 0x%x neigh list not empty %d",
- __func__, &mac->macaddr, mac->flags,
- listcount(mac->neigh_list));
-
/* force de-ref any ES entry linked to the MAC */
zebra_evpn_es_mac_deref_entry(mac);
@@ -1161,6 +1153,26 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
/* Cancel auto recovery */
THREAD_OFF(mac->dad_mac_auto_recovery_timer);
+ /* If the MAC is freed before the neigh we will end up
+ * with a stale pointer against the neigh.
+ * The situation can arise when a MAC is in remote state
+ * and its associated neigh is local state.
+ * zebra_evpn_cfg_cleanup() cleans up remote neighs and MACs.
+ * Instead of deleting remote MAC, if its neigh list is non-empty
+ * (associated to local neighs), mark the MAC as AUTO.
+ */
+ if (!list_isempty(mac->neigh_list)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "MAC %pEA (flags 0x%x vni %u) has non-empty neigh list "
+ "count %u, mark MAC as AUTO",
+ &mac->macaddr, mac->flags, zevpn->vni,
+ listcount(mac->neigh_list));
+
+ SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ return 0;
+ }
+
list_delete(&mac->neigh_list);
/* Free the VNI hash entry and allocated memory. */
@@ -2452,11 +2464,12 @@ int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
return 0;
}
-int zebra_evpn_mac_gw_macip_add(struct interface *ifp, struct zebra_evpn *zevpn,
- const struct ipaddr *ip,
- struct zebra_mac **macp,
- const struct ethaddr *macaddr, vlanid_t vlan_id,
- bool def_gw)
+void zebra_evpn_mac_gw_macip_add(struct interface *ifp,
+ struct zebra_evpn *zevpn,
+ const struct ipaddr *ip,
+ struct zebra_mac **macp,
+ const struct ethaddr *macaddr,
+ vlanid_t vlan_id, bool def_gw)
{
struct zebra_mac *mac;
ns_id_t local_ns_id = NS_DEFAULT;
@@ -2466,9 +2479,13 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, struct zebra_evpn *zevpn,
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
- mac = zebra_evpn_mac_lookup(zevpn, macaddr);
- if (!mac)
- mac = zebra_evpn_mac_add(zevpn, macaddr);
+ if (!*macp) {
+ mac = zebra_evpn_mac_lookup(zevpn, macaddr);
+ if (!mac)
+ mac = zebra_evpn_mac_add(zevpn, macaddr);
+ *macp = mac;
+ } else
+ mac = *macp;
/* Set "local" forwarding info. */
zebra_evpn_mac_clear_fwd_info(mac);
@@ -2476,13 +2493,11 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, struct zebra_evpn *zevpn,
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
if (def_gw)
SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
+ else
+ SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vlan_id;
-
- *macp = mac;
-
- return 0;
}
void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
@@ -2535,10 +2550,7 @@ void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
? true
: false;
- mac = NULL;
zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
- if (mac)
- SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,