back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_evpn_mac.c (source / functions) Hit Total Coverage
Test: test_pim_crp.py::PIMCandidateBSRTest Lines: 7 1161 0.6 %
Date: 2023-02-16 02:09:37 Functions: 3 54 5.6 %

          Line data    Source code
       1             : /*
       2             :  * Zebra EVPN for VxLAN code
       3             :  * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
       4             :  *
       5             :  * This file is part of FRR.
       6             :  *
       7             :  * FRR is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * FRR is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with FRR; see the file COPYING.  If not, write to the Free
      19             :  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :  * 02111-1307, USA.
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #include "hash.h"
      26             : #include "interface.h"
      27             : #include "jhash.h"
      28             : #include "memory.h"
      29             : #include "prefix.h"
      30             : #include "vlan.h"
      31             : #include "json.h"
      32             : #include "printfrr.h"
      33             : 
      34             : #include "zebra/zserv.h"
      35             : #include "zebra/debug.h"
      36             : #include "zebra/zebra_router.h"
      37             : #include "zebra/zebra_errors.h"
      38             : #include "zebra/zebra_vrf.h"
      39             : #include "zebra/zebra_evpn.h"
      40             : #include "zebra/zebra_evpn_mh.h"
      41             : #include "zebra/zebra_evpn_mac.h"
      42             : #include "zebra/zebra_evpn_neigh.h"
      43             : 
      44           9 : DEFINE_MTYPE_STATIC(ZEBRA, MAC, "EVPN MAC");
      45             : 
      46             : /*
      47             :  * Return number of valid MACs in an EVPN's MAC hash table - all
      48             :  * remote MACs and non-internal (auto) local MACs count.
      49             :  */
      50           0 : uint32_t num_valid_macs(struct zebra_evpn *zevpn)
      51             : {
      52           0 :         unsigned int i;
      53           0 :         uint32_t num_macs = 0;
      54           0 :         struct hash *hash;
      55           0 :         struct hash_bucket *hb;
      56           0 :         struct zebra_mac *mac;
      57             : 
      58           0 :         hash = zevpn->mac_table;
      59           0 :         if (!hash)
      60             :                 return num_macs;
      61           0 :         for (i = 0; i < hash->size; i++) {
      62           0 :                 for (hb = hash->index[i]; hb; hb = hb->next) {
      63           0 :                         mac = (struct zebra_mac *)hb->data;
      64           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
      65             :                             || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
      66           0 :                             || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
      67           0 :                                 num_macs++;
      68             :                 }
      69             :         }
      70             : 
      71             :         return num_macs;
      72             : }
      73             : 
      74           0 : uint32_t num_dup_detected_macs(struct zebra_evpn *zevpn)
      75             : {
      76           0 :         unsigned int i;
      77           0 :         uint32_t num_macs = 0;
      78           0 :         struct hash *hash;
      79           0 :         struct hash_bucket *hb;
      80           0 :         struct zebra_mac *mac;
      81             : 
      82           0 :         hash = zevpn->mac_table;
      83           0 :         if (!hash)
      84             :                 return num_macs;
      85           0 :         for (i = 0; i < hash->size; i++) {
      86           0 :                 for (hb = hash->index[i]; hb; hb = hb->next) {
      87           0 :                         mac = (struct zebra_mac *)hb->data;
      88           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
      89           0 :                                 num_macs++;
      90             :                 }
      91             :         }
      92             : 
      93             :         return num_macs;
      94             : }
      95             : 
      96             : /* Setup mac_list against the access port. This is done when a mac uses
      97             :  * the ifp as destination for the first time
      98             :  */
      99           0 : static void zebra_evpn_mac_ifp_new(struct zebra_if *zif)
     100             : {
     101           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
     102           0 :                 zlog_debug("MAC list created for ifp %s (%u)", zif->ifp->name,
     103             :                            zif->ifp->ifindex);
     104             : 
     105           0 :         zif->mac_list = list_new();
     106           0 :         listset_app_node_mem(zif->mac_list);
     107           0 : }
     108             : 
     109             : /* Unlink local mac from a destination access port */
     110           0 : static void zebra_evpn_mac_ifp_unlink(struct zebra_mac *zmac)
     111             : {
     112           0 :         struct zebra_if *zif;
     113           0 :         struct interface *ifp = zmac->ifp;
     114             : 
     115           0 :         if (!ifp)
     116             :                 return;
     117             : 
     118           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
     119           0 :                 zlog_debug("VNI %d MAC %pEA unlinked from ifp %s (%u)",
     120             :                            zmac->zevpn->vni,
     121             :                            &zmac->macaddr,
     122             :                            ifp->name, ifp->ifindex);
     123             : 
     124           0 :         zif = ifp->info;
     125           0 :         list_delete_node(zif->mac_list, &zmac->ifp_listnode);
     126           0 :         zmac->ifp = NULL;
     127             : }
     128             : 
     129             : /* Free up the mac_list if any as a part of the interface del/cleanup */
     130          12 : void zebra_evpn_mac_ifp_del(struct interface *ifp)
     131             : {
     132          12 :         struct zebra_if *zif = ifp->info;
     133          12 :         struct listnode *node;
     134          12 :         struct zebra_mac *zmac;
     135             : 
     136          12 :         if (zif->mac_list) {
     137           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
     138           0 :                         zlog_debug("MAC list deleted for ifp %s (%u)",
     139             :                                    zif->ifp->name, zif->ifp->ifindex);
     140             : 
     141           0 :                 for (ALL_LIST_ELEMENTS_RO(zif->mac_list, node, zmac)) {
     142           0 :                         zebra_evpn_mac_ifp_unlink(zmac);
     143             :                 }
     144           0 :                 list_delete(&zif->mac_list);
     145             :         }
     146          12 : }
     147             : 
     148             : /* Link local mac to destination access port. This is done only if the
     149             :  * local mac is associated with a zero ESI i.e. single attach or lacp-bypass
     150             :  * bridge port member
     151             :  */
     152           0 : static void zebra_evpn_mac_ifp_link(struct zebra_mac *zmac,
     153             :                                     struct interface *ifp)
     154             : {
     155           0 :         struct zebra_if *zif;
     156             : 
     157           0 :         if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
     158             :                 return;
     159             : 
     160             :         /* already linked to the destination */
     161           0 :         if (zmac->ifp == ifp)
     162             :                 return;
     163             : 
     164             :         /* unlink the mac from any old destination */
     165           0 :         if (zmac->ifp)
     166           0 :                 zebra_evpn_mac_ifp_unlink(zmac);
     167             : 
     168           0 :         if (!ifp)
     169             :                 return;
     170             : 
     171           0 :         zif = ifp->info;
     172             :         /* the interface mac_list is created on first mac link attempt */
     173           0 :         if (!zif->mac_list)
     174           0 :                 zebra_evpn_mac_ifp_new(zif);
     175             : 
     176           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
     177           0 :                 zlog_debug("VNI %d MAC %pEA linked to ifp %s (%u)",
     178             :                            zmac->zevpn->vni,
     179             :                            &zmac->macaddr,
     180             :                            ifp->name, ifp->ifindex);
     181             : 
     182           0 :         zmac->ifp = ifp;
     183           0 :         listnode_init(&zmac->ifp_listnode, zmac);
     184           0 :         listnode_add(zif->mac_list, &zmac->ifp_listnode);
     185             : }
     186             : 
     187             : /* If the mac is a local mac clear links to destination access port */
     188           0 : void zebra_evpn_mac_clear_fwd_info(struct zebra_mac *zmac)
     189             : {
     190           0 :         zebra_evpn_mac_ifp_unlink(zmac);
     191           0 :         memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
     192           0 : }
     193             : 
     194             : /*
     195             :  * Install remote MAC into the forwarding plane.
     196             :  */
     197           0 : int zebra_evpn_rem_mac_install(struct zebra_evpn *zevpn, struct zebra_mac *mac,
     198             :                                bool was_static)
     199             : {
     200           0 :         const struct zebra_if *zif, *br_zif;
     201           0 :         const struct zebra_l2info_vxlan *vxl;
     202           0 :         bool sticky;
     203           0 :         enum zebra_dplane_result res;
     204           0 :         const struct interface *br_ifp;
     205           0 :         vlanid_t vid;
     206           0 :         uint32_t nhg_id;
     207           0 :         struct in_addr vtep_ip;
     208             : 
     209           0 :         zif = zevpn->vxlan_if->info;
     210           0 :         if (!zif)
     211             :                 return -1;
     212             : 
     213           0 :         br_ifp = zif->brslave_info.br_if;
     214           0 :         if (br_ifp == NULL)
     215             :                 return -1;
     216             : 
     217           0 :         vxl = &zif->l2info.vxl;
     218             : 
     219           0 :         sticky = !!CHECK_FLAG(mac->flags,
     220             :                               (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
     221             : 
     222             :         /* If nexthop group for the FDB entry is inactive (not programmed in
     223             :          * the dataplane) the MAC entry cannot be installed
     224             :          */
     225           0 :         if (mac->es) {
     226           0 :                 if (!(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
     227             :                         return -1;
     228           0 :                 nhg_id = mac->es->nhg_id;
     229           0 :                 vtep_ip.s_addr = 0;
     230             :         } else {
     231           0 :                 nhg_id = 0;
     232           0 :                 vtep_ip = mac->fwd_info.r_vtep_ip;
     233             :         }
     234             : 
     235           0 :         br_zif = (const struct zebra_if *)(br_ifp->info);
     236             : 
     237           0 :         if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
     238           0 :                 vid = vxl->access_vlan;
     239             :         else
     240             :                 vid = 0;
     241             : 
     242           0 :         res = dplane_rem_mac_add(zevpn->vxlan_if, br_ifp, vid, &mac->macaddr,
     243             :                                  vtep_ip, sticky, nhg_id, was_static);
     244           0 :         if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
     245             :                 return 0;
     246             :         else
     247             :                 return -1;
     248             : }
     249             : 
     250             : /*
     251             :  * Uninstall remote MAC from the forwarding plane.
     252             :  */
     253           0 : int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
     254             :                                  struct zebra_mac *mac, bool force)
     255             : {
     256           0 :         const struct zebra_if *zif, *br_zif;
     257           0 :         const struct zebra_l2info_vxlan *vxl;
     258           0 :         struct in_addr vtep_ip;
     259           0 :         const struct interface *ifp, *br_ifp;
     260           0 :         vlanid_t vid;
     261           0 :         enum zebra_dplane_result res;
     262             : 
     263             :         /* If the MAC was not installed there is no need to uninstall it */
     264           0 :         if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
     265             :                 return -1;
     266             : 
     267           0 :         if (!zevpn->vxlan_if) {
     268           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
     269           0 :                         zlog_debug(
     270             :                                 "VNI %u hash %p couldn't be uninstalled - no intf",
     271             :                                 zevpn->vni, zevpn);
     272           0 :                 return -1;
     273             :         }
     274             : 
     275           0 :         zif = zevpn->vxlan_if->info;
     276           0 :         if (!zif)
     277             :                 return -1;
     278             : 
     279           0 :         br_ifp = zif->brslave_info.br_if;
     280           0 :         if (br_ifp == NULL)
     281             :                 return -1;
     282             : 
     283           0 :         vxl = &zif->l2info.vxl;
     284             : 
     285           0 :         br_zif = (const struct zebra_if *)br_ifp->info;
     286             : 
     287           0 :         if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
     288           0 :                 vid = vxl->access_vlan;
     289             :         else
     290             :                 vid = 0;
     291             : 
     292           0 :         ifp = zevpn->vxlan_if;
     293           0 :         vtep_ip = mac->fwd_info.r_vtep_ip;
     294             : 
     295           0 :         res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vtep_ip);
     296           0 :         if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
     297             :                 return 0;
     298             :         else
     299             :                 return -1;
     300             : }
     301             : 
     302             : /*
     303             :  * Decrement neighbor refcount of MAC; uninstall and free it if
     304             :  * appropriate.
     305             :  */
     306           0 : void zebra_evpn_deref_ip2mac(struct zebra_evpn *zevpn, struct zebra_mac *mac)
     307             : {
     308           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
     309             :                 return;
     310             : 
     311             :         /* If all remote neighbors referencing a remote MAC go away,
     312             :          * we need to uninstall the MAC.
     313             :          */
     314           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
     315           0 :             && remote_neigh_count(mac) == 0) {
     316           0 :                 zebra_evpn_rem_mac_uninstall(zevpn, mac, false /*force*/);
     317           0 :                 zebra_evpn_es_mac_deref_entry(mac);
     318           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
     319             :         }
     320             : 
     321             :         /* If no references, delete the MAC. */
     322           0 :         if (!zebra_evpn_mac_in_use(mac))
     323           0 :                 zebra_evpn_mac_del(zevpn, mac);
     324             : }
     325             : 
     326           0 : static void zebra_evpn_mac_get_access_info(struct zebra_mac *mac,
     327             :                                            struct interface **p_ifp,
     328             :                                            vlanid_t *vid)
     329             : {
     330             :         /* if the mac is associated with an ES we must get the access
     331             :          * info from the ES
     332             :          */
     333           0 :         if (mac->es) {
     334           0 :                 struct zebra_if *zif;
     335             : 
     336             :                 /* get the access port from the es */
     337           0 :                 *p_ifp = mac->es->zif ? mac->es->zif->ifp : NULL;
     338             :                 /* get the vlan from the EVPN */
     339           0 :                 if (mac->zevpn->vxlan_if) {
     340           0 :                         zif = mac->zevpn->vxlan_if->info;
     341           0 :                         *vid = zif->l2info.vxl.access_vlan;
     342             :                 } else {
     343           0 :                         *vid = 0;
     344             :                 }
     345             :         } else {
     346           0 :                 struct zebra_ns *zns;
     347             : 
     348           0 :                 *vid = mac->fwd_info.local.vid;
     349           0 :                 zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
     350           0 :                 *p_ifp = if_lookup_by_index_per_ns(zns,
     351           0 :                                                    mac->fwd_info.local.ifindex);
     352             :         }
     353           0 : }
     354             : 
     355             : #define MAC_BUF_SIZE 256
     356           0 : static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac *mac, char *buf,
     357             :                                             size_t len)
     358             : {
     359           0 :         if (mac->flags == 0) {
     360           0 :                 snprintfrr(buf, len, "None ");
     361           0 :                 return buf;
     362             :         }
     363             : 
     364           0 :         snprintfrr(
     365             :                 buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
     366           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "",
     367           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "",
     368           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "",
     369           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "",
     370           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router "
     371             :                                                               : "",
     372           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "",
     373           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW "
     374             :                                                                 : "",
     375           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "",
     376           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "",
     377           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)
     378             :                         ? "PEER Active "
     379             :                         : "",
     380           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "",
     381           0 :                 CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)
     382             :                         ? "LOC Inactive "
     383             :                         : "");
     384           0 :         return buf;
     385             : }
     386             : 
     387           0 : static void zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
     388             : {
     389           0 :         struct zebra_vrf *zvrf = NULL;
     390           0 :         struct zebra_mac *mac = NULL;
     391           0 :         struct zebra_evpn *zevpn = NULL;
     392           0 :         struct listnode *node = NULL;
     393           0 :         struct zebra_neigh *nbr = NULL;
     394             : 
     395           0 :         mac = THREAD_ARG(t);
     396             : 
     397             :         /* since this is asynchronous we need sanity checks*/
     398           0 :         zvrf = vrf_info_lookup(mac->zevpn->vrf_id);
     399           0 :         if (!zvrf)
     400             :                 return;
     401             : 
     402           0 :         zevpn = zebra_evpn_lookup(mac->zevpn->vni);
     403           0 :         if (!zevpn)
     404             :                 return;
     405             : 
     406           0 :         mac = zebra_evpn_mac_lookup(zevpn, &mac->macaddr);
     407           0 :         if (!mac)
     408             :                 return;
     409             : 
     410           0 :         if (IS_ZEBRA_DEBUG_VXLAN) {
     411           0 :                 char mac_buf[MAC_BUF_SIZE];
     412             : 
     413           0 :                 zlog_debug(
     414             :                         "%s: duplicate addr mac %pEA flags %slearn count %u host count %u auto recovery expired",
     415             :                         __func__, &mac->macaddr,
     416             :                         zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
     417             :                                                        sizeof(mac_buf)),
     418             :                         mac->dad_count, listcount(mac->neigh_list));
     419             :         }
     420             : 
     421             :         /* Remove all IPs as duplicate associcated with this MAC */
     422           0 :         for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
     423           0 :                 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
     424           0 :                         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
     425           0 :                                 ZEBRA_NEIGH_SET_INACTIVE(nbr);
     426           0 :                         else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
     427           0 :                                 zebra_evpn_rem_neigh_install(
     428             :                                         zevpn, nbr, false /*was_static*/);
     429             :                 }
     430             : 
     431           0 :                 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
     432           0 :                 nbr->dad_count = 0;
     433           0 :                 nbr->detect_start_time.tv_sec = 0;
     434           0 :                 nbr->dad_dup_detect_time = 0;
     435             :         }
     436             : 
     437           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
     438           0 :         mac->dad_count = 0;
     439           0 :         mac->detect_start_time.tv_sec = 0;
     440           0 :         mac->detect_start_time.tv_usec = 0;
     441           0 :         mac->dad_dup_detect_time = 0;
     442           0 :         mac->dad_mac_auto_recovery_timer = NULL;
     443             : 
     444           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
     445             :                 /* Inform to BGP */
     446           0 :                 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
     447             :                                                       mac->flags, mac->loc_seq,
     448             :                                                       mac->es))
     449             :                         return;
     450             : 
     451             :                 /* Process all neighbors associated with this MAC. */
     452           0 :                 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
     453             :                                                              0 /*es_change*/);
     454             : 
     455           0 :         } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
     456           0 :                 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
     457             : 
     458             :                 /* Install the entry. */
     459           0 :                 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
     460             :         }
     461             : }
     462             : 
     463           0 : static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
     464             :                                                struct zebra_mac *mac,
     465             :                                                struct in_addr vtep_ip,
     466             :                                                bool do_dad, bool *is_dup_detect,
     467             :                                                bool is_local)
     468             : {
     469           0 :         struct zebra_neigh *nbr;
     470           0 :         struct listnode *node = NULL;
     471           0 :         struct timeval elapsed = {0, 0};
     472           0 :         bool reset_params = false;
     473             : 
     474           0 :         if (!(zebra_evpn_do_dup_addr_detect(zvrf) && do_dad))
     475           0 :                 return;
     476             : 
     477             :         /* MAC is detected as duplicate,
     478             :          * Local MAC event -> hold on advertising to BGP.
     479             :          * Remote MAC event -> hold on installing it.
     480             :          */
     481           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
     482           0 :                 if (IS_ZEBRA_DEBUG_VXLAN) {
     483           0 :                         char mac_buf[MAC_BUF_SIZE];
     484             : 
     485           0 :                         zlog_debug(
     486             :                                 "%s: duplicate addr MAC %pEA flags %sskip update to client, learn count %u recover time %u",
     487             :                                 __func__, &mac->macaddr,
     488             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
     489             :                                                                sizeof(mac_buf)),
     490             :                                 mac->dad_count, zvrf->dad_freeze_time);
     491             :                 }
     492             :                 /* For duplicate MAC do not update
     493             :                  * client but update neigh due to
     494             :                  * this MAC update.
     495             :                  */
     496           0 :                 if (zvrf->dad_freeze)
     497           0 :                         *is_dup_detect = true;
     498             : 
     499           0 :                 return;
     500             :         }
     501             : 
     502             :         /* Check if detection time (M-secs) expired.
     503             :          * Reset learn count and detection start time.
     504             :          */
     505           0 :         monotime_since(&mac->detect_start_time, &elapsed);
     506           0 :         reset_params = (elapsed.tv_sec > zvrf->dad_time);
     507           0 :         if (is_local && !reset_params) {
     508             :                 /* RFC-7432: A PE/VTEP that detects a MAC mobility
     509             :                  * event via LOCAL learning starts an M-second timer.
     510             :                  *
     511             :                  * NOTE: This is the START of the probe with count is
     512             :                  * 0 during LOCAL learn event.
     513             :                  * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
     514             :                  */
     515           0 :                 reset_params = !mac->dad_count;
     516             :         }
     517             : 
     518           0 :         if (reset_params) {
     519           0 :                 if (IS_ZEBRA_DEBUG_VXLAN) {
     520           0 :                         char mac_buf[MAC_BUF_SIZE];
     521             : 
     522           0 :                         zlog_debug(
     523             :                                 "%s: duplicate addr MAC %pEA flags %sdetection time passed, reset learn count %u",
     524             :                                 __func__, &mac->macaddr,
     525             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
     526             :                                                                sizeof(mac_buf)),
     527             :                                 mac->dad_count);
     528             :                 }
     529             : 
     530           0 :                 mac->dad_count = 0;
     531             :                 /* Start dup. addr detection (DAD) start time,
     532             :                  * ONLY during LOCAL learn.
     533             :                  */
     534           0 :                 if (is_local)
     535           0 :                         monotime(&mac->detect_start_time);
     536             : 
     537           0 :         } else if (!is_local) {
     538             :                 /* For REMOTE MAC, increment detection count
     539             :                  * ONLY while in probe window, once window passed,
     540             :                  * next local learn event should trigger DAD.
     541             :                  */
     542           0 :                 mac->dad_count++;
     543             :         }
     544             : 
     545             :         /* For LOCAL MAC learn event, once count is reset above via either
     546             :          * initial/start detection time or passed the probe time, the count
     547             :          * needs to be incremented.
     548             :          */
     549           0 :         if (is_local)
     550           0 :                 mac->dad_count++;
     551             : 
     552           0 :         if (mac->dad_count >= zvrf->dad_max_moves) {
     553           0 :                 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
     554             :                           "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4",
     555             :                           mac->zevpn->vni, &mac->macaddr,
     556             :                           is_local ? "local update, last" :
     557             :                           "remote update, from", &vtep_ip);
     558             : 
     559           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
     560             : 
     561             :                 /* Capture Duplicate detection time */
     562           0 :                 mac->dad_dup_detect_time = monotime(NULL);
     563             : 
     564             :                 /* Mark all IPs/Neighs as duplicate
     565             :                  * associcated with this MAC
     566             :                  */
     567           0 :                 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
     568             : 
     569             :                         /* Ony Mark IPs which are Local */
     570           0 :                         if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
     571           0 :                                 continue;
     572             : 
     573           0 :                         SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
     574             : 
     575           0 :                         nbr->dad_dup_detect_time = monotime(NULL);
     576             : 
     577           0 :                         flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
     578             :                                   "VNI %u: MAC %pEA IP %pIA detected as duplicate during %s update, inherit duplicate from MAC",
     579             :                                   mac->zevpn->vni, &mac->macaddr, &nbr->ip,
     580             :                                   is_local ? "local" : "remote");
     581             :                 }
     582             : 
     583             :                 /* Start auto recovery timer for this MAC */
     584           0 :                 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
     585           0 :                 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
     586           0 :                         if (IS_ZEBRA_DEBUG_VXLAN) {
     587           0 :                                 char mac_buf[MAC_BUF_SIZE];
     588             : 
     589           0 :                                 zlog_debug(
     590             :                                         "%s: duplicate addr MAC %pEA flags %sauto recovery time %u start",
     591             :                                         __func__, &mac->macaddr,
     592             :                                         zebra_evpn_zebra_mac_flag_dump(
     593             :                                                 mac, mac_buf, sizeof(mac_buf)),
     594             :                                         zvrf->dad_freeze_time);
     595             :                         }
     596             : 
     597           0 :                         thread_add_timer(zrouter.master,
     598             :                                          zebra_evpn_dad_mac_auto_recovery_exp,
     599             :                                          mac, zvrf->dad_freeze_time,
     600             :                                          &mac->dad_mac_auto_recovery_timer);
     601             :                 }
     602             : 
     603             :                 /* In case of local update, do not inform to client (BGPd),
     604             :                  * upd_neigh for neigh sequence change.
     605             :                  */
     606           0 :                 if (zvrf->dad_freeze)
     607           0 :                         *is_dup_detect = true;
     608             :         }
     609             : }
     610             : 
     611             : /*
     612             :  * Print a specific MAC entry.
     613             :  */
     614           0 : void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
     615             : {
     616           0 :         struct vty *vty;
     617           0 :         struct zebra_neigh *n = NULL;
     618           0 :         struct listnode *node = NULL;
     619           0 :         char buf1[ETHER_ADDR_STRLEN];
     620           0 :         char buf2[INET6_ADDRSTRLEN];
     621           0 :         struct zebra_vrf *zvrf;
     622           0 :         struct timeval detect_start_time = {0, 0};
     623           0 :         char timebuf[MONOTIME_STRLEN];
     624           0 :         char thread_buf[THREAD_TIMER_STRLEN];
     625           0 :         time_t uptime;
     626           0 :         char up_str[MONOTIME_STRLEN];
     627             : 
     628           0 :         zvrf = zebra_vrf_get_evpn();
     629           0 :         vty = (struct vty *)ctxt;
     630           0 :         prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
     631             : 
     632           0 :         uptime = monotime(NULL);
     633           0 :         uptime -= mac->uptime;
     634             : 
     635           0 :         frrtime_to_interval(uptime, up_str, sizeof(up_str));
     636             : 
     637           0 :         if (json) {
     638           0 :                 json_object *json_mac = json_object_new_object();
     639             : 
     640           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
     641           0 :                         struct interface *ifp;
     642           0 :                         vlanid_t vid;
     643             : 
     644           0 :                         zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
     645           0 :                         json_object_string_add(json_mac, "type", "local");
     646           0 :                         if (ifp) {
     647           0 :                                 json_object_string_add(json_mac, "intf",
     648           0 :                                                        ifp->name);
     649           0 :                                 json_object_int_add(json_mac, "ifindex",
     650           0 :                                                     ifp->ifindex);
     651             :                         }
     652           0 :                         if (vid)
     653           0 :                                 json_object_int_add(json_mac, "vlan", vid);
     654           0 :                 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
     655           0 :                         json_object_string_add(json_mac, "type", "remote");
     656           0 :                         if (mac->es)
     657           0 :                                 json_object_string_add(json_mac, "remoteEs",
     658           0 :                                                        mac->es->esi_str);
     659             :                         else
     660           0 :                                 json_object_string_addf(
     661             :                                         json_mac, "remoteVtep", "%pI4",
     662             :                                         &mac->fwd_info.r_vtep_ip);
     663           0 :                 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
     664           0 :                         json_object_string_add(json_mac, "type", "auto");
     665             : 
     666           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
     667           0 :                         json_object_boolean_true_add(json_mac, "stickyMac");
     668             : 
     669           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
     670           0 :                         json_object_boolean_true_add(json_mac, "sviMac");
     671             : 
     672           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
     673           0 :                         json_object_boolean_true_add(json_mac,
     674             :                                                      "defaultGateway");
     675             : 
     676           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
     677           0 :                         json_object_boolean_true_add(json_mac,
     678             :                                                      "remoteGatewayMac");
     679             : 
     680           0 :                 json_object_string_add(json_mac, "uptime", up_str);
     681           0 :                 json_object_int_add(json_mac, "localSequence", mac->loc_seq);
     682           0 :                 json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
     683             : 
     684           0 :                 json_object_int_add(json_mac, "detectionCount", mac->dad_count);
     685           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
     686           0 :                         json_object_boolean_true_add(json_mac, "isDuplicate");
     687             :                 else
     688           0 :                         json_object_boolean_false_add(json_mac, "isDuplicate");
     689             : 
     690           0 :                 json_object_int_add(json_mac, "syncNeighCount",
     691           0 :                                     mac->sync_neigh_cnt);
     692           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE))
     693           0 :                         json_object_boolean_true_add(json_mac, "localInactive");
     694           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY))
     695           0 :                         json_object_boolean_true_add(json_mac, "peerProxy");
     696           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
     697           0 :                         json_object_boolean_true_add(json_mac, "peerActive");
     698           0 :                 if (mac->hold_timer)
     699           0 :                         json_object_string_add(
     700             :                                 json_mac, "peerActiveHold",
     701           0 :                                 thread_timer_to_hhmmss(thread_buf,
     702             :                                                        sizeof(thread_buf),
     703             :                                                        mac->hold_timer));
     704           0 :                 if (mac->es)
     705           0 :                         json_object_string_add(json_mac, "esi",
     706           0 :                                         mac->es->esi_str);
     707             :                 /* print all the associated neigh */
     708           0 :                 if (!listcount(mac->neigh_list))
     709           0 :                         json_object_string_add(json_mac, "neighbors", "none");
     710             :                 else {
     711           0 :                         json_object *json_active_nbrs = json_object_new_array();
     712           0 :                         json_object *json_inactive_nbrs =
     713           0 :                                 json_object_new_array();
     714           0 :                         json_object *json_nbrs = json_object_new_object();
     715             : 
     716           0 :                         for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
     717           0 :                                 if (IS_ZEBRA_NEIGH_ACTIVE(n))
     718           0 :                                         json_object_array_add(
     719             :                                                 json_active_nbrs,
     720             :                                                 json_object_new_string(
     721           0 :                                                         ipaddr2str(
     722           0 :                                                                 &n->ip, buf2,
     723             :                                                                 sizeof(buf2))));
     724             :                                 else
     725           0 :                                         json_object_array_add(
     726             :                                                 json_inactive_nbrs,
     727             :                                                 json_object_new_string(
     728           0 :                                                         ipaddr2str(
     729           0 :                                                                 &n->ip, buf2,
     730             :                                                                 sizeof(buf2))));
     731             :                         }
     732             : 
     733           0 :                         json_object_object_add(json_nbrs, "active",
     734             :                                                json_active_nbrs);
     735           0 :                         json_object_object_add(json_nbrs, "inactive",
     736             :                                                json_inactive_nbrs);
     737           0 :                         json_object_object_add(json_mac, "neighbors",
     738             :                                                json_nbrs);
     739             :                 }
     740             : 
     741           0 :                 json_object_object_add(json, buf1, json_mac);
     742             :         } else {
     743           0 :                 vty_out(vty, "MAC: %s\n", buf1);
     744             : 
     745           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
     746           0 :                         struct interface *ifp;
     747           0 :                         vlanid_t vid;
     748             : 
     749           0 :                         zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
     750             : 
     751           0 :                         if (mac->es)
     752           0 :                                 vty_out(vty, " ESI: %s\n", mac->es->esi_str);
     753             : 
     754           0 :                         if (ifp)
     755           0 :                                 vty_out(vty, " Intf: %s(%u)", ifp->name,
     756             :                                         ifp->ifindex);
     757             :                         else
     758           0 :                                 vty_out(vty, " Intf: -");
     759           0 :                         vty_out(vty, " VLAN: %u", vid);
     760           0 :                 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
     761           0 :                         if (mac->es)
     762           0 :                                 vty_out(vty, " Remote ES: %s",
     763           0 :                                         mac->es->esi_str);
     764             :                         else
     765           0 :                                 vty_out(vty, " Remote VTEP: %pI4",
     766             :                                         &mac->fwd_info.r_vtep_ip);
     767           0 :                 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
     768           0 :                         vty_out(vty, " Auto Mac ");
     769             :                 }
     770             : 
     771           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
     772           0 :                         vty_out(vty, " Sticky Mac ");
     773             : 
     774           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
     775           0 :                         vty_out(vty, " SVI-Mac ");
     776             : 
     777           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
     778           0 :                         vty_out(vty, " Default-gateway Mac ");
     779             : 
     780           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
     781           0 :                         vty_out(vty, " Remote-gateway Mac ");
     782             : 
     783           0 :                 vty_out(vty, "\n");
     784           0 :                 vty_out(vty, " Sync-info: neigh#: %u", mac->sync_neigh_cnt);
     785           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE))
     786           0 :                         vty_out(vty, " local-inactive");
     787           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY))
     788           0 :                         vty_out(vty, " peer-proxy");
     789           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
     790           0 :                         vty_out(vty, " peer-active");
     791           0 :                 if (mac->hold_timer)
     792           0 :                         vty_out(vty, " (ht: %s)",
     793             :                                 thread_timer_to_hhmmss(thread_buf,
     794             :                                                        sizeof(thread_buf),
     795             :                                                        mac->hold_timer));
     796           0 :                 vty_out(vty, "\n");
     797           0 :                 vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq,
     798             :                         mac->rem_seq);
     799           0 :                 vty_out(vty, " Uptime: %s\n", up_str);
     800             : 
     801           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
     802           0 :                         vty_out(vty, " Duplicate, detected at %s",
     803             :                                 time_to_string(mac->dad_dup_detect_time,
     804             :                                                timebuf));
     805           0 :                 } else if (mac->dad_count) {
     806           0 :                         monotime_since(&mac->detect_start_time,
     807             :                                        &detect_start_time);
     808           0 :                         if (detect_start_time.tv_sec <= zvrf->dad_time) {
     809           0 :                                 time_to_string(mac->detect_start_time.tv_sec,
     810             :                                                timebuf);
     811           0 :                                 vty_out(vty,
     812             :                                         " Duplicate detection started at %s, detection count %u\n",
     813             :                                         timebuf, mac->dad_count);
     814             :                         }
     815             :                 }
     816             : 
     817             :                 /* print all the associated neigh */
     818           0 :                 vty_out(vty, " Neighbors:\n");
     819           0 :                 if (!listcount(mac->neigh_list))
     820           0 :                         vty_out(vty, "    No Neighbors\n");
     821             :                 else {
     822           0 :                         for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
     823           0 :                                 vty_out(vty, "    %s %s\n",
     824           0 :                                         ipaddr2str(&n->ip, buf2, sizeof(buf2)),
     825           0 :                                         (IS_ZEBRA_NEIGH_ACTIVE(n)
     826             :                                                  ? "Active"
     827             :                                                  : "Inactive"));
     828             :                         }
     829             :                 }
     830             : 
     831           0 :                 vty_out(vty, "\n");
     832             :         }
     833           0 : }
     834             : 
     835           0 : static char *zebra_evpn_print_mac_flags(struct zebra_mac *mac, char *flags_buf,
     836             :                                         size_t flags_buf_sz)
     837             : {
     838           0 :         snprintf(flags_buf, flags_buf_sz, "%s%s%s%s",
     839           0 :                  mac->sync_neigh_cnt ? "N" : "",
     840           0 :                  (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
     841           0 :                  (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
     842           0 :                  (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
     843             : 
     844           0 :         return flags_buf;
     845             : }
     846             : 
     847             : /*
     848             :  * Print MAC hash entry - called for display of all MACs.
     849             :  */
     850           0 : void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
     851             : {
     852           0 :         struct vty *vty;
     853           0 :         json_object *json_mac_hdr = NULL, *json_mac = NULL;
     854           0 :         struct zebra_mac *mac;
     855           0 :         char buf1[ETHER_ADDR_STRLEN];
     856           0 :         char addr_buf[PREFIX_STRLEN];
     857           0 :         struct mac_walk_ctx *wctx = ctxt;
     858           0 :         char flags_buf[6];
     859             : 
     860           0 :         vty = wctx->vty;
     861           0 :         json_mac_hdr = wctx->json;
     862           0 :         mac = (struct zebra_mac *)bucket->data;
     863             : 
     864           0 :         prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
     865             : 
     866           0 :         if (json_mac_hdr)
     867           0 :                 json_mac = json_object_new_object();
     868             : 
     869           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
     870           0 :                 struct interface *ifp;
     871           0 :                 vlanid_t vid;
     872             : 
     873           0 :                 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
     874           0 :                         return;
     875             : 
     876           0 :                 zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
     877           0 :                 if (json_mac_hdr == NULL) {
     878           0 :                         vty_out(vty, "%-17s %-6s %-5s %-30s", buf1, "local",
     879             :                                 zebra_evpn_print_mac_flags(mac, flags_buf,
     880             :                 sizeof(flags_buf)),
     881           0 :                                 ifp ? ifp->name : "-");
     882             :                 } else {
     883           0 :                         json_object_string_add(json_mac, "type", "local");
     884           0 :                         if (ifp)
     885           0 :                                 json_object_string_add(json_mac, "intf",
     886           0 :                                                        ifp->name);
     887             :                 }
     888           0 :                 if (vid) {
     889           0 :                         if (json_mac_hdr == NULL)
     890           0 :                                 vty_out(vty, " %-5u", vid);
     891             :                         else
     892           0 :                                 json_object_int_add(json_mac, "vlan", vid);
     893             :                 } else /* No vid? fill out the space */
     894           0 :                         if (json_mac_hdr == NULL)
     895           0 :                         vty_out(vty, " %-5s", "");
     896           0 :                 if (json_mac_hdr == NULL) {
     897           0 :                         vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq);
     898           0 :                         vty_out(vty, "\n");
     899             :                 } else {
     900           0 :                         json_object_int_add(json_mac, "localSequence",
     901           0 :                                             mac->loc_seq);
     902           0 :                         json_object_int_add(json_mac, "remoteSequence",
     903           0 :                                             mac->rem_seq);
     904           0 :                         json_object_int_add(json_mac, "detectionCount",
     905           0 :                                             mac->dad_count);
     906           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
     907           0 :                                 json_object_boolean_true_add(json_mac,
     908             :                                                              "isDuplicate");
     909             :                         else
     910           0 :                                 json_object_boolean_false_add(json_mac,
     911             :                                                               "isDuplicate");
     912           0 :                         json_object_object_add(json_mac_hdr, buf1, json_mac);
     913             :                 }
     914             : 
     915           0 :                 wctx->count++;
     916             : 
     917           0 :         } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
     918             : 
     919           0 :                 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
     920           0 :                     && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
     921             :                                        &wctx->r_vtep_ip))
     922             :                         return;
     923             : 
     924           0 :                 if (json_mac_hdr == NULL) {
     925           0 :                         if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
     926           0 :                             && (wctx->count == 0)) {
     927           0 :                                 vty_out(vty, "\nVNI %u\n\n", wctx->zevpn->vni);
     928           0 :                                 vty_out(vty, "%-17s %-6s %-5s%-30s %-5s %s\n",
     929             :                                         "MAC", "Type", "Flags",
     930             :                                         "Intf/Remote ES/VTEP", "VLAN",
     931             :                                         "Seq #'s");
     932             :                         }
     933           0 :                         if (mac->es == NULL)
     934           0 :                                 inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
     935             :                                           addr_buf, sizeof(addr_buf));
     936             : 
     937           0 :                         vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1,
     938             :                                 "remote",
     939             :                                 zebra_evpn_print_mac_flags(mac, flags_buf,
     940             :                                                            sizeof(flags_buf)),
     941           0 :                                 mac->es ? mac->es->esi_str : addr_buf,
     942             :                                 "", mac->loc_seq, mac->rem_seq);
     943             :                 } else {
     944           0 :                         json_object_string_add(json_mac, "type", "remote");
     945           0 :                         if (mac->es)
     946           0 :                                 json_object_string_add(json_mac, "remoteEs",
     947           0 :                                                        mac->es->esi_str);
     948             :                         else
     949           0 :                                 json_object_string_addf(
     950             :                                         json_mac, "remoteVtep", "%pI4",
     951             :                                         &mac->fwd_info.r_vtep_ip);
     952           0 :                         json_object_object_add(json_mac_hdr, buf1, json_mac);
     953           0 :                         json_object_int_add(json_mac, "localSequence",
     954           0 :                                             mac->loc_seq);
     955           0 :                         json_object_int_add(json_mac, "remoteSequence",
     956           0 :                                             mac->rem_seq);
     957           0 :                         json_object_int_add(json_mac, "detectionCount",
     958           0 :                                             mac->dad_count);
     959           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
     960           0 :                                 json_object_boolean_true_add(json_mac,
     961             :                                                              "isDuplicate");
     962             :                         else
     963           0 :                                 json_object_boolean_false_add(json_mac,
     964             :                                                               "isDuplicate");
     965             :                 }
     966             : 
     967           0 :                 wctx->count++;
     968             :         }
     969             : }
     970             : 
     971             : /*
     972             :  * Print MAC hash entry in detail - called for display of all MACs.
     973             :  */
     974           0 : void zebra_evpn_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
     975             : {
     976           0 :         struct vty *vty;
     977           0 :         json_object *json_mac_hdr = NULL;
     978           0 :         struct zebra_mac *mac;
     979           0 :         struct mac_walk_ctx *wctx = ctxt;
     980           0 :         char buf1[ETHER_ADDR_STRLEN];
     981             : 
     982           0 :         vty = wctx->vty;
     983           0 :         json_mac_hdr = wctx->json;
     984           0 :         mac = (struct zebra_mac *)bucket->data;
     985           0 :         if (!mac)
     986           0 :                 return;
     987             : 
     988           0 :         wctx->count++;
     989           0 :         prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
     990             : 
     991           0 :         zebra_evpn_print_mac(mac, vty, json_mac_hdr);
     992             : }
     993             : 
     994             : /*
     995             :  * Inform BGP about local MACIP.
     996             :  */
     997           0 : int zebra_evpn_macip_send_msg_to_client(vni_t vni,
     998             :                                         const struct ethaddr *macaddr,
     999             :                                         const struct ipaddr *ip, uint8_t flags,
    1000             :                                         uint32_t seq, int state,
    1001             :                                         struct zebra_evpn_es *es, uint16_t cmd)
    1002             : {
    1003           0 :         int ipa_len;
    1004           0 :         struct zserv *client = NULL;
    1005           0 :         struct stream *s = NULL;
    1006           0 :         esi_t *esi = es ? &es->esi : zero_esi;
    1007             : 
    1008           0 :         client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
    1009             :         /* BGP may not be running. */
    1010           0 :         if (!client)
    1011             :                 return 0;
    1012             : 
    1013           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    1014             : 
    1015           0 :         zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
    1016           0 :         stream_putl(s, vni);
    1017           0 :         stream_put(s, macaddr->octet, ETH_ALEN);
    1018           0 :         if (ip) {
    1019           0 :                 ipa_len = 0;
    1020           0 :                 if (IS_IPADDR_V4(ip))
    1021             :                         ipa_len = IPV4_MAX_BYTELEN;
    1022           0 :                 else if (IS_IPADDR_V6(ip))
    1023           0 :                         ipa_len = IPV6_MAX_BYTELEN;
    1024             : 
    1025           0 :                 stream_putl(s, ipa_len); /* IP address length */
    1026           0 :                 if (ipa_len)
    1027           0 :                         stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
    1028             :         } else
    1029           0 :                 stream_putl(s, 0); /* Just MAC. */
    1030             : 
    1031           0 :         if (cmd == ZEBRA_MACIP_ADD) {
    1032           0 :                 stream_putc(s, flags); /* sticky mac/gateway mac */
    1033           0 :                 stream_putl(s, seq);   /* sequence number */
    1034           0 :                 stream_put(s, esi, sizeof(esi_t));
    1035             :         } else {
    1036           0 :                 stream_putl(s, state); /* state - active/inactive */
    1037             :         }
    1038             : 
    1039             : 
    1040             :         /* Write packet size. */
    1041           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    1042             : 
    1043           0 :         if (IS_ZEBRA_DEBUG_VXLAN) {
    1044           0 :                 char flag_buf[MACIP_BUF_SIZE];
    1045             : 
    1046           0 :                 zlog_debug(
    1047             :                         "Send MACIP %s f %s MAC %pEA IP %pIA seq %u L2-VNI %u ESI %s to %s",
    1048             :                         (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
    1049             :                         zclient_evpn_dump_macip_flags(flags, flag_buf,
    1050             :                                                       sizeof(flag_buf)),
    1051             :                         macaddr, ip, seq, vni,
    1052             :                         es ? es->esi_str : "-",
    1053             :                         zebra_route_string(client->proto));
    1054             :         }
    1055             : 
    1056           0 :         if (cmd == ZEBRA_MACIP_ADD)
    1057           0 :                 client->macipadd_cnt++;
    1058             :         else
    1059           0 :                 client->macipdel_cnt++;
    1060             : 
    1061           0 :         return zserv_send_message(client, s);
    1062             : }
    1063             : 
    1064           0 : static unsigned int mac_hash_keymake(const void *p)
    1065             : {
    1066           0 :         const struct zebra_mac *pmac = p;
    1067           0 :         const void *pnt = (void *)pmac->macaddr.octet;
    1068             : 
    1069           0 :         return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
    1070             : }
    1071             : 
    1072             : /*
    1073             :  * Compare two MAC addresses.
    1074             :  */
    1075           0 : static bool mac_cmp(const void *p1, const void *p2)
    1076             : {
    1077           0 :         const struct zebra_mac *pmac1 = p1;
    1078           0 :         const struct zebra_mac *pmac2 = p2;
    1079             : 
    1080           0 :         if (pmac1 == NULL && pmac2 == NULL)
    1081             :                 return true;
    1082             : 
    1083           0 :         if (pmac1 == NULL || pmac2 == NULL)
    1084             :                 return false;
    1085             : 
    1086           0 :         return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
    1087           0 :                 == 0);
    1088             : }
    1089             : 
    1090             : /*
    1091             :  * Callback to allocate MAC hash entry.
    1092             :  */
    1093           0 : static void *zebra_evpn_mac_alloc(void *p)
    1094             : {
    1095           0 :         const struct zebra_mac *tmp_mac = p;
    1096           0 :         struct zebra_mac *mac;
    1097             : 
    1098           0 :         mac = XCALLOC(MTYPE_MAC, sizeof(struct zebra_mac));
    1099           0 :         *mac = *tmp_mac;
    1100             : 
    1101           0 :         return ((void *)mac);
    1102             : }
    1103             : 
    1104             : /*
    1105             :  * Add MAC entry.
    1106             :  */
    1107           0 : struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevpn,
    1108             :                                      const struct ethaddr *macaddr)
    1109             : {
    1110           0 :         struct zebra_mac tmp_mac;
    1111           0 :         struct zebra_mac *mac = NULL;
    1112             : 
    1113           0 :         memset(&tmp_mac, 0, sizeof(tmp_mac));
    1114           0 :         memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
    1115           0 :         mac = hash_get(zevpn->mac_table, &tmp_mac, zebra_evpn_mac_alloc);
    1116             : 
    1117           0 :         mac->zevpn = zevpn;
    1118           0 :         mac->dad_mac_auto_recovery_timer = NULL;
    1119             : 
    1120           0 :         mac->neigh_list = list_new();
    1121           0 :         mac->neigh_list->cmp = neigh_list_cmp;
    1122             : 
    1123           0 :         mac->uptime = monotime(NULL);
    1124           0 :         if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1125           0 :                 char mac_buf[MAC_BUF_SIZE];
    1126             : 
    1127           0 :                 zlog_debug("%s: MAC %pEA flags %s", __func__,
    1128             :                            &mac->macaddr,
    1129             :                            zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1130             :                                                           sizeof(mac_buf)));
    1131             :         }
    1132           0 :         return mac;
    1133             : }
    1134             : 
    1135             : /*
    1136             :  * Delete MAC entry.
    1137             :  */
    1138           0 : int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
    1139             : {
    1140           0 :         struct zebra_mac *tmp_mac;
    1141             : 
    1142           0 :         if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1143           0 :                 char mac_buf[MAC_BUF_SIZE];
    1144             : 
    1145           0 :                 zlog_debug("%s: MAC %pEA flags %s", __func__,
    1146             :                            &mac->macaddr,
    1147             :                            zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1148             :                                                           sizeof(mac_buf)));
    1149             :         }
    1150             : 
    1151             :         /* force de-ref any ES entry linked to the MAC */
    1152           0 :         zebra_evpn_es_mac_deref_entry(mac);
    1153             : 
    1154             :         /* remove links to the destination access port */
    1155           0 :         zebra_evpn_mac_clear_fwd_info(mac);
    1156             : 
    1157             :         /* Cancel proxy hold timer */
    1158           0 :         zebra_evpn_mac_stop_hold_timer(mac);
    1159             : 
    1160             :         /* Cancel auto recovery */
    1161           0 :         THREAD_OFF(mac->dad_mac_auto_recovery_timer);
    1162             : 
    1163             :         /* If the MAC is freed before the neigh we will end up
    1164             :          * with a stale pointer against the neigh.
    1165             :          * The situation can arise when a MAC is in remote state
    1166             :          * and its associated neigh is local state.
    1167             :          * zebra_evpn_cfg_cleanup() cleans up remote neighs and MACs.
    1168             :          * Instead of deleting remote MAC, if its neigh list is non-empty
    1169             :          * (associated to local neighs), mark the MAC as AUTO.
    1170             :          */
    1171           0 :         if (!list_isempty(mac->neigh_list)) {
    1172           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1173           0 :                         zlog_debug(
    1174             :                                 "MAC %pEA (flags 0x%x vni %u) has non-empty neigh list "
    1175             :                                 "count %u, mark MAC as AUTO",
    1176             :                                 &mac->macaddr, mac->flags, zevpn->vni,
    1177             :                                 listcount(mac->neigh_list));
    1178             : 
    1179           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    1180           0 :                 return 0;
    1181             :         }
    1182             : 
    1183           0 :         list_delete(&mac->neigh_list);
    1184             : 
    1185             :         /* Free the VNI hash entry and allocated memory. */
    1186           0 :         tmp_mac = hash_release(zevpn->mac_table, mac);
    1187           0 :         XFREE(MTYPE_MAC, tmp_mac);
    1188             : 
    1189           0 :         return 0;
    1190             : }
    1191             : 
    1192             : /*
    1193             :  * Add Auto MAC entry.
    1194             :  */
    1195           0 : struct zebra_mac *zebra_evpn_mac_add_auto(struct zebra_evpn *zevpn,
    1196             :                                           const struct ethaddr *macaddr)
    1197             : {
    1198           0 :         struct zebra_mac *mac;
    1199             : 
    1200           0 :         mac = zebra_evpn_mac_add(zevpn, macaddr);
    1201           0 :         if (!mac)
    1202             :                 return NULL;
    1203             : 
    1204           0 :         zebra_evpn_mac_clear_fwd_info(mac);
    1205           0 :         memset(&mac->flags, 0, sizeof(uint32_t));
    1206           0 :         SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    1207             : 
    1208           0 :         return mac;
    1209             : }
    1210             : 
    1211           0 : static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
    1212             :                                              struct zebra_mac *mac)
    1213             : {
    1214           0 :         if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
    1215             :                 return true;
    1216           0 :         else if ((wctx->flags & DEL_REMOTE_MAC)
    1217           0 :                  && (mac->flags & ZEBRA_MAC_REMOTE))
    1218             :                 return true;
    1219           0 :         else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
    1220           0 :                  && (mac->flags & ZEBRA_MAC_REMOTE)
    1221           0 :                  && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
    1222             :                 return true;
    1223           0 :         else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
    1224           0 :                  && !listcount(mac->neigh_list)) {
    1225           0 :                 if (IS_ZEBRA_DEBUG_VXLAN) {
    1226           0 :                         char mac_buf[MAC_BUF_SIZE];
    1227             : 
    1228           0 :                         zlog_debug(
    1229             :                                 "%s: Del MAC %pEA flags %s", __func__,
    1230             :                                 &mac->macaddr,
    1231             :                                 zebra_evpn_zebra_mac_flag_dump(
    1232             :                                         mac, mac_buf, sizeof(mac_buf)));
    1233             :                 }
    1234           0 :                 wctx->uninstall = 0;
    1235             : 
    1236           0 :                 return true;
    1237             :         }
    1238             : 
    1239             :         return false;
    1240             : }
    1241             : 
    1242             : /*
    1243             :  * Free MAC hash entry (callback)
    1244             :  */
    1245           0 : static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
    1246             : {
    1247           0 :         struct mac_walk_ctx *wctx = arg;
    1248           0 :         struct zebra_mac *mac = bucket->data;
    1249             : 
    1250           0 :         if (zebra_evpn_check_mac_del_from_db(wctx, mac)) {
    1251           0 :                 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
    1252           0 :                         zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni,
    1253           0 :                                                           &mac->macaddr,
    1254             :                                                           mac->flags, false);
    1255             :                 }
    1256           0 :                 if (wctx->uninstall) {
    1257           0 :                         if (zebra_evpn_mac_is_static(mac))
    1258           0 :                                 zebra_evpn_sync_mac_dp_install(
    1259             :                                         mac, false /* set_inactive */,
    1260             :                                         true /* force_clear_static */,
    1261             :                                         __func__);
    1262             : 
    1263           0 :                         if (mac->flags & ZEBRA_MAC_REMOTE)
    1264           0 :                                 zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac,
    1265             :                                                              false /*force*/);
    1266             :                 }
    1267             : 
    1268           0 :                 zebra_evpn_mac_del(wctx->zevpn, mac);
    1269             :         }
    1270             : 
    1271           0 :         return;
    1272             : }
    1273             : 
    1274             : /*
    1275             :  * Delete all MAC entries for this EVPN.
    1276             :  */
    1277           0 : void zebra_evpn_mac_del_all(struct zebra_evpn *zevpn, int uninstall,
    1278             :                             int upd_client, uint32_t flags)
    1279             : {
    1280           0 :         struct mac_walk_ctx wctx;
    1281             : 
    1282           0 :         if (!zevpn->mac_table)
    1283           0 :                 return;
    1284             : 
    1285           0 :         memset(&wctx, 0, sizeof(wctx));
    1286           0 :         wctx.zevpn = zevpn;
    1287           0 :         wctx.uninstall = uninstall;
    1288           0 :         wctx.upd_client = upd_client;
    1289           0 :         wctx.flags = flags;
    1290             : 
    1291           0 :         hash_iterate(zevpn->mac_table, zebra_evpn_mac_del_hash_entry, &wctx);
    1292             : }
    1293             : 
    1294             : /*
    1295             :  * Look up MAC hash entry.
    1296             :  */
    1297           0 : struct zebra_mac *zebra_evpn_mac_lookup(struct zebra_evpn *zevpn,
    1298             :                                         const struct ethaddr *mac)
    1299             : {
    1300           0 :         struct zebra_mac tmp;
    1301           0 :         struct zebra_mac *pmac;
    1302             : 
    1303           0 :         memset(&tmp, 0, sizeof(tmp));
    1304           0 :         memcpy(&tmp.macaddr, mac, ETH_ALEN);
    1305           0 :         pmac = hash_lookup(zevpn->mac_table, &tmp);
    1306             : 
    1307           0 :         return pmac;
    1308             : }
    1309             : 
    1310             : /*
    1311             :  * Inform BGP about local MAC addition.
    1312             :  */
    1313           0 : int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
    1314             :                                       uint32_t mac_flags, uint32_t seq,
    1315             :                                       struct zebra_evpn_es *es)
    1316             : {
    1317           0 :         uint8_t flags = 0;
    1318             : 
    1319           0 :         if (CHECK_FLAG(mac_flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
    1320             :                 /* host reachability has not been verified locally */
    1321             : 
    1322             :                 /* if no ES peer is claiming reachability we can't advertise the
    1323             :                  * entry
    1324             :                  */
    1325           0 :                 if (!CHECK_FLAG(mac_flags, ZEBRA_MAC_ES_PEER_ACTIVE))
    1326             :                         return 0;
    1327             : 
    1328             :                 /* ES peers are claiming reachability; we will
    1329             :                  * advertise the entry but with a proxy flag
    1330             :                  */
    1331             :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT);
    1332             :         }
    1333             : 
    1334           0 :         if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
    1335           0 :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
    1336           0 :         if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
    1337           0 :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
    1338             : 
    1339           0 :         return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags,
    1340             :                                                    seq, ZEBRA_NEIGH_ACTIVE, es,
    1341             :                                                    ZEBRA_MACIP_ADD);
    1342             : }
    1343             : 
    1344             : /*
    1345             :  * Inform BGP about local MAC deletion.
    1346             :  */
    1347           0 : int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
    1348             :                                       uint32_t flags, bool force)
    1349             : {
    1350           0 :         if (!force) {
    1351           0 :                 if (CHECK_FLAG(flags, ZEBRA_MAC_LOCAL_INACTIVE)
    1352           0 :                     && !CHECK_FLAG(flags, ZEBRA_MAC_ES_PEER_ACTIVE))
    1353             :                         /* the host was not advertised - nothing  to delete */
    1354             :                         return 0;
    1355             :         }
    1356             : 
    1357           0 :         return zebra_evpn_macip_send_msg_to_client(
    1358             :                 vni, macaddr, NULL, 0 /* flags */, 0 /* seq */,
    1359             :                 ZEBRA_NEIGH_ACTIVE, NULL, ZEBRA_MACIP_DEL);
    1360             : }
    1361             : 
    1362             : /*
    1363             :  * wrapper to create a MAC hash table
    1364             :  */
    1365           0 : struct hash *zebra_mac_db_create(const char *desc)
    1366             : {
    1367           0 :         return hash_create_size(8, mac_hash_keymake, mac_cmp, desc);
    1368             : }
    1369             : 
    1370             : /* program sync mac flags in the dataplane  */
    1371           0 : int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
    1372             :                                    bool force_clear_static, const char *caller)
    1373             : {
    1374           0 :         struct interface *ifp;
    1375           0 :         bool sticky;
    1376           0 :         bool set_static;
    1377           0 :         struct zebra_evpn *zevpn = mac->zevpn;
    1378           0 :         vlanid_t vid;
    1379           0 :         struct zebra_if *zif;
    1380           0 :         struct interface *br_ifp;
    1381             : 
    1382             :         /* If the ES-EVI doesn't exist defer install. When the ES-EVI is
    1383             :          * created we will attempt to install the mac entry again
    1384             :          */
    1385           0 :         if (mac->es) {
    1386           0 :                 struct zebra_evpn_es_evi *es_evi;
    1387             : 
    1388           0 :                 es_evi = zebra_evpn_es_evi_find(mac->es, mac->zevpn);
    1389           0 :                 if (!es_evi) {
    1390           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    1391           0 :                                 zlog_debug(
    1392             :                                         "%s: dp-install sync-mac vni %u mac %pEA es %s 0x%x %sskipped, no es-evi",
    1393             :                                         caller, zevpn->vni, &mac->macaddr,
    1394             :                                         mac->es ? mac->es->esi_str : "-",
    1395             :                                         mac->flags,
    1396             :                                         set_inactive ? "inactive " : "");
    1397           0 :                         return -1;
    1398             :                 }
    1399             :         }
    1400             : 
    1401             :         /* get the access vlan from the vxlan_device */
    1402           0 :         zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
    1403             : 
    1404           0 :         if (!ifp) {
    1405           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1406           0 :                         char mac_buf[MAC_BUF_SIZE];
    1407             : 
    1408           0 :                         zlog_debug(
    1409             :                                 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
    1410             :                                 caller, zevpn->vni, &mac->macaddr,
    1411             :                                 mac->es ? mac->es->esi_str : "-",
    1412             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1413             :                                                                sizeof(mac_buf)),
    1414             :                                 set_inactive ? "inactive " : "");
    1415             :                 }
    1416           0 :                 return -1;
    1417             :         }
    1418             : 
    1419           0 :         zif = ifp->info;
    1420           0 :         br_ifp = zif->brslave_info.br_if;
    1421           0 :         if (!br_ifp) {
    1422           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1423           0 :                         char mac_buf[MAC_BUF_SIZE];
    1424             : 
    1425           0 :                         zlog_debug(
    1426             :                                 "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
    1427             :                                 caller, zevpn->vni, &mac->macaddr,
    1428             :                                 mac->es ? mac->es->esi_str : "-",
    1429             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1430             :                                                                sizeof(mac_buf)),
    1431             :                                 set_inactive ? "inactive " : "");
    1432             :                 }
    1433           0 :                 return -1;
    1434             :         }
    1435             : 
    1436           0 :         sticky = !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    1437           0 :         if (force_clear_static)
    1438             :                 set_static = false;
    1439             :         else
    1440           0 :                 set_static = zebra_evpn_mac_is_static(mac);
    1441             : 
    1442             :         /* We can install a local mac that has been synced from the peer
    1443             :          * over the VxLAN-overlay/network-port if fast failover is not
    1444             :          * supported and if the local ES is oper-down.
    1445             :          */
    1446           0 :         if (mac->es && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
    1447           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1448           0 :                         char mac_buf[MAC_BUF_SIZE];
    1449             : 
    1450           0 :                         zlog_debug(
    1451             :                                 "dp-%s sync-nw-mac vni %u mac %pEA es %s %s%s",
    1452             :                                 set_static ? "install" : "uninstall",
    1453             :                                 zevpn->vni, &mac->macaddr,
    1454             :                                 mac->es ? mac->es->esi_str : "-",
    1455             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1456             :                                                                sizeof(mac_buf)),
    1457             :                                 set_inactive ? "inactive " : "");
    1458             :                 }
    1459           0 :                 if (set_static)
    1460             :                         /* XXX - old_static needs to be computed more
    1461             :                          * accurately
    1462             :                          */
    1463           0 :                         zebra_evpn_rem_mac_install(zevpn, mac,
    1464             :                                                    true /* old_static */);
    1465             :                 else
    1466           0 :                         zebra_evpn_rem_mac_uninstall(zevpn, mac,
    1467             :                                                      false /* force */);
    1468             : 
    1469           0 :                 return 0;
    1470             :         }
    1471             : 
    1472           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1473           0 :                 char mac_buf[MAC_BUF_SIZE];
    1474             : 
    1475           0 :                 zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
    1476             :                            zevpn->vni, &mac->macaddr,
    1477             :                            mac->es ? mac->es->esi_str : "-",
    1478             :                            zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1479             :                                                           sizeof(mac_buf)),
    1480             :                            set_static ? "static " : "",
    1481             :                            set_inactive ? "inactive " : "");
    1482             :         }
    1483             : 
    1484           0 :         dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
    1485             :                              set_static, set_inactive);
    1486           0 :         return 0;
    1487             : }
    1488             : 
    1489           0 : void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac,
    1490             :                                            bool old_bgp_ready,
    1491             :                                            bool new_bgp_ready)
    1492             : {
    1493           0 :         if (new_bgp_ready)
    1494           0 :                 zebra_evpn_mac_send_add_to_client(mac->zevpn->vni,
    1495           0 :                                                   &mac->macaddr, mac->flags,
    1496             :                                                   mac->loc_seq, mac->es);
    1497           0 :         else if (old_bgp_ready)
    1498           0 :                 zebra_evpn_mac_send_del_to_client(mac->zevpn->vni,
    1499           0 :                                                   &mac->macaddr, mac->flags,
    1500             :                                                   true /* force */);
    1501           0 : }
    1502             : 
    1503             : /* MAC hold timer is used to age out peer-active flag.
    1504             :  *
    1505             :  * During this wait time we expect the dataplane component or an
    1506             :  * external neighmgr daemon to probe existing hosts to independently
    1507             :  * establish their presence on the ES.
    1508             :  */
    1509           0 : static void zebra_evpn_mac_hold_exp_cb(struct thread *t)
    1510             : {
    1511           0 :         struct zebra_mac *mac;
    1512           0 :         bool old_bgp_ready;
    1513           0 :         bool new_bgp_ready;
    1514           0 :         bool old_static;
    1515           0 :         bool new_static;
    1516             : 
    1517           0 :         mac = THREAD_ARG(t);
    1518             :         /* the purpose of the hold timer is to age out the peer-active
    1519             :          * flag
    1520             :          */
    1521           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
    1522             :                 return;
    1523             : 
    1524           0 :         old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    1525           0 :         old_static = zebra_evpn_mac_is_static(mac);
    1526           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
    1527           0 :         new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    1528           0 :         new_static = zebra_evpn_mac_is_static(mac);
    1529             : 
    1530           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1531           0 :                 char mac_buf[MAC_BUF_SIZE];
    1532             : 
    1533           0 :                 zlog_debug(
    1534             :                         "sync-mac vni %u mac %pEA es %s %shold expired",
    1535             :                         mac->zevpn->vni, &mac->macaddr,
    1536             :                         mac->es ? mac->es->esi_str : "-",
    1537             :                         zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1538             :                                                        sizeof(mac_buf)));
    1539             :         }
    1540             : 
    1541             :         /* re-program the local mac in the dataplane if the mac is no
    1542             :          * longer static
    1543             :          */
    1544           0 :         if (old_static != new_static)
    1545           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
    1546             :                                                false /* force_clear_static */,
    1547             :                                                __func__);
    1548             : 
    1549             :         /* inform bgp if needed */
    1550           0 :         if (old_bgp_ready != new_bgp_ready)
    1551           0 :                 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
    1552             :                                                       new_bgp_ready);
    1553             : }
    1554             : 
    1555           0 : static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
    1556             : {
    1557           0 :         if (mac->hold_timer)
    1558             :                 return;
    1559             : 
    1560           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1561           0 :                 char mac_buf[MAC_BUF_SIZE];
    1562             : 
    1563           0 :                 zlog_debug(
    1564             :                         "sync-mac vni %u mac %pEA es %s %shold started",
    1565             :                         mac->zevpn->vni, &mac->macaddr,
    1566             :                         mac->es ? mac->es->esi_str : "-",
    1567             :                         zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1568             :                                                        sizeof(mac_buf)));
    1569             :         }
    1570           0 :         thread_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
    1571             :                          zmh_info->mac_hold_time, &mac->hold_timer);
    1572             : }
    1573             : 
    1574           0 : void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac)
    1575             : {
    1576           0 :         if (!mac->hold_timer)
    1577             :                 return;
    1578             : 
    1579           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1580           0 :                 char mac_buf[MAC_BUF_SIZE];
    1581             : 
    1582           0 :                 zlog_debug(
    1583             :                         "sync-mac vni %u mac %pEA es %s %shold stopped",
    1584             :                         mac->zevpn->vni, &mac->macaddr,
    1585             :                         mac->es ? mac->es->esi_str : "-",
    1586             :                         zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1587             :                                                        sizeof(mac_buf)));
    1588             :         }
    1589             : 
    1590           0 :         THREAD_OFF(mac->hold_timer);
    1591             : }
    1592             : 
    1593           0 : void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
    1594             : {
    1595           0 :         bool old_static;
    1596           0 :         bool new_static;
    1597             : 
    1598           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1599           0 :                 char mac_buf[MAC_BUF_SIZE];
    1600             : 
    1601           0 :                 zlog_debug(
    1602             :                         "sync-mac del vni %u mac %pEA es %s seq %d f %s",
    1603             :                         mac->zevpn->vni, &mac->macaddr,
    1604             :                         mac->es ? mac->es->esi_str : "-", mac->loc_seq,
    1605             :                         zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1606             :                                                        sizeof(mac_buf)));
    1607             :         }
    1608             : 
    1609           0 :         old_static = zebra_evpn_mac_is_static(mac);
    1610           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
    1611           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
    1612           0 :                 zebra_evpn_mac_start_hold_timer(mac);
    1613           0 :         new_static = zebra_evpn_mac_is_static(mac);
    1614             : 
    1615           0 :         if (old_static != new_static)
    1616             :                 /* program the local mac in the kernel */
    1617           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
    1618             :                                                false /* force_clear_static */,
    1619             :                                                __func__);
    1620           0 : }
    1621             : 
    1622           0 : static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
    1623             :                                                 struct zebra_mac *mac,
    1624             :                                                 uint32_t seq, bool sync)
    1625             : {
    1626           0 :         char mac_buf[MAC_BUF_SIZE];
    1627           0 :         uint32_t tmp_seq;
    1628           0 :         const char *n_type;
    1629           0 :         bool is_local = false;
    1630             : 
    1631           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
    1632           0 :                 tmp_seq = mac->loc_seq;
    1633           0 :                 n_type = "local";
    1634           0 :                 is_local = true;
    1635             :         } else {
    1636           0 :                 tmp_seq = mac->rem_seq;
    1637           0 :                 n_type = "remote";
    1638             :         }
    1639             : 
    1640           0 :         if (seq < tmp_seq) {
    1641             : 
    1642           0 :                 if (is_local && !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) {
    1643           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN)
    1644           0 :                                 zlog_debug(
    1645             :                                         "%s-macip not ready vni %u %s-mac %pEA lower seq %u f 0x%x",
    1646             :                                         sync ? "sync" : "rem", zevpn->vni,
    1647             :                                         n_type, &mac->macaddr, tmp_seq,
    1648             :                                         mac->flags);
    1649           0 :                         return true;
    1650             :                 }
    1651             : 
    1652             :                 /* if the mac was never advertised to bgp we must accept
    1653             :                  * whatever sequence number bgp sends
    1654             :                  */
    1655           0 :                 if (!is_local && zebra_vxlan_get_accept_bgp_seq()) {
    1656           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC ||
    1657           0 :                             IS_ZEBRA_DEBUG_VXLAN) {
    1658           0 :                                 zlog_debug(
    1659             :                                         "%s-macip accept vni %u %s-mac %pEA lower seq %u f %s",
    1660             :                                         sync ? "sync" : "rem", zevpn->vni,
    1661             :                                         n_type, &mac->macaddr, tmp_seq,
    1662             :                                         zebra_evpn_zebra_mac_flag_dump(
    1663             :                                                 mac, mac_buf, sizeof(mac_buf)));
    1664             :                         }
    1665             : 
    1666           0 :                         return true;
    1667             :                 }
    1668             : 
    1669           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
    1670           0 :                         zlog_debug(
    1671             :                                 "%s-macip ignore vni %u %s-mac %pEA as existing has higher seq %u f %s",
    1672             :                                 sync ? "sync" : "rem", zevpn->vni, n_type,
    1673             :                                 &mac->macaddr, tmp_seq,
    1674             :                                 zebra_evpn_zebra_mac_flag_dump(
    1675             :                                         mac, mac_buf, sizeof(mac_buf)));
    1676             :                 }
    1677             : 
    1678           0 :                 return false;
    1679             :         }
    1680             : 
    1681             :         return true;
    1682             : }
    1683             : 
    1684           0 : struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
    1685             :                                                   const struct ethaddr *macaddr,
    1686             :                                                   uint16_t ipa_len,
    1687             :                                                   const struct ipaddr *ipaddr,
    1688             :                                                   uint8_t flags, uint32_t seq,
    1689             :                                                   const esi_t *esi)
    1690             : {
    1691           0 :         struct zebra_mac *mac;
    1692           0 :         bool inform_bgp = false;
    1693           0 :         bool inform_dataplane = false;
    1694           0 :         bool seq_change = false;
    1695           0 :         bool es_change = false;
    1696           0 :         uint32_t tmp_seq;
    1697           0 :         char ipbuf[INET6_ADDRSTRLEN];
    1698           0 :         bool old_local = false;
    1699           0 :         bool old_bgp_ready;
    1700           0 :         bool new_bgp_ready;
    1701           0 :         bool created = false;
    1702             : 
    1703           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    1704           0 :         if (!mac) {
    1705             :                 /* if it is a new local path we need to inform both
    1706             :                  * the control protocol and the data-plane
    1707             :                  */
    1708           0 :                 inform_bgp = true;
    1709           0 :                 inform_dataplane = true;
    1710             : 
    1711             :                 /* create the MAC and associate it with the dest ES */
    1712           0 :                 mac = zebra_evpn_mac_add(zevpn, macaddr);
    1713           0 :                 zebra_evpn_es_mac_ref(mac, esi);
    1714             : 
    1715             :                 /* local mac activated by an ES peer */
    1716           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
    1717             :                 /* if mac-only route setup peer flags */
    1718           0 :                 if (!ipa_len) {
    1719           0 :                         if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
    1720           0 :                                 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY);
    1721             :                         else
    1722           0 :                                 SET_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE);
    1723             :                 }
    1724           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
    1725           0 :                 old_bgp_ready = false;
    1726           0 :                 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    1727           0 :                 created = true;
    1728             :         } else {
    1729           0 :                 uint32_t old_flags;
    1730           0 :                 uint32_t new_flags;
    1731           0 :                 bool old_static;
    1732           0 :                 bool new_static;
    1733           0 :                 bool sticky;
    1734           0 :                 bool remote_gw;
    1735             : 
    1736           0 :                 mac->uptime = monotime(NULL);
    1737             : 
    1738           0 :                 old_flags = mac->flags;
    1739           0 :                 sticky = !!CHECK_FLAG(old_flags, ZEBRA_MAC_STICKY);
    1740           0 :                 remote_gw = !!CHECK_FLAG(old_flags, ZEBRA_MAC_REMOTE_DEF_GW);
    1741           0 :                 if (sticky || remote_gw) {
    1742           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
    1743           0 :                                 zlog_debug(
    1744             :                                         "Ignore sync-macip vni %u mac %pEA%s%s%s%s",
    1745             :                                         zevpn->vni, macaddr,
    1746             :                                         ipa_len ? " IP " : "",
    1747             :                                         ipa_len ? ipaddr2str(ipaddr, ipbuf,
    1748             :                                                              sizeof(ipbuf))
    1749             :                                                 : "",
    1750             :                                         sticky ? " sticky" : "",
    1751             :                                         remote_gw ? " remote_gw" : "");
    1752           0 :                         return NULL;
    1753             :                 }
    1754           0 :                 if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, true))
    1755             :                         return NULL;
    1756             : 
    1757           0 :                 old_local = !!CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL);
    1758           0 :                 old_static = zebra_evpn_mac_is_static(mac);
    1759             : 
    1760             :                 /* re-build the mac flags */
    1761           0 :                 new_flags = 0;
    1762           0 :                 SET_FLAG(new_flags, ZEBRA_MAC_LOCAL);
    1763             :                 /* retain old local activity flag */
    1764           0 :                 if (old_flags & ZEBRA_MAC_LOCAL)
    1765           0 :                         new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE);
    1766             :                 else
    1767             :                         new_flags |= ZEBRA_MAC_LOCAL_INACTIVE;
    1768             : 
    1769           0 :                 if (ipa_len) {
    1770             :                         /* if mac-ip route do NOT update the peer flags
    1771             :                          * i.e. retain only flags as is
    1772             :                          */
    1773           0 :                         new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS);
    1774             :                 } else {
    1775             :                         /* if mac-only route update peer flags */
    1776           0 :                         if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
    1777           0 :                                 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_PROXY);
    1778             :                                 /* if the mac was peer-active previously we
    1779             :                                  * need to keep the flag and start the
    1780             :                                  * holdtimer on it. the peer-active flag is
    1781             :                                  * cleared on holdtimer expiry.
    1782             :                                  */
    1783           0 :                                 if (CHECK_FLAG(old_flags,
    1784             :                                                ZEBRA_MAC_ES_PEER_ACTIVE)) {
    1785           0 :                                         SET_FLAG(new_flags,
    1786             :                                                  ZEBRA_MAC_ES_PEER_ACTIVE);
    1787           0 :                                         zebra_evpn_mac_start_hold_timer(mac);
    1788             :                                 }
    1789             :                         } else {
    1790           0 :                                 SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE);
    1791             :                                 /* stop hold timer if a peer has verified
    1792             :                                  * reachability
    1793             :                                  */
    1794           0 :                                 zebra_evpn_mac_stop_hold_timer(mac);
    1795             :                         }
    1796             :                 }
    1797           0 :                 mac->rem_seq = 0;
    1798           0 :                 zebra_evpn_mac_clear_fwd_info(mac);
    1799           0 :                 mac->flags = new_flags;
    1800             : 
    1801           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) {
    1802           0 :                         char mac_buf[MAC_BUF_SIZE], omac_buf[MAC_BUF_SIZE];
    1803           0 :                         struct zebra_mac omac;
    1804             : 
    1805           0 :                         omac.flags = old_flags;
    1806           0 :                         zlog_debug(
    1807             :                                 "sync-mac vni %u mac %pEA old_f %snew_f %s",
    1808             :                                 zevpn->vni, macaddr,
    1809             :                                 zebra_evpn_zebra_mac_flag_dump(
    1810             :                                         &omac, omac_buf, sizeof(omac_buf)),
    1811             :                                 zebra_evpn_zebra_mac_flag_dump(
    1812             :                                         mac, mac_buf, sizeof(mac_buf)));
    1813             :                 }
    1814             : 
    1815             :                 /* update es */
    1816           0 :                 es_change = zebra_evpn_es_mac_ref(mac, esi);
    1817             :                 /* if mac dest change - inform both sides */
    1818           0 :                 if (es_change) {
    1819             :                         inform_bgp = true;
    1820             :                         inform_dataplane = true;
    1821             :                 }
    1822             : 
    1823             :                 /* if peer-flag is being set notify dataplane that the
    1824             :                  * entry must not be expired because of local inactivity
    1825             :                  */
    1826           0 :                 new_static = zebra_evpn_mac_is_static(mac);
    1827           0 :                 if (old_static != new_static)
    1828           0 :                         inform_dataplane = true;
    1829             : 
    1830           0 :                 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(old_flags);
    1831           0 :                 new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    1832           0 :                 if (old_bgp_ready != new_bgp_ready)
    1833           0 :                         inform_bgp = true;
    1834             :         }
    1835             : 
    1836             : 
    1837             :         /* update sequence number; if that results in a new local sequence
    1838             :          * inform bgp
    1839             :          */
    1840           0 :         tmp_seq = MAX(mac->loc_seq, seq);
    1841           0 :         if (tmp_seq != mac->loc_seq) {
    1842           0 :                 mac->loc_seq = tmp_seq;
    1843           0 :                 seq_change = true;
    1844           0 :                 inform_bgp = true;
    1845             :         }
    1846             : 
    1847           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    1848           0 :                 char mac_buf[MAC_BUF_SIZE];
    1849             : 
    1850           0 :                 zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
    1851             :                            created ? "created" : "updated", zevpn->vni, macaddr,
    1852             :                            mac->es ? mac->es->esi_str : "-", mac->loc_seq,
    1853             :                            zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    1854             :                                                           sizeof(mac_buf)),
    1855             :                            inform_bgp ? "inform_bgp" : "",
    1856             :                            inform_dataplane ? " inform_dp" : "");
    1857             :         }
    1858             : 
    1859           0 :         if (inform_bgp)
    1860           0 :                 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
    1861             :                                                       new_bgp_ready);
    1862             : 
    1863             :         /* neighs using the mac may need to be re-sent to
    1864             :          * bgp with updated info
    1865             :          */
    1866           0 :         if (seq_change || es_change || !old_local)
    1867           0 :                 zebra_evpn_process_neigh_on_local_mac_change(
    1868             :                         zevpn, mac, seq_change, es_change);
    1869             : 
    1870           0 :         if (inform_dataplane && !ipa_len) {
    1871             :                 /* program the local mac in the kernel. when the ES
    1872             :                  * change we need to force the dataplane to reset
    1873             :                  * the activity as we are yet to establish activity
    1874             :                  * locally
    1875             :                  */
    1876           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
    1877             :                                                false /* force_clear_static */,
    1878             :                                                __func__);
    1879             :         }
    1880             : 
    1881             :         return mac;
    1882             : }
    1883             : 
    1884             : /* update local forwarding info. return true if a dest-ES change
    1885             :  * is detected
    1886             :  */
    1887           0 : static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
    1888             :                                                  struct interface *ifp,
    1889             :                                                  vlanid_t vid)
    1890             : {
    1891           0 :         struct zebra_if *zif = ifp->info;
    1892           0 :         bool es_change;
    1893           0 :         ns_id_t local_ns_id = NS_DEFAULT;
    1894           0 :         struct zebra_vrf *zvrf;
    1895           0 :         struct zebra_evpn_es *es;
    1896             : 
    1897           0 :         zvrf = ifp->vrf->info;
    1898           0 :         if (zvrf && zvrf->zns)
    1899           0 :                 local_ns_id = zvrf->zns->ns_id;
    1900             : 
    1901           0 :         zebra_evpn_mac_clear_fwd_info(mac);
    1902             : 
    1903           0 :         es = zif->es_info.es;
    1904           0 :         if (es && (es->flags & ZEBRA_EVPNES_BYPASS))
    1905           0 :                 es = NULL;
    1906           0 :         es_change = zebra_evpn_es_mac_ref_entry(mac, es);
    1907             : 
    1908           0 :         if (!mac->es) {
    1909             :                 /* if es is set fwd_info is not-relevant/taped-out */
    1910           0 :                 mac->fwd_info.local.ifindex = ifp->ifindex;
    1911           0 :                 mac->fwd_info.local.ns_id = local_ns_id;
    1912           0 :                 mac->fwd_info.local.vid = vid;
    1913           0 :                 zebra_evpn_mac_ifp_link(mac, ifp);
    1914             :         }
    1915             : 
    1916           0 :         return es_change;
    1917             : }
    1918             : 
    1919             : /* Notify Local MACs to the clienti, skips GW MAC */
    1920           0 : static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
    1921             :                                                      void *arg)
    1922             : {
    1923           0 :         struct mac_walk_ctx *wctx = arg;
    1924           0 :         struct zebra_mac *zmac = bucket->data;
    1925             : 
    1926           0 :         if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW))
    1927             :                 return;
    1928             : 
    1929           0 :         if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
    1930           0 :                 zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni,
    1931           0 :                                                   &zmac->macaddr, zmac->flags,
    1932             :                                                   zmac->loc_seq, zmac->es);
    1933             : }
    1934             : 
    1935             : /* Iterator to Notify Local MACs of a EVPN */
    1936           0 : void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn)
    1937             : {
    1938           0 :         struct mac_walk_ctx wctx;
    1939             : 
    1940           0 :         if (!zevpn->mac_table)
    1941           0 :                 return;
    1942             : 
    1943           0 :         memset(&wctx, 0, sizeof(wctx));
    1944           0 :         wctx.zevpn = zevpn;
    1945             : 
    1946           0 :         hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client,
    1947             :                      &wctx);
    1948             : }
    1949             : 
    1950           0 : void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
    1951             : {
    1952           0 :         zebra_evpn_process_neigh_on_remote_mac_del(zevpn, mac);
    1953             :         /* the remote sequence number in the auto mac entry
    1954             :          * needs to be reset to 0 as the mac entry may have
    1955             :          * been removed on all VTEPs (including
    1956             :          * the originating one)
    1957             :          */
    1958           0 :         mac->rem_seq = 0;
    1959             : 
    1960             :         /* If all remote neighbors referencing a remote MAC
    1961             :          * go away, we need to uninstall the MAC.
    1962             :          */
    1963           0 :         if (remote_neigh_count(mac) == 0) {
    1964           0 :                 zebra_evpn_rem_mac_uninstall(zevpn, mac, false /*force*/);
    1965           0 :                 zebra_evpn_es_mac_deref_entry(mac);
    1966           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
    1967             :         }
    1968             : 
    1969           0 :         if (list_isempty(mac->neigh_list))
    1970           0 :                 zebra_evpn_mac_del(zevpn, mac);
    1971             :         else
    1972           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    1973           0 : }
    1974             : 
    1975             : /* Print Duplicate MAC */
    1976           0 : void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
    1977             : {
    1978           0 :         struct zebra_mac *mac;
    1979             : 
    1980           0 :         mac = (struct zebra_mac *)bucket->data;
    1981           0 :         if (!mac)
    1982             :                 return;
    1983             : 
    1984           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
    1985           0 :                 zebra_evpn_print_mac_hash(bucket, ctxt);
    1986             : }
    1987             : 
    1988             : /* Print Duplicate MAC in detail */
    1989           0 : void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
    1990             :                                           void *ctxt)
    1991             : {
    1992           0 :         struct zebra_mac *mac;
    1993             : 
    1994           0 :         mac = (struct zebra_mac *)bucket->data;
    1995           0 :         if (!mac)
    1996             :                 return;
    1997             : 
    1998           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
    1999           0 :                 zebra_evpn_print_mac_hash_detail(bucket, ctxt);
    2000             : }
    2001             : 
    2002           0 : int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
    2003             :                                     struct zebra_vrf *zvrf,
    2004             :                                     const struct ethaddr *macaddr,
    2005             :                                     struct in_addr vtep_ip, uint8_t flags,
    2006             :                                     uint32_t seq, const esi_t *esi)
    2007             : {
    2008           0 :         bool sticky;
    2009           0 :         bool remote_gw;
    2010           0 :         int update_mac = 0;
    2011           0 :         bool do_dad = false;
    2012           0 :         bool is_dup_detect = false;
    2013           0 :         esi_t *old_esi;
    2014           0 :         bool old_static = false;
    2015           0 :         struct zebra_mac *mac;
    2016           0 :         bool old_es_present;
    2017           0 :         bool new_es_present;
    2018             : 
    2019           0 :         sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
    2020           0 :         remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
    2021             : 
    2022           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    2023             : 
    2024             :         /* Ignore if the mac is already present as a gateway mac */
    2025           0 :         if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)
    2026           0 :             && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
    2027           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2028           0 :                         zlog_debug(
    2029             :                                 "Ignore remote MACIP ADD VNI %u MAC %pEA as MAC is already configured as gateway MAC",
    2030             :                                 zevpn->vni, macaddr);
    2031           0 :                 return -1;
    2032             :         }
    2033             : 
    2034           0 :         old_esi = (mac && mac->es) ? &mac->es->esi : zero_esi;
    2035             : 
    2036             :         /* check if the remote MAC is unknown or has a change.
    2037             :          * If so, that needs to be updated first. Note that client could
    2038             :          * install MAC and MACIP separately or just install the latter.
    2039             :          */
    2040           0 :         if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
    2041           0 :             || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
    2042           0 :             || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
    2043           0 :             || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
    2044           0 :             || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq)
    2045           0 :                 update_mac = 1;
    2046             : 
    2047           0 :         if (update_mac) {
    2048           0 :                 if (!mac) {
    2049           0 :                         mac = zebra_evpn_mac_add(zevpn, macaddr);
    2050           0 :                         zebra_evpn_es_mac_ref(mac, esi);
    2051             :                 } else {
    2052             :                         /* When host moves but changes its (MAC,IP)
    2053             :                          * binding, BGP may install a MACIP entry that
    2054             :                          * corresponds to "older" location of the host
    2055             :                          * in transient situations (because {IP1,M1}
    2056             :                          * is a different route from {IP1,M2}). Check
    2057             :                          * the sequence number and ignore this update
    2058             :                          * if appropriate.
    2059             :                          */
    2060           0 :                         if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq,
    2061             :                                                           false))
    2062             :                                 return -1;
    2063             : 
    2064           0 :                         old_es_present = !!mac->es;
    2065           0 :                         zebra_evpn_es_mac_ref(mac, esi);
    2066           0 :                         new_es_present = !!mac->es;
    2067             :                         /* XXX - dataplane is curently not able to handle a MAC
    2068             :                          * replace if the destination changes from L2-NHG to
    2069             :                          * single VTEP and vice-versa. So delete the old entry
    2070             :                          * and re-install
    2071             :                          */
    2072           0 :                         if (old_es_present != new_es_present)
    2073           0 :                                 zebra_evpn_rem_mac_uninstall(zevpn, mac, false);
    2074             :                 }
    2075             : 
    2076             :                 /* Check MAC's curent state is local (this is the case
    2077             :                  * where MAC has moved from L->R) and check previous
    2078             :                  * detection started via local learning.
    2079             :                  * RFC-7432: A PE/VTEP that detects a MAC mobility
    2080             :                  * event via local learning starts an M-second timer.
    2081             :                  *
    2082             :                  * VTEP-IP or seq. change alone is not considered
    2083             :                  * for dup. detection.
    2084             :                  *
    2085             :                  * MAC is already marked duplicate set dad, then
    2086             :                  * is_dup_detect will be set to not install the entry.
    2087             :                  */
    2088           0 :                 if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
    2089           0 :                      && mac->dad_count)
    2090           0 :                     || CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
    2091           0 :                         do_dad = true;
    2092             : 
    2093             :                 /* Remove local MAC from BGP. */
    2094           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
    2095             :                         /* force drop the sync flags */
    2096           0 :                         old_static = zebra_evpn_mac_is_static(mac);
    2097           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    2098           0 :                                 char mac_buf[MAC_BUF_SIZE];
    2099             : 
    2100           0 :                                 zlog_debug(
    2101             :                                         "sync-mac->remote vni %u mac %pEA es %s seq %d f %s",
    2102             :                                         zevpn->vni, macaddr,
    2103             :                                         mac->es ? mac->es->esi_str : "-",
    2104             :                                         mac->loc_seq,
    2105             :                                         zebra_evpn_zebra_mac_flag_dump(
    2106             :                                                 mac, mac_buf, sizeof(mac_buf)));
    2107             :                         }
    2108             : 
    2109           0 :                         zebra_evpn_mac_clear_sync_info(mac);
    2110           0 :                         zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
    2111             :                                                           mac->flags,
    2112             :                                                           false /* force */);
    2113             :                 }
    2114             : 
    2115             :                 /* Set "auto" and "remote" forwarding info. */
    2116           0 :                 zebra_evpn_mac_clear_fwd_info(mac);
    2117           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
    2118           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
    2119           0 :                 mac->fwd_info.r_vtep_ip = vtep_ip;
    2120             : 
    2121           0 :                 if (sticky)
    2122           0 :                         SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2123             :                 else
    2124           0 :                         UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2125             : 
    2126           0 :                 if (remote_gw)
    2127           0 :                         SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
    2128             :                 else
    2129           0 :                         UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
    2130             : 
    2131           0 :                 zebra_evpn_dup_addr_detect_for_mac(
    2132             :                         zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad,
    2133             :                         &is_dup_detect, false);
    2134             : 
    2135           0 :                 if (!is_dup_detect) {
    2136           0 :                         zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
    2137             :                         /* Install the entry. */
    2138           0 :                         zebra_evpn_rem_mac_install(zevpn, mac, old_static);
    2139             :                 }
    2140             :         }
    2141             : 
    2142             :         /* Update seq number. */
    2143           0 :         mac->rem_seq = seq;
    2144             : 
    2145           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    2146           0 :         return 0;
    2147             : }
    2148             : 
    2149           0 : int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
    2150             :                                     struct zebra_evpn *zevpn,
    2151             :                                     struct interface *ifp,
    2152             :                                     const struct ethaddr *macaddr, vlanid_t vid,
    2153             :                                     bool sticky, bool local_inactive,
    2154             :                                     bool dp_static, struct zebra_mac *mac)
    2155             : {
    2156           0 :         bool mac_sticky = false;
    2157           0 :         bool inform_client = false;
    2158           0 :         bool upd_neigh = false;
    2159           0 :         bool is_dup_detect = false;
    2160           0 :         struct in_addr vtep_ip = {.s_addr = 0};
    2161           0 :         bool es_change = false;
    2162           0 :         bool new_bgp_ready;
    2163             :         /* assume inactive if not present or if not local */
    2164           0 :         bool old_local_inactive = true;
    2165           0 :         bool old_bgp_ready = false;
    2166           0 :         bool inform_dataplane = false;
    2167           0 :         bool new_static = false;
    2168             : 
    2169           0 :         assert(ifp);
    2170             :         /* Check if we need to create or update or it is a NO-OP. */
    2171           0 :         if (!mac)
    2172           0 :                 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    2173           0 :         if (!mac) {
    2174           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    2175           0 :                         zlog_debug(
    2176             :                                 "ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
    2177             :                                 sticky ? "sticky " : "", macaddr,
    2178             :                                 ifp->name, ifp->ifindex, vid, zevpn->vni,
    2179             :                                 local_inactive ? " local-inactive" : "");
    2180             : 
    2181           0 :                 mac = zebra_evpn_mac_add(zevpn, macaddr);
    2182           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
    2183           0 :                 es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
    2184           0 :                 if (sticky)
    2185           0 :                         SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2186             :                 inform_client = true;
    2187             :         } else {
    2188           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    2189           0 :                         char mac_buf[MAC_BUF_SIZE];
    2190             : 
    2191           0 :                         zlog_debug(
    2192             :                                 "UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
    2193             :                                 sticky ? "sticky " : "", macaddr,
    2194             :                                 ifp->name, ifp->ifindex, vid, zevpn->vni,
    2195             :                                 local_inactive ? "local-inactive " : "",
    2196             :                                 zebra_evpn_zebra_mac_flag_dump(
    2197             :                                         mac, mac_buf, sizeof(mac_buf)));
    2198             :                 }
    2199             : 
    2200           0 :                 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
    2201           0 :                         struct interface *old_ifp;
    2202           0 :                         vlanid_t old_vid;
    2203           0 :                         bool old_static;
    2204             : 
    2205           0 :                         zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
    2206           0 :                         old_bgp_ready =
    2207           0 :                                 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2208           0 :                         old_local_inactive =
    2209           0 :                                 !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
    2210           0 :                         old_static = zebra_evpn_mac_is_static(mac);
    2211           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
    2212           0 :                                 mac_sticky = true;
    2213           0 :                         es_change = zebra_evpn_local_mac_update_fwd_info(
    2214             :                                 mac, ifp, vid);
    2215             : 
    2216             :                         /*
    2217             :                          * Update any changes and if changes are relevant to
    2218             :                          * BGP, note it.
    2219             :                          */
    2220           0 :                         if (mac_sticky == sticky && old_ifp == ifp
    2221           0 :                             && old_vid == vid
    2222           0 :                             && old_local_inactive == local_inactive
    2223           0 :                             && dp_static == old_static && !es_change) {
    2224           0 :                                 if (IS_ZEBRA_DEBUG_VXLAN)
    2225           0 :                                         zlog_debug(
    2226             :                                                 "        Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
    2227             :                                                 "entry exists and has not changed ",
    2228             :                                                 sticky ? "sticky " : "",
    2229             :                                                 macaddr, ifp->name,
    2230             :                                                 ifp->ifindex, vid, zevpn->vni,
    2231             :                                                 local_inactive
    2232             :                                                         ? " local_inactive"
    2233             :                                                         : "");
    2234           0 :                                 return 0;
    2235             :                         }
    2236           0 :                         if (mac_sticky != sticky) {
    2237           0 :                                 if (sticky)
    2238           0 :                                         SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2239             :                                 else
    2240           0 :                                         UNSET_FLAG(mac->flags,
    2241             :                                                    ZEBRA_MAC_STICKY);
    2242             :                                 inform_client = true;
    2243             :                         }
    2244             : 
    2245             :                         /* If an es_change is detected we need to advertise
    2246             :                          * the route with a sequence that is one
    2247             :                          * greater. This is need to indicate a mac-move
    2248             :                          * to the ES peers
    2249             :                          */
    2250           0 :                         if (es_change) {
    2251             :                                 /* update the sequence number only if the entry
    2252             :                                  * is locally active
    2253             :                                  */
    2254           0 :                                 if (!local_inactive)
    2255           0 :                                         mac->loc_seq = mac->loc_seq + 1;
    2256             :                                 /* force drop the peer/sync info as it is
    2257             :                                  * simply no longer relevant
    2258             :                                  */
    2259           0 :                                 if (CHECK_FLAG(mac->flags,
    2260             :                                                ZEBRA_MAC_ALL_PEER_FLAGS)) {
    2261           0 :                                         zebra_evpn_mac_clear_sync_info(mac);
    2262           0 :                                         new_static =
    2263           0 :                                                 zebra_evpn_mac_is_static(mac);
    2264             :                                         /* if we clear peer-flags we
    2265             :                                          * also need to notify the dataplane
    2266             :                                          * to drop the static flag
    2267             :                                          */
    2268           0 :                                         if (old_static != new_static)
    2269           0 :                                                 inform_dataplane = true;
    2270             :                                 }
    2271             :                         }
    2272           0 :                 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
    2273           0 :                            || CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
    2274           0 :                         bool do_dad = false;
    2275             : 
    2276             :                         /*
    2277             :                          * MAC has either moved or was "internally" created due
    2278             :                          * to a neighbor learn and is now actually learnt. If
    2279             :                          * it was learnt as a remote sticky MAC, this is an
    2280             :                          * operator error.
    2281             :                          */
    2282           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
    2283           0 :                                 flog_warn(
    2284             :                                         EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
    2285             :                                         "MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
    2286             :                                         macaddr,
    2287             :                                         &mac->fwd_info.r_vtep_ip,
    2288             :                                         zevpn->vni);
    2289           0 :                                 return 0;
    2290             :                         }
    2291             : 
    2292             :                         /* If an actual move, compute MAC's seq number */
    2293           0 :                         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
    2294           0 :                                 mac->loc_seq =
    2295           0 :                                         MAX(mac->rem_seq + 1, mac->loc_seq);
    2296           0 :                                 vtep_ip = mac->fwd_info.r_vtep_ip;
    2297             :                                 /* Trigger DAD for remote MAC */
    2298           0 :                                 do_dad = true;
    2299             :                         }
    2300             : 
    2301           0 :                         UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
    2302           0 :                         UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    2303           0 :                         SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
    2304           0 :                         es_change = zebra_evpn_local_mac_update_fwd_info(
    2305             :                                 mac, ifp, vid);
    2306           0 :                         if (sticky)
    2307           0 :                                 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2308             :                         else
    2309           0 :                                 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2310             :                         /*
    2311             :                          * We have to inform BGP of this MAC as well as process
    2312             :                          * all neighbors.
    2313             :                          */
    2314           0 :                         inform_client = true;
    2315           0 :                         upd_neigh = true;
    2316             : 
    2317           0 :                         zebra_evpn_dup_addr_detect_for_mac(
    2318             :                                 zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
    2319             :                                 true);
    2320           0 :                         if (is_dup_detect) {
    2321           0 :                                 inform_client = false;
    2322           0 :                                 upd_neigh = false;
    2323           0 :                                 es_change = false;
    2324             :                         }
    2325             :                 }
    2326             :         }
    2327             : 
    2328             :         /* if the dataplane thinks the entry is sync but it is
    2329             :          * not sync in zebra (or vice-versa) we need to re-install
    2330             :          * to fixup
    2331             :          */
    2332           0 :         new_static = zebra_evpn_mac_is_static(mac);
    2333           0 :         if (dp_static != new_static)
    2334           0 :                 inform_dataplane = true;
    2335             : 
    2336           0 :         if (local_inactive)
    2337           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
    2338             :         else
    2339           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
    2340             : 
    2341           0 :         new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2342             :         /* if local-activity has changed we need update bgp
    2343             :          * even if bgp already knows about the mac
    2344             :          */
    2345           0 :         if ((old_local_inactive != local_inactive)
    2346           0 :             || (new_bgp_ready != old_bgp_ready)) {
    2347           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    2348           0 :                         char mac_buf[MAC_BUF_SIZE];
    2349             : 
    2350           0 :                         zlog_debug(
    2351             :                                 "local mac vni %u mac %pEA es %s seq %d f %s%s",
    2352             :                                 zevpn->vni, macaddr,
    2353             :                                 mac->es ? mac->es->esi_str : "", mac->loc_seq,
    2354             :                                 zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
    2355             :                                                                sizeof(mac_buf)),
    2356             :                                 local_inactive ? "local-inactive" : "");
    2357             :                 }
    2358             : 
    2359           0 :                 if (!is_dup_detect)
    2360           0 :                         inform_client = true;
    2361             :         }
    2362             : 
    2363           0 :         if (es_change) {
    2364           0 :                 inform_client = true;
    2365           0 :                 upd_neigh = true;
    2366             :         }
    2367             : 
    2368             :         /* Inform dataplane if required. */
    2369           0 :         if (inform_dataplane)
    2370           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
    2371             :                                                false /* force_clear_static */,
    2372             :                                                __func__);
    2373             : 
    2374             :         /* Inform BGP if required. */
    2375           0 :         if (inform_client)
    2376           0 :                 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
    2377             :                                                       new_bgp_ready);
    2378             : 
    2379             :         /* Process all neighbors associated with this MAC, if required. */
    2380           0 :         if (upd_neigh)
    2381           0 :                 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
    2382             :                                                              es_change);
    2383             : 
    2384             :         return 0;
    2385             : }
    2386             : 
    2387           0 : int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
    2388             :                              bool clear_static)
    2389             : {
    2390           0 :         bool old_bgp_ready;
    2391           0 :         bool new_bgp_ready;
    2392             : 
    2393           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    2394           0 :                 zlog_debug("DEL MAC %pEA VNI %u seq %u flags 0x%x nbr count %u",
    2395             :                            &mac->macaddr, zevpn->vni, mac->loc_seq, mac->flags,
    2396             :                            listcount(mac->neigh_list));
    2397             : 
    2398           0 :         old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2399           0 :         if (!clear_static && zebra_evpn_mac_is_static(mac)) {
    2400             :                 /* this is a synced entry and can only be removed when the
    2401             :                  * es-peers stop advertising it.
    2402             :                  */
    2403           0 :                 zebra_evpn_mac_clear_fwd_info(mac);
    2404             : 
    2405           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
    2406           0 :                         char mac_buf[MAC_BUF_SIZE];
    2407             : 
    2408           0 :                         zlog_debug(
    2409             :                                 "re-add sync-mac vni %u mac %pEA es %s seq %d f %s",
    2410             :                                 zevpn->vni, &mac->macaddr,
    2411             :                                 mac->es ? mac->es->esi_str : "-", mac->loc_seq,
    2412             :                                 zebra_evpn_zebra_mac_flag_dump(
    2413             :                                         mac, mac_buf, sizeof(mac_buf)));
    2414             :                 }
    2415             : 
    2416             :                 /* inform-bgp about change in local-activity if any */
    2417           0 :                 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
    2418           0 :                         SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
    2419           0 :                         new_bgp_ready =
    2420           0 :                                 zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2421           0 :                         zebra_evpn_mac_send_add_del_to_client(
    2422             :                                 mac, old_bgp_ready, new_bgp_ready);
    2423             :                 }
    2424             : 
    2425             :                 /* re-install the inactive entry in the kernel */
    2426           0 :                 zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */,
    2427             :                                                false /* force_clear_static */,
    2428             :                                                __func__);
    2429             : 
    2430           0 :                 return 0;
    2431             :         }
    2432             : 
    2433             :         /* flush the peer info */
    2434           0 :         zebra_evpn_mac_clear_sync_info(mac);
    2435             : 
    2436             :         /* Update all the neigh entries associated with this mac */
    2437           0 :         zebra_evpn_process_neigh_on_local_mac_del(zevpn, mac);
    2438             : 
    2439             :         /* Remove MAC from BGP. */
    2440           0 :         zebra_evpn_mac_send_del_to_client(zevpn->vni, &mac->macaddr, mac->flags,
    2441             :                                           false /* force */);
    2442             : 
    2443           0 :         zebra_evpn_es_mac_deref_entry(mac);
    2444             : 
    2445             :         /* remove links to the destination access port */
    2446           0 :         zebra_evpn_mac_clear_fwd_info(mac);
    2447             : 
    2448             :         /*
    2449             :          * If there are no neigh associated with the mac delete the mac
    2450             :          * else mark it as AUTO for forward reference
    2451             :          */
    2452           0 :         if (!listcount(mac->neigh_list)) {
    2453           0 :                 zebra_evpn_mac_del(zevpn, mac);
    2454             :         } else {
    2455           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
    2456           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    2457           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    2458             :         }
    2459             : 
    2460             :         return 0;
    2461             : }
    2462             : 
    2463           0 : void zebra_evpn_mac_gw_macip_add(struct interface *ifp,
    2464             :                                  struct zebra_evpn *zevpn,
    2465             :                                  const struct ipaddr *ip,
    2466             :                                  struct zebra_mac **macp,
    2467             :                                  const struct ethaddr *macaddr,
    2468             :                                  vlanid_t vlan_id, bool def_gw)
    2469             : {
    2470           0 :         struct zebra_mac *mac;
    2471           0 :         ns_id_t local_ns_id = NS_DEFAULT;
    2472           0 :         struct zebra_vrf *zvrf;
    2473             : 
    2474           0 :         zvrf = ifp->vrf->info;
    2475           0 :         if (zvrf && zvrf->zns)
    2476           0 :                 local_ns_id = zvrf->zns->ns_id;
    2477             : 
    2478           0 :         if (!*macp) {
    2479           0 :                 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    2480           0 :                 if (!mac)
    2481           0 :                         mac = zebra_evpn_mac_add(zevpn, macaddr);
    2482           0 :                 *macp = mac;
    2483             :         } else
    2484             :                 mac = *macp;
    2485             : 
    2486             :         /* Set "local" forwarding info. */
    2487           0 :         zebra_evpn_mac_clear_fwd_info(mac);
    2488           0 :         SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
    2489           0 :         SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    2490           0 :         if (def_gw)
    2491           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
    2492             :         else
    2493           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
    2494           0 :         mac->fwd_info.local.ifindex = ifp->ifindex;
    2495           0 :         mac->fwd_info.local.ns_id = local_ns_id;
    2496           0 :         mac->fwd_info.local.vid = vlan_id;
    2497           0 : }
    2498             : 
    2499           0 : void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
    2500             : {
    2501           0 :         struct zebra_mac *mac;
    2502           0 :         struct ethaddr macaddr;
    2503           0 :         bool old_bgp_ready;
    2504             : 
    2505           0 :         if (!zebra_evpn_mh_do_adv_svi_mac())
    2506           0 :                 return;
    2507             : 
    2508           0 :         memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
    2509           0 :         mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
    2510           0 :         if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI)) {
    2511           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
    2512           0 :                         zlog_debug("SVI %s mac free", ifp->name);
    2513             : 
    2514           0 :                 old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2515           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
    2516           0 :                 zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
    2517             :                                                       false);
    2518           0 :                 zebra_evpn_deref_ip2mac(mac->zevpn, mac);
    2519             :         }
    2520             : }
    2521             : 
    2522           0 : void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
    2523             : {
    2524           0 :         struct zebra_mac *mac = NULL;
    2525           0 :         struct ethaddr macaddr;
    2526           0 :         struct zebra_if *zif = ifp->info;
    2527           0 :         bool old_bgp_ready;
    2528           0 :         bool new_bgp_ready;
    2529             : 
    2530           0 :         if (!zebra_evpn_mh_do_adv_svi_mac()
    2531           0 :             || !zebra_evpn_send_to_client_ok(zevpn))
    2532           0 :                 return;
    2533             : 
    2534           0 :         memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
    2535             : 
    2536             :         /* dup check */
    2537           0 :         mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
    2538           0 :         if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
    2539             :                 return;
    2540             : 
    2541             :         /* add/update mac */
    2542           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
    2543           0 :                 zlog_debug("SVI %s mac add", zif->ifp->name);
    2544             : 
    2545           0 :         old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
    2546             :                                 ? true
    2547           0 :                                 : false;
    2548             : 
    2549           0 :         zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
    2550             : 
    2551           0 :         new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
    2552           0 :         zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
    2553             :                                               new_bgp_ready);
    2554             : }

Generated by: LCOV version v1.16-topotato