}
if (IS_ZEBRA_IF_VXLAN(ifp))
- return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
- vid);
+ return zebra_vxlan_dp_network_mac_add(
+ ifp, br_if, &mac, vid, nhg_id, sticky,
+ !!(ndm->ndm_flags & NTF_EXT_LEARNED));
return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
sticky, local_inactive, dp_static);
}
if (IS_ZEBRA_IF_VXLAN(ifp))
- return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
- vid);
+ return zebra_vxlan_dp_network_mac_del(ifp, br_if, &mac, vid);
return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid);
}
uint32_t nhg_id;
struct in_addr vtep_ip;
- if (!(mac->flags & ZEBRA_MAC_REMOTE))
- return 0;
-
zif = zevpn->vxlan_if->info;
if (!zif)
return -1;
vlanid_t vid;
enum zebra_dplane_result res;
- if (!(mac->flags & ZEBRA_MAC_REMOTE))
- return 0;
-
/* If the MAC was not installed there is no need to uninstall it */
if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
return -1;
}
/* program sync mac flags in the dataplane */
-void zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
- bool force_clear_static, const char *caller)
+int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
+ bool force_clear_static, const char *caller)
{
- char macbuf[ETHER_ADDR_STRLEN];
struct interface *ifp;
bool sticky;
bool set_static;
if (!ifp) {
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
- "%s: dp-install sync-mac vni %u mac %s es %s 0x%x %sskipped, no access-port",
- caller, zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf,
- sizeof(macbuf)),
+ "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no access-port",
+ caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->flags,
set_inactive ? "inactive " : "");
- return;
+ return -1;
}
zif = ifp->info;
if (!br_ifp) {
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
- "%s: dp-install sync-mac vni %u mac %s es %s 0x%x %sskipped, no br",
- caller, zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf,
- sizeof(macbuf)),
+ "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no br",
+ caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->flags,
set_inactive ? "inactive " : "");
- return;
+ return -1;
}
sticky = !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY);
else
set_static = zebra_evpn_mac_is_static(mac);
+ /* We can install a local mac that has been synced from the peer
+ * over the VxLAN-overlay/network-port if fast failover is not
+ * supported and if the local ES is oper-down.
+ */
+ if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "dp-%s sync-nw-mac vni %u mac %pEA es %s 0x%x %s",
+ set_static ? "install" : "uninstall",
+ zevpn->vni, &mac->macaddr,
+ mac->es ? mac->es->esi_str : "-", mac->flags,
+ set_inactive ? "inactive " : "");
+ if (set_static)
+ /* XXX - old_static needs to be computed more
+ * accurately
+ */
+ zebra_evpn_rem_mac_install(zevpn, mac,
+ true /* old_static */);
+ else
+ zebra_evpn_rem_mac_uninstall(zevpn, mac,
+ false /* force */);
+
+ return 0;
+ }
+
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
- "dp-install sync-mac vni %u mac %s es %s 0x%x %s%s",
- zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
+ "dp-install sync-mac vni %u mac %pEA es %s 0x%x %s%s",
+ zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->flags,
set_static ? "static " : "",
set_inactive ? "inactive " : "");
dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
set_static, set_inactive);
+ return 0;
}
void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
zebra_mac_t *mac;
};
-/**************************** SYNC MAC handling *****************************/
/**************************** SYNC MAC handling *****************************/
/* if the mac has been added of a mac-route from the peer
* or if it is being referenced by a neigh added by the
void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json);
void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt);
void zebra_evpn_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt);
-void zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
- bool force_clear_static,
- const char *caller);
+int zebra_evpn_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
+ bool force_clear_static, const char *caller);
void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
bool new_bgp_ready);
* A L2 NH entry is programmed in the kernel for every ES-VTEP entry. This
* NH is then added to the L2-ECMP-NHG associated with the ES.
*/
-static uint32_t zebra_evpn_nhid_alloc(bool is_nhg)
+static uint32_t zebra_evpn_nhid_alloc(struct zebra_evpn_es *es)
{
uint32_t id;
- int type;
+ uint32_t nh_id;
bf_assign_index(zmh_info->nh_id_bitmap, id);
if (!id)
return 0;
- type = is_nhg ? EVPN_NHG_ID_TYPE_BIT : EVPN_NH_ID_TYPE_BIT;
- return (id | type);
+ if (es) {
+ nh_id = id | EVPN_NHG_ID_TYPE_BIT;
+ /* Add to NHG hash */
+ es->nhg_id = nh_id;
+ if (!hash_get(zmh_info->nhg_table, es, hash_alloc_intern)) {
+ bf_release_index(zmh_info->nh_id_bitmap, id);
+ return 0;
+ }
+ } else {
+ nh_id = id | EVPN_NH_ID_TYPE_BIT;
+ }
+
+ return nh_id;
}
-static void zebra_evpn_nhid_free(uint32_t nh_id)
+static void zebra_evpn_nhid_free(uint32_t nh_id, struct zebra_evpn_es *es)
{
uint32_t id = (nh_id & EVPN_NH_ID_VAL_MASK);
if (!id)
return;
+ if (es) {
+ hash_release(zmh_info->nhg_table, es);
+ es->nhg_id = 0;
+ }
+
bf_release_index(zmh_info->nh_id_bitmap, id);
}
+static unsigned int zebra_evpn_nhg_hash_keymake(const void *p)
+{
+ const struct zebra_evpn_es *es = p;
+
+ return jhash_1word(es->nhg_id, 0);
+}
+
+static bool zebra_evpn_nhg_cmp(const void *p1, const void *p2)
+{
+ const struct zebra_evpn_es *es1 = p1;
+ const struct zebra_evpn_es *es2 = p2;
+
+ if (es1 == NULL && es2 == NULL)
+ return true;
+
+ if (es1 == NULL || es2 == NULL)
+ return false;
+
+ return (es1->nhg_id == es2->nhg_id);
+}
+
+/* Lookup ES using the NHG id associated with it */
+static struct zebra_evpn_es *zebra_evpn_nhg_find(uint32_t nhg_id)
+{
+ struct zebra_evpn_es *es;
+ struct zebra_evpn_es tmp;
+
+ tmp.nhg_id = nhg_id;
+ es = hash_lookup(zmh_info->nhg_table, &tmp);
+
+ return es;
+}
+
+/* Returns TRUE if the NHG is associated with a local ES */
+bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
+ struct zebra_evpn_es **local_es)
+{
+ struct zebra_evpn_es *es;
+
+ es = zebra_evpn_nhg_find(nhg_id);
+ if (es && (es->flags & ZEBRA_EVPNES_LOCAL)) {
+ *local_es = es;
+ return true;
+ }
+
+ *local_es = NULL;
+ return false;
+}
+
/* update remote macs associated with the ES */
static void zebra_evpn_nhg_mac_update(struct zebra_evpn_es *es)
{
zebra_mac_t *mac;
struct listnode *node;
+ bool local_via_nw;
- for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
- if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
- continue;
+ local_via_nw = zebra_evpn_es_local_mac_via_network_port(es);
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("mac update on es %s nhg %s", es->esi_str,
+ (es->flags & ZEBRA_EVPNES_NHG_ACTIVE)
+ ? "activate"
+ : "de-activate");
- if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE)
- zebra_evpn_rem_mac_install(mac->zevpn, mac,
- false /*was_static*/);
- else
- zebra_evpn_rem_mac_uninstall(mac->zevpn, mac,
- true /*force*/);
+ for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
+ || (local_via_nw && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
+ && zebra_evpn_mac_is_static(mac))) {
+ if (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "%smac %pEA install via es %s nhg 0x%x",
+ (mac->flags & ZEBRA_MAC_REMOTE)
+ ? "rem"
+ : "local-nw",
+ &mac->macaddr, es->esi_str,
+ es->nhg_id);
+ zebra_evpn_rem_mac_install(
+ mac->zevpn, mac, false /*was_static*/);
+ } else {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "%smac %pEA un-install es %s",
+ (mac->flags & ZEBRA_MAC_REMOTE)
+ ? "rem"
+ : "local-nw",
+ &mac->macaddr, es->esi_str);
+ zebra_evpn_rem_mac_uninstall(mac->zevpn, mac,
+ true /*force*/);
+ }
+ }
}
}
if (es_vtep->nh_id)
return;
- es_vtep->nh_id = zebra_evpn_nhid_alloc(false);
+ es_vtep->nh_id = zebra_evpn_nhid_alloc(NULL /*NHG-es*/);
if (!es_vtep->nh_id)
return;
zebra_evpn_nhg_update(es_vtep->es);
/* uninstall the NH */
kernel_del_mac_nh(nh_id);
- zebra_evpn_nhid_free(nh_id);
-
+ zebra_evpn_nhid_free(nh_id, NULL /*NHG-es*/);
}
/*****************************************************************************/
listset_app_node_mem(es->mac_list);
/* reserve a NHG */
- es->nhg_id = zebra_evpn_nhid_alloc(true);
+ es->nhg_id = zebra_evpn_nhid_alloc(es);
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("es %s nhg %u new", es->esi_str, es->nhg_id);
es->flags &= ~ZEBRA_EVPNES_NHG_ACTIVE;
kernel_del_mac_nhg(es->nhg_id);
}
- zebra_evpn_nhid_free(es->nhg_id);
+ zebra_evpn_nhid_free(es->nhg_id, es);
/* cleanup resources maintained against the ES */
list_delete(&es->es_evi_list);
es->flags &= ~ZEBRA_EVPNES_OPER_UP;
zebra_evpn_es_run_df_election(es, __func__);
+ zebra_evpn_local_mac_oper_state_change(es);
/* inform BGP of the ES oper state change */
if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
if (zmh_info->startup_delay_time != ZEBRA_EVPN_MH_STARTUP_DELAY_DEF)
vty_out(vty, "evpn mh startup-delay %d\n",
zmh_info->startup_delay_time);
+
+ if (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF)
+ vty_out(vty, "evpn mh redirect-off\n");
}
int zebra_evpn_mh_neigh_holdtime_update(struct vty *vty,
return 0;
}
+int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off)
+{
+ /* This knob needs to be set before ESs are configured
+ * i.e. cannot be changed on the fly
+ */
+ if (redirect_off)
+ zmh_info->flags |= ZEBRA_EVPN_MH_REDIRECT_OFF;
+ else
+ zmh_info->flags &= ~ZEBRA_EVPN_MH_REDIRECT_OFF;
+
+ return 0;
+}
+
void zebra_evpn_interface_init(void)
{
install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
bf_init(zmh_info->nh_id_bitmap, EVPN_NH_ID_MAX);
bf_assign_zero_index(zmh_info->nh_id_bitmap);
+ zmh_info->nhg_table = hash_create(zebra_evpn_nhg_hash_keymake,
+ zebra_evpn_nhg_cmp, "l2 NHG table");
/* setup broadcast domain tables */
zmh_info->evpn_vlan_table = hash_create(zebra_evpn_acc_vl_hash_keymake,
#define zmh_info (zrouter.mh_info)
struct zebra_evpn_mh_info {
uint32_t flags;
+/* If the dataplane is not capable of handling a backup NHG on an access
+ * port we will need to explicitly failover each MAC entry on
+ * local ES down
+ */
+#define ZEBRA_EVPN_MH_REDIRECT_OFF (1 << 0)
/* DAD support for EVPN-MH is yet to be added. So on detection of
* first local ES, DAD is turned off
*/
*/
#define EVPN_NH_ID_TYPE_BIT (1 << EVPN_NH_ID_TYPE_POS)
#define EVPN_NHG_ID_TYPE_BIT (2 << EVPN_NH_ID_TYPE_POS)
+ /* L2-NHG table - key: nhg_id, data: zebra_evpn_es */
+ struct hash *nhg_table;
/* XXX - re-visit the default hold timer value */
int mac_hold_time;
(id & EVPN_NH_ID_TYPE_BIT));
}
+static inline bool
+zebra_evpn_es_local_mac_via_network_port(struct zebra_evpn_es *es)
+{
+ return !(es->flags & ZEBRA_EVPNES_OPER_UP)
+ && (zmh_info->flags & ZEBRA_EVPN_MH_REDIRECT_OFF);
+}
+
static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
{
return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
}
-
/*****************************************************************************/
extern esi_t *zero_esi;
extern void zebra_evpn_mh_init(void);
extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
extern void zebra_evpn_mh_print(struct vty *vty);
extern void zebra_evpn_mh_json(json_object *json);
+extern bool zebra_evpn_nhg_is_local_es(uint32_t nhg_id,
+ struct zebra_evpn_es **local_es);
+extern int zebra_evpn_mh_redirect_off(struct vty *vty, bool redirect_off);
#endif /* _ZEBRA_EVPN_MH_H */
no ? true : false);
}
+DEFPY(evpn_mh_redirect_off, evpn_mh_redirect_off_cmd,
+ "[no$no] evpn mh redirect-off",
+ NO_STR
+ "EVPN\n"
+ "Multihoming\n"
+ "ES bond redirect for fast-failover off\n")
+{
+ bool redirect_off;
+
+ redirect_off = no ? false : true;
+
+ return zebra_evpn_mh_redirect_off(vty, redirect_off);
+}
+
DEFUN (default_vrf_vni_mapping,
default_vrf_vni_mapping_cmd,
"vni " CMD_VNI_RANGE "[prefix-routes-only]",
install_element(CONFIG_NODE, &evpn_mh_mac_holdtime_cmd);
install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd);
install_element(CONFIG_NODE, &evpn_mh_startup_delay_cmd);
+ install_element(CONFIG_NODE, &evpn_mh_redirect_off_cmd);
install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
install_element(VRF_NODE, &vrf_vni_mapping_cmd);
* us, this must involve a multihoming scenario. Treat this as implicit delete
* of any prior local MAC.
*/
-int zebra_vxlan_check_del_local_mac(struct interface *ifp,
- struct interface *br_if,
- struct ethaddr *macaddr, vlanid_t vid)
+static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
+ struct interface *br_if,
+ struct ethaddr *macaddr,
+ vlanid_t vid)
{
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
return 0;
}
+/* MAC notification from the dataplane with a network dest port -
+ * 1. This can be a local MAC on a down ES (if fast-failover is not possible
+ * 2. Or it can be a remote MAC
+ */
+int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
+ struct interface *br_if,
+ struct ethaddr *macaddr, vlanid_t vid,
+ uint32_t nhg_id, bool sticky, bool dp_static)
+{
+ struct zebra_evpn_es *es;
+ struct interface *acc_ifp;
+
+ /* if remote mac delete the local entry */
+ if (!nhg_id || !zebra_evpn_nhg_is_local_es(nhg_id, &es)
+ || !zebra_evpn_es_local_mac_via_network_port(es)) {
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr,
+ vid);
+ return zebra_vxlan_check_del_local_mac(ifp, br_if, macaddr,
+ vid);
+ }
+
+ /* If local MAC on a down local ES translate the network-mac-add
+ * to a local-inactive-mac-add
+ */
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr, vid);
+ acc_ifp = es->zif->ifp;
+ return zebra_vxlan_local_mac_add_update(
+ acc_ifp, br_if, macaddr, vid, sticky,
+ false /* local_inactive */, dp_static);
+}
+
/*
- * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
- * This can happen because the remote MAC entries are also added as "dynamic",
- * so the kernel can ageout the entry.
+ * Handle network MAC delete by kernel -
+ * 1. readd the remote MAC if we have it
+ * 2. local MAC with does ES may also need to be re-installed
*/
-int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
- struct interface *br_if,
- struct ethaddr *macaddr, vlanid_t vid)
+static int zebra_vxlan_do_local_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac);
+int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
+ struct interface *br_if,
+ struct ethaddr *macaddr, vlanid_t vid)
{
struct zebra_if *zif = NULL;
struct zebra_l2info_vxlan *vxl = NULL;
zebra_evpn_t *zevpn = NULL;
zebra_l3vni_t *zl3vni = NULL;
zebra_mac_t *mac = NULL;
- char buf[ETHER_ADDR_STRLEN];
zif = ifp->info;
assert(zif);
if (!mac)
return 0;
- /* Is it a remote entry? */
- if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
- return 0;
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
+ /* If remote entry simply re-install */
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
+ macaddr, ifp->name, ifp->ifindex, vni);
+ zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
+ } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && mac->es
+ && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
+ /* If local entry via nw-port call local-del which will
+ * re-install entry in the dataplane is needed
+ */
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr,
+ vni);
+ zebra_vxlan_do_local_mac_del(zevpn, mac);
+ }
+
+ return 0;
+}
+
+static int zebra_vxlan_do_local_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac)
+{
+ bool old_bgp_ready;
+ bool new_bgp_ready;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
- prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
- ifp->ifindex, vni);
+ zlog_debug("DEL MAC %pEA VNI %u seq %u flags 0x%x nbr count %u",
+ &mac->macaddr, zevpn->vni, mac->loc_seq, mac->flags,
+ listcount(mac->neigh_list));
+
+ old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ if (zebra_evpn_mac_is_static(mac)) {
+ /* this is a synced entry and can only be removed when the
+ * es-peers stop advertising it.
+ */
+ memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "re-add sync-mac vni %u mac %pEA es %s seq %d f 0x%x",
+ zevpn->vni, &mac->macaddr,
+ mac->es ? mac->es->esi_str : "-", mac->loc_seq,
+ mac->flags);
+
+ /* inform-bgp about change in local-activity if any */
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
+ SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
+ new_bgp_ready =
+ zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ zebra_evpn_mac_send_add_del_to_client(
+ mac, old_bgp_ready, new_bgp_ready);
+ }
+
+ /* re-install the entry in the kernel */
+ zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
+ false /* force_clear_static */,
+ __func__);
+
+ return 0;
+ }
+
+ /* Update all the neigh entries associated with this mac */
+ zebra_evpn_process_neigh_on_local_mac_del(zevpn, mac);
+
+ /* Remove MAC from BGP. */
+ zebra_evpn_mac_send_del_to_client(zevpn->vni, &mac->macaddr, mac->flags,
+ false /* force */);
+
+ zebra_evpn_es_mac_deref_entry(mac);
+
+ /*
+ * If there are no neigh associated with the mac delete the mac
+ * else mark it as AUTO for forward reference
+ */
+ if (!listcount(mac->neigh_list)) {
+ zebra_evpn_mac_del(zevpn, mac);
+ } else {
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ }
- zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
return 0;
}
struct ethaddr *macaddr, vlanid_t vid)
{
zebra_evpn_t *zevpn;
+ zebra_mac_t *mac;
/* We are interested in MACs only on ports or (port, VLAN) that
* map to a VNI.
return -1;
}
- return zebra_evpn_del_local_mac(zevpn, macaddr, ifp);
+ /* If entry doesn't exist, nothing to do. */
+ mac = zebra_evpn_mac_lookup(zevpn, macaddr);
+ if (!mac)
+ return 0;
+
+ /* Is it a local entry? */
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ return 0;
+
+ return zebra_vxlan_do_local_mac_del(zevpn, mac);
}
/*
extern int zebra_vxlan_local_mac_del(struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
-extern int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
- struct interface *br_if,
- struct ethaddr *mac,
- vlanid_t vid);
-extern int zebra_vxlan_check_del_local_mac(struct interface *ifp,
- struct interface *br_if,
- struct ethaddr *mac, vlanid_t vid);
extern int zebra_vxlan_check_readd_vtep(struct interface *ifp,
struct in_addr vtep_ip);
extern int zebra_vxlan_if_up(struct interface *ifp);
extern void zebra_vxlan_macvlan_up(struct interface *ifp);
extern void zebra_vxlan_macvlan_down(struct interface *ifp);
extern int vni_list_cmp(void *p1, void *p2);
+extern int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
+ struct interface *br_if,
+ struct ethaddr *macaddr, vlanid_t vid,
+ uint32_t nhg_id, bool sticky,
+ bool dp_static);
+extern int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
+ struct interface *br_if,
+ struct ethaddr *macaddr,
+ vlanid_t vid);
#ifdef __cplusplus
}