zebra_evpn_mac_del(zevpn, mac);
}
-void zebra_evpn_mac_get_access_info(zebra_mac_t *mac, struct interface **ifpP,
- vlanid_t *vid)
+static void zebra_evpn_mac_get_access_info(zebra_mac_t *mac,
+ struct interface **ifpP,
+ vlanid_t *vid)
{
/* if the mac is associated with an ES we must get the access
* info from the ES
return 0;
}
-void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
- zebra_mac_t *mac,
- struct in_addr vtep_ip, bool do_dad,
- bool *is_dup_detect, bool is_local)
+static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
+ zebra_mac_t *mac,
+ struct in_addr vtep_ip,
+ bool do_dad, bool *is_dup_detect,
+ bool is_local)
{
zebra_neigh_t *nbr;
struct listnode *node = NULL;
/* update local fowarding info. return true if a dest-ES change
* is detected
*/
-bool zebra_evpn_local_mac_update_fwd_info(zebra_mac_t *mac,
- struct interface *ifp, vlanid_t vid)
+static bool zebra_evpn_local_mac_update_fwd_info(zebra_mac_t *mac,
+ struct interface *ifp,
+ vlanid_t vid)
{
struct zebra_if *zif = ifp->info;
bool es_change;
*macp = mac;
return 0;
}
+
+int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
+ struct interface *ifp,
+ struct ethaddr *macaddr, vlanid_t vid,
+ bool sticky, bool local_inactive,
+ bool dp_static)
+{
+ zebra_mac_t *mac;
+ char buf[ETHER_ADDR_STRLEN];
+ bool mac_sticky = false;
+ bool inform_client = false;
+ bool upd_neigh = false;
+ bool is_dup_detect = false;
+ struct in_addr vtep_ip = {.s_addr = 0};
+ bool es_change = false;
+ bool new_bgp_ready;
+ /* assume inactive if not present or if not local */
+ bool old_local_inactive = true;
+ bool old_bgp_ready = false;
+ bool inform_dataplane = false;
+ bool new_static = false;
+
+ /* Check if we need to create or update or it is a NO-OP. */
+ mac = zebra_evpn_mac_lookup(zevpn, macaddr);
+ if (!mac) {
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u%s",
+ sticky ? "sticky " : "",
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ifp->name, ifp->ifindex, vid, zevpn->vni,
+ local_inactive ? " local-inactive" : "");
+
+ mac = zebra_evpn_mac_add(zevpn, macaddr);
+ if (!mac) {
+ flog_err(
+ EC_ZEBRA_MAC_ADD_FAILED,
+ "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ifp->name, ifp->ifindex, vid, zevpn->vni);
+ return -1;
+ }
+ SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+ es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
+ if (sticky)
+ SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ inform_client = true;
+ } else {
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags 0x%x",
+ sticky ? "sticky " : "",
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ifp->name, ifp->ifindex, vid, zevpn->vni,
+ local_inactive ? "local-inactive " : "",
+ mac->flags);
+
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
+ struct interface *old_ifp;
+ vlanid_t old_vid;
+ bool old_static;
+
+ zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
+ old_bgp_ready =
+ zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ old_local_inactive =
+ !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
+ old_static = zebra_evpn_mac_is_static(mac);
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
+ mac_sticky = true;
+
+ /*
+ * Update any changes and if changes are relevant to
+ * BGP, note it.
+ */
+ if (mac_sticky == sticky && old_ifp == ifp
+ && old_vid == vid
+ && old_local_inactive == local_inactive
+ && dp_static == old_static) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u%s, "
+ "entry exists and has not changed ",
+ sticky ? "sticky " : "",
+ prefix_mac2str(macaddr, buf,
+ sizeof(buf)),
+ ifp->name, ifp->ifindex, vid,
+ zevpn->vni,
+ local_inactive
+ ? " local_inactive"
+ : "");
+ return 0;
+ }
+ if (mac_sticky != sticky) {
+ if (sticky)
+ SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ else
+ UNSET_FLAG(mac->flags,
+ ZEBRA_MAC_STICKY);
+ inform_client = true;
+ }
+
+ es_change = zebra_evpn_local_mac_update_fwd_info(
+ mac, ifp, vid);
+ /* If an es_change is detected we need to advertise
+ * the route with a sequence that is one
+ * greater. This is need to indicate a mac-move
+ * to the ES peers
+ */
+ if (es_change) {
+ mac->loc_seq = mac->loc_seq + 1;
+ /* force drop the peer/sync info as it is
+ * simply no longer relevant
+ */
+ if (CHECK_FLAG(mac->flags,
+ ZEBRA_MAC_ALL_PEER_FLAGS)) {
+ zebra_evpn_mac_clear_sync_info(mac);
+ new_static =
+ zebra_evpn_mac_is_static(mac);
+ /* if we clear peer-flags we
+ * also need to notify the dataplane
+ * to drop the static flag
+ */
+ if (old_static != new_static)
+ inform_dataplane = true;
+ }
+ }
+ } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
+ || CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
+ bool do_dad = false;
+
+ /*
+ * MAC has either moved or was "internally" created due
+ * to a neighbor learn and is now actually learnt. If
+ * it was learnt as a remote sticky MAC, this is an
+ * operator error.
+ */
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
+ flog_warn(
+ EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
+ "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
+ prefix_mac2str(macaddr, buf,
+ sizeof(buf)),
+ inet_ntoa(mac->fwd_info.r_vtep_ip),
+ zevpn->vni);
+ return 0;
+ }
+
+ /* If an actual move, compute MAC's seq number */
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
+ mac->loc_seq =
+ MAX(mac->rem_seq + 1, mac->loc_seq);
+ vtep_ip = mac->fwd_info.r_vtep_ip;
+ /* Trigger DAD for remote MAC */
+ do_dad = true;
+ }
+
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+ es_change = zebra_evpn_local_mac_update_fwd_info(
+ mac, ifp, vid);
+ if (sticky)
+ SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ else
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ /*
+ * We have to inform BGP of this MAC as well as process
+ * all neighbors.
+ */
+ inform_client = true;
+ upd_neigh = true;
+
+ zebra_evpn_dup_addr_detect_for_mac(
+ zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
+ true);
+ if (is_dup_detect) {
+ inform_client = false;
+ upd_neigh = false;
+ }
+ }
+ }
+
+ /* if the dataplane thinks the entry is sync but it is
+ * not sync in zebra we need to re-install to fixup
+ */
+ if (dp_static) {
+ new_static = zebra_evpn_mac_is_static(mac);
+ if (!new_static)
+ inform_dataplane = true;
+ }
+
+ if (local_inactive)
+ SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
+ else
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
+
+ new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ /* if local-activity has changed we need update bgp
+ * even if bgp already knows about the mac
+ */
+ if ((old_local_inactive != local_inactive)
+ || (new_bgp_ready != old_bgp_ready)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug(
+ "local mac vni %u mac %s es %s seq %d f 0x%x%s",
+ zevpn->vni,
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ mac->es ? mac->es->esi_str : "", mac->loc_seq,
+ mac->flags,
+ local_inactive ? " local-inactive" : "");
+ inform_client = true;
+ }
+
+ if (es_change) {
+ inform_client = true;
+ upd_neigh = true;
+ }
+
+ /* Inform dataplane if required. */
+ if (inform_dataplane)
+ zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
+ false /* force_clear_static */,
+ __func__);
+
+ /* Inform BGP if required. */
+ if (inform_client)
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
+ new_bgp_ready);
+
+ /* Process all neighbors associated with this MAC, if required. */
+ if (upd_neigh)
+ zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
+ es_change);
+
+ return 0;
+}
int zebra_evpn_rem_mac_install(zebra_evpn_t *zevi, zebra_mac_t *mac,
bool was_static);
void zebra_evpn_deref_ip2mac(zebra_evpn_t *zevi, zebra_mac_t *mac);
-void zebra_evpn_mac_get_access_info(zebra_mac_t *mac, struct interface **ifpP,
- vlanid_t *vid);
zebra_mac_t *zebra_evpn_mac_lookup(zebra_evpn_t *zevi, struct ethaddr *mac);
zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevi, struct ethaddr *macaddr);
int zebra_evpn_mac_del(zebra_evpn_t *zevi, zebra_mac_t *mac);
struct ipaddr *ip, uint8_t flags,
uint32_t seq, int state,
struct zebra_evpn_es *es, uint16_t cmd);
-void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
- bool new_bgp_ready);
-void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
- zebra_mac_t *mac,
- struct in_addr vtep_ip, bool do_dad,
- bool *is_dup_detect, bool is_local);
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);
+void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
+ bool new_bgp_ready);
void zebra_evpn_mac_del_all(zebra_evpn_t *zevi, int uninstall, int upd_client,
uint32_t flags);
struct in_addr vtep_ip, uint8_t flags,
uint32_t seq, esi_t *esi);
-// remove later
-void zebra_evpn_mac_send_add_del_to_client(zebra_mac_t *mac, bool old_bgp_ready,
- bool new_bgp_ready);
-bool zebra_evpn_local_mac_update_fwd_info(zebra_mac_t *mac,
- struct interface *ifp, vlanid_t vid);
-
+int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
+ struct interface *ifp,
+ struct ethaddr *macaddr, vlanid_t vid,
+ bool sticky, bool local_inactive,
+ bool dp_static);
#ifdef __cplusplus
}
#endif
bool dp_static)
{
zebra_evpn_t *zevpn;
- zebra_mac_t *mac;
struct zebra_vrf *zvrf;
char buf[ETHER_ADDR_STRLEN];
- bool mac_sticky = false;
- bool inform_client = false;
- bool upd_neigh = false;
- bool is_dup_detect = false;
- struct in_addr vtep_ip = {.s_addr = 0};
- bool es_change = false;
- bool new_bgp_ready;
- /* assume inactive if not present or if not local */
- bool old_local_inactive = true;
- bool old_bgp_ready = false;
- bool inform_dataplane = false;
- bool new_static = false;
if (ifp == NULL)
return -1;
return -1;
}
- /* Check if we need to create or update or it is a NO-OP. */
- mac = zebra_evpn_mac_lookup(zevpn, macaddr);
- if (!mac) {
- if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
- zlog_debug(
- "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u%s",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, vid, zevpn->vni,
- local_inactive ? " local-inactive" : "");
-
- mac = zebra_evpn_mac_add(zevpn, macaddr);
- if (!mac) {
- flog_err(
- EC_ZEBRA_MAC_ADD_FAILED,
- "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, vid, zevpn->vni);
- return -1;
- }
- SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
- es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
- if (sticky)
- SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
- inform_client = true;
- } else {
- if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
- zlog_debug(
- "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags 0x%x",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, vid, zevpn->vni,
- local_inactive ? "local-inactive " : "",
- mac->flags);
-
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
- struct interface *old_ifp;
- vlanid_t old_vid;
- bool old_static;
-
- zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
- old_bgp_ready =
- zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- old_local_inactive = !!(mac->flags &
- ZEBRA_MAC_LOCAL_INACTIVE);
- old_static = zebra_evpn_mac_is_static(mac);
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
- mac_sticky = true;
-
- /*
- * Update any changes and if changes are relevant to
- * BGP, note it.
- */
- if (mac_sticky == sticky
- && old_ifp == ifp
- && old_vid == vid
- && old_local_inactive == local_inactive
- && dp_static == old_static) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u%s, entry exists and has not changed ",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
- ifp->name, ifp->ifindex, vid,
- zevpn->vni,
- local_inactive ?
- " local_inactive" : "");
- return 0;
- }
- if (mac_sticky != sticky) {
- if (sticky)
- SET_FLAG(mac->flags,
- ZEBRA_MAC_STICKY);
- else
- UNSET_FLAG(mac->flags,
- ZEBRA_MAC_STICKY);
- inform_client = true;
- }
-
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
- /* If an es_change is detected we need to advertise
- * the route with a sequence that is one
- * greater. This is need to indicate a mac-move
- * to the ES peers
- */
- if (es_change) {
- mac->loc_seq = mac->loc_seq + 1;
- /* force drop the peer/sync info as it is
- * simply no longer relevant
- */
- if (CHECK_FLAG(mac->flags,
- ZEBRA_MAC_ALL_PEER_FLAGS)) {
- zebra_evpn_mac_clear_sync_info(mac);
- new_static =
- zebra_evpn_mac_is_static(mac);
- /* if we clear peer-flags we
- * also need to notify the dataplane
- * to drop the static flag
- */
- if (old_static != new_static)
- inform_dataplane = true;
- }
- }
- } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ||
- CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
- bool do_dad = false;
-
- /*
- * MAC has either moved or was "internally" created due
- * to a neighbor learn and is now actually learnt. If
- * it was learnt as a remote sticky MAC, this is an
- * operator error.
- */
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
- flog_warn(
- EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
- "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
- inet_ntoa(mac->fwd_info.r_vtep_ip),
- zevpn->vni);
- return 0;
- }
-
- /* If an actual move, compute MAC's seq number */
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
- mac->loc_seq = MAX(mac->rem_seq + 1,
- mac->loc_seq);
- vtep_ip = mac->fwd_info.r_vtep_ip;
- /* Trigger DAD for remote MAC */
- do_dad = true;
- }
-
- UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
- UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
- SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
- if (sticky)
- SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
- else
- UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
- /*
- * We have to inform BGP of this MAC as well as process
- * all neighbors.
- */
- inform_client = true;
- upd_neigh = true;
-
- zebra_evpn_dup_addr_detect_for_mac(
- zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
- true);
- if (is_dup_detect) {
- inform_client = false;
- upd_neigh = false;
- }
- }
- }
-
- /* if the dataplane thinks the entry is sync but it is
- * not sync in zebra we need to re-install to fixup
- */
- if (dp_static) {
- new_static = zebra_evpn_mac_is_static(mac);
- if (!new_static)
- inform_dataplane = true;
- }
-
- if (local_inactive)
- SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
- else
- UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
-
- new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- /* if local-activity has changed we need update bgp
- * even if bgp already knows about the mac
- */
- if ((old_local_inactive != local_inactive) ||
- (new_bgp_ready != old_bgp_ready)) {
- if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
- zlog_debug("local mac vni %u mac %s es %s seq %d f 0x%x%s",
- zevpn->vni,
- prefix_mac2str(macaddr,
- buf, sizeof(buf)),
- mac->es ? mac->es->esi_str : "",
- mac->loc_seq,
- mac->flags,
- local_inactive ?
- " local-inactive" : "");
- inform_client = true;
- }
-
- if (es_change) {
- inform_client = true;
- upd_neigh = true;
- }
-
- /* Inform dataplane if required. */
- if (inform_dataplane)
- zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
-
- /* Inform BGP if required. */
- if (inform_client)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
-
- /* Process all neighbors associated with this MAC, if required. */
- if (upd_neigh)
- zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
- es_change);
-
- return 0;
+ return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid,
+ sticky, local_inactive,
+ dp_static);
}
/*