back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_evpn_neigh.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 1 1083 0.1 %
Date: 2023-02-24 19:38:44 Functions: 2 54 3.7 %

          Line data    Source code
       1             : /*
       2             :  * Zebra EVPN Neighbor 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             : 
      33             : #include "zebra/zserv.h"
      34             : #include "zebra/debug.h"
      35             : #include "zebra/zebra_router.h"
      36             : #include "zebra/rt.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_neigh.h"
      42             : #include "zebra/zebra_evpn_mac.h"
      43             : 
      44         279 : DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "EVI Neighbor");
      45             : 
      46             : /*
      47             :  * Make hash key for neighbors.
      48             :  */
      49           0 : static unsigned int neigh_hash_keymake(const void *p)
      50             : {
      51           0 :         const struct zebra_neigh *n = p;
      52           0 :         const struct ipaddr *ip = &n->ip;
      53             : 
      54           0 :         if (IS_IPADDR_V4(ip))
      55           0 :                 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
      56             : 
      57           0 :         return jhash2(ip->ipaddr_v6.s6_addr32,
      58             :                       array_size(ip->ipaddr_v6.s6_addr32), 0);
      59             : }
      60             : 
      61             : /*
      62             :  * Compare two neighbor hash structures.
      63             :  */
      64           0 : static bool neigh_cmp(const void *p1, const void *p2)
      65             : {
      66           0 :         const struct zebra_neigh *n1 = p1;
      67           0 :         const struct zebra_neigh *n2 = p2;
      68             : 
      69           0 :         if (n1 == NULL && n2 == NULL)
      70             :                 return true;
      71             : 
      72           0 :         if (n1 == NULL || n2 == NULL)
      73             :                 return false;
      74             : 
      75           0 :         return ipaddr_cmp(&n1->ip, &n2->ip) == 0;
      76             : }
      77             : 
      78           0 : int neigh_list_cmp(void *p1, void *p2)
      79             : {
      80           0 :         const struct zebra_neigh *n1 = p1;
      81           0 :         const struct zebra_neigh *n2 = p2;
      82             : 
      83           0 :         return ipaddr_cmp(&n1->ip, &n2->ip);
      84             : }
      85             : 
      86           0 : struct hash *zebra_neigh_db_create(const char *desc)
      87             : {
      88           0 :         return hash_create_size(8, neigh_hash_keymake, neigh_cmp, desc);
      89             : }
      90             : 
      91           0 : uint32_t num_dup_detected_neighs(struct zebra_evpn *zevpn)
      92             : {
      93           0 :         unsigned int i;
      94           0 :         uint32_t num_neighs = 0;
      95           0 :         struct hash *hash;
      96           0 :         struct hash_bucket *hb;
      97           0 :         struct zebra_neigh *nbr;
      98             : 
      99           0 :         hash = zevpn->neigh_table;
     100           0 :         if (!hash)
     101             :                 return num_neighs;
     102           0 :         for (i = 0; i < hash->size; i++) {
     103           0 :                 for (hb = hash->index[i]; hb; hb = hb->next) {
     104           0 :                         nbr = (struct zebra_neigh *)hb->data;
     105           0 :                         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
     106           0 :                                 num_neighs++;
     107             :                 }
     108             :         }
     109             : 
     110             :         return num_neighs;
     111             : }
     112             : 
     113             : /*
     114             :  * Helper function to determine maximum width of neighbor IP address for
     115             :  * display - just because we're dealing with IPv6 addresses that can
     116             :  * widely vary.
     117             :  */
     118           0 : void zebra_evpn_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt)
     119             : {
     120           0 :         struct zebra_neigh *n;
     121           0 :         char buf[INET6_ADDRSTRLEN];
     122           0 :         struct neigh_walk_ctx *wctx = ctxt;
     123           0 :         int width;
     124             : 
     125           0 :         n = (struct zebra_neigh *)bucket->data;
     126             : 
     127           0 :         ipaddr2str(&n->ip, buf, sizeof(buf));
     128           0 :         width = strlen(buf);
     129           0 :         if (width > wctx->addr_width)
     130           0 :                 wctx->addr_width = width;
     131           0 : }
     132             : 
     133             : /*
     134             :  * Count of remote neighbors referencing this MAC.
     135             :  */
     136           0 : int remote_neigh_count(struct zebra_mac *zmac)
     137             : {
     138           0 :         struct zebra_neigh *n = NULL;
     139           0 :         struct listnode *node = NULL;
     140           0 :         int count = 0;
     141             : 
     142           0 :         for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
     143           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
     144           0 :                         count++;
     145             :         }
     146             : 
     147           0 :         return count;
     148             : }
     149             : 
     150             : /*
     151             :  * Install remote neighbor into the kernel.
     152             :  */
     153           0 : int zebra_evpn_rem_neigh_install(struct zebra_evpn *zevpn,
     154             :                                  struct zebra_neigh *n, bool was_static)
     155             : {
     156           0 :         struct interface *vlan_if;
     157           0 :         int flags;
     158           0 :         int ret = 0;
     159             : 
     160           0 :         if (!(n->flags & ZEBRA_NEIGH_REMOTE))
     161             :                 return 0;
     162             : 
     163           0 :         vlan_if = zevpn_map_to_svi(zevpn);
     164           0 :         if (!vlan_if)
     165             :                 return -1;
     166             : 
     167           0 :         flags = DPLANE_NTF_EXT_LEARNED;
     168           0 :         if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
     169           0 :                 flags |= DPLANE_NTF_ROUTER;
     170           0 :         ZEBRA_NEIGH_SET_ACTIVE(n);
     171             : 
     172           0 :         dplane_rem_neigh_add(vlan_if, &n->ip, &n->emac, flags, was_static);
     173             : 
     174           0 :         return ret;
     175             : }
     176             : 
     177             : /*
     178             :  * Install neighbor hash entry - called upon access VLAN change.
     179             :  */
     180           0 : void zebra_evpn_install_neigh_hash(struct hash_bucket *bucket, void *ctxt)
     181             : {
     182           0 :         struct zebra_neigh *n;
     183           0 :         struct neigh_walk_ctx *wctx = ctxt;
     184             : 
     185           0 :         n = (struct zebra_neigh *)bucket->data;
     186             : 
     187           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
     188           0 :                 zebra_evpn_rem_neigh_install(wctx->zevpn, n,
     189             :                                              false /*was_static*/);
     190           0 : }
     191             : 
     192             : /*
     193             :  * Callback to allocate neighbor hash entry.
     194             :  */
     195           0 : static void *zebra_evpn_neigh_alloc(void *p)
     196             : {
     197           0 :         const struct zebra_neigh *tmp_n = p;
     198           0 :         struct zebra_neigh *n;
     199             : 
     200           0 :         n = XCALLOC(MTYPE_NEIGH, sizeof(struct zebra_neigh));
     201           0 :         *n = *tmp_n;
     202             : 
     203           0 :         return ((void *)n);
     204             : }
     205             : 
     206           0 : static void zebra_evpn_local_neigh_ref_mac(struct zebra_neigh *n,
     207             :                                            const struct ethaddr *macaddr,
     208             :                                            struct zebra_mac *mac,
     209             :                                            bool send_mac_update)
     210             : {
     211           0 :         bool old_static;
     212           0 :         bool new_static;
     213             : 
     214           0 :         memcpy(&n->emac, macaddr, ETH_ALEN);
     215           0 :         n->mac = mac;
     216             : 
     217             :         /* Link to new MAC */
     218           0 :         if (!mac)
     219             :                 return;
     220             : 
     221           0 :         listnode_add_sort(mac->neigh_list, n);
     222           0 :         if (n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) {
     223           0 :                 old_static = zebra_evpn_mac_is_static(mac);
     224           0 :                 ++mac->sync_neigh_cnt;
     225           0 :                 new_static = zebra_evpn_mac_is_static(mac);
     226           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     227           0 :                         zlog_debug(
     228             :                                 "sync-neigh ref mac vni %u ip %pIA mac %pEA ref %d",
     229             :                                 n->zevpn->vni, &n->ip, &n->emac,
     230             :                                 mac->sync_neigh_cnt);
     231           0 :                 if ((old_static != new_static) && send_mac_update)
     232             :                         /* program the local mac in the kernel */
     233           0 :                         zebra_evpn_sync_mac_dp_install(
     234             :                                 mac, false /*set_inactive*/,
     235             :                                 false /*force_clear_static*/, __func__);
     236             :         }
     237             : }
     238             : 
     239             : /* sync-path that is active on an ES peer */
     240           0 : static void zebra_evpn_sync_neigh_dp_install(struct zebra_neigh *n,
     241             :                                              bool set_inactive,
     242             :                                              bool force_clear_static,
     243             :                                              const char *caller)
     244             : {
     245           0 :         struct zebra_ns *zns;
     246           0 :         struct interface *ifp;
     247           0 :         bool set_static;
     248           0 :         bool set_router;
     249             : 
     250           0 :         zns = zebra_ns_lookup(NS_DEFAULT);
     251           0 :         ifp = if_lookup_by_index_per_ns(zns, n->ifindex);
     252           0 :         if (!ifp) {
     253           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     254           0 :                         zlog_debug(
     255             :                                 "%s: dp-install sync-neigh vni %u ip %pIA mac %pEA if %d f 0x%x skipped",
     256             :                                 caller, n->zevpn->vni, &n->ip, &n->emac,
     257             :                                 n->ifindex, n->flags);
     258           0 :                 return;
     259             :         }
     260             : 
     261           0 :         if (force_clear_static)
     262             :                 set_static = false;
     263             :         else
     264           0 :                 set_static = zebra_evpn_neigh_is_static(n);
     265             : 
     266           0 :         set_router = !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
     267             : 
     268             :         /* XXX - this will change post integration with the new kernel */
     269           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
     270           0 :                 set_inactive = true;
     271             : 
     272           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     273           0 :                 zlog_debug(
     274             :                         "%s: dp-install sync-neigh vni %u ip %pIA mac %pEA if %s(%d) f 0x%x%s%s%s",
     275             :                         caller, n->zevpn->vni, &n->ip, &n->emac,
     276             :                         ifp->name, n->ifindex, n->flags,
     277             :                         set_router ? " router" : "",
     278             :                         set_static ? " static" : "",
     279             :                         set_inactive ? " inactive" : "");
     280           0 :         dplane_local_neigh_add(ifp, &n->ip, &n->emac, set_router, set_static,
     281             :                                set_inactive);
     282             : }
     283             : 
     284             : /*
     285             :  * Inform BGP about local neighbor addition.
     286             :  */
     287           0 : int zebra_evpn_neigh_send_add_to_client(vni_t vni, const struct ipaddr *ip,
     288             :                                         const struct ethaddr *macaddr,
     289             :                                         struct zebra_mac *zmac,
     290             :                                         uint32_t neigh_flags, uint32_t seq)
     291             : {
     292           0 :         uint8_t flags = 0;
     293             : 
     294           0 :         if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_LOCAL_INACTIVE)) {
     295             :                 /* host reachability has not been verified locally */
     296             : 
     297             :                 /* if no ES peer is claiming reachability we can't advertise
     298             :                  * the entry
     299             :                  */
     300           0 :                 if (!CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
     301             :                         return 0;
     302             : 
     303             :                 /* ES peers are claiming reachability; we will
     304             :                  * advertise the entry but with a proxy flag
     305             :                  */
     306             :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT);
     307             :         }
     308             : 
     309           0 :         if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
     310           0 :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
     311             :         /* Set router flag (R-bit) based on local neigh entry add */
     312           0 :         if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
     313           0 :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
     314           0 :         if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_SVI_IP))
     315           0 :                 SET_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP);
     316             : 
     317           0 :         return zebra_evpn_macip_send_msg_to_client(vni, macaddr, ip, flags, seq,
     318             :                                                    ZEBRA_NEIGH_ACTIVE, zmac->es,
     319             :                                                    ZEBRA_MACIP_ADD);
     320             : }
     321             : 
     322             : /*
     323             :  * Inform BGP about local neighbor deletion.
     324             :  */
     325           0 : int zebra_evpn_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
     326             :                                         struct ethaddr *macaddr, uint32_t flags,
     327             :                                         int state, bool force)
     328             : {
     329           0 :         if (!force) {
     330           0 :                 if (CHECK_FLAG(flags, ZEBRA_NEIGH_LOCAL_INACTIVE)
     331           0 :                     && !CHECK_FLAG(flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
     332             :                         /* the neigh was not advertised - nothing  to delete */
     333             :                         return 0;
     334             :         }
     335             : 
     336           0 :         return zebra_evpn_macip_send_msg_to_client(
     337             :                 vni, macaddr, ip, flags, 0, state, NULL, ZEBRA_MACIP_DEL);
     338             : }
     339             : 
     340           0 : static void zebra_evpn_neigh_send_add_del_to_client(struct zebra_neigh *n,
     341             :                                                     bool old_bgp_ready,
     342             :                                                     bool new_bgp_ready)
     343             : {
     344           0 :         if (new_bgp_ready)
     345           0 :                 zebra_evpn_neigh_send_add_to_client(n->zevpn->vni, &n->ip,
     346           0 :                                                     &n->emac, n->mac, n->flags,
     347             :                                                     n->loc_seq);
     348           0 :         else if (old_bgp_ready)
     349           0 :                 zebra_evpn_neigh_send_del_to_client(n->zevpn->vni, &n->ip,
     350             :                                                     &n->emac, n->flags,
     351           0 :                                                     n->state, true /*force*/);
     352           0 : }
     353             : 
     354             : /* if the static flag associated with the neigh changes we need
     355             :  * to update the sync-neigh references against the MAC
     356             :  * and inform the dataplane about the static flag changes.
     357             :  */
     358           0 : void zebra_evpn_sync_neigh_static_chg(struct zebra_neigh *n, bool old_n_static,
     359             :                                       bool new_n_static, bool defer_n_dp,
     360             :                                       bool defer_mac_dp, const char *caller)
     361             : {
     362           0 :         struct zebra_mac *mac = n->mac;
     363           0 :         bool old_mac_static;
     364           0 :         bool new_mac_static;
     365             : 
     366           0 :         if (old_n_static == new_n_static)
     367             :                 return;
     368             : 
     369             :         /* update the neigh sync references in the dataplane. if
     370             :          * the neigh is in the middle of updates the caller can
     371             :          * request for a defer
     372             :          */
     373           0 :         if (!defer_n_dp)
     374           0 :                 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
     375             :                                                  false /* force_clear_static */,
     376             :                                                  __func__);
     377             : 
     378           0 :         if (!mac)
     379             :                 return;
     380             : 
     381             :         /* update the mac sync ref cnt */
     382           0 :         old_mac_static = zebra_evpn_mac_is_static(mac);
     383           0 :         if (new_n_static) {
     384           0 :                 ++mac->sync_neigh_cnt;
     385           0 :         } else if (old_n_static) {
     386           0 :                 if (mac->sync_neigh_cnt)
     387           0 :                         --mac->sync_neigh_cnt;
     388             :         }
     389           0 :         new_mac_static = zebra_evpn_mac_is_static(mac);
     390             : 
     391             :         /* update the mac sync references in the dataplane */
     392           0 :         if ((old_mac_static != new_mac_static) && !defer_mac_dp)
     393           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
     394             :                                                false /* force_clear_static */,
     395             :                                                __func__);
     396             : 
     397           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     398           0 :                 zlog_debug(
     399             :                         "sync-neigh ref-chg vni %u ip %pIA mac %pEA f 0x%x %d%s%s%s%s by %s",
     400             :                         n->zevpn->vni, &n->ip, &n->emac, n->flags,
     401             :                         mac->sync_neigh_cnt,
     402             :                         old_n_static ? " old_n_static" : "",
     403             :                         new_n_static ? " new_n_static" : "",
     404             :                         old_mac_static ? " old_mac_static" : "",
     405             :                         new_mac_static ? " new_mac_static" : "", caller);
     406             : }
     407             : 
     408             : /* Neigh hold timer is used to age out peer-active flag.
     409             :  *
     410             :  * During this wait time we expect the dataplane component or an
     411             :  * external neighmgr daemon to probe existing hosts to independently
     412             :  * establish their presence on the ES.
     413             :  */
     414           0 : static void zebra_evpn_neigh_hold_exp_cb(struct thread *t)
     415             : {
     416           0 :         struct zebra_neigh *n;
     417           0 :         bool old_bgp_ready;
     418           0 :         bool new_bgp_ready;
     419           0 :         bool old_n_static;
     420           0 :         bool new_n_static;
     421             : 
     422           0 :         n = THREAD_ARG(t);
     423             :         /* the purpose of the hold timer is to age out the peer-active
     424             :          * flag
     425             :          */
     426           0 :         if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
     427             :                 return;
     428             : 
     429           0 :         old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
     430           0 :         old_n_static = zebra_evpn_neigh_is_static(n);
     431           0 :         UNSET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
     432           0 :         new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
     433           0 :         new_n_static = zebra_evpn_neigh_is_static(n);
     434             : 
     435           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     436           0 :                 zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold expired",
     437             :                            n->zevpn->vni, &n->ip, &n->emac, n->flags);
     438             : 
     439             :         /* re-program the local neigh in the dataplane if the neigh is no
     440             :          * longer static
     441             :          */
     442           0 :         if (old_n_static != new_n_static)
     443           0 :                 zebra_evpn_sync_neigh_static_chg(
     444             :                         n, old_n_static, new_n_static, false /*defer_n_dp*/,
     445             :                         false /*defer_mac_dp*/, __func__);
     446             : 
     447             :         /* inform bgp if needed */
     448           0 :         if (old_bgp_ready != new_bgp_ready)
     449           0 :                 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
     450             :                                                         new_bgp_ready);
     451             : }
     452             : 
     453           0 : static inline void zebra_evpn_neigh_start_hold_timer(struct zebra_neigh *n)
     454             : {
     455           0 :         if (n->hold_timer)
     456             :                 return;
     457             : 
     458           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     459           0 :                 zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold start",
     460             :                            n->zevpn->vni, &n->ip, &n->emac, n->flags);
     461           0 :         thread_add_timer(zrouter.master, zebra_evpn_neigh_hold_exp_cb, n,
     462             :                          zmh_info->neigh_hold_time, &n->hold_timer);
     463             : }
     464             : 
     465           0 : static void zebra_evpn_local_neigh_deref_mac(struct zebra_neigh *n,
     466             :                                              bool send_mac_update)
     467             : {
     468           0 :         struct zebra_mac *mac = n->mac;
     469           0 :         struct zebra_evpn *zevpn = n->zevpn;
     470           0 :         bool old_static;
     471           0 :         bool new_static;
     472             : 
     473           0 :         n->mac = NULL;
     474           0 :         if (!mac)
     475             :                 return;
     476             : 
     477           0 :         if ((n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) && mac->sync_neigh_cnt) {
     478           0 :                 old_static = zebra_evpn_mac_is_static(mac);
     479           0 :                 --mac->sync_neigh_cnt;
     480           0 :                 new_static = zebra_evpn_mac_is_static(mac);
     481           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     482           0 :                         zlog_debug(
     483             :                                 "sync-neigh deref mac vni %u ip %pIA mac %pEA ref %d",
     484             :                                 n->zevpn->vni, &n->ip, &n->emac,
     485             :                                 mac->sync_neigh_cnt);
     486           0 :                 if ((old_static != new_static) && send_mac_update)
     487             :                         /* program the local mac in the kernel */
     488           0 :                         zebra_evpn_sync_mac_dp_install(
     489             :                                 mac, false /* set_inactive */,
     490             :                                 false /* force_clear_static */, __func__);
     491             :         }
     492             : 
     493           0 :         listnode_delete(mac->neigh_list, n);
     494           0 :         zebra_evpn_deref_ip2mac(zevpn, mac);
     495             : }
     496             : 
     497           0 : bool zebra_evpn_neigh_is_bgp_seq_ok(struct zebra_evpn *zevpn,
     498             :                                     struct zebra_neigh *n,
     499             :                                     const struct ethaddr *macaddr, uint32_t seq,
     500             :                                     bool sync)
     501             : {
     502           0 :         uint32_t tmp_seq;
     503           0 :         const char *n_type;
     504           0 :         bool is_local = false;
     505             : 
     506           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
     507           0 :                 tmp_seq = n->loc_seq;
     508           0 :                 n_type = "local";
     509           0 :                 is_local = true;
     510             :         } else {
     511           0 :                 tmp_seq = n->rem_seq;
     512           0 :                 n_type = "remote";
     513             :         }
     514             : 
     515           0 :         if (seq < tmp_seq) {
     516           0 :                 if (is_local && !zebra_evpn_neigh_is_ready_for_bgp(n)) {
     517           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH ||
     518           0 :                             IS_ZEBRA_DEBUG_VXLAN)
     519           0 :                                 zlog_debug(
     520             :                                         "%s-macip not ready vni %u %s mac %pEA IP %pIA lower seq %u f 0x%x",
     521             :                                         sync ? "sync" : "remote", zevpn->vni,
     522             :                                         n_type, macaddr, &n->ip, tmp_seq,
     523             :                                         n->flags);
     524           0 :                         return true;
     525             :                 }
     526             : 
     527             :                 /* if the neigh was never advertised to bgp we must accept
     528             :                  * whatever sequence number bgp sends
     529             :                  */
     530           0 :                 if (!is_local && zebra_vxlan_get_accept_bgp_seq()) {
     531           0 :                         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
     532           0 :                             || IS_ZEBRA_DEBUG_VXLAN)
     533           0 :                                 zlog_debug(
     534             :                                         "%s-macip accept vni %u %s mac %pEA IP %pIA lower seq %u f 0x%x",
     535             :                                         sync ? "sync" : "remote", zevpn->vni,
     536             :                                         n_type, macaddr, &n->ip,
     537             :                                         tmp_seq, n->flags);
     538           0 :                         return true;
     539             :                 }
     540             : 
     541           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH || IS_ZEBRA_DEBUG_VXLAN)
     542           0 :                         zlog_debug(
     543             :                                 "%s-macip ignore vni %u %s mac %pEA IP %pIA as existing has higher seq %u f 0x%x",
     544             :                                 sync ? "sync" : "remote", zevpn->vni, n_type,
     545             :                                 macaddr, &n->ip, tmp_seq, n->flags);
     546           0 :                 return false;
     547             :         }
     548             : 
     549             :         return true;
     550             : }
     551             : 
     552             : /*
     553             :  * Add neighbor entry.
     554             :  */
     555           0 : static struct zebra_neigh *zebra_evpn_neigh_add(struct zebra_evpn *zevpn,
     556             :                                                 const struct ipaddr *ip,
     557             :                                                 const struct ethaddr *mac,
     558             :                                                 struct zebra_mac *zmac,
     559             :                                                 uint32_t n_flags)
     560             : {
     561           0 :         struct zebra_neigh tmp_n;
     562           0 :         struct zebra_neigh *n = NULL;
     563             : 
     564           0 :         memset(&tmp_n, 0, sizeof(tmp_n));
     565           0 :         memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
     566           0 :         n = hash_get(zevpn->neigh_table, &tmp_n, zebra_evpn_neigh_alloc);
     567             : 
     568           0 :         n->state = ZEBRA_NEIGH_INACTIVE;
     569           0 :         n->zevpn = zevpn;
     570           0 :         n->dad_ip_auto_recovery_timer = NULL;
     571           0 :         n->flags = n_flags;
     572           0 :         n->uptime = monotime(NULL);
     573             : 
     574           0 :         if (!zmac)
     575           0 :                 zmac = zebra_evpn_mac_lookup(zevpn, mac);
     576           0 :         zebra_evpn_local_neigh_ref_mac(n, mac, zmac,
     577             :                                        false /* send_mac_update */);
     578             : 
     579           0 :         return n;
     580             : }
     581             : 
     582             : /*
     583             :  * Delete neighbor entry.
     584             :  */
     585           0 : int zebra_evpn_neigh_del(struct zebra_evpn *zevpn, struct zebra_neigh *n)
     586             : {
     587           0 :         struct zebra_neigh *tmp_n;
     588             : 
     589           0 :         if (n->mac)
     590           0 :                 listnode_delete(n->mac->neigh_list, n);
     591             : 
     592             :         /* Cancel auto recovery */
     593           0 :         THREAD_OFF(n->dad_ip_auto_recovery_timer);
     594             : 
     595             :         /* Cancel proxy hold timer */
     596           0 :         zebra_evpn_neigh_stop_hold_timer(n);
     597             : 
     598             :         /* Free the VNI hash entry and allocated memory. */
     599           0 :         tmp_n = hash_release(zevpn->neigh_table, n);
     600           0 :         XFREE(MTYPE_NEIGH, tmp_n);
     601             : 
     602           0 :         return 0;
     603             : }
     604             : 
     605           0 : void zebra_evpn_sync_neigh_del(struct zebra_neigh *n)
     606             : {
     607           0 :         bool old_n_static;
     608           0 :         bool new_n_static;
     609             : 
     610           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     611           0 :                 zlog_debug("sync-neigh del vni %u ip %pIA mac %pEA f 0x%x",
     612             :                            n->zevpn->vni, &n->ip, &n->emac, n->flags);
     613             : 
     614           0 :         old_n_static = zebra_evpn_neigh_is_static(n);
     615           0 :         UNSET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
     616           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
     617           0 :                 zebra_evpn_neigh_start_hold_timer(n);
     618           0 :         new_n_static = zebra_evpn_neigh_is_static(n);
     619             : 
     620           0 :         if (old_n_static != new_n_static)
     621           0 :                 zebra_evpn_sync_neigh_static_chg(
     622             :                         n, old_n_static, new_n_static, false /*defer-dp*/,
     623             :                         false /*defer_mac_dp*/, __func__);
     624           0 : }
     625             : 
     626           0 : struct zebra_neigh *zebra_evpn_proc_sync_neigh_update(
     627             :         struct zebra_evpn *zevpn, struct zebra_neigh *n, uint16_t ipa_len,
     628             :         const struct ipaddr *ipaddr, uint8_t flags, uint32_t seq,
     629             :         const esi_t *esi, struct zebra_mac *mac)
     630             : {
     631           0 :         struct interface *ifp = NULL;
     632           0 :         bool is_router;
     633           0 :         uint32_t tmp_seq;
     634           0 :         bool old_router = false;
     635           0 :         bool old_bgp_ready = false;
     636           0 :         bool new_bgp_ready;
     637           0 :         bool inform_dataplane = false;
     638           0 :         bool inform_bgp = false;
     639           0 :         bool old_mac_static;
     640           0 :         bool new_mac_static;
     641           0 :         bool set_dp_inactive = false;
     642           0 :         bool created;
     643           0 :         ifindex_t ifindex = 0;
     644             : 
     645             :         /* locate l3-svi */
     646           0 :         ifp = zevpn_map_to_svi(zevpn);
     647           0 :         if (ifp)
     648           0 :                 ifindex = ifp->ifindex;
     649             : 
     650           0 :         is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
     651           0 :         old_mac_static = zebra_evpn_mac_is_static(mac);
     652             : 
     653           0 :         if (!n) {
     654           0 :                 uint32_t n_flags = 0;
     655             : 
     656             :                 /* New neighbor - create */
     657           0 :                 SET_FLAG(n_flags, ZEBRA_NEIGH_LOCAL);
     658           0 :                 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
     659             :                         SET_FLAG(n_flags, ZEBRA_NEIGH_ES_PEER_PROXY);
     660             :                 else
     661           0 :                         SET_FLAG(n_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
     662           0 :                 SET_FLAG(n_flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
     663             : 
     664           0 :                 n = zebra_evpn_neigh_add(zevpn, ipaddr, &mac->macaddr, mac,
     665             :                                          n_flags);
     666           0 :                 n->ifindex = ifindex;
     667           0 :                 ZEBRA_NEIGH_SET_ACTIVE(n);
     668             : 
     669           0 :                 created = true;
     670           0 :                 inform_dataplane = true;
     671           0 :                 inform_bgp = true;
     672           0 :                 set_dp_inactive = true;
     673             :         } else {
     674           0 :                 bool mac_change;
     675           0 :                 uint32_t old_flags = n->flags;
     676           0 :                 bool old_n_static;
     677           0 :                 bool new_n_static;
     678             : 
     679           0 :                 created = false;
     680           0 :                 old_n_static = zebra_evpn_neigh_is_static(n);
     681           0 :                 old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
     682           0 :                 old_router = !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
     683             : 
     684           0 :                 mac_change = !!memcmp(&n->emac, &mac->macaddr, ETH_ALEN);
     685             : 
     686             :                 /* deref and clear old info */
     687           0 :                 if (mac_change) {
     688           0 :                         if (old_bgp_ready) {
     689           0 :                                 zebra_evpn_neigh_send_del_to_client(
     690             :                                         zevpn->vni, &n->ip, &n->emac, n->flags,
     691           0 :                                         n->state, false /*force*/);
     692           0 :                                 old_bgp_ready = false;
     693             :                         }
     694           0 :                         zebra_evpn_local_neigh_deref_mac(n,
     695             :                                                          false /*send_mac_update*/);
     696             :                 }
     697             :                 /* clear old fwd info */
     698           0 :                 n->rem_seq = 0;
     699           0 :                 n->r_vtep_ip.s_addr = 0;
     700             : 
     701             :                 /* setup new flags */
     702           0 :                 n->flags = 0;
     703           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
     704             :                 /* retain activity flag if the neigh was
     705             :                  * previously local
     706             :                  */
     707           0 :                 if (old_flags & ZEBRA_NEIGH_LOCAL) {
     708           0 :                         n->flags |= (old_flags & ZEBRA_NEIGH_LOCAL_INACTIVE);
     709             :                 } else {
     710           0 :                         inform_dataplane = true;
     711           0 :                         set_dp_inactive = true;
     712           0 :                         n->flags |= ZEBRA_NEIGH_LOCAL_INACTIVE;
     713             :                 }
     714             : 
     715           0 :                 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
     716           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
     717             :                         /* if the neigh was peer-active previously we
     718             :                          * need to keep the flag and start the
     719             :                          * holdtimer on it. the peer-active flag is
     720             :                          * cleared on holdtimer expiry.
     721             :                          */
     722           0 :                         if (CHECK_FLAG(old_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE)) {
     723           0 :                                 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
     724           0 :                                 zebra_evpn_neigh_start_hold_timer(n);
     725             :                         }
     726             :                 } else {
     727           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
     728             :                         /* stop hold timer if a peer has verified
     729             :                          * reachability
     730             :                          */
     731           0 :                         zebra_evpn_neigh_stop_hold_timer(n);
     732             :                 }
     733           0 :                 ZEBRA_NEIGH_SET_ACTIVE(n);
     734             : 
     735           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH && (old_flags != n->flags))
     736           0 :                         zlog_debug(
     737             :                                 "sync-neigh vni %u ip %pIA mac %pEA old_f 0x%x new_f 0x%x",
     738             :                                 n->zevpn->vni, &n->ip, &n->emac,
     739             :                                 old_flags, n->flags);
     740             : 
     741           0 :                 new_n_static = zebra_evpn_neigh_is_static(n);
     742           0 :                 if (mac_change) {
     743           0 :                         set_dp_inactive = true;
     744           0 :                         n->flags |= ZEBRA_NEIGH_LOCAL_INACTIVE;
     745           0 :                         inform_dataplane = true;
     746           0 :                         zebra_evpn_local_neigh_ref_mac(
     747             :                                 n, &mac->macaddr, mac,
     748             :                                 false /*send_mac_update*/);
     749           0 :                 } else if (old_n_static != new_n_static) {
     750           0 :                         inform_dataplane = true;
     751             :                         /* if static flags have changed without a mac change
     752             :                          * we need to create the correct sync-refs against
     753             :                          * the existing mac
     754             :                          */
     755           0 :                         zebra_evpn_sync_neigh_static_chg(
     756             :                                 n, old_n_static, new_n_static,
     757             :                                 true /*defer_dp*/, true /*defer_mac_dp*/,
     758             :                                 __func__);
     759             :                 }
     760             : 
     761             :                 /* Update the forwarding info. */
     762           0 :                 if (n->ifindex != ifindex) {
     763           0 :                         n->ifindex = ifindex;
     764           0 :                         inform_dataplane = true;
     765             :                 }
     766             : 
     767           0 :                 n->uptime = monotime(NULL);
     768             :         }
     769             : 
     770             :         /* update the neigh seq. we don't bother with the mac seq as
     771             :          * sync_mac_update already took care of that
     772             :          */
     773           0 :         tmp_seq = MAX(n->loc_seq, seq);
     774           0 :         if (tmp_seq != n->loc_seq) {
     775           0 :                 n->loc_seq = tmp_seq;
     776           0 :                 inform_bgp = true;
     777             :         }
     778             : 
     779             :         /* Mark Router flag (R-bit) */
     780           0 :         if (is_router)
     781           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
     782             :         else
     783           0 :                 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
     784             : 
     785           0 :         if (old_router != is_router)
     786           0 :                 inform_dataplane = true;
     787             : 
     788           0 :         new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
     789           0 :         if (old_bgp_ready != new_bgp_ready)
     790           0 :                 inform_bgp = true;
     791             : 
     792           0 :         new_mac_static = zebra_evpn_mac_is_static(mac);
     793           0 :         if (old_mac_static != new_mac_static)
     794           0 :                 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
     795             :                                                false /* force_clear_static */,
     796             :                                                __func__);
     797             : 
     798           0 :         if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
     799           0 :                 zlog_debug(
     800             :                         "sync-neigh %s vni %u ip %pIA mac %pEA if %s(%d) seq %d f 0x%x%s%s",
     801             :                         created ? "created" : "updated", n->zevpn->vni,
     802             :                         &n->ip, &n->emac,
     803             :                         ifp ? ifp->name : "", ifindex, n->loc_seq, n->flags,
     804             :                         inform_bgp ? " inform_bgp" : "",
     805             :                         inform_dataplane ? " inform_dp" : "");
     806             : 
     807           0 :         if (inform_dataplane)
     808           0 :                 zebra_evpn_sync_neigh_dp_install(n, set_dp_inactive,
     809             :                                                  false /* force_clear_static */,
     810             :                                                  __func__);
     811             : 
     812           0 :         if (inform_bgp)
     813           0 :                 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
     814             :                                                         new_bgp_ready);
     815             : 
     816           0 :         return n;
     817             : }
     818             : 
     819             : /*
     820             :  * Uninstall remote neighbor from the kernel.
     821             :  */
     822           0 : static int zebra_evpn_neigh_uninstall(struct zebra_evpn *zevpn,
     823             :                                       struct zebra_neigh *n)
     824             : {
     825           0 :         struct interface *vlan_if;
     826             : 
     827           0 :         if (!(n->flags & ZEBRA_NEIGH_REMOTE))
     828             :                 return 0;
     829             : 
     830           0 :         vlan_if = zevpn_map_to_svi(zevpn);
     831           0 :         if (!vlan_if)
     832             :                 return -1;
     833             : 
     834           0 :         ZEBRA_NEIGH_SET_INACTIVE(n);
     835           0 :         n->loc_seq = 0;
     836             : 
     837           0 :         dplane_rem_neigh_delete(vlan_if, &n->ip);
     838             : 
     839           0 :         return 0;
     840             : }
     841             : 
     842             : /*
     843             :  * Free neighbor hash entry (callback)
     844             :  */
     845           0 : static void zebra_evpn_neigh_del_hash_entry(struct hash_bucket *bucket,
     846             :                                             void *arg)
     847             : {
     848           0 :         struct neigh_walk_ctx *wctx = arg;
     849           0 :         struct zebra_neigh *n = bucket->data;
     850             : 
     851           0 :         if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
     852           0 :             || ((wctx->flags & DEL_REMOTE_NEIGH)
     853           0 :                 && (n->flags & ZEBRA_NEIGH_REMOTE))
     854           0 :             || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
     855           0 :                 && (n->flags & ZEBRA_NEIGH_REMOTE)
     856           0 :                 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
     857           0 :                 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
     858           0 :                         zebra_evpn_neigh_send_del_to_client(
     859           0 :                                 wctx->zevpn->vni, &n->ip, &n->emac, n->flags,
     860           0 :                                 n->state, false /*force*/);
     861             : 
     862           0 :                 if (wctx->uninstall) {
     863           0 :                         if (zebra_evpn_neigh_is_static(n))
     864           0 :                                 zebra_evpn_sync_neigh_dp_install(
     865             :                                         n, false /* set_inactive */,
     866             :                                         true /* force_clear_static */,
     867             :                                         __func__);
     868           0 :                         if ((n->flags & ZEBRA_NEIGH_REMOTE))
     869           0 :                                 zebra_evpn_neigh_uninstall(wctx->zevpn, n);
     870             :                 }
     871             : 
     872           0 :                 zebra_evpn_neigh_del(wctx->zevpn, n);
     873             :         }
     874             : 
     875           0 :         return;
     876             : }
     877             : 
     878             : /*
     879             :  * Delete all neighbor entries for this EVPN.
     880             :  */
     881           0 : void zebra_evpn_neigh_del_all(struct zebra_evpn *zevpn, int uninstall,
     882             :                               int upd_client, uint32_t flags)
     883             : {
     884           0 :         struct neigh_walk_ctx wctx;
     885             : 
     886           0 :         if (!zevpn->neigh_table)
     887           0 :                 return;
     888             : 
     889           0 :         memset(&wctx, 0, sizeof(wctx));
     890           0 :         wctx.zevpn = zevpn;
     891           0 :         wctx.uninstall = uninstall;
     892           0 :         wctx.upd_client = upd_client;
     893           0 :         wctx.flags = flags;
     894             : 
     895           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_neigh_del_hash_entry,
     896             :                      &wctx);
     897             : }
     898             : 
     899             : /*
     900             :  * Look up neighbor hash entry.
     901             :  */
     902           0 : struct zebra_neigh *zebra_evpn_neigh_lookup(struct zebra_evpn *zevpn,
     903             :                                             const struct ipaddr *ip)
     904             : {
     905           0 :         struct zebra_neigh tmp;
     906           0 :         struct zebra_neigh *n;
     907             : 
     908           0 :         memset(&tmp, 0, sizeof(tmp));
     909           0 :         memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
     910           0 :         n = hash_lookup(zevpn->neigh_table, &tmp);
     911             : 
     912           0 :         return n;
     913             : }
     914             : 
     915             : /*
     916             :  * Process all neighbors associated with a MAC upon the MAC being learnt
     917             :  * locally or undergoing any other change (such as sequence number).
     918             :  */
     919           0 : void zebra_evpn_process_neigh_on_local_mac_change(struct zebra_evpn *zevpn,
     920             :                                                   struct zebra_mac *zmac,
     921             :                                                   bool seq_change,
     922             :                                                   bool es_change)
     923             : {
     924           0 :         struct zebra_neigh *n = NULL;
     925           0 :         struct listnode *node = NULL;
     926           0 :         struct zebra_vrf *zvrf = NULL;
     927             : 
     928           0 :         zvrf = zevpn->vxlan_if->vrf->info;
     929             : 
     930           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
     931           0 :                 zlog_debug("Processing neighbors on local MAC %pEA %s, VNI %u",
     932             :                            &zmac->macaddr, seq_change ? "CHANGE" : "ADD",
     933             :                            zevpn->vni);
     934             : 
     935             :         /* Walk all neighbors and mark any inactive local neighbors as
     936             :          * active and/or update sequence number upon a move, and inform BGP.
     937             :          * The action for remote neighbors is TBD.
     938             :          * NOTE: We can't simply uninstall remote neighbors as the kernel may
     939             :          * accidentally end up deleting a just-learnt local neighbor.
     940             :          */
     941           0 :         for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
     942           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
     943           0 :                         if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change
     944           0 :                             || es_change) {
     945           0 :                                 ZEBRA_NEIGH_SET_ACTIVE(n);
     946           0 :                                 n->loc_seq = zmac->loc_seq;
     947           0 :                                 if (!(zebra_evpn_do_dup_addr_detect(zvrf)
     948           0 :                                       && zvrf->dad_freeze
     949           0 :                                       && !!CHECK_FLAG(n->flags,
     950             :                                                       ZEBRA_NEIGH_DUPLICATE)))
     951           0 :                                         zebra_evpn_neigh_send_add_to_client(
     952           0 :                                                 zevpn->vni, &n->ip, &n->emac,
     953             :                                                 n->mac, n->flags, n->loc_seq);
     954             :                         }
     955             :                 }
     956             :         }
     957           0 : }
     958             : 
     959             : /*
     960             :  * Process all neighbors associated with a local MAC upon the MAC being
     961             :  * deleted.
     962             :  */
     963           0 : void zebra_evpn_process_neigh_on_local_mac_del(struct zebra_evpn *zevpn,
     964             :                                                struct zebra_mac *zmac)
     965             : {
     966           0 :         struct zebra_neigh *n = NULL;
     967           0 :         struct listnode *node = NULL;
     968             : 
     969           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
     970           0 :                 zlog_debug("Processing neighbors on local MAC %pEA DEL, VNI %u",
     971             :                            &zmac->macaddr, zevpn->vni);
     972             : 
     973             :         /* Walk all local neighbors and mark as inactive and inform
     974             :          * BGP, if needed.
     975             :          * TBD: There is currently no handling for remote neighbors. We
     976             :          * don't expect them to exist, if they do, do we install the MAC
     977             :          * as a remote MAC and the neighbor as remote?
     978             :          */
     979           0 :         for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
     980           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
     981           0 :                         if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
     982           0 :                                 ZEBRA_NEIGH_SET_INACTIVE(n);
     983           0 :                                 n->loc_seq = 0;
     984           0 :                                 zebra_evpn_neigh_send_del_to_client(
     985             :                                         zevpn->vni, &n->ip, &n->emac, n->flags,
     986             :                                         ZEBRA_NEIGH_ACTIVE, false /*force*/);
     987             :                         }
     988             :                 }
     989             :         }
     990           0 : }
     991             : 
     992             : /*
     993             :  * Process all neighbors associated with a MAC upon the MAC being remotely
     994             :  * learnt.
     995             :  */
     996           0 : void zebra_evpn_process_neigh_on_remote_mac_add(struct zebra_evpn *zevpn,
     997             :                                                 struct zebra_mac *zmac)
     998             : {
     999           0 :         struct zebra_neigh *n = NULL;
    1000           0 :         struct listnode *node = NULL;
    1001             : 
    1002           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    1003           0 :                 zlog_debug("Processing neighbors on remote MAC %pEA ADD, VNI %u",
    1004             :                            &zmac->macaddr, zevpn->vni);
    1005             : 
    1006             :         /* Walk all local neighbors and mark as inactive and inform
    1007             :          * BGP, if needed.
    1008             :          */
    1009           0 :         for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
    1010           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
    1011           0 :                         if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
    1012           0 :                                 ZEBRA_NEIGH_SET_INACTIVE(n);
    1013           0 :                                 n->loc_seq = 0;
    1014           0 :                                 zebra_evpn_neigh_send_del_to_client(
    1015             :                                         zevpn->vni, &n->ip, &n->emac, n->flags,
    1016             :                                         ZEBRA_NEIGH_ACTIVE, false /* force */);
    1017             :                         }
    1018             :                 }
    1019             :         }
    1020           0 : }
    1021             : 
    1022             : /*
    1023             :  * Process all neighbors associated with a remote MAC upon the MAC being
    1024             :  * deleted.
    1025             :  */
    1026           0 : void zebra_evpn_process_neigh_on_remote_mac_del(struct zebra_evpn *zevpn,
    1027             :                                                 struct zebra_mac *zmac)
    1028             : {
    1029             :         /* NOTE: Currently a NO-OP. */
    1030           0 : }
    1031             : 
    1032           0 : static inline void zebra_evpn_local_neigh_update_log(
    1033             :         const char *pfx, struct zebra_neigh *n, bool is_router,
    1034             :         bool local_inactive, bool old_bgp_ready, bool new_bgp_ready,
    1035             :         bool inform_dataplane, bool inform_bgp, const char *sfx)
    1036             : {
    1037           0 :         if (!IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
    1038             :                 return;
    1039             : 
    1040           0 :         zlog_debug("%s neigh vni %u ip %pIA mac %pEA f 0x%x%s%s%s%s%s%s %s", pfx,
    1041             :                    n->zevpn->vni, &n->ip, &n->emac, n->flags,
    1042             :                    is_router ? " router" : "",
    1043             :                    local_inactive ? " local-inactive" : "",
    1044             :                    old_bgp_ready ? " old_bgp_ready" : "",
    1045             :                    new_bgp_ready ? " new_bgp_ready" : "",
    1046             :                    inform_dataplane ? " inform_dp" : "",
    1047             :                    inform_bgp ? " inform_bgp" : "", sfx);
    1048             : }
    1049             : 
    1050             : /* As part Duplicate Address Detection (DAD) for IP mobility
    1051             :  * MAC binding changes, ensure to inherit duplicate flag
    1052             :  * from MAC.
    1053             :  */
    1054           0 : static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
    1055             :                                               struct zebra_mac *old_zmac,
    1056             :                                               struct zebra_mac *new_zmac,
    1057             :                                               struct zebra_neigh *nbr)
    1058             : {
    1059           0 :         bool is_old_mac_dup = false;
    1060           0 :         bool is_new_mac_dup = false;
    1061             : 
    1062           0 :         if (!zebra_evpn_do_dup_addr_detect(zvrf))
    1063             :                 return 0;
    1064             :         /* Check old or new MAC is detected as duplicate
    1065             :          * mark this neigh as duplicate
    1066             :          */
    1067           0 :         if (old_zmac)
    1068           0 :                 is_old_mac_dup =
    1069           0 :                         CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE);
    1070           0 :         if (new_zmac)
    1071           0 :                 is_new_mac_dup =
    1072           0 :                         CHECK_FLAG(new_zmac->flags, ZEBRA_MAC_DUPLICATE);
    1073             :         /* Old and/or new MAC can be in duplicate state,
    1074             :          * based on that IP/Neigh Inherits the flag.
    1075             :          * If New MAC is marked duplicate, inherit to the IP.
    1076             :          * If old MAC is duplicate but new MAC is not, clear
    1077             :          * duplicate flag for IP and reset detection params
    1078             :          * and let IP DAD retrigger.
    1079             :          */
    1080           0 :         if (is_new_mac_dup && !CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
    1081           0 :                 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    1082             :                 /* Capture Duplicate detection time */
    1083           0 :                 nbr->dad_dup_detect_time = monotime(NULL);
    1084             :                 /* Mark neigh inactive */
    1085           0 :                 ZEBRA_NEIGH_SET_INACTIVE(nbr);
    1086             : 
    1087           0 :                 return 1;
    1088           0 :         } else if (is_old_mac_dup && !is_new_mac_dup) {
    1089           0 :                 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    1090           0 :                 nbr->dad_count = 0;
    1091           0 :                 nbr->detect_start_time.tv_sec = 0;
    1092           0 :                 nbr->detect_start_time.tv_usec = 0;
    1093             :         }
    1094             :         return 0;
    1095             : }
    1096             : 
    1097           0 : static void zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t)
    1098             : {
    1099           0 :         struct zebra_vrf *zvrf = NULL;
    1100           0 :         struct zebra_neigh *nbr = NULL;
    1101           0 :         struct zebra_evpn *zevpn = NULL;
    1102             : 
    1103           0 :         nbr = THREAD_ARG(t);
    1104             : 
    1105             :         /* since this is asynchronous we need sanity checks*/
    1106           0 :         zvrf = vrf_info_lookup(nbr->zevpn->vrf_id);
    1107           0 :         if (!zvrf)
    1108             :                 return;
    1109             : 
    1110           0 :         zevpn = zebra_evpn_lookup(nbr->zevpn->vni);
    1111           0 :         if (!zevpn)
    1112             :                 return;
    1113             : 
    1114           0 :         nbr = zebra_evpn_neigh_lookup(zevpn, &nbr->ip);
    1115           0 :         if (!nbr)
    1116             :                 return;
    1117             : 
    1118           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    1119           0 :                 zlog_debug(
    1120             :                         "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x learn count %u vni %u auto recovery expired",
    1121             :                         __func__, &nbr->emac, &nbr->ip, nbr->flags,
    1122             :                         nbr->dad_count, zevpn->vni);
    1123             : 
    1124           0 :         UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    1125           0 :         nbr->dad_count = 0;
    1126           0 :         nbr->detect_start_time.tv_sec = 0;
    1127           0 :         nbr->detect_start_time.tv_usec = 0;
    1128           0 :         nbr->dad_dup_detect_time = 0;
    1129           0 :         nbr->dad_ip_auto_recovery_timer = NULL;
    1130           0 :         ZEBRA_NEIGH_SET_ACTIVE(nbr);
    1131             : 
    1132             :         /* Send to BGP */
    1133           0 :         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
    1134           0 :                 zebra_evpn_neigh_send_add_to_client(zevpn->vni, &nbr->ip,
    1135           0 :                                                     &nbr->emac, nbr->mac,
    1136             :                                                     nbr->flags, nbr->loc_seq);
    1137           0 :         } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
    1138           0 :                 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
    1139             :         }
    1140             : }
    1141             : 
    1142           0 : static void zebra_evpn_dup_addr_detect_for_neigh(
    1143             :         struct zebra_vrf *zvrf, struct zebra_neigh *nbr, struct in_addr vtep_ip,
    1144             :         bool do_dad, bool *is_dup_detect, bool is_local)
    1145             : {
    1146             : 
    1147           0 :         struct timeval elapsed = {0, 0};
    1148           0 :         bool reset_params = false;
    1149             : 
    1150           0 :         if (!zebra_evpn_do_dup_addr_detect(zvrf))
    1151           0 :                 return;
    1152             : 
    1153             :         /* IP is detected as duplicate or inherit dup
    1154             :          * state, hold on to install as remote entry
    1155             :          * only if freeze is enabled.
    1156             :          */
    1157           0 :         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
    1158           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1159           0 :                         zlog_debug(
    1160             :                                 "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x skip installing, learn count %u recover time %u",
    1161             :                                 __func__, &nbr->emac, &nbr->ip,
    1162             :                                 nbr->flags, nbr->dad_count,
    1163             :                                 zvrf->dad_freeze_time);
    1164             : 
    1165           0 :                 if (zvrf->dad_freeze)
    1166           0 :                         *is_dup_detect = true;
    1167             : 
    1168             :                 /* warn-only action, neigh will be installed.
    1169             :                  * freeze action, it wil not be installed.
    1170             :                  */
    1171           0 :                 return;
    1172             :         }
    1173             : 
    1174           0 :         if (!do_dad)
    1175             :                 return;
    1176             : 
    1177             :         /* Check if detection time (M-secs) expired.
    1178             :          * Reset learn count and detection start time.
    1179             :          * During remote mac add, count should already be 1
    1180             :          * via local learning.
    1181             :          */
    1182           0 :         monotime_since(&nbr->detect_start_time, &elapsed);
    1183           0 :         reset_params = (elapsed.tv_sec > zvrf->dad_time);
    1184             : 
    1185           0 :         if (is_local && !reset_params) {
    1186             :                 /* RFC-7432: A PE/VTEP that detects a MAC mobility
    1187             :                  * event via LOCAL learning starts an M-second timer.
    1188             :                  *
    1189             :                  * NOTE: This is the START of the probe with count is
    1190             :                  * 0 during LOCAL learn event.
    1191             :                  */
    1192           0 :                 reset_params = !nbr->dad_count;
    1193             :         }
    1194             : 
    1195           0 :         if (reset_params) {
    1196           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1197           0 :                         zlog_debug(
    1198             :                                 "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x detection time passed, reset learn count %u",
    1199             :                                 __func__, &nbr->emac, &nbr->ip,
    1200             :                                 nbr->flags, nbr->dad_count);
    1201             :                 /* Reset learn count but do not start detection
    1202             :                  * during REMOTE learn event.
    1203             :                  */
    1204           0 :                 nbr->dad_count = 0;
    1205             :                 /* Start dup. addr detection (DAD) start time,
    1206             :                  * ONLY during LOCAL learn.
    1207             :                  */
    1208           0 :                 if (is_local)
    1209           0 :                         monotime(&nbr->detect_start_time);
    1210             : 
    1211           0 :         } else if (!is_local) {
    1212             :                 /* For REMOTE IP/Neigh, increment detection count
    1213             :                  * ONLY while in probe window, once window passed,
    1214             :                  * next local learn event should trigger DAD.
    1215             :                  */
    1216           0 :                 nbr->dad_count++;
    1217             :         }
    1218             : 
    1219             :         /* For LOCAL IP/Neigh learn event, once count is reset above via either
    1220             :          * initial/start detection time or passed the probe time, the count
    1221             :          * needs to be incremented.
    1222             :          */
    1223           0 :         if (is_local)
    1224           0 :                 nbr->dad_count++;
    1225             : 
    1226           0 :         if (nbr->dad_count >= zvrf->dad_max_moves) {
    1227           0 :                 flog_warn(
    1228             :                         EC_ZEBRA_DUP_IP_DETECTED,
    1229             :                         "VNI %u: MAC %pEA IP %pIA detected as duplicate during %s VTEP %pI4",
    1230             :                         nbr->zevpn->vni, &nbr->emac, &nbr->ip,
    1231             :                         is_local ? "local update, last" : "remote update, from",
    1232             :                         &vtep_ip);
    1233             : 
    1234           0 :                 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    1235             : 
    1236             :                 /* Capture Duplicate detection time */
    1237           0 :                 nbr->dad_dup_detect_time = monotime(NULL);
    1238             : 
    1239             :                 /* Start auto recovery timer for this IP */
    1240           0 :                 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
    1241           0 :                 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
    1242           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    1243           0 :                                 zlog_debug(
    1244             :                                         "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x auto recovery time %u start",
    1245             :                                         __func__, &nbr->emac, &nbr->ip,
    1246             :                                         nbr->flags, zvrf->dad_freeze_time);
    1247             : 
    1248           0 :                         thread_add_timer(zrouter.master,
    1249             :                                          zebra_evpn_dad_ip_auto_recovery_exp,
    1250             :                                          nbr, zvrf->dad_freeze_time,
    1251             :                                          &nbr->dad_ip_auto_recovery_timer);
    1252             :                 }
    1253           0 :                 if (zvrf->dad_freeze)
    1254           0 :                         *is_dup_detect = true;
    1255             :         }
    1256             : }
    1257             : 
    1258           0 : int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn,
    1259             :                                   struct interface *ifp,
    1260             :                                   const struct ipaddr *ip,
    1261             :                                   const struct ethaddr *macaddr, bool is_router,
    1262             :                                   bool local_inactive, bool dp_static)
    1263             : {
    1264           0 :         struct zebra_vrf *zvrf;
    1265           0 :         struct zebra_neigh *n = NULL;
    1266           0 :         struct zebra_mac *zmac = NULL, *old_zmac = NULL;
    1267           0 :         uint32_t old_mac_seq = 0, mac_new_seq = 0;
    1268           0 :         bool upd_mac_seq = false;
    1269           0 :         bool neigh_mac_change = false;
    1270           0 :         bool neigh_on_hold = false;
    1271           0 :         bool neigh_was_remote = false;
    1272           0 :         bool do_dad = false;
    1273           0 :         struct in_addr vtep_ip = {.s_addr = 0};
    1274           0 :         bool inform_dataplane = false;
    1275           0 :         bool created = false;
    1276           0 :         bool new_static = false;
    1277           0 :         bool old_bgp_ready = false;
    1278           0 :         bool new_bgp_ready;
    1279             : 
    1280             :         /* Check if the MAC exists. */
    1281           0 :         zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
    1282           0 :         if (!zmac) {
    1283             :                 /* create a dummy MAC if the MAC is not already present */
    1284           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1285           0 :                         zlog_debug("AUTO MAC %pEA created for neigh %pIA on VNI %u",
    1286             :                                    macaddr, ip, zevpn->vni);
    1287             : 
    1288           0 :                 zmac = zebra_evpn_mac_add_auto(zevpn, macaddr);
    1289           0 :                 if (!zmac) {
    1290           0 :                         zlog_debug("Failed to add MAC %pEA VNI %u", macaddr,
    1291             :                                    zevpn->vni);
    1292           0 :                         return -1;
    1293             :                 }
    1294             :         } else {
    1295           0 :                 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
    1296             :                         /*
    1297             :                          * We don't change the MAC to local upon a neighbor
    1298             :                          * learn event, we wait for the explicit local MAC
    1299             :                          * learn. However, we have to compute its sequence
    1300             :                          * number in preparation for when it actually turns
    1301             :                          * local.
    1302             :                          */
    1303           0 :                         upd_mac_seq = true;
    1304             :                 }
    1305             :         }
    1306             : 
    1307           0 :         zvrf = zevpn->vxlan_if->vrf->info;
    1308           0 :         if (!zvrf) {
    1309           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1310           0 :                         zlog_debug("        Unable to find vrf for: %d",
    1311             :                                    zevpn->vxlan_if->vrf->vrf_id);
    1312           0 :                 return -1;
    1313             :         }
    1314             : 
    1315             :         /* Check if the neighbor exists. */
    1316           0 :         n = zebra_evpn_neigh_lookup(zevpn, ip);
    1317           0 :         if (!n) {
    1318             :                 /* New neighbor - create */
    1319           0 :                 n = zebra_evpn_neigh_add(zevpn, ip, macaddr, zmac, 0);
    1320             : 
    1321             :                 /* Set "local" forwarding info. */
    1322           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
    1323           0 :                 n->ifindex = ifp->ifindex;
    1324           0 :                 created = true;
    1325             :         } else {
    1326           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
    1327           0 :                         bool mac_different;
    1328           0 :                         bool cur_is_router;
    1329           0 :                         bool old_local_inactive;
    1330             : 
    1331           0 :                         old_local_inactive = !!CHECK_FLAG(
    1332             :                                 n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
    1333             : 
    1334           0 :                         old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
    1335             : 
    1336             :                         /* Note any changes and see if of interest to BGP. */
    1337           0 :                         mac_different = !!memcmp(&n->emac, macaddr, ETH_ALEN);
    1338           0 :                         cur_is_router =
    1339           0 :                                 !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    1340           0 :                         new_static = zebra_evpn_neigh_is_static(n);
    1341           0 :                         if (!mac_different && is_router == cur_is_router
    1342           0 :                             && old_local_inactive == local_inactive
    1343           0 :                             && dp_static != new_static) {
    1344           0 :                                 if (IS_ZEBRA_DEBUG_VXLAN)
    1345           0 :                                         zlog_debug(
    1346             :                                                 "        Ignoring entry mac is the same and is_router == cur_is_router");
    1347           0 :                                 n->ifindex = ifp->ifindex;
    1348           0 :                                 return 0;
    1349             :                         }
    1350             : 
    1351           0 :                         old_zmac = n->mac;
    1352           0 :                         if (!mac_different) {
    1353             :                                 /* XXX - cleanup this code duplication */
    1354           0 :                                 bool is_neigh_freezed = false;
    1355             : 
    1356             :                                 /* Only the router flag has changed. */
    1357           0 :                                 if (is_router)
    1358           0 :                                         SET_FLAG(n->flags,
    1359             :                                                  ZEBRA_NEIGH_ROUTER_FLAG);
    1360             :                                 else
    1361           0 :                                         UNSET_FLAG(n->flags,
    1362             :                                                    ZEBRA_NEIGH_ROUTER_FLAG);
    1363             : 
    1364           0 :                                 if (local_inactive)
    1365           0 :                                         SET_FLAG(n->flags,
    1366             :                                                  ZEBRA_NEIGH_LOCAL_INACTIVE);
    1367             :                                 else
    1368           0 :                                         UNSET_FLAG(n->flags,
    1369             :                                                    ZEBRA_NEIGH_LOCAL_INACTIVE);
    1370           0 :                                 new_bgp_ready =
    1371           0 :                                         zebra_evpn_neigh_is_ready_for_bgp(n);
    1372             : 
    1373           0 :                                 if (dp_static != new_static)
    1374           0 :                                         inform_dataplane = true;
    1375             : 
    1376             :                                 /* Neigh is in freeze state and freeze action
    1377             :                                  * is enabled, do not send update to client.
    1378             :                                  */
    1379           0 :                                 is_neigh_freezed =
    1380           0 :                                         (zebra_evpn_do_dup_addr_detect(zvrf)
    1381           0 :                                          && zvrf->dad_freeze
    1382           0 :                                          && CHECK_FLAG(n->flags,
    1383             :                                                        ZEBRA_NEIGH_DUPLICATE));
    1384             : 
    1385           0 :                                 zebra_evpn_local_neigh_update_log(
    1386             :                                         "local", n, is_router, local_inactive,
    1387             :                                         old_bgp_ready, new_bgp_ready, false,
    1388             :                                         false, "flag-update");
    1389             : 
    1390           0 :                                 if (inform_dataplane)
    1391           0 :                                         zebra_evpn_sync_neigh_dp_install(
    1392             :                                                 n, false /* set_inactive */,
    1393             :                                                 false /* force_clear_static */,
    1394             :                                                 __func__);
    1395             : 
    1396             :                                 /* if the neigh can no longer be advertised
    1397             :                                  * remove it from bgp
    1398             :                                  */
    1399           0 :                                 if (!is_neigh_freezed) {
    1400           0 :                                         zebra_evpn_neigh_send_add_del_to_client(
    1401             :                                                 n, old_bgp_ready,
    1402             :                                                 new_bgp_ready);
    1403             :                                 } else {
    1404           0 :                                         if (IS_ZEBRA_DEBUG_VXLAN
    1405           0 :                                             && IS_ZEBRA_NEIGH_ACTIVE(n))
    1406           0 :                                                 zlog_debug(
    1407             :                                                         "        Neighbor active and frozen");
    1408             :                                 }
    1409           0 :                                 return 0;
    1410             :                         }
    1411             : 
    1412             :                         /* The MAC has changed, need to issue a delete
    1413             :                          * first as this means a different MACIP route.
    1414             :                          * Also, need to do some unlinking/relinking.
    1415             :                          * We also need to update the MAC's sequence number
    1416             :                          * in different situations.
    1417             :                          */
    1418           0 :                         if (old_bgp_ready) {
    1419           0 :                                 zebra_evpn_neigh_send_del_to_client(
    1420             :                                         zevpn->vni, &n->ip, &n->emac, n->flags,
    1421           0 :                                         n->state, false /*force*/);
    1422           0 :                                 old_bgp_ready = false;
    1423             :                         }
    1424           0 :                         if (old_zmac) {
    1425           0 :                                 old_mac_seq = CHECK_FLAG(old_zmac->flags,
    1426             :                                                          ZEBRA_MAC_REMOTE)
    1427             :                                                       ? old_zmac->rem_seq
    1428           0 :                                                       : old_zmac->loc_seq;
    1429           0 :                                 neigh_mac_change = upd_mac_seq = true;
    1430           0 :                                 zebra_evpn_local_neigh_deref_mac(
    1431             :                                         n, true /* send_mac_update */);
    1432             :                         }
    1433             : 
    1434             :                         /* if mac changes abandon peer flags and tell
    1435             :                          * dataplane to clear the static flag
    1436             :                          */
    1437           0 :                         if (zebra_evpn_neigh_clear_sync_info(n))
    1438             :                                 inform_dataplane = true;
    1439             :                         /* Update the forwarding info. */
    1440           0 :                         n->ifindex = ifp->ifindex;
    1441             : 
    1442             :                         /* Link to new MAC */
    1443           0 :                         zebra_evpn_local_neigh_ref_mac(
    1444             :                                 n, macaddr, zmac, true /* send_mac_update */);
    1445           0 :                 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    1446             :                         /*
    1447             :                          * Neighbor has moved from remote to local. Its
    1448             :                          * MAC could have also changed as part of the move.
    1449             :                          */
    1450           0 :                         if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN)
    1451             :                             != 0) {
    1452           0 :                                 old_zmac = n->mac;
    1453           0 :                                 if (old_zmac) {
    1454           0 :                                         old_mac_seq =
    1455           0 :                                                 CHECK_FLAG(old_zmac->flags,
    1456             :                                                            ZEBRA_MAC_REMOTE)
    1457             :                                                         ? old_zmac->rem_seq
    1458           0 :                                                         : old_zmac->loc_seq;
    1459           0 :                                         neigh_mac_change = upd_mac_seq = true;
    1460           0 :                                         zebra_evpn_local_neigh_deref_mac(
    1461             :                                                 n, true /* send_update */);
    1462             :                                 }
    1463             : 
    1464             :                                 /* Link to new MAC */
    1465           0 :                                 zebra_evpn_local_neigh_ref_mac(
    1466             :                                         n, macaddr, zmac, true /*send_update*/);
    1467             :                         }
    1468             :                         /* Based on Mobility event Scenario-B from the
    1469             :                          * draft, neigh's previous state was remote treat this
    1470             :                          * event for DAD.
    1471             :                          */
    1472           0 :                         neigh_was_remote = true;
    1473           0 :                         vtep_ip = n->r_vtep_ip;
    1474             :                         /* Mark appropriately */
    1475           0 :                         UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
    1476           0 :                         n->r_vtep_ip.s_addr = INADDR_ANY;
    1477           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
    1478           0 :                         n->ifindex = ifp->ifindex;
    1479             :                 }
    1480             :         }
    1481             : 
    1482             :         /* If MAC was previously remote, or the neighbor had a different
    1483             :          * MAC earlier, recompute the sequence number.
    1484             :          */
    1485           0 :         if (upd_mac_seq) {
    1486           0 :                 uint32_t seq1, seq2;
    1487             : 
    1488           0 :                 seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)
    1489           0 :                                ? zmac->rem_seq + 1
    1490           0 :                                : zmac->loc_seq;
    1491           0 :                 seq2 = neigh_mac_change ? old_mac_seq + 1 : 0;
    1492           0 :                 mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ? MAX(seq1, seq2)
    1493             :                                                               : zmac->loc_seq;
    1494             :         }
    1495             : 
    1496           0 :         if (local_inactive)
    1497           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
    1498             :         else
    1499           0 :                 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
    1500             : 
    1501             :         /* Mark Router flag (R-bit) */
    1502           0 :         if (is_router)
    1503           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    1504             :         else
    1505           0 :                 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    1506             : 
    1507             :         /* if zebra and dataplane don't agree this is a sync entry
    1508             :          * re-install in the dataplane */
    1509           0 :         new_static = zebra_evpn_neigh_is_static(n);
    1510           0 :         if (dp_static != new_static)
    1511           0 :                 inform_dataplane = true;
    1512             : 
    1513             :         /* Check old and/or new MAC detected as duplicate mark
    1514             :          * the neigh as duplicate
    1515             :          */
    1516           0 :         if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
    1517           0 :                 flog_warn(
    1518             :                         EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
    1519             :                         "VNI %u: MAC %pEA IP %pIA detected as duplicate during local update, inherit duplicate from MAC",
    1520             :                         zevpn->vni, macaddr, &n->ip);
    1521             :         }
    1522             : 
    1523             :         /* For IP Duplicate Address Detection (DAD) is trigger,
    1524             :          * when the event is extended mobility based on scenario-B
    1525             :          * from the draft, IP/Neigh's MAC binding changed and
    1526             :          * neigh's previous state was remote.
    1527             :          */
    1528           0 :         if (neigh_mac_change && neigh_was_remote)
    1529             :                 do_dad = true;
    1530             : 
    1531           0 :         zebra_evpn_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad,
    1532             :                                              &neigh_on_hold, true);
    1533             : 
    1534           0 :         if (inform_dataplane)
    1535           0 :                 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
    1536             :                                                  false /* force_clear_static */,
    1537             :                                                  __func__);
    1538             : 
    1539             :         /* Before we program this in BGP, we need to check if MAC is locally
    1540             :          * learnt. If not, force neighbor to be inactive and reset its seq.
    1541             :          */
    1542           0 :         if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
    1543           0 :                 zebra_evpn_local_neigh_update_log(
    1544             :                         "local", n, is_router, local_inactive, false, false,
    1545             :                         inform_dataplane, false, "auto-mac");
    1546           0 :                 ZEBRA_NEIGH_SET_INACTIVE(n);
    1547           0 :                 n->loc_seq = 0;
    1548           0 :                 zmac->loc_seq = mac_new_seq;
    1549           0 :                 return 0;
    1550             :         }
    1551             : 
    1552           0 :         zebra_evpn_local_neigh_update_log("local", n, is_router, local_inactive,
    1553             :                                           false, false, inform_dataplane, true,
    1554             :                                           created ? "created" : "updated");
    1555             : 
    1556             :         /* If the MAC's sequence number has changed, inform the MAC and all
    1557             :          * neighbors associated with the MAC to BGP, else just inform this
    1558             :          * neighbor.
    1559             :          */
    1560           0 :         if (upd_mac_seq && zmac->loc_seq != mac_new_seq) {
    1561           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1562           0 :                         zlog_debug(
    1563             :                                 "Seq changed for MAC %pEA VNI %u - old %u new %u",
    1564             :                                 macaddr, zevpn->vni,
    1565             :                                 zmac->loc_seq, mac_new_seq);
    1566           0 :                 zmac->loc_seq = mac_new_seq;
    1567           0 :                 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, macaddr,
    1568             :                                                       zmac->flags,
    1569             :                                                       zmac->loc_seq, zmac->es))
    1570             :                         return -1;
    1571           0 :                 zebra_evpn_process_neigh_on_local_mac_change(zevpn, zmac, 1,
    1572             :                                                              0 /*es_change*/);
    1573           0 :                 return 0;
    1574             :         }
    1575             : 
    1576           0 :         n->loc_seq = zmac->loc_seq;
    1577             : 
    1578           0 :         if (!neigh_on_hold) {
    1579           0 :                 ZEBRA_NEIGH_SET_ACTIVE(n);
    1580           0 :                 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
    1581           0 :                 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
    1582             :                                                         new_bgp_ready);
    1583             :         } else {
    1584           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1585           0 :                         zlog_debug("        Neighbor on hold not sending");
    1586             :         }
    1587             :         return 0;
    1588             : }
    1589             : 
    1590           0 : int zebra_evpn_remote_neigh_update(struct zebra_evpn *zevpn,
    1591             :                                    struct interface *ifp,
    1592             :                                    const struct ipaddr *ip,
    1593             :                                    const struct ethaddr *macaddr,
    1594             :                                    uint16_t state)
    1595             : {
    1596           0 :         struct zebra_neigh *n = NULL;
    1597           0 :         struct zebra_mac *zmac = NULL;
    1598             : 
    1599             :         /* If the neighbor is unknown, there is no further action. */
    1600           0 :         n = zebra_evpn_neigh_lookup(zevpn, ip);
    1601           0 :         if (!n)
    1602             :                 return 0;
    1603             : 
    1604             :         /* If a remote entry, see if it needs to be refreshed */
    1605           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    1606             : #ifdef GNU_LINUX
    1607           0 :                 if (state & NUD_STALE)
    1608           0 :                         zebra_evpn_rem_neigh_install(zevpn, n,
    1609             :                                                      false /*was_static*/);
    1610             : #endif
    1611             :         } else {
    1612             :                 /* We got a "remote" neighbor notification for an entry
    1613             :                  * we think is local. This can happen in a multihoming
    1614             :                  * scenario - but only if the MAC is already "remote".
    1615             :                  * Just mark our entry as "remote".
    1616             :                  */
    1617           0 :                 zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
    1618           0 :                 if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
    1619           0 :                         zlog_debug(
    1620             :                                 "Ignore remote neigh %pIA (MAC %pEA) on L2-VNI %u - MAC unknown or local",
    1621             :                                 &n->ip, macaddr, zevpn->vni);
    1622           0 :                         return -1;
    1623             :                 }
    1624             : 
    1625           0 :                 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS);
    1626           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
    1627           0 :                 ZEBRA_NEIGH_SET_ACTIVE(n);
    1628           0 :                 n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
    1629             :         }
    1630             : 
    1631             :         return 0;
    1632             : }
    1633             : 
    1634             : /* Notify Neighbor entries to the Client, skips the GW entry */
    1635             : static void
    1636           0 : zebra_evpn_send_neigh_hash_entry_to_client(struct hash_bucket *bucket,
    1637             :                                            void *arg)
    1638             : {
    1639           0 :         struct mac_walk_ctx *wctx = arg;
    1640           0 :         struct zebra_neigh *zn = bucket->data;
    1641           0 :         struct zebra_mac *zmac = NULL;
    1642             : 
    1643           0 :         if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_DEF_GW))
    1644             :                 return;
    1645             : 
    1646           0 :         if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_LOCAL)
    1647           0 :             && IS_ZEBRA_NEIGH_ACTIVE(zn)) {
    1648           0 :                 zmac = zebra_evpn_mac_lookup(wctx->zevpn, &zn->emac);
    1649           0 :                 if (!zmac)
    1650             :                         return;
    1651             : 
    1652           0 :                 zebra_evpn_neigh_send_add_to_client(wctx->zevpn->vni, &zn->ip,
    1653             :                                                     &zn->emac, zn->mac,
    1654             :                                                     zn->flags, zn->loc_seq);
    1655             :         }
    1656             : }
    1657             : 
    1658             : /* Iterator of a specific EVPN */
    1659           0 : void zebra_evpn_send_neigh_to_client(struct zebra_evpn *zevpn)
    1660             : {
    1661           0 :         struct neigh_walk_ctx wctx;
    1662             : 
    1663           0 :         memset(&wctx, 0, sizeof(wctx));
    1664           0 :         wctx.zevpn = zevpn;
    1665             : 
    1666           0 :         hash_iterate(zevpn->neigh_table,
    1667             :                      zebra_evpn_send_neigh_hash_entry_to_client, &wctx);
    1668           0 : }
    1669             : 
    1670           0 : void zebra_evpn_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt)
    1671             : {
    1672           0 :         struct neigh_walk_ctx *wctx = ctxt;
    1673           0 :         struct zebra_neigh *nbr;
    1674           0 :         struct zebra_evpn *zevpn;
    1675           0 :         char buf[INET6_ADDRSTRLEN];
    1676             : 
    1677           0 :         nbr = (struct zebra_neigh *)bucket->data;
    1678           0 :         if (!nbr)
    1679           0 :                 return;
    1680             : 
    1681           0 :         zevpn = wctx->zevpn;
    1682             : 
    1683           0 :         if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
    1684             :                 return;
    1685             : 
    1686           0 :         if (IS_ZEBRA_DEBUG_VXLAN) {
    1687           0 :                 ipaddr2str(&nbr->ip, buf, sizeof(buf));
    1688           0 :                 zlog_debug("%s: clear neigh %s dup state, flags 0x%x seq %u",
    1689             :                            __func__, buf, nbr->flags, nbr->loc_seq);
    1690             :         }
    1691             : 
    1692           0 :         UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    1693           0 :         nbr->dad_count = 0;
    1694           0 :         nbr->detect_start_time.tv_sec = 0;
    1695           0 :         nbr->detect_start_time.tv_usec = 0;
    1696           0 :         nbr->dad_dup_detect_time = 0;
    1697           0 :         THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
    1698             : 
    1699           0 :         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
    1700           0 :                 zebra_evpn_neigh_send_add_to_client(zevpn->vni, &nbr->ip,
    1701           0 :                                                     &nbr->emac, nbr->mac,
    1702             :                                                     nbr->flags, nbr->loc_seq);
    1703           0 :         } else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
    1704           0 :                 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
    1705             :         }
    1706             : }
    1707             : 
    1708             : /*
    1709             :  * Print a specific neighbor entry.
    1710             :  */
    1711           0 : void zebra_evpn_print_neigh(struct zebra_neigh *n, void *ctxt,
    1712             :                             json_object *json)
    1713             : {
    1714           0 :         struct vty *vty;
    1715           0 :         char buf1[ETHER_ADDR_STRLEN];
    1716           0 :         char buf2[INET6_ADDRSTRLEN];
    1717           0 :         const char *type_str;
    1718           0 :         const char *state_str;
    1719           0 :         bool flags_present = false;
    1720           0 :         struct zebra_vrf *zvrf = NULL;
    1721           0 :         struct timeval detect_start_time = {0, 0};
    1722           0 :         char timebuf[MONOTIME_STRLEN];
    1723           0 :         char thread_buf[THREAD_TIMER_STRLEN];
    1724           0 :         time_t uptime;
    1725           0 :         char up_str[MONOTIME_STRLEN];
    1726             : 
    1727           0 :         zvrf = zebra_vrf_get_evpn();
    1728           0 :         uptime = monotime(NULL);
    1729           0 :         uptime -= n->uptime;
    1730             : 
    1731           0 :         frrtime_to_interval(uptime, up_str, sizeof(up_str));
    1732             : 
    1733           0 :         ipaddr2str(&n->ip, buf2, sizeof(buf2));
    1734           0 :         prefix_mac2str(&n->emac, buf1, sizeof(buf1));
    1735           0 :         type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? "local" : "remote";
    1736           0 :         state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
    1737           0 :         vty = (struct vty *)ctxt;
    1738           0 :         if (json == NULL) {
    1739           0 :                 bool sync_info = false;
    1740             : 
    1741           0 :                 vty_out(vty, "IP: %s\n",
    1742           0 :                         ipaddr2str(&n->ip, buf2, sizeof(buf2)));
    1743           0 :                 vty_out(vty, " Type: %s\n", type_str);
    1744           0 :                 vty_out(vty, " State: %s\n", state_str);
    1745           0 :                 vty_out(vty, " Uptime: %s\n", up_str);
    1746           0 :                 vty_out(vty, " MAC: %s\n",
    1747             :                         prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
    1748           0 :                 vty_out(vty, " Sync-info:");
    1749           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE)) {
    1750           0 :                         vty_out(vty, " local-inactive");
    1751           0 :                         sync_info = true;
    1752             :                 }
    1753           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY)) {
    1754           0 :                         vty_out(vty, " peer-proxy");
    1755           0 :                         sync_info = true;
    1756             :                 }
    1757           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE)) {
    1758           0 :                         vty_out(vty, " peer-active");
    1759           0 :                         sync_info = true;
    1760             :                 }
    1761           0 :                 if (n->hold_timer) {
    1762           0 :                         vty_out(vty, " (ht: %s)",
    1763             :                                 thread_timer_to_hhmmss(thread_buf,
    1764             :                                                        sizeof(thread_buf),
    1765             :                                                        n->hold_timer));
    1766           0 :                         sync_info = true;
    1767             :                 }
    1768           0 :                 if (!sync_info)
    1769           0 :                         vty_out(vty, " -");
    1770           0 :                 vty_out(vty, "\n");
    1771             :         } else {
    1772           0 :                 json_object_string_add(json, "uptime", up_str);
    1773           0 :                 json_object_string_add(json, "ip", buf2);
    1774           0 :                 json_object_string_add(json, "type", type_str);
    1775           0 :                 json_object_string_add(json, "state", state_str);
    1776           0 :                 json_object_string_add(json, "mac", buf1);
    1777           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
    1778           0 :                         json_object_boolean_true_add(json, "localInactive");
    1779           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY))
    1780           0 :                         json_object_boolean_true_add(json, "peerProxy");
    1781           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
    1782           0 :                         json_object_boolean_true_add(json, "peerActive");
    1783           0 :                 if (n->hold_timer)
    1784           0 :                         json_object_string_add(
    1785             :                                 json, "peerActiveHold",
    1786           0 :                                 thread_timer_to_hhmmss(thread_buf,
    1787             :                                                        sizeof(thread_buf),
    1788             :                                                        n->hold_timer));
    1789             :         }
    1790           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    1791           0 :                 if (n->mac->es) {
    1792           0 :                         if (json)
    1793           0 :                                 json_object_string_add(json, "remoteEs",
    1794           0 :                                                        n->mac->es->esi_str);
    1795             :                         else
    1796           0 :                                 vty_out(vty, " Remote ES: %s\n",
    1797           0 :                                         n->mac->es->esi_str);
    1798             :                 } else {
    1799           0 :                         if (json)
    1800           0 :                                 json_object_string_addf(json, "remoteVtep",
    1801             :                                                         "%pI4", &n->r_vtep_ip);
    1802             :                         else
    1803           0 :                                 vty_out(vty, " Remote VTEP: %pI4\n",
    1804             :                                         &n->r_vtep_ip);
    1805             :                 }
    1806             :         }
    1807           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
    1808           0 :                 if (!json) {
    1809           0 :                         vty_out(vty, " Flags: Default-gateway");
    1810           0 :                         flags_present = true;
    1811             :                 } else
    1812           0 :                         json_object_boolean_true_add(json, "defaultGateway");
    1813             :         }
    1814           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
    1815           0 :                 if (!json) {
    1816           0 :                         vty_out(vty,
    1817             :                                 flags_present ? " ,Router" : " Flags: Router");
    1818           0 :                         flags_present = true;
    1819             :                 }
    1820             :         }
    1821           0 :         if (json == NULL) {
    1822           0 :                 if (flags_present)
    1823           0 :                         vty_out(vty, "\n");
    1824           0 :                 vty_out(vty, " Local Seq: %u Remote Seq: %u\n", n->loc_seq,
    1825             :                         n->rem_seq);
    1826             : 
    1827           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
    1828           0 :                         vty_out(vty, " Duplicate, detected at %s",
    1829             :                                 time_to_string(n->dad_dup_detect_time,
    1830             :                                                timebuf));
    1831           0 :                 } else if (n->dad_count) {
    1832           0 :                         monotime_since(&n->detect_start_time,
    1833             :                                        &detect_start_time);
    1834           0 :                         if (detect_start_time.tv_sec <= zvrf->dad_time) {
    1835           0 :                                 time_to_string(n->detect_start_time.tv_sec,
    1836             :                                                timebuf);
    1837           0 :                                 vty_out(vty,
    1838             :                                         " Duplicate detection started at %s, detection count %u\n",
    1839             :                                         timebuf, n->dad_count);
    1840             :                         }
    1841             :                 }
    1842             :         } else {
    1843           0 :                 json_object_int_add(json, "localSequence", n->loc_seq);
    1844           0 :                 json_object_int_add(json, "remoteSequence", n->rem_seq);
    1845           0 :                 json_object_int_add(json, "detectionCount", n->dad_count);
    1846           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
    1847           0 :                         json_object_boolean_true_add(json, "isDuplicate");
    1848             :                 else
    1849           0 :                         json_object_boolean_false_add(json, "isDuplicate");
    1850             :         }
    1851           0 : }
    1852             : 
    1853           0 : void zebra_evpn_print_neigh_hdr(struct vty *vty, struct neigh_walk_ctx *wctx)
    1854             : {
    1855           0 :         vty_out(vty, "Flags: I=local-inactive, P=peer-active, X=peer-proxy\n");
    1856           0 :         vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %s\n", -wctx->addr_width,
    1857             :                 "Neighbor", "Type", "Flags", "State", "MAC", "Remote ES/VTEP",
    1858             :                 "Seq #'s");
    1859           0 : }
    1860             : 
    1861           0 : static char *zebra_evpn_print_neigh_flags(struct zebra_neigh *n,
    1862             :                                           char *flags_buf,
    1863             :                                           uint32_t flags_buf_sz)
    1864             : {
    1865           0 :         snprintf(flags_buf, flags_buf_sz, "%s%s%s",
    1866           0 :                         (n->flags & ZEBRA_NEIGH_ES_PEER_ACTIVE) ?
    1867             :                         "P" : "",
    1868           0 :                         (n->flags & ZEBRA_NEIGH_ES_PEER_PROXY) ?
    1869             :                         "X" : "",
    1870           0 :                         (n->flags & ZEBRA_NEIGH_LOCAL_INACTIVE) ?
    1871             :                         "I" : "");
    1872             : 
    1873           0 :         return flags_buf;
    1874             : }
    1875             : 
    1876             : /*
    1877             :  * Print neighbor hash entry - called for display of all neighbors.
    1878             :  */
    1879           0 : void zebra_evpn_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
    1880             : {
    1881           0 :         struct vty *vty;
    1882           0 :         json_object *json_evpn = NULL, *json_row = NULL;
    1883           0 :         struct zebra_neigh *n;
    1884           0 :         char buf1[ETHER_ADDR_STRLEN];
    1885           0 :         char buf2[INET6_ADDRSTRLEN];
    1886           0 :         char addr_buf[PREFIX_STRLEN];
    1887           0 :         struct neigh_walk_ctx *wctx = ctxt;
    1888           0 :         const char *state_str;
    1889           0 :         char flags_buf[6];
    1890             : 
    1891           0 :         vty = wctx->vty;
    1892           0 :         json_evpn = wctx->json;
    1893           0 :         n = (struct zebra_neigh *)bucket->data;
    1894             : 
    1895           0 :         if (json_evpn)
    1896           0 :                 json_row = json_object_new_object();
    1897             : 
    1898           0 :         prefix_mac2str(&n->emac, buf1, sizeof(buf1));
    1899           0 :         ipaddr2str(&n->ip, buf2, sizeof(buf2));
    1900           0 :         state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
    1901           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
    1902           0 :                 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
    1903           0 :                         return;
    1904             : 
    1905           0 :                 if (json_evpn == NULL) {
    1906           0 :                         vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
    1907           0 :                                 -wctx->addr_width, buf2, "local",
    1908             :                                 zebra_evpn_print_neigh_flags(n, flags_buf,
    1909             :                     sizeof(flags_buf)), state_str, buf1,
    1910             :                     "", n->loc_seq, n->rem_seq);
    1911             :                 } else {
    1912           0 :                         json_object_string_add(json_row, "type", "local");
    1913           0 :                         json_object_string_add(json_row, "state", state_str);
    1914           0 :                         json_object_string_add(json_row, "mac", buf1);
    1915           0 :                         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
    1916           0 :                                 json_object_boolean_true_add(json_row,
    1917             :                                                              "defaultGateway");
    1918           0 :                         json_object_int_add(json_row, "localSequence",
    1919           0 :                                             n->loc_seq);
    1920           0 :                         json_object_int_add(json_row, "remoteSequence",
    1921           0 :                                             n->rem_seq);
    1922           0 :                         json_object_int_add(json_row, "detectionCount",
    1923           0 :                                             n->dad_count);
    1924           0 :                         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
    1925           0 :                                 json_object_boolean_true_add(json_row,
    1926             :                                                              "isDuplicate");
    1927             :                         else
    1928           0 :                                 json_object_boolean_false_add(json_row,
    1929             :                                                               "isDuplicate");
    1930             :                 }
    1931           0 :                 wctx->count++;
    1932           0 :         } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    1933           0 :                 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
    1934           0 :                     && !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))
    1935             :                         return;
    1936             : 
    1937           0 :                 if (json_evpn == NULL) {
    1938           0 :                         if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
    1939           0 :                             && (wctx->count == 0))
    1940           0 :                                 zebra_evpn_print_neigh_hdr(vty, wctx);
    1941             : 
    1942           0 :                         if (n->mac->es == NULL)
    1943           0 :                                 inet_ntop(AF_INET, &n->r_vtep_ip,
    1944             :                                           addr_buf, sizeof(addr_buf));
    1945             : 
    1946           0 :                         vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
    1947           0 :                                 -wctx->addr_width, buf2, "remote",
    1948             :                                 zebra_evpn_print_neigh_flags(n, flags_buf,
    1949             :                                 sizeof(flags_buf)), state_str, buf1,
    1950           0 :                                 n->mac->es ? n->mac->es->esi_str : addr_buf,
    1951             :                                 n->loc_seq, n->rem_seq);
    1952             :                 } else {
    1953           0 :                         json_object_string_add(json_row, "type", "remote");
    1954           0 :                         json_object_string_add(json_row, "state", state_str);
    1955           0 :                         json_object_string_add(json_row, "mac", buf1);
    1956           0 :                         if (n->mac->es)
    1957           0 :                                 json_object_string_add(json_row, "remoteEs",
    1958           0 :                                                        n->mac->es->esi_str);
    1959             :                         else
    1960           0 :                                 json_object_string_addf(json_row, "remoteVtep",
    1961             :                                                         "%pI4", &n->r_vtep_ip);
    1962           0 :                         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
    1963           0 :                                 json_object_boolean_true_add(json_row,
    1964             :                                                              "defaultGateway");
    1965           0 :                         json_object_int_add(json_row, "localSequence",
    1966           0 :                                             n->loc_seq);
    1967           0 :                         json_object_int_add(json_row, "remoteSequence",
    1968           0 :                                             n->rem_seq);
    1969           0 :                         json_object_int_add(json_row, "detectionCount",
    1970           0 :                                             n->dad_count);
    1971           0 :                         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
    1972           0 :                                 json_object_boolean_true_add(json_row,
    1973             :                                                              "isDuplicate");
    1974             :                         else
    1975           0 :                                 json_object_boolean_false_add(json_row,
    1976             :                                                               "isDuplicate");
    1977             :                 }
    1978           0 :                 wctx->count++;
    1979             :         }
    1980             : 
    1981           0 :         if (json_evpn)
    1982           0 :                 json_object_object_add(json_evpn, buf2, json_row);
    1983             : }
    1984             : 
    1985             : /*
    1986             :  * Print neighbor hash entry in detail - called for display of all neighbors.
    1987             :  */
    1988           0 : void zebra_evpn_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt)
    1989             : {
    1990           0 :         struct vty *vty;
    1991           0 :         json_object *json_evpn = NULL, *json_row = NULL;
    1992           0 :         struct zebra_neigh *n;
    1993           0 :         char buf[INET6_ADDRSTRLEN];
    1994           0 :         struct neigh_walk_ctx *wctx = ctxt;
    1995             : 
    1996           0 :         vty = wctx->vty;
    1997           0 :         json_evpn = wctx->json;
    1998           0 :         n = (struct zebra_neigh *)bucket->data;
    1999           0 :         if (!n)
    2000           0 :                 return;
    2001             : 
    2002           0 :         ipaddr2str(&n->ip, buf, sizeof(buf));
    2003           0 :         if (json_evpn)
    2004           0 :                 json_row = json_object_new_object();
    2005             : 
    2006           0 :         zebra_evpn_print_neigh(n, vty, json_row);
    2007             : 
    2008           0 :         if (json_evpn)
    2009           0 :                 json_object_object_add(json_evpn, buf, json_row);
    2010             : }
    2011             : 
    2012           0 : void zebra_evpn_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt)
    2013             : {
    2014           0 :         struct zebra_neigh *nbr;
    2015             : 
    2016           0 :         nbr = (struct zebra_neigh *)bucket->data;
    2017           0 :         if (!nbr)
    2018             :                 return;
    2019             : 
    2020           0 :         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
    2021           0 :                 zebra_evpn_print_neigh_hash(bucket, ctxt);
    2022             : }
    2023             : 
    2024           0 : void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
    2025             :                                             void *ctxt)
    2026             : {
    2027           0 :         struct zebra_neigh *nbr;
    2028             : 
    2029           0 :         nbr = (struct zebra_neigh *)bucket->data;
    2030           0 :         if (!nbr)
    2031             :                 return;
    2032             : 
    2033           0 :         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
    2034           0 :                 zebra_evpn_print_neigh_hash_detail(bucket, ctxt);
    2035             : }
    2036             : 
    2037           0 : void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn,
    2038             :                                        struct zebra_vrf *zvrf,
    2039             :                                        const struct ipaddr *ipaddr,
    2040             :                                        struct zebra_mac *mac,
    2041             :                                        struct in_addr vtep_ip, uint8_t flags,
    2042             :                                        uint32_t seq)
    2043             : {
    2044           0 :         struct zebra_neigh *n;
    2045           0 :         int update_neigh = 0;
    2046           0 :         struct zebra_mac *old_mac = NULL;
    2047           0 :         bool old_static = false;
    2048           0 :         bool do_dad = false;
    2049           0 :         bool is_dup_detect = false;
    2050           0 :         bool is_router;
    2051             : 
    2052           0 :         assert(mac);
    2053           0 :         is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
    2054             : 
    2055             :         /* Check if the remote neighbor itself is unknown or has a
    2056             :          * change. If so, create or update and then install the entry.
    2057             :          */
    2058           0 :         n = zebra_evpn_neigh_lookup(zevpn, ipaddr);
    2059           0 :         if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
    2060           0 :             || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)
    2061           0 :             || (memcmp(&n->emac, &mac->macaddr, sizeof(struct ethaddr)) != 0)
    2062           0 :             || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) || seq != n->rem_seq)
    2063           0 :                 update_neigh = 1;
    2064             : 
    2065           0 :         if (update_neigh) {
    2066           0 :                 if (!n) {
    2067           0 :                         n = zebra_evpn_neigh_add(zevpn, ipaddr, &mac->macaddr,
    2068             :                                                  mac, 0);
    2069             :                 } else {
    2070             :                         /* When host moves but changes its (MAC,IP)
    2071             :                          * binding, BGP may install a MACIP entry that
    2072             :                          * corresponds to "older" location of the host
    2073             :                          * in transient situations (because {IP1,M1}
    2074             :                          * is a different route from {IP1,M2}). Check
    2075             :                          * the sequence number and ignore this update
    2076             :                          * if appropriate.
    2077             :                          */
    2078             : 
    2079           0 :                         if (!zebra_evpn_neigh_is_bgp_seq_ok(
    2080           0 :                                     zevpn, n, &mac->macaddr, seq, false))
    2081           0 :                                 return;
    2082           0 :                         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
    2083           0 :                                 old_static = zebra_evpn_neigh_is_static(n);
    2084           0 :                                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
    2085           0 :                                         zlog_debug(
    2086             :                                                 "sync->remote neigh vni %u ip %pIA mac %pEA seq %d f0x%x",
    2087             :                                                 n->zevpn->vni, &n->ip, &n->emac,
    2088             :                                                 seq, n->flags);
    2089           0 :                                 if (IS_ZEBRA_NEIGH_ACTIVE(n))
    2090           0 :                                         zebra_evpn_neigh_send_del_to_client(
    2091             :                                                 zevpn->vni, &n->ip, &n->emac,
    2092             :                                                 n->flags, n->state,
    2093             :                                                 false /*force*/);
    2094           0 :                                 zebra_evpn_neigh_clear_sync_info(n);
    2095             :                         }
    2096           0 :                         if (memcmp(&n->emac, &mac->macaddr,
    2097             :                                    sizeof(struct ethaddr))
    2098             :                             != 0) {
    2099             :                                 /* update neigh list for macs */
    2100           0 :                                 old_mac =
    2101           0 :                                         zebra_evpn_mac_lookup(zevpn, &n->emac);
    2102           0 :                                 if (old_mac) {
    2103           0 :                                         listnode_delete(old_mac->neigh_list, n);
    2104           0 :                                         n->mac = NULL;
    2105           0 :                                         zebra_evpn_deref_ip2mac(zevpn, old_mac);
    2106             :                                 }
    2107           0 :                                 n->mac = mac;
    2108           0 :                                 listnode_add_sort(mac->neigh_list, n);
    2109           0 :                                 memcpy(&n->emac, &mac->macaddr, ETH_ALEN);
    2110             : 
    2111             :                                 /* Check Neigh's curent state is local
    2112             :                                  * (this is the case where neigh/host has  moved
    2113             :                                  * from L->R) and check previous detction
    2114             :                                  * started via local learning.
    2115             :                                  *
    2116             :                                  * RFC-7432: A PE/VTEP that detects a MAC
    2117             :                                  * mobilit event via local learning starts
    2118             :                                  * an M-second timer.
    2119             :                                  * VTEP-IP or seq. change along is not
    2120             :                                  * considered for dup. detection.
    2121             :                                  *
    2122             :                                  * Mobilty event scenario-B IP-MAC binding
    2123             :                                  * changed.
    2124             :                                  */
    2125           0 :                                 if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
    2126           0 :                                     && n->dad_count)
    2127           0 :                                         do_dad = true;
    2128             :                         }
    2129             :                 }
    2130             : 
    2131             :                 /* Set "remote" forwarding info. */
    2132           0 :                 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS);
    2133           0 :                 n->r_vtep_ip = vtep_ip;
    2134           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
    2135             : 
    2136             :                 /* Set router flag (R-bit) to this Neighbor entry */
    2137           0 :                 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
    2138           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    2139             :                 else
    2140           0 :                         UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    2141             : 
    2142             :                 /* Check old or new MAC detected as duplicate,
    2143             :                  * inherit duplicate flag to this neigh.
    2144             :                  */
    2145           0 :                 if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) {
    2146           0 :                         flog_warn(
    2147             :                                 EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
    2148             :                                 "VNI %u: MAC %pEA IP %pIA detected as duplicate during remote update, inherit duplicate from MAC",
    2149             :                                 zevpn->vni, &mac->macaddr, &n->ip);
    2150             :                 }
    2151             : 
    2152             :                 /* Check duplicate address detection for IP */
    2153           0 :                 zebra_evpn_dup_addr_detect_for_neigh(
    2154             :                         zvrf, n, n->r_vtep_ip, do_dad, &is_dup_detect, false);
    2155             :                 /* Install the entry. */
    2156           0 :                 if (!is_dup_detect)
    2157           0 :                         zebra_evpn_rem_neigh_install(zevpn, n, old_static);
    2158             :         }
    2159             : 
    2160             :         /* Update seq number. */
    2161           0 :         n->rem_seq = seq;
    2162             : }
    2163             : 
    2164           0 : int zebra_evpn_neigh_gw_macip_add(struct interface *ifp,
    2165             :                                   struct zebra_evpn *zevpn, struct ipaddr *ip,
    2166             :                                   struct zebra_mac *mac)
    2167             : {
    2168           0 :         struct zebra_neigh *n;
    2169             : 
    2170           0 :         assert(mac);
    2171             : 
    2172           0 :         n = zebra_evpn_neigh_lookup(zevpn, ip);
    2173           0 :         if (!n)
    2174           0 :                 n = zebra_evpn_neigh_add(zevpn, ip, &mac->macaddr, mac, 0);
    2175             : 
    2176             :         /* Set "local" forwarding info. */
    2177           0 :         SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
    2178           0 :         ZEBRA_NEIGH_SET_ACTIVE(n);
    2179           0 :         memcpy(&n->emac, &mac->macaddr, ETH_ALEN);
    2180           0 :         n->ifindex = ifp->ifindex;
    2181             : 
    2182             :         /* Only advertise in BGP if the knob is enabled */
    2183           0 :         if (advertise_gw_macip_enabled(zevpn)) {
    2184             : 
    2185           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
    2186             :                 /* Set Router flag (R-bit) */
    2187           0 :                 if (ip->ipa_type == IPADDR_V6)
    2188           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
    2189             : 
    2190           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2191           0 :                         zlog_debug(
    2192             :                                 "SVI %s(%u) L2-VNI %u, sending GW MAC %pEA IP %pIA add to BGP with flags 0x%x",
    2193             :                                 ifp->name, ifp->ifindex, zevpn->vni,
    2194             :                                 &mac->macaddr, ip, n->flags);
    2195             : 
    2196           0 :                 zebra_evpn_neigh_send_add_to_client(
    2197             :                         zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
    2198           0 :         } else if (advertise_svi_macip_enabled(zevpn)) {
    2199             : 
    2200           0 :                 SET_FLAG(n->flags, ZEBRA_NEIGH_SVI_IP);
    2201           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2202           0 :                         zlog_debug(
    2203             :                                 "SVI %s(%u) L2-VNI %u, sending SVI MAC %pEA IP %pIA add to BGP with flags 0x%x",
    2204             :                                 ifp->name, ifp->ifindex, zevpn->vni,
    2205             :                                 &mac->macaddr, ip, n->flags);
    2206             : 
    2207           0 :                 zebra_evpn_neigh_send_add_to_client(
    2208             :                         zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
    2209             :         }
    2210             : 
    2211           0 :         return 0;
    2212             : }
    2213             : 
    2214           0 : void zebra_evpn_neigh_remote_uninstall(struct zebra_evpn *zevpn,
    2215             :                                        struct zebra_vrf *zvrf,
    2216             :                                        struct zebra_neigh *n,
    2217             :                                        struct zebra_mac *mac,
    2218             :                                        const struct ipaddr *ipaddr)
    2219             : {
    2220           0 :         if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)
    2221           0 :             && CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
    2222           0 :             && (memcmp(n->emac.octet, mac->macaddr.octet, ETH_ALEN) == 0)) {
    2223           0 :                 struct interface *vlan_if;
    2224             : 
    2225           0 :                 vlan_if = zevpn_map_to_svi(zevpn);
    2226           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2227           0 :                         zlog_debug(
    2228             :                                 "%s: IP %pIA (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
    2229             :                                 __func__, ipaddr, n->flags,
    2230             :                                 vlan_if ? vlan_if->name : "Unknown");
    2231           0 :                 if (vlan_if)
    2232           0 :                         neigh_read_specific_ip(ipaddr, vlan_if);
    2233             :         }
    2234             : 
    2235             :         /* When the MAC changes for an IP, it is possible the
    2236             :          * client may update the new MAC before trying to delete the
    2237             :          * "old" neighbor (as these are two different MACIP routes).
    2238             :          * Do the delete only if the MAC matches.
    2239             :          */
    2240           0 :         if (!memcmp(n->emac.octet, mac->macaddr.octet, ETH_ALEN)) {
    2241           0 :                 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
    2242           0 :                         zebra_evpn_sync_neigh_del(n);
    2243           0 :                 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    2244           0 :                         zebra_evpn_neigh_uninstall(zevpn, n);
    2245           0 :                         zebra_evpn_neigh_del(zevpn, n);
    2246           0 :                         zebra_evpn_deref_ip2mac(zevpn, mac);
    2247             :                 }
    2248             :         } else {
    2249           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2250           0 :                         zlog_debug(
    2251             :                                 "%s: IP %pIA MAC %pEA (flags 0x%x) found doesn't match MAC %pEA, ignoring Neigh DEL",
    2252             :                                 __func__, ipaddr, &n->emac, n->flags,
    2253             :                                 &mac->macaddr);
    2254             :         }
    2255           0 : }
    2256             : 
    2257           0 : int zebra_evpn_neigh_del_ip(struct zebra_evpn *zevpn, const struct ipaddr *ip)
    2258             : {
    2259           0 :         struct zebra_neigh *n;
    2260           0 :         struct zebra_mac *zmac;
    2261           0 :         bool old_bgp_ready;
    2262           0 :         bool new_bgp_ready;
    2263           0 :         struct zebra_vrf *zvrf;
    2264             : 
    2265             :         /* If entry doesn't exist, nothing to do. */
    2266           0 :         n = zebra_evpn_neigh_lookup(zevpn, ip);
    2267           0 :         if (!n)
    2268             :                 return 0;
    2269             : 
    2270           0 :         zmac = zebra_evpn_mac_lookup(zevpn, &n->emac);
    2271           0 :         if (!zmac) {
    2272           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2273           0 :                         zlog_debug(
    2274             :                                 "Trying to del a neigh %pIA without a mac %pEA on VNI %u",
    2275             :                                 ip, &n->emac,
    2276             :                                 zevpn->vni);
    2277             : 
    2278           0 :                 return 0;
    2279             :         }
    2280             : 
    2281             :         /* If it is a remote entry, the kernel has aged this out or someone has
    2282             :          * deleted it, it needs to be re-installed as FRR is the owner.
    2283             :          */
    2284           0 :         if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
    2285           0 :                 zebra_evpn_rem_neigh_install(zevpn, n, false /*was_static*/);
    2286           0 :                 return 0;
    2287             :         }
    2288             : 
    2289             :         /* if this is a sync entry it cannot be dropped re-install it in
    2290             :          * the dataplane
    2291             :          */
    2292           0 :         old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
    2293           0 :         if (zebra_evpn_neigh_is_static(n)) {
    2294           0 :                 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
    2295           0 :                         zlog_debug("re-add sync neigh vni %u ip %pIA mac %pEA 0x%x",
    2296             :                                    n->zevpn->vni, &n->ip, &n->emac,
    2297             :                                    n->flags);
    2298             : 
    2299           0 :                 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
    2300           0 :                         SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
    2301             :                 /* inform-bgp about change in local-activity if any */
    2302           0 :                 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
    2303           0 :                 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
    2304             :                                                         new_bgp_ready);
    2305             : 
    2306             :                 /* re-install the entry in the kernel */
    2307           0 :                 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
    2308             :                                                  false /* force_clear_static */,
    2309             :                                                  __func__);
    2310             : 
    2311           0 :                 return 0;
    2312             :         }
    2313             : 
    2314           0 :         zvrf = zevpn->vxlan_if->vrf->info;
    2315           0 :         if (!zvrf) {
    2316           0 :                 zlog_debug("%s: VNI %u vrf lookup failed.", __func__,
    2317             :                            zevpn->vni);
    2318           0 :                 return -1;
    2319             :         }
    2320             : 
    2321             :         /* In case of feeze action, if local neigh is in duplicate state,
    2322             :          * Mark the Neigh as inactive before sending delete request to BGPd,
    2323             :          * If BGPd has remote entry, it will re-install
    2324             :          */
    2325           0 :         if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
    2326           0 :                 ZEBRA_NEIGH_SET_INACTIVE(n);
    2327             : 
    2328             :         /* Remove neighbor from BGP. */
    2329           0 :         zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac,
    2330           0 :                                             n->flags, n->state,
    2331             :                                             false /* force */);
    2332             : 
    2333             :         /* Delete this neighbor entry. */
    2334           0 :         zebra_evpn_neigh_del(zevpn, n);
    2335             : 
    2336             :         /* see if the AUTO mac needs to be deleted */
    2337           0 :         if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
    2338           0 :             && !zebra_evpn_mac_in_use(zmac))
    2339           0 :                 zebra_evpn_mac_del(zevpn, zmac);
    2340             : 
    2341             :         return 0;
    2342             : }

Generated by: LCOV version v1.16-topotato