back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_vxlan.c (source / functions) Hit Total Coverage
Test: test_pim_bfd.py::PIMBFDTest Lines: 83 3056 2.7 %
Date: 2023-02-24 18:39:40 Functions: 26 182 14.3 %

          Line data    Source code
       1             : /*
       2             :  * Zebra EVPN for VxLAN code
       3             :  * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
       4             :  *
       5             :  * This file is part of FRR.
       6             :  *
       7             :  * FRR is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * FRR is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with FRR; see the file COPYING.  If not, write to the Free
      19             :  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :  * 02111-1307, USA.
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #include "hash.h"
      26             : #include "if.h"
      27             : #include "jhash.h"
      28             : #include "linklist.h"
      29             : #include "log.h"
      30             : #include "memory.h"
      31             : #include "prefix.h"
      32             : #include "stream.h"
      33             : #include "table.h"
      34             : #include "vlan.h"
      35             : #include "vxlan.h"
      36             : #ifdef GNU_LINUX
      37             : #include <linux/neighbour.h>
      38             : #endif
      39             : #include "lib/printfrr.h"
      40             : 
      41             : #include "zebra/zebra_router.h"
      42             : #include "zebra/debug.h"
      43             : #include "zebra/interface.h"
      44             : #include "zebra/rib.h"
      45             : #include "zebra/rt.h"
      46             : #include "zebra/rt_netlink.h"
      47             : #include "zebra/zebra_errors.h"
      48             : #include "zebra/zebra_l2.h"
      49             : #include "zebra/zebra_ns.h"
      50             : #include "zebra/zebra_vrf.h"
      51             : #include "zebra/zebra_vxlan.h"
      52             : #include "zebra/zebra_evpn.h"
      53             : #include "zebra/zebra_evpn_mac.h"
      54             : #include "zebra/zebra_evpn_neigh.h"
      55             : #include "zebra/zebra_vxlan_private.h"
      56             : #include "zebra/zebra_evpn_mh.h"
      57             : #include "zebra/zebra_evpn_vxlan.h"
      58             : #include "zebra/zebra_router.h"
      59             : 
      60          12 : DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
      61          12 : DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
      62          12 : DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC");
      63          12 : DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor");
      64          12 : DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");
      65          12 : DEFINE_MTYPE_STATIC(ZEBRA, EVPN_VTEP, "zebra VxLAN VTEP IP");
      66             : 
      67           0 : DEFINE_HOOK(zebra_rmac_update,
      68             :             (struct zebra_mac * rmac, struct zebra_l3vni *zl3vni, bool delete,
      69             :              const char *reason),
      70             :             (rmac, zl3vni, delete, reason));
      71             : 
      72             : /* config knobs */
      73             : static bool accept_bgp_seq = true;
      74             : 
      75             : /* static function declarations */
      76             : static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
      77             :                                             void **args);
      78             : static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
      79             :                             json_object *json);
      80             : static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
      81             :                               json_object *json);
      82             : static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt);
      83             : 
      84             : /* l3-vni next-hop neigh related APIs */
      85             : static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
      86             :                                             const struct ipaddr *ip);
      87             : static void *zl3vni_nh_alloc(void *p);
      88             : static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
      89             :                                          const struct ipaddr *vtep_ip,
      90             :                                          const struct ethaddr *rmac);
      91             : static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
      92             : static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
      93             : static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
      94             :                                struct zebra_neigh *n);
      95             : 
      96             : /* l3-vni rmac related APIs */
      97             : static void zl3vni_print_rmac_hash(struct hash_bucket *, void *);
      98             : static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
      99             :                                             const struct ethaddr *rmac);
     100             : static void *zl3vni_rmac_alloc(void *p);
     101             : static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
     102             :                                          const struct ethaddr *rmac);
     103             : static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac);
     104             : static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
     105             :                                struct zebra_mac *zrmac);
     106             : static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
     107             :                                  struct zebra_mac *zrmac);
     108             : 
     109             : /* l3-vni related APIs*/
     110             : static void *zl3vni_alloc(void *p);
     111             : static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
     112             : static int zl3vni_del(struct zebra_l3vni *zl3vni);
     113             : static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
     114             : static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
     115             : 
     116             : static void zevpn_build_hash_table(void);
     117             : static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
     118             : static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
     119             : static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
     120             :                 struct in_addr sip, struct in_addr mcast_grp);
     121             : static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
     122             :                                                     struct in_addr sip,
     123             :                                                     struct in_addr mcast_grp);
     124             : static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
     125             :                                 struct in_addr mcast_grp);
     126             : static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
     127             :                                 struct in_addr mcast_grp);
     128             : static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);
     129             : 
     130           0 : bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
     131             : {
     132           0 :         return zvrf->dup_addr_detect && zebra_evpn_mh_do_dup_addr_detect();
     133             : }
     134             : 
     135             : /* Private functions */
     136           0 : static int host_rb_entry_compare(const struct host_rb_entry *hle1,
     137             :                                  const struct host_rb_entry *hle2)
     138             : {
     139           0 :         if (hle1->p.family < hle2->p.family)
     140             :                 return -1;
     141             : 
     142           0 :         if (hle1->p.family > hle2->p.family)
     143             :                 return 1;
     144             : 
     145           0 :         if (hle1->p.prefixlen < hle2->p.prefixlen)
     146             :                 return -1;
     147             : 
     148           0 :         if (hle1->p.prefixlen > hle2->p.prefixlen)
     149             :                 return 1;
     150             : 
     151           0 :         if (hle1->p.family == AF_INET) {
     152           0 :                 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
     153             :                         return -1;
     154             : 
     155           0 :                 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
     156             :                         return 1;
     157             : 
     158             :                 return 0;
     159           0 :         } else if (hle1->p.family == AF_INET6) {
     160           0 :                 return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
     161             :                               IPV6_MAX_BYTELEN);
     162           0 :         } else if (hle1->p.family == AF_EVPN) {
     163           0 :                 uint8_t family1;
     164           0 :                 uint8_t family2;
     165             : 
     166             :                 /* two (v4/v6) dummy prefixes of route_type BGP_EVPN_AD_ROUTE
     167             :                  * are used for all nexthops associated with a non-zero ESI
     168             :                  */
     169           0 :                 family1 = is_evpn_prefix_ipaddr_v4(
     170           0 :                                   (const struct prefix_evpn *)&hle1->p)
     171             :                                   ? AF_INET
     172             :                                   : AF_INET6;
     173           0 :                 family2 = is_evpn_prefix_ipaddr_v4(
     174           0 :                                   (const struct prefix_evpn *)&hle2->p)
     175             :                                   ? AF_INET
     176             :                                   : AF_INET6;
     177             : 
     178             : 
     179           0 :                 if (family1 < family2)
     180             :                         return -1;
     181             : 
     182           0 :                 if (family1 > family2)
     183             :                         return 1;
     184             : 
     185             :                 return 0;
     186             :         } else {
     187           0 :                 zlog_debug("%s: Unexpected family type: %d", __func__,
     188             :                            hle1->p.family);
     189           0 :                 return 0;
     190             :         }
     191             : }
     192           0 : RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
     193             : 
     194           0 : static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
     195             : {
     196           0 :         struct host_rb_entry *hle;
     197           0 :         uint32_t count = 0;
     198             : 
     199           0 :         RB_FOREACH (hle, host_rb_tree_entry, hrbe)
     200           0 :                 count++;
     201             : 
     202           0 :         return count;
     203             : }
     204             : 
     205           0 : static int l3vni_rmac_nh_list_cmp(void *p1, void *p2)
     206             : {
     207           0 :         const struct ipaddr *vtep_ip1 = p1;
     208           0 :         const struct ipaddr *vtep_ip2 = p2;
     209             : 
     210           0 :         return !ipaddr_cmp(vtep_ip1, vtep_ip2);
     211             : }
     212             : 
     213           0 : static void l3vni_rmac_nh_free(struct ipaddr *vtep_ip)
     214             : {
     215           0 :         XFREE(MTYPE_EVPN_VTEP, vtep_ip);
     216           0 : }
     217             : 
     218           0 : static void l3vni_rmac_nh_list_nh_delete(struct zebra_l3vni *zl3vni,
     219             :                                          struct zebra_mac *zrmac,
     220             :                                          struct ipaddr *vtep_ip)
     221             : {
     222           0 :         struct listnode *node = NULL, *nnode = NULL;
     223           0 :         struct ipaddr *vtep = NULL;
     224             : 
     225           0 :         for (ALL_LIST_ELEMENTS(zrmac->nh_list, node, nnode, vtep)) {
     226           0 :                 if (ipaddr_cmp(vtep, vtep_ip) == 0)
     227             :                         break;
     228             :         }
     229             : 
     230           0 :         if (node) {
     231           0 :                 l3vni_rmac_nh_free(vtep);
     232           0 :                 list_delete_node(zrmac->nh_list, node);
     233             :         }
     234           0 : }
     235             : 
     236             : /*
     237             :  * Print neighbors for all EVPN.
     238             :  */
     239           0 : static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
     240             :                                           void **args)
     241             : {
     242           0 :         struct vty *vty;
     243           0 :         json_object *json = NULL, *json_evpn = NULL;
     244           0 :         struct zebra_evpn *zevpn;
     245           0 :         uint32_t num_neigh;
     246           0 :         struct neigh_walk_ctx wctx;
     247           0 :         char vni_str[VNI_STR_LEN];
     248           0 :         uint32_t print_dup;
     249             : 
     250           0 :         vty = (struct vty *)args[0];
     251           0 :         json = (json_object *)args[1];
     252           0 :         print_dup = (uint32_t)(uintptr_t)args[2];
     253             : 
     254           0 :         zevpn = (struct zebra_evpn *)bucket->data;
     255             : 
     256           0 :         num_neigh = hashcount(zevpn->neigh_table);
     257             : 
     258           0 :         if (print_dup)
     259           0 :                 num_neigh = num_dup_detected_neighs(zevpn);
     260             : 
     261           0 :         if (json == NULL) {
     262           0 :                 vty_out(vty,
     263             :                         "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
     264             :                         zevpn->vni, num_neigh);
     265             :         } else {
     266           0 :                 json_evpn = json_object_new_object();
     267           0 :                 json_object_int_add(json_evpn, "numArpNd", num_neigh);
     268           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
     269             :         }
     270             : 
     271           0 :         if (!num_neigh) {
     272           0 :                 if (json)
     273           0 :                         json_object_object_add(json, vni_str, json_evpn);
     274           0 :                 return;
     275             :         }
     276             : 
     277             :         /* Since we have IPv6 addresses to deal with which can vary widely in
     278             :          * size, we try to be a bit more elegant in display by first computing
     279             :          * the maximum width.
     280             :          */
     281           0 :         memset(&wctx, 0, sizeof(wctx));
     282           0 :         wctx.zevpn = zevpn;
     283           0 :         wctx.vty = vty;
     284           0 :         wctx.addr_width = 15;
     285           0 :         wctx.json = json_evpn;
     286           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
     287             :                      &wctx);
     288             : 
     289           0 :         if (json == NULL)
     290           0 :                 zebra_evpn_print_neigh_hdr(vty, &wctx);
     291             : 
     292           0 :         if (print_dup)
     293           0 :                 hash_iterate(zevpn->neigh_table,
     294             :                              zebra_evpn_print_dad_neigh_hash, &wctx);
     295             :         else
     296           0 :                 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash,
     297             :                              &wctx);
     298             : 
     299           0 :         if (json)
     300           0 :                 json_object_object_add(json, vni_str, json_evpn);
     301             : }
     302             : 
     303             : /*
     304             :  * Print neighbors for all EVPNs in detail.
     305             :  */
     306           0 : static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket,
     307             :                                                  void **args)
     308             : {
     309           0 :         struct vty *vty;
     310           0 :         json_object *json = NULL, *json_evpn = NULL;
     311           0 :         struct zebra_evpn *zevpn;
     312           0 :         uint32_t num_neigh;
     313           0 :         struct neigh_walk_ctx wctx;
     314           0 :         char vni_str[VNI_STR_LEN];
     315           0 :         uint32_t print_dup;
     316             : 
     317           0 :         vty = (struct vty *)args[0];
     318           0 :         json = (json_object *)args[1];
     319           0 :         print_dup = (uint32_t)(uintptr_t)args[2];
     320             : 
     321           0 :         zevpn = (struct zebra_evpn *)bucket->data;
     322           0 :         if (!zevpn) {
     323           0 :                 if (json)
     324           0 :                         vty_out(vty, "{}\n");
     325           0 :                 return;
     326             :         }
     327           0 :         num_neigh = hashcount(zevpn->neigh_table);
     328             : 
     329           0 :         if (print_dup && num_dup_detected_neighs(zevpn) == 0)
     330             :                 return;
     331             : 
     332           0 :         if (json == NULL) {
     333           0 :                 vty_out(vty,
     334             :                         "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
     335             :                         zevpn->vni, num_neigh);
     336             :         } else {
     337           0 :                 json_evpn = json_object_new_object();
     338           0 :                 json_object_int_add(json_evpn, "numArpNd", num_neigh);
     339           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
     340             :         }
     341           0 :         if (!num_neigh) {
     342           0 :                 if (json)
     343           0 :                         json_object_object_add(json, vni_str, json_evpn);
     344           0 :                 return;
     345             :         }
     346             : 
     347           0 :         memset(&wctx, 0, sizeof(wctx));
     348           0 :         wctx.zevpn = zevpn;
     349           0 :         wctx.vty = vty;
     350           0 :         wctx.addr_width = 15;
     351           0 :         wctx.json = json_evpn;
     352             : 
     353           0 :         if (print_dup)
     354           0 :                 hash_iterate(zevpn->neigh_table,
     355             :                              zebra_evpn_print_dad_neigh_hash_detail, &wctx);
     356             :         else
     357           0 :                 hash_iterate(zevpn->neigh_table,
     358             :                              zebra_evpn_print_neigh_hash_detail, &wctx);
     359             : 
     360           0 :         if (json)
     361           0 :                 json_object_object_add(json, vni_str, json_evpn);
     362             : }
     363             : 
     364             : /* print a specific next hop for an l3vni */
     365           0 : static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
     366             :                             json_object *json)
     367             : {
     368           0 :         char buf1[ETHER_ADDR_STRLEN];
     369           0 :         char buf2[INET6_ADDRSTRLEN];
     370           0 :         json_object *json_hosts = NULL;
     371           0 :         struct host_rb_entry *hle;
     372             : 
     373           0 :         if (!json) {
     374           0 :                 vty_out(vty, "Ip: %s\n",
     375           0 :                         ipaddr2str(&n->ip, buf2, sizeof(buf2)));
     376           0 :                 vty_out(vty, "  RMAC: %s\n",
     377           0 :                         prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
     378           0 :                 vty_out(vty, "  Refcount: %d\n",
     379             :                         rb_host_count(&n->host_rb));
     380           0 :                 vty_out(vty, "  Prefixes:\n");
     381           0 :                 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
     382           0 :                         vty_out(vty, "    %pFX\n", &hle->p);
     383             :         } else {
     384           0 :                 json_hosts = json_object_new_array();
     385           0 :                 json_object_string_add(
     386           0 :                         json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
     387           0 :                 json_object_string_add(
     388             :                         json, "routerMac",
     389           0 :                         prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
     390           0 :                 json_object_int_add(json, "refCount",
     391           0 :                                     rb_host_count(&n->host_rb));
     392           0 :                 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
     393           0 :                         json_object_array_add(json_hosts,
     394             :                                               json_object_new_string(prefix2str(
     395           0 :                                                                                 &hle->p, buf2, sizeof(buf2))));
     396           0 :                 json_object_object_add(json, "prefixList", json_hosts);
     397             :         }
     398           0 : }
     399             : 
     400             : /* Print a specific RMAC entry */
     401           0 : static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
     402             :                               json_object *json)
     403             : {
     404           0 :         struct listnode *node = NULL;
     405           0 :         struct ipaddr *vtep = NULL;
     406           0 :         json_object *json_nhs = NULL;
     407             : 
     408           0 :         if (!json) {
     409           0 :                 vty_out(vty, "MAC: %pEA\n", &zrmac->macaddr);
     410           0 :                 vty_out(vty, " Remote VTEP: %pI4\n",
     411             :                         &zrmac->fwd_info.r_vtep_ip);
     412             :         } else {
     413           0 :                 json_nhs = json_object_new_array();
     414           0 :                 json_object_string_addf(json, "routerMac", "%pEA",
     415             :                                         &zrmac->macaddr);
     416           0 :                 json_object_string_addf(json, "vtepIp", "%pI4",
     417             :                                         &zrmac->fwd_info.r_vtep_ip);
     418           0 :                 for (ALL_LIST_ELEMENTS_RO(zrmac->nh_list, node, vtep)) {
     419           0 :                         json_object_array_add(json_nhs, json_object_new_stringf(
     420             :                                                                 "%pIA", vtep));
     421             :                 }
     422           0 :                 json_object_object_add(json, "nexthops", json_nhs);
     423             :         }
     424           0 : }
     425             : 
     426             : /*
     427             :  * Print MACs for all EVPNs.
     428             :  */
     429           0 : static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt)
     430             : {
     431           0 :         struct vty *vty;
     432           0 :         json_object *json = NULL, *json_evpn = NULL;
     433           0 :         json_object *json_mac = NULL;
     434           0 :         struct zebra_evpn *zevpn;
     435           0 :         uint32_t num_macs;
     436           0 :         struct mac_walk_ctx *wctx = ctxt;
     437           0 :         char vni_str[VNI_STR_LEN];
     438             : 
     439           0 :         vty = wctx->vty;
     440           0 :         json = wctx->json;
     441             : 
     442           0 :         zevpn = (struct zebra_evpn *)bucket->data;
     443           0 :         wctx->zevpn = zevpn;
     444             : 
     445             :         /*We are iterating over a new VNI, set the count to 0*/
     446           0 :         wctx->count = 0;
     447             : 
     448           0 :         num_macs = num_valid_macs(zevpn);
     449           0 :         if (!num_macs)
     450           0 :                 return;
     451             : 
     452           0 :         if (wctx->print_dup)
     453           0 :                 num_macs = num_dup_detected_macs(zevpn);
     454             : 
     455           0 :         if (json) {
     456           0 :                 json_evpn = json_object_new_object();
     457           0 :                 json_mac = json_object_new_object();
     458           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
     459             :         }
     460             : 
     461           0 :         if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
     462           0 :                 if (json == NULL) {
     463           0 :                         vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
     464             :                                 zevpn->vni, num_macs);
     465           0 :                         vty_out(vty,
     466             :                                 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
     467           0 :                         vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
     468             :                                 "Type", "Flags", "Intf/Remote ES/VTEP",
     469             :                                 "VLAN", "Seq #'s");
     470             :                 } else
     471           0 :                         json_object_int_add(json_evpn, "numMacs", num_macs);
     472             :         }
     473             : 
     474           0 :         if (!num_macs) {
     475           0 :                 if (json) {
     476           0 :                         json_object_int_add(json_evpn, "numMacs", num_macs);
     477           0 :                         json_object_object_add(json, vni_str, json_evpn);
     478             :                 }
     479           0 :                 return;
     480             :         }
     481             : 
     482             :         /* assign per-evpn to wctx->json object to fill macs
     483             :          * under the evpn. Re-assign primary json object to fill
     484             :          * next evpn information.
     485             :          */
     486           0 :         wctx->json = json_mac;
     487           0 :         if (wctx->print_dup)
     488           0 :                 hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash,
     489             :                              wctx);
     490             :         else
     491           0 :                 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, wctx);
     492           0 :         wctx->json = json;
     493           0 :         if (json) {
     494           0 :                 if (wctx->count)
     495           0 :                         json_object_object_add(json_evpn, "macs", json_mac);
     496           0 :                 json_object_object_add(json, vni_str, json_evpn);
     497             :         }
     498             : }
     499             : 
     500             : /*
     501             :  * Print MACs in detail for all EVPNs.
     502             :  */
     503           0 : static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket,
     504             :                                                void *ctxt)
     505             : {
     506           0 :         struct vty *vty;
     507           0 :         json_object *json = NULL, *json_evpn = NULL;
     508           0 :         json_object *json_mac = NULL;
     509           0 :         struct zebra_evpn *zevpn;
     510           0 :         uint32_t num_macs;
     511           0 :         struct mac_walk_ctx *wctx = ctxt;
     512           0 :         char vni_str[VNI_STR_LEN];
     513             : 
     514           0 :         vty = wctx->vty;
     515           0 :         json = wctx->json;
     516             : 
     517           0 :         zevpn = (struct zebra_evpn *)bucket->data;
     518           0 :         if (!zevpn) {
     519           0 :                 if (json)
     520           0 :                         vty_out(vty, "{}\n");
     521           0 :                 return;
     522             :         }
     523           0 :         wctx->zevpn = zevpn;
     524             : 
     525             :         /*We are iterating over a new EVPN, set the count to 0*/
     526           0 :         wctx->count = 0;
     527             : 
     528           0 :         num_macs = num_valid_macs(zevpn);
     529           0 :         if (!num_macs)
     530             :                 return;
     531             : 
     532           0 :         if (wctx->print_dup && (num_dup_detected_macs(zevpn) == 0))
     533             :                 return;
     534             : 
     535           0 :         if (json) {
     536           0 :                 json_evpn = json_object_new_object();
     537           0 :                 json_mac = json_object_new_object();
     538           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
     539             :         }
     540             : 
     541           0 :         if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
     542           0 :                 if (json == NULL) {
     543           0 :                         vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
     544             :                                 zevpn->vni, num_macs);
     545             :                 } else
     546           0 :                         json_object_int_add(json_evpn, "numMacs", num_macs);
     547             :         }
     548             :         /* assign per-evpn to wctx->json object to fill macs
     549             :          * under the evpn. Re-assign primary json object to fill
     550             :          * next evpn information.
     551             :          */
     552           0 :         wctx->json = json_mac;
     553           0 :         if (wctx->print_dup)
     554           0 :                 hash_iterate(zevpn->mac_table,
     555             :                              zebra_evpn_print_dad_mac_hash_detail, wctx);
     556             :         else
     557           0 :                 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail,
     558             :                              wctx);
     559           0 :         wctx->json = json;
     560           0 :         if (json) {
     561           0 :                 if (wctx->count)
     562           0 :                         json_object_object_add(json_evpn, "macs", json_mac);
     563           0 :                 json_object_object_add(json, vni_str, json_evpn);
     564             :         }
     565             : }
     566             : 
     567           0 : static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx)
     568             : {
     569           0 :         struct nh_walk_ctx *wctx = NULL;
     570           0 :         struct vty *vty = NULL;
     571           0 :         struct json_object *json_evpn = NULL;
     572           0 :         struct json_object *json_nh = NULL;
     573           0 :         struct zebra_neigh *n = NULL;
     574           0 :         char buf1[ETHER_ADDR_STRLEN];
     575           0 :         char buf2[INET6_ADDRSTRLEN];
     576             : 
     577           0 :         wctx = (struct nh_walk_ctx *)ctx;
     578           0 :         vty = wctx->vty;
     579           0 :         json_evpn = wctx->json;
     580           0 :         if (json_evpn)
     581           0 :                 json_nh = json_object_new_object();
     582           0 :         n = (struct zebra_neigh *)bucket->data;
     583             : 
     584           0 :         if (!json_evpn) {
     585           0 :                 vty_out(vty, "%-15s %-17s\n",
     586           0 :                         ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
     587           0 :                         prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
     588             :         } else {
     589           0 :                 json_object_string_add(json_nh, "nexthopIp",
     590           0 :                                        ipaddr2str(&n->ip, buf2, sizeof(buf2)));
     591           0 :                 json_object_string_add(
     592             :                         json_nh, "routerMac",
     593           0 :                         prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
     594           0 :                 json_object_object_add(json_evpn,
     595           0 :                                        ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
     596             :                                        json_nh);
     597             :         }
     598           0 : }
     599             : 
     600           0 : static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket,
     601             :                                          void **args)
     602             : {
     603           0 :         struct vty *vty = NULL;
     604           0 :         json_object *json = NULL;
     605           0 :         json_object *json_evpn = NULL;
     606           0 :         struct zebra_l3vni *zl3vni = NULL;
     607           0 :         uint32_t num_nh = 0;
     608           0 :         struct nh_walk_ctx wctx;
     609           0 :         char vni_str[VNI_STR_LEN];
     610             : 
     611           0 :         vty = (struct vty *)args[0];
     612           0 :         json = (struct json_object *)args[1];
     613             : 
     614           0 :         zl3vni = (struct zebra_l3vni *)bucket->data;
     615             : 
     616           0 :         num_nh = hashcount(zl3vni->nh_table);
     617           0 :         if (!num_nh)
     618           0 :                 return;
     619             : 
     620           0 :         if (json) {
     621           0 :                 json_evpn = json_object_new_object();
     622           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
     623             :         }
     624             : 
     625           0 :         if (json == NULL) {
     626           0 :                 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
     627           0 :                 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
     628             :         } else
     629           0 :                 json_object_int_add(json_evpn, "numNextHops", num_nh);
     630             : 
     631           0 :         memset(&wctx, 0, sizeof(wctx));
     632           0 :         wctx.vty = vty;
     633           0 :         wctx.json = json_evpn;
     634           0 :         hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
     635           0 :         if (json)
     636           0 :                 json_object_object_add(json, vni_str, json_evpn);
     637             : }
     638             : 
     639           0 : static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket,
     640             :                                            void **args)
     641             : {
     642           0 :         struct vty *vty = NULL;
     643           0 :         json_object *json = NULL;
     644           0 :         json_object *json_evpn = NULL;
     645           0 :         struct zebra_l3vni *zl3vni = NULL;
     646           0 :         uint32_t num_rmacs;
     647           0 :         struct rmac_walk_ctx wctx;
     648           0 :         char vni_str[VNI_STR_LEN];
     649             : 
     650           0 :         vty = (struct vty *)args[0];
     651           0 :         json = (struct json_object *)args[1];
     652             : 
     653           0 :         zl3vni = (struct zebra_l3vni *)bucket->data;
     654             : 
     655           0 :         num_rmacs = hashcount(zl3vni->rmac_table);
     656           0 :         if (!num_rmacs)
     657           0 :                 return;
     658             : 
     659           0 :         if (json) {
     660           0 :                 json_evpn = json_object_new_object();
     661           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
     662             :         }
     663             : 
     664           0 :         if (json == NULL) {
     665           0 :                 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
     666           0 :                 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
     667             :         } else
     668           0 :                 json_object_int_add(json_evpn, "numRmacs", num_rmacs);
     669             : 
     670             :         /* assign per-vni to wctx->json object to fill macs
     671             :          * under the vni. Re-assign primary json object to fill
     672             :          * next vni information.
     673             :          */
     674           0 :         memset(&wctx, 0, sizeof(wctx));
     675           0 :         wctx.vty = vty;
     676           0 :         wctx.json = json_evpn;
     677           0 :         hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
     678           0 :         if (json)
     679           0 :                 json_object_object_add(json, vni_str, json_evpn);
     680             : }
     681             : 
     682           0 : static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
     683             : {
     684           0 :         struct zebra_mac *zrmac = NULL;
     685           0 :         struct rmac_walk_ctx *wctx = NULL;
     686           0 :         struct vty *vty = NULL;
     687           0 :         struct json_object *json = NULL;
     688           0 :         struct json_object *json_rmac = NULL;
     689           0 :         char buf[PREFIX_STRLEN];
     690             : 
     691           0 :         wctx = (struct rmac_walk_ctx *)ctx;
     692           0 :         vty = wctx->vty;
     693           0 :         json = wctx->json;
     694           0 :         if (json)
     695           0 :                 json_rmac = json_object_new_object();
     696           0 :         zrmac = (struct zebra_mac *)bucket->data;
     697             : 
     698           0 :         if (!json) {
     699           0 :                 vty_out(vty, "%-17s %-21pI4\n",
     700           0 :                         prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
     701             :                         &zrmac->fwd_info.r_vtep_ip);
     702             :         } else {
     703           0 :                 json_object_string_add(
     704             :                         json_rmac, "routerMac",
     705           0 :                         prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
     706           0 :                 json_object_string_addf(json_rmac, "vtepIp", "%pI4",
     707             :                                         &zrmac->fwd_info.r_vtep_ip);
     708           0 :                 json_object_object_add(
     709           0 :                         json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
     710             :                         json_rmac);
     711             :         }
     712           0 : }
     713             : 
     714             : /* print a specific L3 VNI entry */
     715           0 : static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
     716             : {
     717           0 :         char buf[PREFIX_STRLEN];
     718           0 :         struct vty *vty = NULL;
     719           0 :         json_object *json = NULL;
     720           0 :         struct zebra_evpn *zevpn = NULL;
     721           0 :         json_object *json_evpn_list = NULL;
     722           0 :         struct listnode *node = NULL, *nnode = NULL;
     723             : 
     724           0 :         vty = ctx[0];
     725           0 :         json = ctx[1];
     726             : 
     727           0 :         if (!json) {
     728           0 :                 vty_out(vty, "VNI: %u\n", zl3vni->vni);
     729           0 :                 vty_out(vty, "  Type: %s\n", "L3");
     730           0 :                 vty_out(vty, "  Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
     731           0 :                 vty_out(vty, "  Local Vtep Ip: %pI4\n",
     732             :                         &zl3vni->local_vtep_ip);
     733           0 :                 vty_out(vty, "  Vxlan-Intf: %s\n",
     734             :                         zl3vni_vxlan_if_name(zl3vni));
     735           0 :                 vty_out(vty, "  SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
     736           0 :                 vty_out(vty, "  State: %s\n", zl3vni_state2str(zl3vni));
     737           0 :                 vty_out(vty, "  VNI Filter: %s\n",
     738           0 :                         CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
     739             :                                 ? "prefix-routes-only"
     740             :                                 : "none");
     741           0 :                 vty_out(vty, "  System MAC: %s\n",
     742             :                         zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
     743           0 :                 vty_out(vty, "  Router MAC: %s\n",
     744             :                         zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
     745           0 :                 vty_out(vty, "  L2 VNIs: ");
     746           0 :                 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn))
     747           0 :                         vty_out(vty, "%u ", zevpn->vni);
     748           0 :                 vty_out(vty, "\n");
     749             :         } else {
     750           0 :                 json_evpn_list = json_object_new_array();
     751           0 :                 json_object_int_add(json, "vni", zl3vni->vni);
     752           0 :                 json_object_string_add(json, "type", "L3");
     753             : #if CONFDATE > 20240210
     754             : CPP_NOTICE("Drop `vrf` from JSON outputs")
     755             : #endif
     756           0 :                 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
     757           0 :                 json_object_string_add(json, "tenantVrf",
     758             :                                        zl3vni_vrf_name(zl3vni));
     759           0 :                 json_object_string_addf(json, "localVtepIp", "%pI4",
     760             :                                         &zl3vni->local_vtep_ip);
     761           0 :                 json_object_string_add(json, "vxlanIntf",
     762             :                                        zl3vni_vxlan_if_name(zl3vni));
     763           0 :                 json_object_string_add(json, "sviIntf",
     764             :                                        zl3vni_svi_if_name(zl3vni));
     765           0 :                 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
     766           0 :                 json_object_string_add(
     767             :                         json, "sysMac",
     768             :                         zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
     769           0 :                 json_object_string_add(
     770             :                         json, "routerMac",
     771             :                         zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
     772           0 :                 json_object_string_add(
     773             :                         json, "vniFilter",
     774           0 :                         CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
     775             :                                 ? "prefix-routes-only"
     776             :                                 : "none");
     777           0 :                 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) {
     778           0 :                         json_object_array_add(json_evpn_list,
     779           0 :                                               json_object_new_int(zevpn->vni));
     780             :                 }
     781           0 :                 json_object_object_add(json, "l2Vnis", json_evpn_list);
     782             :         }
     783           0 : }
     784             : 
     785             : /* print a L3 VNI hash entry */
     786           0 : static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])
     787             : {
     788           0 :         struct vty *vty = NULL;
     789           0 :         json_object *json = NULL;
     790           0 :         json_object *json_evpn = NULL;
     791           0 :         struct zebra_l3vni *zl3vni = NULL;
     792             : 
     793           0 :         vty = (struct vty *)ctx[0];
     794           0 :         json = (json_object *)ctx[1];
     795             : 
     796           0 :         zl3vni = (struct zebra_l3vni *)bucket->data;
     797             : 
     798           0 :         if (!json) {
     799           0 :                 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
     800             :                         zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
     801           0 :                         hashcount(zl3vni->rmac_table),
     802           0 :                         hashcount(zl3vni->nh_table), "n/a",
     803             :                         zl3vni_vrf_name(zl3vni));
     804             :         } else {
     805           0 :                 char vni_str[VNI_STR_LEN];
     806             : 
     807           0 :                 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
     808           0 :                 json_evpn = json_object_new_object();
     809           0 :                 json_object_int_add(json_evpn, "vni", zl3vni->vni);
     810           0 :                 json_object_string_add(json_evpn, "vxlanIf",
     811             :                                        zl3vni_vxlan_if_name(zl3vni));
     812           0 :                 json_object_int_add(json_evpn, "numMacs",
     813           0 :                                     hashcount(zl3vni->rmac_table));
     814           0 :                 json_object_int_add(json_evpn, "numArpNd",
     815           0 :                                     hashcount(zl3vni->nh_table));
     816           0 :                 json_object_string_add(json_evpn, "numRemoteVteps", "n/a");
     817           0 :                 json_object_string_add(json_evpn, "type", "L3");
     818           0 :                 json_object_string_add(json_evpn, "tenantVrf",
     819             :                                        zl3vni_vrf_name(zl3vni));
     820           0 :                 json_object_object_add(json, vni_str, json_evpn);
     821             :         }
     822           0 : }
     823             : 
     824             : /* print a L3 VNI hash entry in detail*/
     825           0 : static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
     826             : {
     827           0 :         struct vty *vty = NULL;
     828           0 :         struct zebra_l3vni *zl3vni = NULL;
     829           0 :         json_object *json_array = NULL;
     830           0 :         bool use_json = false;
     831           0 :         struct zebra_evpn_show *zes = data;
     832             : 
     833           0 :         vty = zes->vty;
     834           0 :         json_array = zes->json;
     835           0 :         use_json = zes->use_json;
     836             : 
     837           0 :         zl3vni = (struct zebra_l3vni *)bucket->data;
     838             : 
     839           0 :         zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni,
     840             :                 use_json, json_array);
     841             : 
     842           0 :         if (!use_json)
     843           0 :                 vty_out(vty, "\n");
     844           0 : }
     845             : 
     846           0 : static int zvni_map_to_svi_ns(struct ns *ns,
     847             :                               void *_in_param,
     848             :                               void **_p_ifp)
     849             : {
     850           0 :         struct zebra_ns *zns = ns->info;
     851           0 :         struct route_node *rn;
     852           0 :         struct zebra_from_svi_param *in_param =
     853             :                 (struct zebra_from_svi_param *)_in_param;
     854           0 :         struct zebra_l2info_vlan *vl;
     855           0 :         struct interface *tmp_if = NULL;
     856           0 :         struct interface **p_ifp = (struct interface **)_p_ifp;
     857           0 :         struct zebra_if *zif;
     858             : 
     859           0 :         assert(in_param && p_ifp);
     860             : 
     861             :         /* TODO: Optimize with a hash. */
     862           0 :         for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
     863           0 :                 tmp_if = (struct interface *)rn->info;
     864             :                 /* Check oper status of the SVI. */
     865           0 :                 if (!tmp_if || !if_is_operative(tmp_if))
     866           0 :                         continue;
     867           0 :                 zif = tmp_if->info;
     868           0 :                 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
     869           0 :                     || zif->link != in_param->br_if)
     870           0 :                         continue;
     871           0 :                 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
     872             : 
     873           0 :                 if (vl->vid == in_param->vid) {
     874           0 :                         *p_ifp = tmp_if;
     875           0 :                         return NS_WALK_STOP;
     876             :                 }
     877             :         }
     878             :         return NS_WALK_CONTINUE;
     879             : }
     880             : 
     881             : /* Map to SVI on bridge corresponding to specified VLAN. This can be one
     882             :  * of two cases:
     883             :  * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
     884             :  * linked to the bridge
     885             :  * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
     886             :  * itself
     887             :  */
     888           0 : struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
     889             : {
     890           0 :         struct interface *tmp_if = NULL;
     891           0 :         struct zebra_if *zif;
     892           0 :         struct zebra_l2info_bridge *br;
     893           0 :         struct zebra_from_svi_param in_param;
     894           0 :         struct interface **p_ifp;
     895             :         /* Defensive check, caller expected to invoke only with valid bridge. */
     896           0 :         if (!br_if)
     897             :                 return NULL;
     898             : 
     899             :         /* Determine if bridge is VLAN-aware or not */
     900           0 :         zif = br_if->info;
     901           0 :         assert(zif);
     902           0 :         br = &zif->l2info.br;
     903           0 :         in_param.bridge_vlan_aware = br->vlan_aware;
     904             :         /* Check oper status of the SVI. */
     905           0 :         if (!in_param.bridge_vlan_aware)
     906           0 :                 return if_is_operative(br_if) ? br_if : NULL;
     907             : 
     908           0 :         in_param.vid = vid;
     909           0 :         in_param.br_if = br_if;
     910           0 :         in_param.zif = NULL;
     911           0 :         p_ifp = &tmp_if;
     912             :         /* Identify corresponding VLAN interface. */
     913           0 :         ns_walk_func(zvni_map_to_svi_ns, (void *)&in_param,
     914             :                      (void **)p_ifp);
     915           0 :         return tmp_if;
     916             : }
     917             : 
     918           0 : static int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
     919             : {
     920           0 :         zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);
     921             : 
     922             :         /* Remove references to the BUM mcast grp */
     923           0 :         zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp);
     924             : 
     925           0 :         return zebra_evpn_del(zevpn);
     926             : }
     927             : 
     928           0 : static int zevpn_build_hash_table_zns(struct ns *ns,
     929             :                                      void *param_in __attribute__((unused)),
     930             :                                      void **param_out __attribute__((unused)))
     931             : {
     932           0 :         struct zebra_ns *zns = ns->info;
     933           0 :         struct route_node *rn;
     934           0 :         struct interface *ifp;
     935           0 :         struct zebra_vrf *zvrf;
     936             : 
     937           0 :         zvrf = zebra_vrf_get_evpn();
     938             : 
     939             :         /* Walk VxLAN interfaces and create EVPN hash. */
     940           0 :         for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
     941           0 :                 vni_t vni;
     942           0 :                 struct zebra_evpn *zevpn = NULL;
     943           0 :                 struct zebra_l3vni *zl3vni = NULL;
     944           0 :                 struct zebra_if *zif;
     945           0 :                 struct zebra_l2info_vxlan *vxl;
     946             : 
     947           0 :                 ifp = (struct interface *)rn->info;
     948           0 :                 if (!ifp)
     949           0 :                         continue;
     950           0 :                 zif = ifp->info;
     951           0 :                 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
     952           0 :                         continue;
     953             : 
     954           0 :                 vxl = &zif->l2info.vxl;
     955           0 :                 vni = vxl->vni;
     956             :                 /* link of VXLAN interface should be in zebra_evpn_vrf */
     957           0 :                 if (zvrf->zns->ns_id != vxl->link_nsid) {
     958           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
     959           0 :                                 zlog_debug(
     960             :                                         "Intf %s(%u) VNI %u, link not in same "
     961             :                                         "namespace than BGP EVPN core instance ",
     962             :                                         ifp->name, ifp->ifindex, vni);
     963           0 :                         continue;
     964             :                 }
     965             :                 /* L3-VNI and L2-VNI are handled seperately */
     966           0 :                 zl3vni = zl3vni_lookup(vni);
     967           0 :                 if (zl3vni) {
     968             : 
     969           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
     970           0 :                                 zlog_debug(
     971             :                                         "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
     972             :                                         ifp->name, ifp->ifindex, vni);
     973             : 
     974             :                         /* associate with vxlan_if */
     975           0 :                         zl3vni->local_vtep_ip = vxl->vtep_ip;
     976           0 :                         zl3vni->vxlan_if = ifp;
     977             : 
     978             :                         /*
     979             :                          * we need to associate with SVI.
     980             :                          * we can associate with svi-if only after association
     981             :                          * with vxlan-intf is complete
     982             :                          */
     983           0 :                         zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
     984             : 
     985             :                         /* Associate l3vni to mac-vlan and extract VRR MAC */
     986           0 :                         zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
     987             : 
     988           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
     989           0 :                                 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
     990             :                                    vni, zl3vni->svi_if ? zl3vni->svi_if->name
     991             :                                    : "NIL",
     992             :                                    zl3vni->mac_vlan_if ?
     993             :                                    zl3vni->mac_vlan_if->name : "NIL");
     994             : 
     995           0 :                         if (is_l3vni_oper_up(zl3vni))
     996           0 :                                 zebra_vxlan_process_l3vni_oper_up(zl3vni);
     997             : 
     998             :                 } else {
     999           0 :                         struct interface *vlan_if = NULL;
    1000             : 
    1001           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    1002           0 :                                 zlog_debug(
    1003             :                                         "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
    1004             :                                         ifp->name, ifp->ifindex, vni,
    1005             :                                         &vxl->vtep_ip);
    1006             : 
    1007             :                         /* EVPN hash entry is expected to exist, if the BGP process is killed */
    1008           0 :                         zevpn = zebra_evpn_lookup(vni);
    1009           0 :                         if (zevpn) {
    1010           0 :                                 zlog_debug(
    1011             :                                         "EVPN hash already present for IF %s(%u) L2-VNI %u",
    1012             :                                         ifp->name, ifp->ifindex, vni);
    1013             : 
    1014             :                                 /*
    1015             :                                  * Inform BGP if intf is up and mapped to
    1016             :                                  * bridge.
    1017             :                                  */
    1018           0 :                                 if (if_is_operative(ifp) &&
    1019           0 :                                         zif->brslave_info.br_if)
    1020           0 :                                         zebra_evpn_send_add_to_client(zevpn);
    1021             : 
    1022             :                                 /* Send Local MAC-entries to client */
    1023           0 :                                 zebra_evpn_send_mac_list_to_client(zevpn);
    1024             : 
    1025             :                                 /* Send Loval Neighbor entries to client */
    1026           0 :                                 zebra_evpn_send_neigh_to_client(zevpn);
    1027             :                         } else {
    1028           0 :                                 zevpn = zebra_evpn_add(vni);
    1029           0 :                                 if (!zevpn) {
    1030           0 :                                         zlog_debug(
    1031             :                                                 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
    1032             :                                                 ifp->name, ifp->ifindex, vni);
    1033           0 :                                         return NS_WALK_CONTINUE;
    1034             :                                 }
    1035             : 
    1036           0 :                                 if (zevpn->local_vtep_ip.s_addr !=
    1037           0 :                                         vxl->vtep_ip.s_addr ||
    1038           0 :                                         zevpn->mcast_grp.s_addr !=
    1039           0 :                                         vxl->mcast_grp.s_addr) {
    1040           0 :                                         zebra_vxlan_sg_deref(
    1041             :                                                 zevpn->local_vtep_ip,
    1042             :                                                 zevpn->mcast_grp);
    1043           0 :                                         zebra_vxlan_sg_ref(vxl->vtep_ip,
    1044             :                                                 vxl->mcast_grp);
    1045           0 :                                         zevpn->local_vtep_ip = vxl->vtep_ip;
    1046           0 :                                         zevpn->mcast_grp = vxl->mcast_grp;
    1047             :                                         /* on local vtep-ip check if ES
    1048             :                                          * orig-ip needs to be updated
    1049             :                                          */
    1050           0 :                                         zebra_evpn_es_set_base_evpn(zevpn);
    1051             :                                 }
    1052           0 :                                 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
    1053           0 :                                 vlan_if = zvni_map_to_svi(
    1054           0 :                                         vxl->access_vlan,
    1055             :                                         zif->brslave_info.br_if);
    1056           0 :                                 if (vlan_if) {
    1057           0 :                                         zevpn->svi_if = vlan_if;
    1058           0 :                                         zevpn->vrf_id = vlan_if->vrf->vrf_id;
    1059           0 :                                         zl3vni = zl3vni_from_vrf(
    1060             :                                                 vlan_if->vrf->vrf_id);
    1061           0 :                                         if (zl3vni)
    1062           0 :                                                 listnode_add_sort(
    1063             :                                                         zl3vni->l2vnis, zevpn);
    1064             :                                 }
    1065             : 
    1066             :                                 /*
    1067             :                                  * Inform BGP if intf is up and mapped to
    1068             :                                  * bridge.
    1069             :                                  */
    1070           0 :                                 if (if_is_operative(ifp) &&
    1071           0 :                                         zif->brslave_info.br_if)
    1072           0 :                                         zebra_evpn_send_add_to_client(zevpn);
    1073             :                         }
    1074             :                 }
    1075             :         }
    1076             :         return NS_WALK_CONTINUE;
    1077             : }
    1078             : 
    1079             : /*
    1080             :  * Build the VNI hash table by going over the VxLAN interfaces. This
    1081             :  * is called when EVPN (advertise-all-vni) is enabled.
    1082             :  */
    1083             : 
    1084           0 : static void zevpn_build_hash_table(void)
    1085             : {
    1086           0 :         ns_walk_func(zevpn_build_hash_table_zns, NULL, NULL);
    1087             : }
    1088             : 
    1089             : /*
    1090             :  * Cleanup EVPN/VTEP and update kernel
    1091             :  */
    1092           0 : static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket *bucket, void *arg)
    1093             : {
    1094           0 :         struct zebra_evpn *zevpn = NULL;
    1095           0 :         struct zebra_l3vni *zl3vni = NULL;
    1096             : 
    1097           0 :         zevpn = (struct zebra_evpn *)bucket->data;
    1098             : 
    1099             :         /* remove l2vni from l2vni's tenant-vrf l3-vni list */
    1100           0 :         zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    1101           0 :         if (zl3vni)
    1102           0 :                 listnode_delete(zl3vni->l2vnis, zevpn);
    1103             : 
    1104           0 :         zebra_evpn_cleanup_all(bucket, arg);
    1105           0 : }
    1106             : 
    1107             : /* cleanup L3VNI */
    1108           0 : static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args)
    1109             : {
    1110           0 :         struct zebra_l3vni *zl3vni = NULL;
    1111             : 
    1112           0 :         zl3vni = (struct zebra_l3vni *)bucket->data;
    1113             : 
    1114           0 :         zebra_vxlan_process_l3vni_oper_down(zl3vni);
    1115           0 : }
    1116             : 
    1117           0 : static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
    1118             :                                 const struct prefix *host)
    1119             : {
    1120           0 :         struct host_rb_entry lookup;
    1121           0 :         struct host_rb_entry *hle;
    1122             : 
    1123           0 :         memset(&lookup, 0, sizeof(lookup));
    1124           0 :         memcpy(&lookup.p, host, sizeof(*host));
    1125             : 
    1126           0 :         hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
    1127           0 :         if (hle)
    1128           0 :                 return;
    1129             : 
    1130           0 :         hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
    1131           0 :         memcpy(hle, &lookup, sizeof(lookup));
    1132             : 
    1133           0 :         RB_INSERT(host_rb_tree_entry, hrbe, hle);
    1134             : }
    1135             : 
    1136           0 : static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
    1137             : {
    1138           0 :         struct host_rb_entry lookup;
    1139           0 :         struct host_rb_entry *hle;
    1140             : 
    1141           0 :         memset(&lookup, 0, sizeof(lookup));
    1142           0 :         memcpy(&lookup.p, host, sizeof(*host));
    1143             : 
    1144           0 :         hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
    1145           0 :         if (hle) {
    1146           0 :                 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
    1147           0 :                 XFREE(MTYPE_HOST_PREFIX, hle);
    1148             :         }
    1149             : 
    1150           0 :         return;
    1151             : }
    1152             : 
    1153             : /*
    1154             :  * Look up MAC hash entry.
    1155             :  */
    1156           0 : static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
    1157             :                                             const struct ethaddr *rmac)
    1158             : {
    1159           0 :         struct zebra_mac tmp;
    1160           0 :         struct zebra_mac *pmac;
    1161             : 
    1162           0 :         memset(&tmp, 0, sizeof(tmp));
    1163           0 :         memcpy(&tmp.macaddr, rmac, ETH_ALEN);
    1164           0 :         pmac = hash_lookup(zl3vni->rmac_table, &tmp);
    1165             : 
    1166           0 :         return pmac;
    1167             : }
    1168             : 
    1169             : /*
    1170             :  * Callback to allocate RMAC hash entry.
    1171             :  */
    1172           0 : static void *zl3vni_rmac_alloc(void *p)
    1173             : {
    1174           0 :         const struct zebra_mac *tmp_rmac = p;
    1175           0 :         struct zebra_mac *zrmac;
    1176             : 
    1177           0 :         zrmac = XCALLOC(MTYPE_L3VNI_MAC, sizeof(struct zebra_mac));
    1178           0 :         *zrmac = *tmp_rmac;
    1179             : 
    1180           0 :         return ((void *)zrmac);
    1181             : }
    1182             : 
    1183             : /*
    1184             :  * Add RMAC entry to l3-vni
    1185             :  */
    1186           0 : static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
    1187             :                                          const struct ethaddr *rmac)
    1188             : {
    1189           0 :         struct zebra_mac tmp_rmac;
    1190           0 :         struct zebra_mac *zrmac = NULL;
    1191             : 
    1192           0 :         memset(&tmp_rmac, 0, sizeof(tmp_rmac));
    1193           0 :         memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
    1194           0 :         zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
    1195           0 :         zrmac->nh_list = list_new();
    1196           0 :         zrmac->nh_list->cmp = (int (*)(void *, void *))l3vni_rmac_nh_list_cmp;
    1197           0 :         zrmac->nh_list->del = (void (*)(void *))l3vni_rmac_nh_free;
    1198             : 
    1199           0 :         SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
    1200           0 :         SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
    1201             : 
    1202           0 :         return zrmac;
    1203             : }
    1204             : 
    1205             : /*
    1206             :  * Delete MAC entry.
    1207             :  */
    1208           0 : static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac)
    1209             : {
    1210           0 :         struct zebra_mac *tmp_rmac;
    1211             : 
    1212             :         /* free the list of nh list*/
    1213           0 :         list_delete(&zrmac->nh_list);
    1214             : 
    1215           0 :         tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
    1216           0 :         XFREE(MTYPE_L3VNI_MAC, tmp_rmac);
    1217             : 
    1218           0 :         return 0;
    1219             : }
    1220             : 
    1221             : /*
    1222             :  * Install remote RMAC into the forwarding plane.
    1223             :  */
    1224           0 : static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
    1225             :                                struct zebra_mac *zrmac)
    1226             : {
    1227           0 :         const struct zebra_if *zif = NULL, *br_zif = NULL;
    1228           0 :         const struct zebra_l2info_vxlan *vxl = NULL;
    1229           0 :         const struct interface *br_ifp;
    1230           0 :         enum zebra_dplane_result res;
    1231           0 :         vlanid_t vid;
    1232             : 
    1233           0 :         if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
    1234           0 :             || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
    1235             :                 return 0;
    1236             : 
    1237           0 :         zif = zl3vni->vxlan_if->info;
    1238           0 :         if (!zif)
    1239             :                 return -1;
    1240             : 
    1241           0 :         br_ifp = zif->brslave_info.br_if;
    1242           0 :         if (br_ifp == NULL)
    1243             :                 return -1;
    1244             : 
    1245           0 :         vxl = &zif->l2info.vxl;
    1246             : 
    1247           0 :         br_zif = (const struct zebra_if *)br_ifp->info;
    1248             : 
    1249           0 :         if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
    1250           0 :                 vid = vxl->access_vlan;
    1251             :         else
    1252             :                 vid = 0;
    1253             : 
    1254           0 :         res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid,
    1255           0 :                              &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0,
    1256             :                                  false /*was_static*/);
    1257           0 :         if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
    1258             :                 return 0;
    1259             :         else
    1260             :                 return -1;
    1261             : }
    1262             : 
    1263             : /*
    1264             :  * Uninstall remote RMAC from the forwarding plane.
    1265             :  */
    1266           0 : static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
    1267             :                                  struct zebra_mac *zrmac)
    1268             : {
    1269           0 :         const struct zebra_if *zif = NULL, *br_zif;
    1270           0 :         const struct zebra_l2info_vxlan *vxl = NULL;
    1271           0 :         const struct interface *br_ifp;
    1272           0 :         vlanid_t vid;
    1273           0 :         enum zebra_dplane_result res;
    1274             : 
    1275           0 :         if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
    1276           0 :             || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
    1277             :                 return 0;
    1278             : 
    1279           0 :         if (!zl3vni->vxlan_if) {
    1280           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1281           0 :                         zlog_debug(
    1282             :                                 "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
    1283             :                                 &zrmac->macaddr, zl3vni->vni, zl3vni);
    1284           0 :                 return -1;
    1285             :         }
    1286             : 
    1287           0 :         zif = zl3vni->vxlan_if->info;
    1288           0 :         if (!zif)
    1289             :                 return -1;
    1290             : 
    1291           0 :         br_ifp = zif->brslave_info.br_if;
    1292           0 :         if (br_ifp == NULL)
    1293             :                 return -1;
    1294             : 
    1295           0 :         vxl = &zif->l2info.vxl;
    1296             : 
    1297           0 :         br_zif = (const struct zebra_if *)br_ifp->info;
    1298           0 :         if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
    1299           0 :                 vid = vxl->access_vlan;
    1300             :         else
    1301             :                 vid = 0;
    1302             : 
    1303           0 :         res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid,
    1304           0 :                              &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
    1305           0 :         if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
    1306             :                 return 0;
    1307             :         else
    1308             :                 return -1;
    1309             : }
    1310             : 
    1311             : /* handle rmac add */
    1312           0 : static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
    1313             :                                   const struct ethaddr *rmac,
    1314             :                                   const struct ipaddr *vtep_ip)
    1315             : {
    1316           0 :         struct zebra_mac *zrmac = NULL;
    1317           0 :         struct ipaddr *vtep = NULL;
    1318             : 
    1319           0 :         zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
    1320           0 :         if (!zrmac) {
    1321             : 
    1322             :                  /* Create the RMAC entry, or update its vtep, if necessary. */
    1323           0 :                 zrmac = zl3vni_rmac_add(zl3vni, rmac);
    1324           0 :                 if (!zrmac) {
    1325           0 :                         zlog_debug(
    1326             :                                 "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA",
    1327             :                                 rmac, zl3vni->vni, vtep_ip);
    1328           0 :                         return -1;
    1329             :                 }
    1330           0 :                 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
    1331           0 :                 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
    1332             : 
    1333           0 :                 vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
    1334           0 :                 memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
    1335           0 :                 if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
    1336           0 :                         XFREE(MTYPE_EVPN_VTEP, vtep);
    1337             : 
    1338             :                 /* Send RMAC for FPM processing */
    1339           0 :                 hook_call(zebra_rmac_update, zrmac, zl3vni, false,
    1340             :                           "new RMAC added");
    1341             : 
    1342             :                 /* install rmac in kernel */
    1343           0 :                 zl3vni_rmac_install(zl3vni, zrmac);
    1344           0 :         } else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
    1345             :                                    &vtep_ip->ipaddr_v4)) {
    1346           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1347           0 :                         zlog_debug(
    1348             :                                 "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
    1349             :                                 zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
    1350             :                                 vtep_ip, rmac);
    1351             : 
    1352           0 :                 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
    1353             : 
    1354           0 :                 vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
    1355           0 :                 memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
    1356           0 :                 if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
    1357           0 :                         XFREE(MTYPE_EVPN_VTEP, vtep);
    1358             : 
    1359             :                 /* install rmac in kernel */
    1360           0 :                 zl3vni_rmac_install(zl3vni, zrmac);
    1361             :         }
    1362             : 
    1363             :         return 0;
    1364             : }
    1365             : 
    1366             : 
    1367             : /* handle rmac delete */
    1368           0 : static void zl3vni_remote_rmac_del(struct zebra_l3vni *zl3vni,
    1369             :                                    struct zebra_mac *zrmac,
    1370             :                                    struct ipaddr *vtep_ip)
    1371             : {
    1372           0 :         struct ipaddr ipv4_vtep;
    1373             : 
    1374           0 :         if (!zl3vni_nh_lookup(zl3vni, vtep_ip)) {
    1375           0 :                 memset(&ipv4_vtep, 0, sizeof(ipv4_vtep));
    1376           0 :                 ipv4_vtep.ipa_type = IPADDR_V4;
    1377           0 :                 if (vtep_ip->ipa_type == IPADDR_V6)
    1378           0 :                         ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
    1379             :                                                  &ipv4_vtep.ipaddr_v4);
    1380             :                 else
    1381           0 :                         memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
    1382             :                                sizeof(struct in_addr));
    1383             : 
    1384             :                 /* remove nh from rmac's list */
    1385           0 :                 l3vni_rmac_nh_list_nh_delete(zl3vni, zrmac, &ipv4_vtep);
    1386             :                 /* delete nh is same as current selected, fall back to
    1387             :                  * one present in the list
    1388             :                  */
    1389           0 :                 if (IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
    1390           0 :                                    &ipv4_vtep.ipaddr_v4) &&
    1391           0 :                     listcount(zrmac->nh_list)) {
    1392           0 :                         struct ipaddr *vtep;
    1393             : 
    1394           0 :                         vtep = listgetdata(listhead(zrmac->nh_list));
    1395           0 :                         zrmac->fwd_info.r_vtep_ip = vtep->ipaddr_v4;
    1396           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    1397           0 :                                 zlog_debug(
    1398             :                                         "L3VNI %u Remote VTEP nh change(%pIA -> %pI4) for RMAC %pEA",
    1399             :                                         zl3vni->vni, &ipv4_vtep,
    1400             :                                         &zrmac->fwd_info.r_vtep_ip,
    1401             :                                         &zrmac->macaddr);
    1402             : 
    1403             :                         /* install rmac in kernel */
    1404           0 :                         zl3vni_rmac_install(zl3vni, zrmac);
    1405             :                 }
    1406             : 
    1407           0 :                 if (!listcount(zrmac->nh_list)) {
    1408             :                         /* uninstall from kernel */
    1409           0 :                         zl3vni_rmac_uninstall(zl3vni, zrmac);
    1410             : 
    1411             :                         /* Send RMAC for FPM processing */
    1412           0 :                         hook_call(zebra_rmac_update, zrmac, zl3vni, true,
    1413             :                                   "RMAC deleted");
    1414             : 
    1415           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    1416           0 :                                 zlog_debug(
    1417             :                                         "L3VNI %u RMAC %pEA vtep_ip %pIA delete",
    1418             :                                         zl3vni->vni, &zrmac->macaddr, vtep_ip);
    1419             : 
    1420             :                         /* del the rmac entry */
    1421           0 :                         zl3vni_rmac_del(zl3vni, zrmac);
    1422             :                 }
    1423             :         }
    1424           0 : }
    1425             : 
    1426             : /*
    1427             :  * Look up nh hash entry on a l3-vni.
    1428             :  */
    1429           0 : static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
    1430             :                                             const struct ipaddr *ip)
    1431             : {
    1432           0 :         struct zebra_neigh tmp;
    1433           0 :         struct zebra_neigh *n;
    1434             : 
    1435           0 :         memset(&tmp, 0, sizeof(tmp));
    1436           0 :         memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
    1437           0 :         n = hash_lookup(zl3vni->nh_table, &tmp);
    1438             : 
    1439           0 :         return n;
    1440             : }
    1441             : 
    1442             : 
    1443             : /*
    1444             :  * Callback to allocate NH hash entry on L3-VNI.
    1445             :  */
    1446           0 : static void *zl3vni_nh_alloc(void *p)
    1447             : {
    1448           0 :         const struct zebra_neigh *tmp_n = p;
    1449           0 :         struct zebra_neigh *n;
    1450             : 
    1451           0 :         n = XCALLOC(MTYPE_L3NEIGH, sizeof(struct zebra_neigh));
    1452           0 :         *n = *tmp_n;
    1453             : 
    1454           0 :         return ((void *)n);
    1455             : }
    1456             : 
    1457             : /*
    1458             :  * Add neighbor entry.
    1459             :  */
    1460           0 : static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
    1461             :                                          const struct ipaddr *ip,
    1462             :                                          const struct ethaddr *mac)
    1463             : {
    1464           0 :         struct zebra_neigh tmp_n;
    1465           0 :         struct zebra_neigh *n = NULL;
    1466             : 
    1467           0 :         memset(&tmp_n, 0, sizeof(tmp_n));
    1468           0 :         memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
    1469           0 :         n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
    1470             : 
    1471           0 :         RB_INIT(host_rb_tree_entry, &n->host_rb);
    1472             : 
    1473           0 :         memcpy(&n->emac, mac, ETH_ALEN);
    1474           0 :         SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
    1475           0 :         SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
    1476             : 
    1477           0 :         return n;
    1478             : }
    1479             : 
    1480             : /*
    1481             :  * Delete neighbor entry.
    1482             :  */
    1483           0 : static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
    1484             : {
    1485           0 :         struct zebra_neigh *tmp_n;
    1486           0 :         struct host_rb_entry *hle;
    1487             : 
    1488           0 :         while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
    1489           0 :                 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
    1490             : 
    1491           0 :                 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
    1492           0 :                 XFREE(MTYPE_HOST_PREFIX, hle);
    1493             :         }
    1494             : 
    1495           0 :         tmp_n = hash_release(zl3vni->nh_table, n);
    1496           0 :         XFREE(MTYPE_L3NEIGH, tmp_n);
    1497             : 
    1498           0 :         return 0;
    1499             : }
    1500             : 
    1501             : /*
    1502             :  * Install remote nh as neigh into the kernel.
    1503             :  */
    1504           0 : static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
    1505             : {
    1506           0 :         uint8_t flags;
    1507           0 :         int ret = 0;
    1508             : 
    1509           0 :         if (!is_l3vni_oper_up(zl3vni))
    1510             :                 return -1;
    1511             : 
    1512           0 :         if (!(n->flags & ZEBRA_NEIGH_REMOTE)
    1513           0 :             || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
    1514             :                 return 0;
    1515             : 
    1516           0 :         flags = DPLANE_NTF_EXT_LEARNED;
    1517           0 :         if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
    1518           0 :                 flags |= DPLANE_NTF_ROUTER;
    1519             : 
    1520           0 :         dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags,
    1521             :                         false /*was_static*/);
    1522             : 
    1523           0 :         return ret;
    1524             : }
    1525             : 
    1526             : /*
    1527             :  * Uninstall remote nh from the kernel.
    1528             :  */
    1529           0 : static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
    1530             :                                struct zebra_neigh *n)
    1531             : {
    1532           0 :         if (!(n->flags & ZEBRA_NEIGH_REMOTE)
    1533           0 :             || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
    1534             :                 return 0;
    1535             : 
    1536           0 :         if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
    1537           0 :                 return 0;
    1538             : 
    1539           0 :         dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip);
    1540             : 
    1541           0 :         return 0;
    1542             : }
    1543             : 
    1544             : /* add remote vtep as a neigh entry */
    1545           0 : static int zl3vni_remote_nh_add(struct zebra_l3vni *zl3vni,
    1546             :                                 const struct ipaddr *vtep_ip,
    1547             :                                 const struct ethaddr *rmac,
    1548             :                                 const struct prefix *host_prefix)
    1549             : {
    1550           0 :         struct zebra_neigh *nh = NULL;
    1551             : 
    1552             :         /* Create the next hop entry, or update its mac, if necessary. */
    1553           0 :         nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
    1554           0 :         if (!nh) {
    1555           0 :                 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
    1556           0 :                 if (!nh) {
    1557           0 :                         zlog_debug(
    1558             :                                 "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
    1559             :                                 vtep_ip, rmac, zl3vni->vni, host_prefix);
    1560           0 :                         return -1;
    1561             :                 }
    1562             : 
    1563             :                 /* install the nh neigh in kernel */
    1564           0 :                 zl3vni_nh_install(zl3vni, nh);
    1565           0 :         } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) {
    1566           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    1567           0 :                         zlog_debug(
    1568             :                                 "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
    1569             :                                 zl3vni->vni, &nh->emac, rmac, vtep_ip,
    1570             :                                 host_prefix);
    1571             : 
    1572           0 :                 memcpy(&nh->emac, rmac, ETH_ALEN);
    1573             :                 /* install (update) the nh neigh in kernel */
    1574           0 :                 zl3vni_nh_install(zl3vni, nh);
    1575             :         }
    1576             : 
    1577           0 :         rb_find_or_add_host(&nh->host_rb, host_prefix);
    1578             : 
    1579           0 :         return 0;
    1580             : }
    1581             : 
    1582             : /* handle nh neigh delete */
    1583           0 : static void zl3vni_remote_nh_del(struct zebra_l3vni *zl3vni,
    1584             :                                  struct zebra_neigh *nh,
    1585             :                                  struct prefix *host_prefix)
    1586             : {
    1587           0 :         rb_delete_host(&nh->host_rb, host_prefix);
    1588             : 
    1589           0 :         if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
    1590             :                 /* uninstall from kernel */
    1591           0 :                 zl3vni_nh_uninstall(zl3vni, nh);
    1592             : 
    1593             :                 /* delete the nh entry */
    1594           0 :                 zl3vni_nh_del(zl3vni, nh);
    1595             :         }
    1596           0 : }
    1597             : 
    1598             : /* handle neigh update from kernel - the only thing of interest is to
    1599             :  * readd stale entries.
    1600             :  */
    1601           0 : static int zl3vni_local_nh_add_update(struct zebra_l3vni *zl3vni,
    1602             :                                       struct ipaddr *ip, uint16_t state)
    1603             : {
    1604             : #ifdef GNU_LINUX
    1605           0 :         struct zebra_neigh *n = NULL;
    1606             : 
    1607           0 :         n = zl3vni_nh_lookup(zl3vni, ip);
    1608           0 :         if (!n)
    1609             :                 return 0;
    1610             : 
    1611             :         /* all next hop neigh are remote and installed by frr.
    1612             :          * If the kernel has aged this entry, re-install.
    1613             :          */
    1614           0 :         if (state & NUD_STALE)
    1615           0 :                 zl3vni_nh_install(zl3vni, n);
    1616             : #endif
    1617             :         return 0;
    1618             : }
    1619             : 
    1620             : /* handle neigh delete from kernel */
    1621           0 : static int zl3vni_local_nh_del(struct zebra_l3vni *zl3vni, struct ipaddr *ip)
    1622             : {
    1623           0 :         struct zebra_neigh *n = NULL;
    1624             : 
    1625           0 :         n = zl3vni_nh_lookup(zl3vni, ip);
    1626           0 :         if (!n)
    1627             :                 return 0;
    1628             : 
    1629             :         /* all next hop neigh are remote and installed by frr.
    1630             :          * If we get an age out notification for these neigh entries, we have to
    1631             :          * install it back
    1632             :          */
    1633           0 :         zl3vni_nh_install(zl3vni, n);
    1634             : 
    1635           0 :         return 0;
    1636             : }
    1637             : 
    1638             : /*
    1639             :  * Hash function for L3 VNI.
    1640             :  */
    1641           0 : static unsigned int l3vni_hash_keymake(const void *p)
    1642             : {
    1643           0 :         const struct zebra_l3vni *zl3vni = p;
    1644             : 
    1645           0 :         return jhash_1word(zl3vni->vni, 0);
    1646             : }
    1647             : 
    1648             : /*
    1649             :  * Compare 2 L3 VNI hash entries.
    1650             :  */
    1651           0 : static bool l3vni_hash_cmp(const void *p1, const void *p2)
    1652             : {
    1653           0 :         const struct zebra_l3vni *zl3vni1 = p1;
    1654           0 :         const struct zebra_l3vni *zl3vni2 = p2;
    1655             : 
    1656           0 :         return (zl3vni1->vni == zl3vni2->vni);
    1657             : }
    1658             : 
    1659             : /*
    1660             :  * Callback to allocate L3 VNI hash entry.
    1661             :  */
    1662           0 : static void *zl3vni_alloc(void *p)
    1663             : {
    1664           0 :         struct zebra_l3vni *zl3vni = NULL;
    1665           0 :         const struct zebra_l3vni *tmp_l3vni = p;
    1666             : 
    1667           0 :         zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(struct zebra_l3vni));
    1668           0 :         zl3vni->vni = tmp_l3vni->vni;
    1669           0 :         return ((void *)zl3vni);
    1670             : }
    1671             : 
    1672             : /*
    1673             :  * Look up L3 VNI hash entry.
    1674             :  */
    1675           0 : struct zebra_l3vni *zl3vni_lookup(vni_t vni)
    1676             : {
    1677           0 :         struct zebra_l3vni tmp_l3vni;
    1678           0 :         struct zebra_l3vni *zl3vni = NULL;
    1679             : 
    1680           0 :         memset(&tmp_l3vni, 0, sizeof(tmp_l3vni));
    1681           0 :         tmp_l3vni.vni = vni;
    1682           0 :         zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni);
    1683             : 
    1684           0 :         return zl3vni;
    1685             : }
    1686             : 
    1687             : /*
    1688             :  * Add L3 VNI hash entry.
    1689             :  */
    1690           0 : static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
    1691             : {
    1692           0 :         struct zebra_l3vni tmp_zl3vni;
    1693           0 :         struct zebra_l3vni *zl3vni = NULL;
    1694             : 
    1695           0 :         memset(&tmp_zl3vni, 0, sizeof(tmp_zl3vni));
    1696           0 :         tmp_zl3vni.vni = vni;
    1697             : 
    1698           0 :         zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc);
    1699             : 
    1700           0 :         zl3vni->vrf_id = vrf_id;
    1701           0 :         zl3vni->svi_if = NULL;
    1702           0 :         zl3vni->vxlan_if = NULL;
    1703           0 :         zl3vni->l2vnis = list_new();
    1704           0 :         zl3vni->l2vnis->cmp = zebra_evpn_list_cmp;
    1705             : 
    1706             :         /* Create hash table for remote RMAC */
    1707           0 :         zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
    1708             : 
    1709             :         /* Create hash table for neighbors */
    1710           0 :         zl3vni->nh_table = zebra_neigh_db_create("Zebra L3-VNI next-hop table");
    1711             : 
    1712           0 :         return zl3vni;
    1713             : }
    1714             : 
    1715             : /*
    1716             :  * Delete L3 VNI hash entry.
    1717             :  */
    1718           0 : static int zl3vni_del(struct zebra_l3vni *zl3vni)
    1719             : {
    1720           0 :         struct zebra_l3vni *tmp_zl3vni;
    1721             : 
    1722             :         /* free the list of l2vnis */
    1723           0 :         list_delete(&zl3vni->l2vnis);
    1724           0 :         zl3vni->l2vnis = NULL;
    1725             : 
    1726             :         /* Free the rmac table */
    1727           0 :         hash_free(zl3vni->rmac_table);
    1728           0 :         zl3vni->rmac_table = NULL;
    1729             : 
    1730             :         /* Free the nh table */
    1731           0 :         hash_free(zl3vni->nh_table);
    1732           0 :         zl3vni->nh_table = NULL;
    1733             : 
    1734             :         /* Free the VNI hash entry and allocated memory. */
    1735           0 :         tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
    1736           0 :         XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
    1737             : 
    1738           0 :         return 0;
    1739             : }
    1740             : 
    1741           0 : static int zl3vni_map_to_vxlan_if_ns(struct ns *ns,
    1742             :                                      void *_zl3vni,
    1743             :                                      void **_pifp)
    1744             : {
    1745           0 :         struct zebra_ns *zns = ns->info;
    1746           0 :         struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)_zl3vni;
    1747           0 :         struct route_node *rn = NULL;
    1748           0 :         struct interface *ifp = NULL;
    1749           0 :         struct zebra_vrf *zvrf;
    1750             : 
    1751           0 :         zvrf = zebra_vrf_get_evpn();
    1752             : 
    1753           0 :         assert(_pifp);
    1754             : 
    1755             :         /* loop through all vxlan-interface */
    1756           0 :         for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
    1757             : 
    1758           0 :                 struct zebra_if *zif = NULL;
    1759           0 :                 struct zebra_l2info_vxlan *vxl = NULL;
    1760             : 
    1761           0 :                 ifp = (struct interface *)rn->info;
    1762           0 :                 if (!ifp)
    1763           0 :                         continue;
    1764             : 
    1765           0 :                 zif = ifp->info;
    1766           0 :                 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
    1767           0 :                         continue;
    1768             : 
    1769           0 :                 vxl = &zif->l2info.vxl;
    1770           0 :                 if (vxl->vni != zl3vni->vni)
    1771           0 :                         continue;
    1772             : 
    1773             :                 /* link of VXLAN interface should be in zebra_evpn_vrf */
    1774           0 :                 if (zvrf->zns->ns_id != vxl->link_nsid) {
    1775           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    1776           0 :                                 zlog_debug(
    1777             :                                         "Intf %s(%u) VNI %u, link not in same "
    1778             :                                         "namespace than BGP EVPN core instance ",
    1779             :                                         ifp->name, ifp->ifindex, vxl->vni);
    1780           0 :                         continue;
    1781             :                 }
    1782             : 
    1783             : 
    1784           0 :                 zl3vni->local_vtep_ip = vxl->vtep_ip;
    1785           0 :                 *_pifp = (void *)ifp;
    1786           0 :                 return NS_WALK_STOP;
    1787             :         }
    1788             : 
    1789             :         return NS_WALK_CONTINUE;
    1790             : }
    1791             : 
    1792           0 : struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni)
    1793             : {
    1794           0 :         struct interface **p_ifp;
    1795           0 :         struct interface *ifp = NULL;
    1796             : 
    1797           0 :         p_ifp = &ifp;
    1798             : 
    1799           0 :         ns_walk_func(zl3vni_map_to_vxlan_if_ns,
    1800             :                      (void *)zl3vni, (void **)p_ifp);
    1801           0 :         return ifp;
    1802             : }
    1803             : 
    1804           0 : struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni)
    1805             : {
    1806           0 :         struct zebra_if *zif = NULL;       /* zebra_if for vxlan_if */
    1807           0 :         struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
    1808             : 
    1809           0 :         if (!zl3vni)
    1810             :                 return NULL;
    1811             : 
    1812           0 :         if (!zl3vni->vxlan_if)
    1813             :                 return NULL;
    1814             : 
    1815           0 :         zif = zl3vni->vxlan_if->info;
    1816           0 :         if (!zif)
    1817             :                 return NULL;
    1818             : 
    1819           0 :         vxl = &zif->l2info.vxl;
    1820             : 
    1821           0 :         return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
    1822             : }
    1823             : 
    1824           0 : struct interface *zl3vni_map_to_mac_vlan_if(struct zebra_l3vni *zl3vni)
    1825             : {
    1826           0 :         struct zebra_if *zif = NULL;       /* zebra_if for vxlan_if */
    1827             : 
    1828           0 :         if (!zl3vni)
    1829             :                 return NULL;
    1830             : 
    1831           0 :         if (!zl3vni->vxlan_if)
    1832             :                 return NULL;
    1833             : 
    1834           0 :         zif = zl3vni->vxlan_if->info;
    1835           0 :         if (!zif)
    1836             :                 return NULL;
    1837             : 
    1838           0 :         return zebra_evpn_map_to_macvlan(zif->brslave_info.br_if,
    1839             :                                          zl3vni->svi_if);
    1840             : }
    1841             : 
    1842             : 
    1843           0 : struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id)
    1844             : {
    1845           0 :         struct zebra_vrf *zvrf = NULL;
    1846             : 
    1847           0 :         zvrf = zebra_vrf_lookup_by_id(vrf_id);
    1848           0 :         if (!zvrf)
    1849             :                 return NULL;
    1850             : 
    1851           0 :         return zl3vni_lookup(zvrf->l3vni);
    1852             : }
    1853             : 
    1854           0 : static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
    1855             : {
    1856           0 :         struct zebra_ns *zns = ns->info;
    1857           0 :         struct zebra_l3vni **p_zl3vni = (struct zebra_l3vni **)_p_zl3vni;
    1858           0 :         struct zebra_from_svi_param *in_param =
    1859             :                 (struct zebra_from_svi_param *)_in_param;
    1860           0 :         struct route_node *rn = NULL;
    1861           0 :         struct interface *tmp_if = NULL;
    1862           0 :         struct zebra_if *zif = NULL;
    1863           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    1864             : 
    1865           0 :         assert(in_param && p_zl3vni);
    1866             : 
    1867             :         /* loop through all vxlan-interface */
    1868           0 :         for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
    1869           0 :                 tmp_if = (struct interface *)rn->info;
    1870           0 :                 if (!tmp_if)
    1871           0 :                         continue;
    1872           0 :                 zif = tmp_if->info;
    1873           0 :                 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
    1874           0 :                         continue;
    1875           0 :                 if (!if_is_operative(tmp_if))
    1876           0 :                         continue;
    1877           0 :                 vxl = &zif->l2info.vxl;
    1878             : 
    1879           0 :                 if (zif->brslave_info.br_if != in_param->br_if)
    1880           0 :                         continue;
    1881             : 
    1882           0 :                 if (!in_param->bridge_vlan_aware
    1883           0 :                     || vxl->access_vlan == in_param->vid) {
    1884           0 :                         *p_zl3vni = zl3vni_lookup(vxl->vni);
    1885           0 :                         return NS_WALK_STOP;
    1886             :                 }
    1887             :         }
    1888             : 
    1889             :         return NS_WALK_CONTINUE;
    1890             : }
    1891             : 
    1892             : /*
    1893             :  * Map SVI and associated bridge to a VNI. This is invoked upon getting
    1894             :  * neighbor notifications, to see if they are of interest.
    1895             :  */
    1896           0 : static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
    1897             :                                            struct interface *br_if)
    1898             : {
    1899           0 :         struct zebra_l3vni *zl3vni = NULL;
    1900           0 :         struct zebra_if *zif = NULL;
    1901           0 :         struct zebra_l2info_bridge *br = NULL;
    1902           0 :         struct zebra_from_svi_param in_param = {};
    1903           0 :         struct zebra_l3vni **p_zl3vni;
    1904             : 
    1905           0 :         if (!br_if)
    1906             :                 return NULL;
    1907             : 
    1908             :         /* Make sure the linked interface is a bridge. */
    1909           0 :         if (!IS_ZEBRA_IF_BRIDGE(br_if))
    1910             :                 return NULL;
    1911           0 :         in_param.br_if = br_if;
    1912             : 
    1913             :         /* Determine if bridge is VLAN-aware or not */
    1914           0 :         zif = br_if->info;
    1915           0 :         assert(zif);
    1916           0 :         br = &zif->l2info.br;
    1917           0 :         in_param.bridge_vlan_aware = br->vlan_aware;
    1918           0 :         if (in_param.bridge_vlan_aware) {
    1919           0 :                 struct zebra_l2info_vlan *vl;
    1920             : 
    1921           0 :                 if (!IS_ZEBRA_IF_VLAN(ifp))
    1922             :                         return NULL;
    1923             : 
    1924           0 :                 zif = ifp->info;
    1925           0 :                 assert(zif);
    1926           0 :                 vl = &zif->l2info.vl;
    1927           0 :                 in_param.vid = vl->vid;
    1928             :         }
    1929             : 
    1930             :         /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
    1931             :         /* TODO: Optimize with a hash. */
    1932             : 
    1933           0 :         p_zl3vni = &zl3vni;
    1934             : 
    1935           0 :         ns_walk_func(zl3vni_from_svi_ns, (void *)&in_param, (void **)p_zl3vni);
    1936           0 :         return zl3vni;
    1937             : }
    1938             : 
    1939           0 : vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if)
    1940             : {
    1941           0 :         vni_t vni = 0;
    1942           0 :         struct zebra_evpn *zevpn = NULL;
    1943           0 :         struct zebra_l3vni *zl3vni = NULL;
    1944             : 
    1945             :         /* Check if an L3VNI belongs to this SVI interface.
    1946             :          * If not, check if an L2VNI belongs to this SVI interface.
    1947             :          */
    1948           0 :         zl3vni = zl3vni_from_svi(ifp, br_if);
    1949           0 :         if (zl3vni)
    1950           0 :                 vni = zl3vni->vni;
    1951             :         else {
    1952           0 :                 zevpn = zebra_evpn_from_svi(ifp, br_if);
    1953           0 :                 if (zevpn)
    1954           0 :                         vni = zevpn->vni;
    1955             :         }
    1956             : 
    1957           0 :         return vni;
    1958             : }
    1959             : 
    1960           0 : static inline void zl3vni_get_vrr_rmac(struct zebra_l3vni *zl3vni,
    1961             :                                        struct ethaddr *rmac)
    1962             : {
    1963           0 :         if (!zl3vni)
    1964             :                 return;
    1965             : 
    1966           0 :         if (!is_l3vni_oper_up(zl3vni))
    1967             :                 return;
    1968             : 
    1969           0 :         if (zl3vni->mac_vlan_if && if_is_operative(zl3vni->mac_vlan_if))
    1970           0 :                 memcpy(rmac->octet, zl3vni->mac_vlan_if->hw_addr, ETH_ALEN);
    1971             : }
    1972             : 
    1973             : /*
    1974             :  * Inform BGP about l3-vni.
    1975             :  */
    1976           0 : static int zl3vni_send_add_to_client(struct zebra_l3vni *zl3vni)
    1977             : {
    1978           0 :         struct stream *s = NULL;
    1979           0 :         struct zserv *client = NULL;
    1980           0 :         struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
    1981           0 :         struct zebra_vrf *zvrf;
    1982           0 :         bool is_anycast_mac = true;
    1983             : 
    1984           0 :         client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
    1985             :         /* BGP may not be running. */
    1986           0 :         if (!client)
    1987             :                 return 0;
    1988             : 
    1989           0 :         zvrf = zebra_vrf_lookup_by_id(zl3vni->vrf_id);
    1990           0 :         assert(zvrf);
    1991             : 
    1992             :         /* get the svi and vrr rmac values */
    1993           0 :         memset(&svi_rmac, 0, sizeof(svi_rmac));
    1994           0 :         zl3vni_get_svi_rmac(zl3vni, &svi_rmac);
    1995           0 :         zl3vni_get_vrr_rmac(zl3vni, &vrr_rmac);
    1996             : 
    1997             :         /* In absence of vrr mac use svi mac as anycast MAC value */
    1998           0 :         if (is_zero_mac(&vrr_rmac)) {
    1999           0 :                 memcpy(&vrr_rmac, &svi_rmac, ETH_ALEN);
    2000           0 :                 is_anycast_mac = false;
    2001             :         }
    2002             : 
    2003           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2004             : 
    2005             :         /* The message is used for both vni add and/or update like
    2006             :          * vrr mac is added for l3vni SVI.
    2007             :          */
    2008           0 :         zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
    2009           0 :         stream_putl(s, zl3vni->vni);
    2010           0 :         stream_put(s, &svi_rmac, sizeof(struct ethaddr));
    2011           0 :         stream_put_in_addr(s, &zl3vni->local_vtep_ip);
    2012           0 :         stream_put(s, &zl3vni->filter, sizeof(int));
    2013           0 :         stream_putl(s, zl3vni->svi_if->ifindex);
    2014           0 :         stream_put(s, &vrr_rmac, sizeof(struct ethaddr));
    2015           0 :         stream_putl(s, is_anycast_mac);
    2016             : 
    2017             :         /* Write packet size. */
    2018           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2019             : 
    2020           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    2021           0 :                 zlog_debug(
    2022             :                         "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
    2023             :                         zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
    2024             :                         &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
    2025             :                         CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
    2026             :                                 ? "prefix-routes-only"
    2027             :                                 : "none",
    2028             :                         zebra_route_string(client->proto));
    2029             : 
    2030           0 :         client->l3vniadd_cnt++;
    2031           0 :         return zserv_send_message(client, s);
    2032             : }
    2033             : 
    2034             : /*
    2035             :  * Inform BGP about local l3-VNI deletion.
    2036             :  */
    2037           0 : static int zl3vni_send_del_to_client(struct zebra_l3vni *zl3vni)
    2038             : {
    2039           0 :         struct stream *s = NULL;
    2040           0 :         struct zserv *client = NULL;
    2041             : 
    2042           0 :         client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
    2043             :         /* BGP may not be running. */
    2044           0 :         if (!client)
    2045             :                 return 0;
    2046             : 
    2047           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    2048             : 
    2049           0 :         zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
    2050           0 :         stream_putl(s, zl3vni->vni);
    2051             : 
    2052             :         /* Write packet size. */
    2053           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    2054             : 
    2055           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    2056           0 :                 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
    2057             :                            vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
    2058             :                            zebra_route_string(client->proto));
    2059             : 
    2060           0 :         client->l3vnidel_cnt++;
    2061           0 :         return zserv_send_message(client, s);
    2062             : }
    2063             : 
    2064           0 : static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni)
    2065             : {
    2066           0 :         if (!zl3vni)
    2067             :                 return;
    2068             : 
    2069             :         /* send l3vni add to BGP */
    2070           0 :         zl3vni_send_add_to_client(zl3vni);
    2071             : }
    2072             : 
    2073           0 : static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni)
    2074             : {
    2075           0 :         if (!zl3vni)
    2076             :                 return;
    2077             : 
    2078             :         /* send l3-vni del to BGP*/
    2079           0 :         zl3vni_send_del_to_client(zl3vni);
    2080             : }
    2081             : 
    2082           0 : static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
    2083             : {
    2084           0 :         struct zebra_evpn *zevpn = (struct zebra_evpn *)bucket->data;
    2085           0 :         struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)ctxt;
    2086             : 
    2087           0 :         if (zevpn->vrf_id == zl3vni_vrf_id(zl3vni))
    2088           0 :                 listnode_add_sort(zl3vni->l2vnis, zevpn);
    2089           0 : }
    2090             : 
    2091             : /*
    2092             :  * Handle transition of vni from l2 to l3 and vice versa.
    2093             :  * This function handles only the L2VNI add/delete part of
    2094             :  * the above transition.
    2095             :  * L3VNI add/delete is handled by the calling functions.
    2096             :  */
    2097           0 : static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
    2098             :                                              int add)
    2099             : {
    2100           0 :         struct zebra_evpn *zevpn = NULL;
    2101           0 :         struct zebra_l3vni *zl3vni = NULL;
    2102             : 
    2103             :         /* There is a possibility that VNI notification was already received
    2104             :          * from kernel and we programmed it as L2-VNI
    2105             :          * In such a case we need to delete this L2-VNI first, so
    2106             :          * that it can be reprogrammed as L3-VNI in the system. It is also
    2107             :          * possible that the vrf-vni mapping is removed from FRR while the vxlan
    2108             :          * interface is still present in kernel. In this case to keep it
    2109             :          * symmetric, we will delete the l3-vni and reprogram it as l2-vni
    2110             :          */
    2111           0 :         if (add) {
    2112             :                 /* Locate hash entry */
    2113           0 :                 zevpn = zebra_evpn_lookup(vni);
    2114           0 :                 if (!zevpn)
    2115             :                         return 0;
    2116             : 
    2117           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2118           0 :                         zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
    2119             : 
    2120             :                 /* Delete EVPN from BGP. */
    2121           0 :                 zebra_evpn_send_del_to_client(zevpn);
    2122             : 
    2123           0 :                 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
    2124           0 :                 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
    2125             : 
    2126             :                 /* Free up all remote VTEPs, if any. */
    2127           0 :                 zebra_evpn_vtep_del_all(zevpn, 1);
    2128             : 
    2129           0 :                 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    2130           0 :                 if (zl3vni)
    2131           0 :                         listnode_delete(zl3vni->l2vnis, zevpn);
    2132             : 
    2133             :                 /* Delete the hash entry. */
    2134           0 :                 if (zebra_evpn_vxlan_del(zevpn)) {
    2135           0 :                         flog_err(EC_ZEBRA_VNI_DEL_FAILED,
    2136             :                                  "Failed to del EVPN hash %p, VNI %u", zevpn,
    2137             :                                  zevpn->vni);
    2138           0 :                         return -1;
    2139             :                 }
    2140             :         } else {
    2141           0 :                 struct zebra_ns *zns;
    2142           0 :                 struct route_node *rn;
    2143           0 :                 struct interface *ifp;
    2144           0 :                 struct zebra_if *zif;
    2145           0 :                 struct zebra_l2info_vxlan *vxl;
    2146           0 :                 struct interface *vlan_if;
    2147           0 :                 bool found = false;
    2148             : 
    2149           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    2150           0 :                         zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
    2151             :                                    vni);
    2152             : 
    2153             :                 /* Find VxLAN interface for this VNI. */
    2154           0 :                 zns = zebra_ns_lookup(NS_DEFAULT);
    2155           0 :                 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
    2156           0 :                         ifp = (struct interface *)rn->info;
    2157           0 :                         if (!ifp)
    2158           0 :                                 continue;
    2159           0 :                         zif = ifp->info;
    2160           0 :                         if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
    2161           0 :                                 continue;
    2162             : 
    2163           0 :                         vxl = &zif->l2info.vxl;
    2164           0 :                         if (vxl->vni == vni) {
    2165             :                                 found = true;
    2166             :                                 break;
    2167             :                         }
    2168             :                 }
    2169             : 
    2170           0 :                 if (!found) {
    2171           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    2172           0 :                                 zlog_err(
    2173             :                                         "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
    2174             :                                         vni);
    2175           0 :                         return -1;
    2176             :                 }
    2177             : 
    2178             :                 /* Create VNI hash entry for L2VNI */
    2179           0 :                 zevpn = zebra_evpn_lookup(vni);
    2180           0 :                 if (zevpn)
    2181             :                         return 0;
    2182             : 
    2183           0 :                 zevpn = zebra_evpn_add(vni);
    2184             : 
    2185             :                 /* Find bridge interface for the VNI */
    2186           0 :                 vlan_if = zvni_map_to_svi(vxl->access_vlan,
    2187             :                                           zif->brslave_info.br_if);
    2188           0 :                 if (vlan_if) {
    2189           0 :                         zevpn->vrf_id = vlan_if->vrf->vrf_id;
    2190           0 :                         zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
    2191           0 :                         if (zl3vni)
    2192           0 :                                 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
    2193             :                 }
    2194             : 
    2195           0 :                 zevpn->vxlan_if = ifp;
    2196           0 :                 zevpn->local_vtep_ip = vxl->vtep_ip;
    2197             : 
    2198             :                 /* Inform BGP if the VNI is up and mapped to a bridge. */
    2199           0 :                 if (if_is_operative(ifp) && zif->brslave_info.br_if) {
    2200           0 :                         zebra_evpn_send_add_to_client(zevpn);
    2201           0 :                         zebra_evpn_read_mac_neigh(zevpn, ifp);
    2202             :                 }
    2203             :         }
    2204             : 
    2205             :         return 0;
    2206             : }
    2207             : 
    2208             : /* delete and uninstall rmac hash entry */
    2209           0 : static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
    2210             : {
    2211           0 :         struct zebra_mac *zrmac = NULL;
    2212           0 :         struct zebra_l3vni *zl3vni = NULL;
    2213             : 
    2214           0 :         zrmac = (struct zebra_mac *)bucket->data;
    2215           0 :         zl3vni = (struct zebra_l3vni *)ctx;
    2216           0 :         zl3vni_rmac_uninstall(zl3vni, zrmac);
    2217             : 
    2218             :         /* Send RMAC for FPM processing */
    2219           0 :         hook_call(zebra_rmac_update, zrmac, zl3vni, true, "RMAC deleted");
    2220             : 
    2221           0 :         zl3vni_rmac_del(zl3vni, zrmac);
    2222           0 : }
    2223             : 
    2224             : /* delete and uninstall nh hash entry */
    2225           0 : static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
    2226             : {
    2227           0 :         struct zebra_neigh *n = NULL;
    2228           0 :         struct zebra_l3vni *zl3vni = NULL;
    2229             : 
    2230           0 :         n = (struct zebra_neigh *)bucket->data;
    2231           0 :         zl3vni = (struct zebra_l3vni *)ctx;
    2232           0 :         zl3vni_nh_uninstall(zl3vni, n);
    2233           0 :         zl3vni_nh_del(zl3vni, n);
    2234           0 : }
    2235             : 
    2236             : /* re-add remote rmac if needed */
    2237           0 : static int zebra_vxlan_readd_remote_rmac(struct zebra_l3vni *zl3vni,
    2238             :                                          struct ethaddr *rmac)
    2239             : {
    2240           0 :         struct zebra_mac *zrmac = NULL;
    2241             : 
    2242           0 :         zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
    2243           0 :         if (!zrmac)
    2244             :                 return 0;
    2245             : 
    2246           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    2247           0 :                 zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
    2248             :                            rmac, zl3vni->vni);
    2249             : 
    2250           0 :         zl3vni_rmac_install(zl3vni, zrmac);
    2251           0 :         return 0;
    2252             : }
    2253             : 
    2254             : /* Public functions */
    2255             : 
    2256           0 : int is_l3vni_for_prefix_routes_only(vni_t vni)
    2257             : {
    2258           0 :         struct zebra_l3vni *zl3vni = NULL;
    2259             : 
    2260           0 :         zl3vni = zl3vni_lookup(vni);
    2261           0 :         if (!zl3vni)
    2262             :                 return 0;
    2263             : 
    2264           0 :         return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
    2265             : }
    2266             : 
    2267             : /* handle evpn route in vrf table */
    2268           0 : void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
    2269             :                                     const struct ipaddr *vtep_ip,
    2270             :                                     const struct prefix *host_prefix)
    2271             : {
    2272           0 :         struct zebra_l3vni *zl3vni = NULL;
    2273           0 :         struct ipaddr ipv4_vtep;
    2274             : 
    2275           0 :         zl3vni = zl3vni_from_vrf(vrf_id);
    2276           0 :         if (!zl3vni || !is_l3vni_oper_up(zl3vni))
    2277           0 :                 return;
    2278             : 
    2279             :         /*
    2280             :          * add the next hop neighbor -
    2281             :          * neigh to be installed is the ipv6 nexthop neigh
    2282             :          */
    2283           0 :         zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
    2284             : 
    2285             :         /*
    2286             :          * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
    2287             :          * address. Rmac is programmed against the ipv4 vtep because we only
    2288             :          * support ipv4 tunnels in the h/w right now
    2289             :          */
    2290           0 :         memset(&ipv4_vtep, 0, sizeof(ipv4_vtep));
    2291           0 :         ipv4_vtep.ipa_type = IPADDR_V4;
    2292           0 :         if (vtep_ip->ipa_type == IPADDR_V6)
    2293           0 :                 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
    2294             :                                          &(ipv4_vtep.ipaddr_v4));
    2295             :         else
    2296           0 :                 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
    2297             :                        sizeof(struct in_addr));
    2298             : 
    2299             :         /*
    2300             :          * add the rmac - remote rmac to be installed is against the ipv4
    2301             :          * nexthop address
    2302             :          */
    2303           0 :         zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep);
    2304             : }
    2305             : 
    2306             : /* handle evpn vrf route delete */
    2307           0 : void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
    2308             :                                     struct ipaddr *vtep_ip,
    2309             :                                     struct prefix *host_prefix)
    2310             : {
    2311           0 :         struct zebra_l3vni *zl3vni = NULL;
    2312           0 :         struct zebra_neigh *nh = NULL;
    2313           0 :         struct zebra_mac *zrmac = NULL;
    2314             : 
    2315           0 :         zl3vni = zl3vni_from_vrf(vrf_id);
    2316           0 :         if (!zl3vni)
    2317             :                 return;
    2318             : 
    2319             :         /* find the next hop entry and rmac entry */
    2320           0 :         nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
    2321           0 :         if (!nh)
    2322             :                 return;
    2323           0 :         zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
    2324             : 
    2325             :         /* delete the next hop entry */
    2326           0 :         zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
    2327             : 
    2328             :         /* delete the rmac entry */
    2329           0 :         if (zrmac)
    2330           0 :                 zl3vni_remote_rmac_del(zl3vni, zrmac, vtep_ip);
    2331             : }
    2332             : 
    2333           0 : void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
    2334             :                                            struct ethaddr *rmac, bool use_json)
    2335             : {
    2336           0 :         struct zebra_l3vni *zl3vni = NULL;
    2337           0 :         struct zebra_mac *zrmac = NULL;
    2338           0 :         json_object *json = NULL;
    2339             : 
    2340           0 :         if (!is_evpn_enabled()) {
    2341           0 :                 if (use_json)
    2342           0 :                         vty_out(vty, "{}\n");
    2343           0 :                 return;
    2344             :         }
    2345             : 
    2346           0 :         if (use_json)
    2347           0 :                 json = json_object_new_object();
    2348             : 
    2349           0 :         zl3vni = zl3vni_lookup(l3vni);
    2350           0 :         if (!zl3vni) {
    2351           0 :                 if (use_json)
    2352           0 :                         vty_out(vty, "{}\n");
    2353             :                 else
    2354           0 :                         vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
    2355           0 :                 return;
    2356             :         }
    2357             : 
    2358           0 :         zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
    2359           0 :         if (!zrmac) {
    2360           0 :                 if (use_json)
    2361           0 :                         vty_out(vty, "{}\n");
    2362             :                 else
    2363           0 :                         vty_out(vty,
    2364             :                                 "%% Requested RMAC doesn't exist in L3-VNI %u\n",
    2365             :                                 l3vni);
    2366           0 :                 return;
    2367             :         }
    2368             : 
    2369           0 :         zl3vni_print_rmac(zrmac, vty, json);
    2370             : 
    2371           0 :         if (use_json)
    2372           0 :                 vty_json(vty, json);
    2373             : }
    2374             : 
    2375           0 : void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
    2376             : {
    2377           0 :         struct zebra_l3vni *zl3vni;
    2378           0 :         uint32_t num_rmacs;
    2379           0 :         struct rmac_walk_ctx wctx;
    2380           0 :         json_object *json = NULL;
    2381             : 
    2382           0 :         if (!is_evpn_enabled())
    2383           0 :                 return;
    2384             : 
    2385           0 :         zl3vni = zl3vni_lookup(l3vni);
    2386           0 :         if (!zl3vni) {
    2387           0 :                 if (use_json)
    2388           0 :                         vty_out(vty, "{}\n");
    2389             :                 else
    2390           0 :                         vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
    2391           0 :                 return;
    2392             :         }
    2393           0 :         num_rmacs = hashcount(zl3vni->rmac_table);
    2394           0 :         if (!num_rmacs)
    2395             :                 return;
    2396             : 
    2397           0 :         if (use_json)
    2398           0 :                 json = json_object_new_object();
    2399             : 
    2400           0 :         memset(&wctx, 0, sizeof(wctx));
    2401           0 :         wctx.vty = vty;
    2402           0 :         wctx.json = json;
    2403           0 :         if (!use_json) {
    2404           0 :                 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
    2405             :                         num_rmacs);
    2406           0 :                 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
    2407             :         } else
    2408           0 :                 json_object_int_add(json, "numRmacs", num_rmacs);
    2409             : 
    2410           0 :         hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
    2411             : 
    2412           0 :         if (use_json)
    2413           0 :                 vty_json(vty, json);
    2414             : }
    2415             : 
    2416           0 : void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
    2417             : {
    2418           0 :         json_object *json = NULL;
    2419           0 :         void *args[2];
    2420             : 
    2421           0 :         if (!is_evpn_enabled()) {
    2422           0 :                 if (use_json)
    2423           0 :                         vty_out(vty, "{}\n");
    2424           0 :                 return;
    2425             :         }
    2426             : 
    2427           0 :         if (use_json)
    2428           0 :                 json = json_object_new_object();
    2429             : 
    2430           0 :         args[0] = vty;
    2431           0 :         args[1] = json;
    2432           0 :         hash_iterate(zrouter.l3vni_table,
    2433             :                      (void (*)(struct hash_bucket *,
    2434             :                                void *))zl3vni_print_rmac_hash_all_vni,
    2435             :                      args);
    2436             : 
    2437           0 :         if (use_json)
    2438           0 :                 vty_json(vty, json);
    2439             : }
    2440             : 
    2441           0 : void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
    2442             :                                          struct ipaddr *ip, bool use_json)
    2443             : {
    2444           0 :         struct zebra_l3vni *zl3vni = NULL;
    2445           0 :         struct zebra_neigh *n = NULL;
    2446           0 :         json_object *json = NULL;
    2447             : 
    2448           0 :         if (!is_evpn_enabled()) {
    2449           0 :                 if (use_json)
    2450           0 :                         vty_out(vty, "{}\n");
    2451           0 :                 return;
    2452             :         }
    2453             : 
    2454           0 :         if (use_json)
    2455           0 :                 json = json_object_new_object();
    2456             : 
    2457           0 :         zl3vni = zl3vni_lookup(l3vni);
    2458           0 :         if (!zl3vni) {
    2459           0 :                 if (use_json)
    2460           0 :                         vty_out(vty, "{}\n");
    2461             :                 else
    2462           0 :                         vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
    2463           0 :                 return;
    2464             :         }
    2465             : 
    2466           0 :         n = zl3vni_nh_lookup(zl3vni, ip);
    2467           0 :         if (!n) {
    2468           0 :                 if (use_json)
    2469           0 :                         vty_out(vty, "{}\n");
    2470             :                 else
    2471           0 :                         vty_out(vty,
    2472             :                                 "%% Requested next-hop not present for L3-VNI %u",
    2473             :                                 l3vni);
    2474           0 :                 return;
    2475             :         }
    2476             : 
    2477           0 :         zl3vni_print_nh(n, vty, json);
    2478             : 
    2479           0 :         if (use_json)
    2480           0 :                 vty_json(vty, json);
    2481             : }
    2482             : 
    2483           0 : void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
    2484             : {
    2485           0 :         uint32_t num_nh;
    2486           0 :         struct nh_walk_ctx wctx;
    2487           0 :         json_object *json = NULL;
    2488           0 :         struct zebra_l3vni *zl3vni = NULL;
    2489             : 
    2490           0 :         if (!is_evpn_enabled())
    2491           0 :                 return;
    2492             : 
    2493           0 :         zl3vni = zl3vni_lookup(l3vni);
    2494           0 :         if (!zl3vni) {
    2495           0 :                 if (use_json)
    2496           0 :                         vty_out(vty, "{}\n");
    2497             :                 else
    2498           0 :                         vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
    2499           0 :                 return;
    2500             :         }
    2501             : 
    2502           0 :         num_nh = hashcount(zl3vni->nh_table);
    2503           0 :         if (!num_nh)
    2504             :                 return;
    2505             : 
    2506           0 :         if (use_json)
    2507           0 :                 json = json_object_new_object();
    2508             : 
    2509           0 :         wctx.vty = vty;
    2510           0 :         wctx.json = json;
    2511           0 :         if (!use_json) {
    2512           0 :                 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
    2513             :                         num_nh);
    2514           0 :                 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
    2515             :         } else
    2516           0 :                 json_object_int_add(json, "numNextHops", num_nh);
    2517             : 
    2518           0 :         hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
    2519             : 
    2520           0 :         if (use_json)
    2521           0 :                 vty_json(vty, json);
    2522             : }
    2523             : 
    2524           0 : void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
    2525             : {
    2526           0 :         json_object *json = NULL;
    2527           0 :         void *args[2];
    2528             : 
    2529           0 :         if (!is_evpn_enabled()) {
    2530           0 :                 if (use_json)
    2531           0 :                         vty_out(vty, "{}\n");
    2532           0 :                 return;
    2533             :         }
    2534             : 
    2535           0 :         if (use_json)
    2536           0 :                 json = json_object_new_object();
    2537             : 
    2538           0 :         args[0] = vty;
    2539           0 :         args[1] = json;
    2540           0 :         hash_iterate(zrouter.l3vni_table,
    2541             :                      (void (*)(struct hash_bucket *,
    2542             :                                void *))zl3vni_print_nh_hash_all_vni,
    2543             :                      args);
    2544             : 
    2545           0 :         if (use_json)
    2546           0 :                 vty_json(vty, json);
    2547             : }
    2548             : 
    2549             : /*
    2550             :  * Display L3 VNI information (VTY command handler).
    2551             :  */
    2552           0 : void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
    2553             : {
    2554           0 :         void *args[2];
    2555           0 :         json_object *json = NULL;
    2556           0 :         struct zebra_l3vni *zl3vni = NULL;
    2557             : 
    2558           0 :         if (!is_evpn_enabled()) {
    2559           0 :                 if (use_json)
    2560           0 :                         vty_out(vty, "{}\n");
    2561           0 :                 return;
    2562             :         }
    2563             : 
    2564           0 :         zl3vni = zl3vni_lookup(vni);
    2565           0 :         if (!zl3vni) {
    2566           0 :                 if (use_json)
    2567           0 :                         vty_out(vty, "{}\n");
    2568             :                 else
    2569           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    2570           0 :                 return;
    2571             :         }
    2572             : 
    2573           0 :         if (use_json)
    2574           0 :                 json = json_object_new_object();
    2575             : 
    2576           0 :         args[0] = vty;
    2577           0 :         args[1] = json;
    2578           0 :         zl3vni_print(zl3vni, (void *)args);
    2579             : 
    2580           0 :         if (use_json)
    2581           0 :                 vty_json(vty, json);
    2582             : }
    2583             : 
    2584           0 : void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
    2585             :                                json_object *json_vrfs)
    2586             : {
    2587           0 :         char buf[ETHER_ADDR_STRLEN];
    2588           0 :         struct zebra_l3vni *zl3vni = NULL;
    2589             : 
    2590           0 :         zl3vni = zl3vni_lookup(zvrf->l3vni);
    2591           0 :         if (!zl3vni)
    2592           0 :                 return;
    2593             : 
    2594           0 :         if (!json_vrfs) {
    2595           0 :                 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
    2596             :                         zvrf_name(zvrf), zl3vni->vni,
    2597             :                         zl3vni_vxlan_if_name(zl3vni),
    2598             :                         zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
    2599             :                         zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
    2600             :         } else {
    2601           0 :                 json_object *json_vrf = NULL;
    2602             : 
    2603           0 :                 json_vrf = json_object_new_object();
    2604           0 :                 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
    2605           0 :                 json_object_int_add(json_vrf, "vni", zl3vni->vni);
    2606           0 :                 json_object_string_add(json_vrf, "vxlanIntf",
    2607             :                                        zl3vni_vxlan_if_name(zl3vni));
    2608           0 :                 json_object_string_add(json_vrf, "sviIntf",
    2609             :                                        zl3vni_svi_if_name(zl3vni));
    2610           0 :                 json_object_string_add(json_vrf, "state",
    2611             :                                        zl3vni_state2str(zl3vni));
    2612           0 :                 json_object_string_add(
    2613             :                         json_vrf, "routerMac",
    2614             :                         zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
    2615           0 :                 json_object_array_add(json_vrfs, json_vrf);
    2616             :         }
    2617             : }
    2618             : 
    2619             : /*
    2620             :  * Display Neighbors for a VNI (VTY command handler).
    2621             :  */
    2622           0 : void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
    2623             :                                  vni_t vni, bool use_json)
    2624             : {
    2625           0 :         struct zebra_evpn *zevpn;
    2626           0 :         uint32_t num_neigh;
    2627           0 :         struct neigh_walk_ctx wctx;
    2628           0 :         json_object *json = NULL;
    2629             : 
    2630           0 :         if (!is_evpn_enabled())
    2631           0 :                 return;
    2632           0 :         zevpn = zebra_evpn_lookup(vni);
    2633           0 :         if (!zevpn) {
    2634           0 :                 if (use_json)
    2635           0 :                         vty_out(vty, "{}\n");
    2636             :                 else
    2637           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    2638           0 :                 return;
    2639             :         }
    2640           0 :         num_neigh = hashcount(zevpn->neigh_table);
    2641           0 :         if (!num_neigh)
    2642             :                 return;
    2643             : 
    2644           0 :         if (use_json)
    2645           0 :                 json = json_object_new_object();
    2646             : 
    2647             :         /* Since we have IPv6 addresses to deal with which can vary widely in
    2648             :          * size, we try to be a bit more elegant in display by first computing
    2649             :          * the maximum width.
    2650             :          */
    2651           0 :         memset(&wctx, 0, sizeof(wctx));
    2652           0 :         wctx.zevpn = zevpn;
    2653           0 :         wctx.vty = vty;
    2654           0 :         wctx.addr_width = 15;
    2655           0 :         wctx.json = json;
    2656           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
    2657             :                      &wctx);
    2658             : 
    2659           0 :         if (!use_json) {
    2660           0 :                 vty_out(vty,
    2661             :                         "Number of ARPs (local and remote) known for this VNI: %u\n",
    2662             :                         num_neigh);
    2663           0 :                 zebra_evpn_print_neigh_hdr(vty, &wctx);
    2664             :         } else
    2665           0 :                 json_object_int_add(json, "numArpNd", num_neigh);
    2666             : 
    2667           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
    2668           0 :         if (use_json)
    2669           0 :                 vty_json(vty, json);
    2670             : }
    2671             : 
    2672             : /*
    2673             :  * Display neighbors across all VNIs (VTY command handler).
    2674             :  */
    2675           0 : void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
    2676             :                                      bool print_dup, bool use_json)
    2677             : {
    2678           0 :         json_object *json = NULL;
    2679           0 :         void *args[3];
    2680             : 
    2681           0 :         if (!is_evpn_enabled())
    2682           0 :                 return;
    2683             : 
    2684           0 :         if (use_json)
    2685           0 :                 json = json_object_new_object();
    2686             : 
    2687           0 :         args[0] = vty;
    2688           0 :         args[1] = json;
    2689           0 :         args[2] = (void *)(ptrdiff_t)print_dup;
    2690             : 
    2691           0 :         hash_iterate(zvrf->evpn_table,
    2692             :                      (void (*)(struct hash_bucket *,
    2693             :                                void *))zevpn_print_neigh_hash_all_evpn,
    2694             :                      args);
    2695           0 :         if (use_json)
    2696           0 :                 vty_json(vty, json);
    2697             : }
    2698             : 
    2699             : /*
    2700             :  * Display neighbors across all VNIs in detail(VTY command handler).
    2701             :  */
    2702           0 : void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
    2703             :                                             struct zebra_vrf *zvrf,
    2704             :                                             bool print_dup, bool use_json)
    2705             : {
    2706           0 :         json_object *json = NULL;
    2707           0 :         void *args[3];
    2708             : 
    2709           0 :         if (!is_evpn_enabled())
    2710           0 :                 return;
    2711             : 
    2712           0 :         if (use_json)
    2713           0 :                 json = json_object_new_object();
    2714             : 
    2715           0 :         args[0] = vty;
    2716           0 :         args[1] = json;
    2717           0 :         args[2] = (void *)(ptrdiff_t)print_dup;
    2718             : 
    2719           0 :         hash_iterate(zvrf->evpn_table,
    2720             :                      (void (*)(struct hash_bucket *,
    2721             :                                void *))zevpn_print_neigh_hash_all_evpn_detail,
    2722             :                      args);
    2723           0 :         if (use_json)
    2724           0 :                 vty_json(vty, json);
    2725             : }
    2726             : 
    2727             : /*
    2728             :  * Display specific neighbor for a VNI, if present (VTY command handler).
    2729             :  */
    2730           0 : void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
    2731             :                                           struct zebra_vrf *zvrf, vni_t vni,
    2732             :                                           struct ipaddr *ip, bool use_json)
    2733             : {
    2734           0 :         struct zebra_evpn *zevpn;
    2735           0 :         struct zebra_neigh *n;
    2736           0 :         json_object *json = NULL;
    2737             : 
    2738           0 :         if (!is_evpn_enabled())
    2739             :                 return;
    2740           0 :         zevpn = zebra_evpn_lookup(vni);
    2741           0 :         if (!zevpn) {
    2742           0 :                 if (use_json)
    2743           0 :                         vty_out(vty, "{}\n");
    2744             :                 else
    2745           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    2746           0 :                 return;
    2747             :         }
    2748           0 :         n = zebra_evpn_neigh_lookup(zevpn, ip);
    2749           0 :         if (!n) {
    2750           0 :                 if (!use_json)
    2751           0 :                         vty_out(vty,
    2752             :                                 "%% Requested neighbor does not exist in VNI %u\n",
    2753             :                                 vni);
    2754           0 :                 return;
    2755             :         }
    2756           0 :         if (use_json)
    2757           0 :                 json = json_object_new_object();
    2758             : 
    2759           0 :         zebra_evpn_print_neigh(n, vty, json);
    2760             : 
    2761           0 :         if (use_json)
    2762           0 :                 vty_json(vty, json);
    2763             : }
    2764             : 
    2765             : /*
    2766             :  * Display neighbors for a VNI from specific VTEP (VTY command handler).
    2767             :  * By definition, these are remote neighbors.
    2768             :  */
    2769           0 : void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
    2770             :                                       vni_t vni, struct in_addr vtep_ip,
    2771             :                                       bool use_json)
    2772             : {
    2773           0 :         struct zebra_evpn *zevpn;
    2774           0 :         uint32_t num_neigh;
    2775           0 :         struct neigh_walk_ctx wctx;
    2776           0 :         json_object *json = NULL;
    2777             : 
    2778           0 :         if (!is_evpn_enabled())
    2779           0 :                 return;
    2780           0 :         zevpn = zebra_evpn_lookup(vni);
    2781           0 :         if (!zevpn) {
    2782           0 :                 if (use_json)
    2783           0 :                         vty_out(vty, "{}\n");
    2784             :                 else
    2785           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    2786           0 :                 return;
    2787             :         }
    2788           0 :         num_neigh = hashcount(zevpn->neigh_table);
    2789           0 :         if (!num_neigh)
    2790             :                 return;
    2791             : 
    2792           0 :         if (use_json)
    2793           0 :                 json = json_object_new_object();
    2794             : 
    2795           0 :         memset(&wctx, 0, sizeof(wctx));
    2796           0 :         wctx.zevpn = zevpn;
    2797           0 :         wctx.vty = vty;
    2798           0 :         wctx.addr_width = 15;
    2799           0 :         wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
    2800           0 :         wctx.r_vtep_ip = vtep_ip;
    2801           0 :         wctx.json = json;
    2802           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
    2803             :                      &wctx);
    2804           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
    2805             : 
    2806           0 :         if (use_json)
    2807           0 :                 vty_json(vty, json);
    2808             : }
    2809             : 
    2810             : /*
    2811             :  * Display Duplicate detected Neighbors for a VNI
    2812             :  * (VTY command handler).
    2813             :  */
    2814           0 : void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
    2815             :                                      struct zebra_vrf *zvrf,
    2816             :                                      vni_t vni,
    2817             :                                      bool use_json)
    2818             : {
    2819           0 :         struct zebra_evpn *zevpn;
    2820           0 :         uint32_t num_neigh;
    2821           0 :         struct neigh_walk_ctx wctx;
    2822           0 :         json_object *json = NULL;
    2823             : 
    2824           0 :         if (!is_evpn_enabled())
    2825           0 :                 return;
    2826             : 
    2827           0 :         zevpn = zebra_evpn_lookup(vni);
    2828           0 :         if (!zevpn) {
    2829           0 :                 vty_out(vty, "%% VNI %u does not exist\n", vni);
    2830           0 :                 return;
    2831             :         }
    2832             : 
    2833           0 :         num_neigh = hashcount(zevpn->neigh_table);
    2834           0 :         if (!num_neigh)
    2835             :                 return;
    2836             : 
    2837           0 :         num_neigh = num_dup_detected_neighs(zevpn);
    2838           0 :         if (!num_neigh)
    2839             :                 return;
    2840             : 
    2841           0 :         if (use_json)
    2842           0 :                 json = json_object_new_object();
    2843             : 
    2844             :         /* Since we have IPv6 addresses to deal with which can vary widely in
    2845             :          * size, we try to be a bit more elegant in display by first computing
    2846             :          * the maximum width.
    2847             :          */
    2848           0 :         memset(&wctx, 0, sizeof(wctx));
    2849           0 :         wctx.zevpn = zevpn;
    2850           0 :         wctx.vty = vty;
    2851           0 :         wctx.addr_width = 15;
    2852           0 :         wctx.json = json;
    2853           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
    2854             :                      &wctx);
    2855             : 
    2856           0 :         if (!use_json) {
    2857           0 :                 vty_out(vty,
    2858             :                         "Number of ARPs (local and remote) known for this VNI: %u\n",
    2859             :                         num_neigh);
    2860           0 :                 vty_out(vty, "%*s %-6s %-8s %-17s %-30s\n",
    2861           0 :                         -wctx.addr_width, "IP", "Type",
    2862             :                         "State", "MAC", "Remote ES/VTEP");
    2863             :         } else
    2864           0 :                 json_object_int_add(json, "numArpNd", num_neigh);
    2865             : 
    2866           0 :         hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash,
    2867             :                      &wctx);
    2868             : 
    2869           0 :         if (use_json)
    2870           0 :                 vty_json(vty, json);
    2871             : }
    2872             : 
    2873             : /*
    2874             :  * Display MACs for a VNI (VTY command handler).
    2875             :  */
    2876           0 : void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
    2877             :                                 vni_t vni, bool use_json, bool detail)
    2878             : {
    2879           0 :         struct zebra_evpn *zevpn;
    2880           0 :         uint32_t num_macs;
    2881           0 :         struct mac_walk_ctx wctx;
    2882           0 :         json_object *json = NULL;
    2883           0 :         json_object *json_mac = NULL;
    2884             : 
    2885           0 :         if (!is_evpn_enabled())
    2886           0 :                 return;
    2887           0 :         zevpn = zebra_evpn_lookup(vni);
    2888           0 :         if (!zevpn) {
    2889           0 :                 if (use_json)
    2890           0 :                         vty_out(vty, "{}\n");
    2891             :                 else
    2892           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    2893           0 :                 return;
    2894             :         }
    2895           0 :         num_macs = num_valid_macs(zevpn);
    2896           0 :         if (!num_macs)
    2897             :                 return;
    2898             : 
    2899           0 :         if (use_json) {
    2900           0 :                 json = json_object_new_object();
    2901           0 :                 json_mac = json_object_new_object();
    2902             :         }
    2903             : 
    2904           0 :         memset(&wctx, 0, sizeof(wctx));
    2905           0 :         wctx.zevpn = zevpn;
    2906           0 :         wctx.vty = vty;
    2907           0 :         wctx.json = json_mac;
    2908             : 
    2909           0 :         if (!use_json) {
    2910           0 :                 if (detail) {
    2911           0 :                         vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
    2912             :                                 zevpn->vni, num_macs);
    2913             :                 } else {
    2914           0 :                         vty_out(vty,
    2915             :                                 "Number of MACs (local and remote) known for this VNI: %u\n",
    2916             :                                 num_macs);
    2917           0 :                         vty_out(vty,
    2918             :                                 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
    2919           0 :                         vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
    2920             :                                 "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN",
    2921             :                                 "Seq #'s");
    2922             :                 }
    2923             :         } else
    2924           0 :                 json_object_int_add(json, "numMacs", num_macs);
    2925             : 
    2926           0 :         if (detail)
    2927           0 :                 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail,
    2928             :                              &wctx);
    2929             :         else
    2930           0 :                 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash,
    2931             :                              &wctx);
    2932             : 
    2933           0 :         if (use_json) {
    2934           0 :                 json_object_object_add(json, "macs", json_mac);
    2935           0 :                 vty_json(vty, json);
    2936             :         }
    2937             : }
    2938             : 
    2939             : /*
    2940             :  * Display MACs for all VNIs (VTY command handler).
    2941             :  */
    2942           0 : void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
    2943             :                                     bool print_dup, bool use_json)
    2944             : {
    2945           0 :         struct mac_walk_ctx wctx;
    2946           0 :         json_object *json = NULL;
    2947             : 
    2948           0 :         if (!is_evpn_enabled()) {
    2949           0 :                 if (use_json)
    2950           0 :                         vty_out(vty, "{}\n");
    2951           0 :                 return;
    2952             :         }
    2953           0 :         if (use_json)
    2954           0 :                 json = json_object_new_object();
    2955             : 
    2956           0 :         memset(&wctx, 0, sizeof(wctx));
    2957           0 :         wctx.vty = vty;
    2958           0 :         wctx.json = json;
    2959           0 :         wctx.print_dup = print_dup;
    2960           0 :         hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
    2961             : 
    2962           0 :         if (use_json)
    2963           0 :                 vty_json(vty, json);
    2964             : }
    2965             : 
    2966             : /*
    2967             :  * Display MACs in detail for all VNIs (VTY command handler).
    2968             :  */
    2969           0 : void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
    2970             :                                            struct zebra_vrf *zvrf,
    2971             :                                            bool print_dup, bool use_json)
    2972             : {
    2973           0 :         struct mac_walk_ctx wctx;
    2974           0 :         json_object *json = NULL;
    2975             : 
    2976           0 :         if (!is_evpn_enabled()) {
    2977           0 :                 if (use_json)
    2978           0 :                         vty_out(vty, "{}\n");
    2979           0 :                 return;
    2980             :         }
    2981           0 :         if (use_json)
    2982           0 :                 json = json_object_new_object();
    2983             : 
    2984           0 :         memset(&wctx, 0, sizeof(wctx));
    2985           0 :         wctx.vty = vty;
    2986           0 :         wctx.json = json;
    2987           0 :         wctx.print_dup = print_dup;
    2988           0 :         hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail,
    2989             :                      &wctx);
    2990             : 
    2991           0 :         if (use_json)
    2992           0 :                 vty_json(vty, json);
    2993             : }
    2994             : 
    2995             : /*
    2996             :  * Display MACs for all VNIs (VTY command handler).
    2997             :  */
    2998           0 : void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
    2999             :                                          struct zebra_vrf *zvrf,
    3000             :                                          struct in_addr vtep_ip, bool use_json)
    3001             : {
    3002           0 :         struct mac_walk_ctx wctx;
    3003           0 :         json_object *json = NULL;
    3004             : 
    3005           0 :         if (!is_evpn_enabled())
    3006           0 :                 return;
    3007             : 
    3008           0 :         if (use_json)
    3009           0 :                 json = json_object_new_object();
    3010             : 
    3011           0 :         memset(&wctx, 0, sizeof(wctx));
    3012           0 :         wctx.vty = vty;
    3013           0 :         wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
    3014           0 :         wctx.r_vtep_ip = vtep_ip;
    3015           0 :         wctx.json = json;
    3016           0 :         hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
    3017             : 
    3018           0 :         if (use_json)
    3019           0 :                 vty_json(vty, json);
    3020             : }
    3021             : 
    3022             : /*
    3023             :  * Display specific MAC for a VNI, if present (VTY command handler).
    3024             :  */
    3025           0 : void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
    3026             :                                         vni_t vni, struct ethaddr *macaddr,
    3027             :                                         bool use_json)
    3028             : {
    3029           0 :         struct zebra_evpn *zevpn;
    3030           0 :         struct zebra_mac *mac;
    3031           0 :         json_object *json = NULL;
    3032             : 
    3033           0 :         if (!is_evpn_enabled())
    3034             :                 return;
    3035             : 
    3036           0 :         zevpn = zebra_evpn_lookup(vni);
    3037           0 :         if (!zevpn) {
    3038           0 :                 if (use_json)
    3039           0 :                         vty_out(vty, "{}\n");
    3040             :                 else
    3041           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    3042           0 :                 return;
    3043             :         }
    3044           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    3045           0 :         if (!mac) {
    3046           0 :                 if (use_json)
    3047           0 :                         vty_out(vty, "{}\n");
    3048             :                 else
    3049           0 :                         vty_out(vty,
    3050             :                                 "%% Requested MAC does not exist in VNI %u\n",
    3051             :                                 vni);
    3052           0 :                 return;
    3053             :         }
    3054             : 
    3055           0 :         if (use_json)
    3056           0 :                 json = json_object_new_object();
    3057             : 
    3058           0 :         zebra_evpn_print_mac(mac, vty, json);
    3059           0 :         if (use_json)
    3060           0 :                 vty_json(vty, json);
    3061             : }
    3062             : 
    3063             : /* Print Duplicate MACs per VNI */
    3064           0 : void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
    3065             :                                     struct zebra_vrf *zvrf,
    3066             :                                     vni_t vni, bool use_json)
    3067             : {
    3068           0 :         struct zebra_evpn *zevpn;
    3069           0 :         struct mac_walk_ctx wctx;
    3070           0 :         uint32_t num_macs;
    3071           0 :         json_object *json = NULL;
    3072           0 :         json_object *json_mac = NULL;
    3073             : 
    3074           0 :         if (!is_evpn_enabled())
    3075           0 :                 return;
    3076             : 
    3077           0 :         zevpn = zebra_evpn_lookup(vni);
    3078           0 :         if (!zevpn) {
    3079           0 :                 vty_out(vty, "%% VNI %u does not exist\n", vni);
    3080           0 :                 return;
    3081             :         }
    3082             : 
    3083           0 :         num_macs = num_valid_macs(zevpn);
    3084           0 :         if (!num_macs)
    3085             :                 return;
    3086             : 
    3087           0 :         num_macs = num_dup_detected_macs(zevpn);
    3088           0 :         if (!num_macs)
    3089             :                 return;
    3090             : 
    3091           0 :         if (use_json) {
    3092           0 :                 json = json_object_new_object();
    3093           0 :                 json_mac = json_object_new_object();
    3094             :         }
    3095             : 
    3096           0 :         memset(&wctx, 0, sizeof(wctx));
    3097           0 :         wctx.zevpn = zevpn;
    3098           0 :         wctx.vty = vty;
    3099           0 :         wctx.json = json_mac;
    3100             : 
    3101           0 :         if (!use_json) {
    3102           0 :                 vty_out(vty,
    3103             :                 "Number of MACs (local and remote) known for this VNI: %u\n",
    3104             :                         num_macs);
    3105           0 :                 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
    3106             :                         "Flags", "Intf/Remote ES/VTEP", "VLAN");
    3107             :         } else
    3108           0 :                 json_object_int_add(json, "numMacs", num_macs);
    3109             : 
    3110           0 :         hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, &wctx);
    3111             : 
    3112           0 :         if (use_json) {
    3113           0 :                 json_object_object_add(json, "macs", json_mac);
    3114           0 :                 vty_json(vty, json);
    3115             :         }
    3116             : 
    3117             : }
    3118             : 
    3119           0 : int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni,
    3120             :                                          struct ethaddr *macaddr, char *errmsg,
    3121             :                                          size_t errmsg_len)
    3122             : {
    3123           0 :         struct zebra_evpn *zevpn;
    3124           0 :         struct zebra_mac *mac;
    3125           0 :         struct listnode *node = NULL;
    3126           0 :         struct zebra_neigh *nbr = NULL;
    3127             : 
    3128           0 :         if (!is_evpn_enabled())
    3129             :                 return 0;
    3130             : 
    3131           0 :         zevpn = zebra_evpn_lookup(vni);
    3132           0 :         if (!zevpn) {
    3133           0 :                 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist", vni);
    3134           0 :                 return -1;
    3135             :         }
    3136             : 
    3137           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    3138           0 :         if (!mac) {
    3139           0 :                 snprintf(errmsg, errmsg_len,
    3140             :                          "Requested MAC does not exist in VNI %u\n", vni);
    3141           0 :                 return -1;
    3142             :         }
    3143             : 
    3144           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
    3145           0 :                 snprintfrr(errmsg, errmsg_len,
    3146             :                            "Requested MAC is not duplicate detected\n");
    3147           0 :                 return -1;
    3148             :         }
    3149             : 
    3150             :         /* Remove all IPs as duplicate associcated with this MAC */
    3151           0 :         for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
    3152             :                 /* For local neigh mark inactive so MACIP update is generated
    3153             :                  * to BGP. This is a scenario where MAC update received
    3154             :                  * and detected as duplicate which marked neigh as duplicate.
    3155             :                  * Later local neigh update did not get a chance to relay
    3156             :                  * to BGP. Similarly remote macip update, neigh needs to be
    3157             :                  * installed locally.
    3158             :                  */
    3159           0 :                 if (zvrf->dad_freeze &&
    3160           0 :                     CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
    3161           0 :                         if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
    3162           0 :                                 ZEBRA_NEIGH_SET_INACTIVE(nbr);
    3163           0 :                         else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
    3164           0 :                                 zebra_evpn_rem_neigh_install(
    3165             :                                         zevpn, nbr, false /*was_static*/);
    3166             :                 }
    3167             : 
    3168           0 :                 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    3169           0 :                 nbr->dad_count = 0;
    3170           0 :                 nbr->detect_start_time.tv_sec = 0;
    3171           0 :                 nbr->dad_dup_detect_time = 0;
    3172             :         }
    3173             : 
    3174           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
    3175           0 :         mac->dad_count = 0;
    3176           0 :         mac->detect_start_time.tv_sec = 0;
    3177           0 :         mac->detect_start_time.tv_usec = 0;
    3178           0 :         mac->dad_dup_detect_time = 0;
    3179           0 :         THREAD_OFF(mac->dad_mac_auto_recovery_timer);
    3180             : 
    3181             :         /* warn-only action return */
    3182           0 :         if (!zvrf->dad_freeze)
    3183             :                 return 0;
    3184             : 
    3185             :         /* Local: Notify Peer VTEPs, Remote: Install the entry */
    3186           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
    3187             :                 /* Inform to BGP */
    3188           0 :                 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
    3189             :                                                       mac->flags, mac->loc_seq,
    3190             :                                                       mac->es))
    3191             :                         return 0;
    3192             : 
    3193             :                 /* Process all neighbors associated with this MAC. */
    3194           0 :                 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
    3195             :                                                              0 /*es_change*/);
    3196             : 
    3197           0 :         } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
    3198           0 :                 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
    3199             : 
    3200             :                 /* Install the entry. */
    3201           0 :                 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
    3202             :         }
    3203             : 
    3204             :         return 0;
    3205             : }
    3206             : 
    3207           0 : int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni,
    3208             :                                         struct ipaddr *ip, char *errmsg,
    3209             :                                         size_t errmsg_len)
    3210             : {
    3211           0 :         struct zebra_evpn *zevpn;
    3212           0 :         struct zebra_neigh *nbr;
    3213           0 :         struct zebra_mac *mac;
    3214           0 :         char buf[INET6_ADDRSTRLEN];
    3215           0 :         char buf2[ETHER_ADDR_STRLEN];
    3216             : 
    3217           0 :         if (!is_evpn_enabled())
    3218             :                 return 0;
    3219             : 
    3220           0 :         zevpn = zebra_evpn_lookup(vni);
    3221           0 :         if (!zevpn) {
    3222           0 :                 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist\n", vni);
    3223           0 :                 return -1;
    3224             :         }
    3225             : 
    3226           0 :         nbr = zebra_evpn_neigh_lookup(zevpn, ip);
    3227           0 :         if (!nbr) {
    3228           0 :                 snprintfrr(errmsg, errmsg_len,
    3229             :                            "Requested host IP does not exist in VNI %u\n", vni);
    3230           0 :                 return -1;
    3231             :         }
    3232             : 
    3233           0 :         ipaddr2str(&nbr->ip, buf, sizeof(buf));
    3234             : 
    3235           0 :         if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
    3236           0 :                 snprintfrr(errmsg, errmsg_len,
    3237             :                            "Requested host IP %s is not duplicate detected\n",
    3238             :                            buf);
    3239           0 :                 return -1;
    3240             :         }
    3241             : 
    3242           0 :         mac = zebra_evpn_mac_lookup(zevpn, &nbr->emac);
    3243             : 
    3244           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
    3245           0 :                 snprintfrr(
    3246             :                         errmsg, errmsg_len,
    3247             :                         "Requested IP's associated MAC %s is still in duplicate state\n",
    3248             :                         prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
    3249           0 :                 return -1;
    3250             :         }
    3251             : 
    3252           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    3253           0 :                 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
    3254             :                            __func__, buf, nbr->flags, nbr->loc_seq);
    3255             : 
    3256           0 :         UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    3257           0 :         nbr->dad_count = 0;
    3258           0 :         nbr->detect_start_time.tv_sec = 0;
    3259           0 :         nbr->detect_start_time.tv_usec = 0;
    3260           0 :         nbr->dad_dup_detect_time = 0;
    3261           0 :         THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
    3262             : 
    3263           0 :         if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
    3264           0 :                 zebra_evpn_neigh_send_add_to_client(zevpn->vni, ip, &nbr->emac,
    3265             :                                                     nbr->mac, nbr->flags,
    3266             :                                                     nbr->loc_seq);
    3267           0 :         } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
    3268           0 :                 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
    3269             :         }
    3270             : 
    3271             :         return 0;
    3272             : }
    3273             : 
    3274           0 : static void zevpn_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt)
    3275             : {
    3276           0 :         struct mac_walk_ctx *wctx = ctxt;
    3277           0 :         struct zebra_mac *mac;
    3278           0 :         struct zebra_evpn *zevpn;
    3279           0 :         struct listnode *node = NULL;
    3280           0 :         struct zebra_neigh *nbr = NULL;
    3281             : 
    3282           0 :         mac = (struct zebra_mac *)bucket->data;
    3283           0 :         if (!mac)
    3284             :                 return;
    3285             : 
    3286           0 :         zevpn = wctx->zevpn;
    3287             : 
    3288           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
    3289             :                 return;
    3290             : 
    3291           0 :         UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
    3292           0 :         mac->dad_count = 0;
    3293           0 :         mac->detect_start_time.tv_sec = 0;
    3294           0 :         mac->detect_start_time.tv_usec = 0;
    3295           0 :         mac->dad_dup_detect_time = 0;
    3296           0 :         THREAD_OFF(mac->dad_mac_auto_recovery_timer);
    3297             : 
    3298             :         /* Remove all IPs as duplicate associcated with this MAC */
    3299           0 :         for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
    3300           0 :                 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
    3301           0 :                     && nbr->dad_count)
    3302           0 :                         ZEBRA_NEIGH_SET_INACTIVE(nbr);
    3303             : 
    3304           0 :                 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
    3305           0 :                 nbr->dad_count = 0;
    3306           0 :                 nbr->detect_start_time.tv_sec = 0;
    3307           0 :                 nbr->dad_dup_detect_time = 0;
    3308             :         }
    3309             : 
    3310             :         /* Local: Notify Peer VTEPs, Remote: Install the entry */
    3311           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
    3312             :                 /* Inform to BGP */
    3313           0 :                 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
    3314             :                                                       mac->flags, mac->loc_seq,
    3315             :                                                       mac->es))
    3316             :                         return;
    3317             : 
    3318             :                 /* Process all neighbors associated with this MAC. */
    3319           0 :                 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
    3320             :                                                              0 /*es_change*/);
    3321             : 
    3322           0 :         } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
    3323           0 :                 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
    3324             : 
    3325             :                 /* Install the entry. */
    3326           0 :                 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
    3327             :         }
    3328             : }
    3329             : 
    3330           0 : static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket,
    3331             :                                             void **args)
    3332             : {
    3333           0 :         struct zebra_evpn *zevpn;
    3334           0 :         struct zebra_vrf *zvrf;
    3335           0 :         struct mac_walk_ctx m_wctx;
    3336           0 :         struct neigh_walk_ctx n_wctx;
    3337             : 
    3338           0 :         zevpn = (struct zebra_evpn *)bucket->data;
    3339           0 :         if (!zevpn)
    3340           0 :                 return;
    3341             : 
    3342           0 :         zvrf = (struct zebra_vrf *)args[0];
    3343             : 
    3344           0 :         if (hashcount(zevpn->neigh_table)) {
    3345           0 :                 memset(&n_wctx, 0, sizeof(n_wctx));
    3346           0 :                 n_wctx.zevpn = zevpn;
    3347           0 :                 n_wctx.zvrf = zvrf;
    3348           0 :                 hash_iterate(zevpn->neigh_table,
    3349             :                              zebra_evpn_clear_dup_neigh_hash, &n_wctx);
    3350             :         }
    3351             : 
    3352           0 :         if (num_valid_macs(zevpn)) {
    3353           0 :                 memset(&m_wctx, 0, sizeof(m_wctx));
    3354           0 :                 m_wctx.zevpn = zevpn;
    3355           0 :                 m_wctx.zvrf = zvrf;
    3356           0 :                 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
    3357             :         }
    3358             : 
    3359             : }
    3360             : 
    3361           0 : int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf *zvrf)
    3362             : {
    3363           0 :         void *args[1];
    3364             : 
    3365           0 :         if (!is_evpn_enabled())
    3366             :                 return 0;
    3367             : 
    3368           0 :         args[0] = zvrf;
    3369             : 
    3370           0 :         hash_iterate(zvrf->evpn_table,
    3371             :                      (void (*)(struct hash_bucket *, void *))
    3372             :                      zevpn_clear_dup_detect_hash_vni_all, args);
    3373             : 
    3374           0 :         return 0;
    3375             : }
    3376             : 
    3377           0 : int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni)
    3378             : {
    3379           0 :         struct zebra_evpn *zevpn;
    3380           0 :         struct mac_walk_ctx m_wctx;
    3381           0 :         struct neigh_walk_ctx n_wctx;
    3382             : 
    3383           0 :         if (!is_evpn_enabled())
    3384             :                 return 0;
    3385             : 
    3386           0 :         zevpn = zebra_evpn_lookup(vni);
    3387           0 :         if (!zevpn) {
    3388           0 :                 zlog_warn("VNI %u does not exist", vni);
    3389           0 :                 return CMD_WARNING;
    3390             :         }
    3391             : 
    3392           0 :         if (hashcount(zevpn->neigh_table)) {
    3393           0 :                 memset(&n_wctx, 0, sizeof(n_wctx));
    3394           0 :                 n_wctx.zevpn = zevpn;
    3395           0 :                 n_wctx.zvrf = zvrf;
    3396           0 :                 hash_iterate(zevpn->neigh_table,
    3397             :                              zebra_evpn_clear_dup_neigh_hash, &n_wctx);
    3398             :         }
    3399             : 
    3400           0 :         if (num_valid_macs(zevpn)) {
    3401           0 :                 memset(&m_wctx, 0, sizeof(m_wctx));
    3402           0 :                 m_wctx.zevpn = zevpn;
    3403           0 :                 m_wctx.zvrf = zvrf;
    3404           0 :                 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
    3405             :         }
    3406             : 
    3407             :         return 0;
    3408             : }
    3409             : 
    3410             : /*
    3411             :  * Display MACs for a VNI from specific VTEP (VTY command handler).
    3412             :  */
    3413           0 : void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
    3414             :                                      vni_t vni, struct in_addr vtep_ip,
    3415             :                                      bool use_json)
    3416             : {
    3417           0 :         struct zebra_evpn *zevpn;
    3418           0 :         uint32_t num_macs;
    3419           0 :         struct mac_walk_ctx wctx;
    3420           0 :         json_object *json = NULL;
    3421           0 :         json_object *json_mac = NULL;
    3422             : 
    3423           0 :         if (!is_evpn_enabled())
    3424           0 :                 return;
    3425           0 :         zevpn = zebra_evpn_lookup(vni);
    3426           0 :         if (!zevpn) {
    3427           0 :                 if (use_json)
    3428           0 :                         vty_out(vty, "{}\n");
    3429             :                 else
    3430           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    3431           0 :                 return;
    3432             :         }
    3433           0 :         num_macs = num_valid_macs(zevpn);
    3434           0 :         if (!num_macs)
    3435             :                 return;
    3436             : 
    3437           0 :         if (use_json) {
    3438           0 :                 json = json_object_new_object();
    3439           0 :                 json_mac = json_object_new_object();
    3440             :         }
    3441             : 
    3442           0 :         memset(&wctx, 0, sizeof(wctx));
    3443           0 :         wctx.zevpn = zevpn;
    3444           0 :         wctx.vty = vty;
    3445           0 :         wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
    3446           0 :         wctx.r_vtep_ip = vtep_ip;
    3447           0 :         wctx.json = json_mac;
    3448           0 :         hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
    3449             : 
    3450           0 :         if (use_json) {
    3451           0 :                 json_object_int_add(json, "numMacs", wctx.count);
    3452           0 :                 if (wctx.count)
    3453           0 :                         json_object_object_add(json, "macs", json_mac);
    3454           0 :                 vty_json(vty, json);
    3455             :         }
    3456             : }
    3457             : 
    3458             : 
    3459             : /*
    3460             :  * Display VNI information (VTY command handler).
    3461             :  *
    3462             :  * use_json flag indicates that output should be in JSON format.
    3463             :  * json_array is non NULL when JSON output needs to be aggregated (by the
    3464             :  * caller) and then printed, otherwise, JSON evpn vni info is printed
    3465             :  * right away.
    3466             :  */
    3467           0 : void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
    3468             :                            bool use_json, json_object *json_array)
    3469             : {
    3470           0 :         json_object *json = NULL;
    3471           0 :         void *args[2];
    3472           0 :         struct zebra_l3vni *zl3vni = NULL;
    3473           0 :         struct zebra_evpn *zevpn = NULL;
    3474             : 
    3475           0 :         if (!is_evpn_enabled())
    3476           0 :                 return;
    3477             : 
    3478           0 :         if (use_json)
    3479           0 :                 json = json_object_new_object();
    3480             : 
    3481           0 :         args[0] = vty;
    3482           0 :         args[1] = json;
    3483             : 
    3484           0 :         zl3vni = zl3vni_lookup(vni);
    3485           0 :         if (zl3vni) {
    3486           0 :                 zl3vni_print(zl3vni, (void *)args);
    3487             :         } else {
    3488           0 :                 zevpn = zebra_evpn_lookup(vni);
    3489           0 :                 if (zevpn)
    3490           0 :                         zebra_evpn_print(zevpn, (void *)args);
    3491           0 :                 else if (!json)
    3492           0 :                         vty_out(vty, "%% VNI %u does not exist\n", vni);
    3493             :         }
    3494             : 
    3495           0 :         if (use_json) {
    3496             :                 /*
    3497             :                  * Each "json" object contains info about 1 VNI.
    3498             :                  * When "json_array" is non-null, we aggreggate the json output
    3499             :                  * into json_array and print it as a JSON array.
    3500             :                  */
    3501           0 :                 if (json_array)
    3502           0 :                         json_object_array_add(json_array, json);
    3503             :                 else
    3504           0 :                         vty_json(vty, json);
    3505             :         }
    3506             : }
    3507             : 
    3508             : /* Display all global details for EVPN */
    3509           0 : void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
    3510             : {
    3511           0 :         int num_l2vnis = 0;
    3512           0 :         int num_l3vnis = 0;
    3513           0 :         int num_vnis = 0;
    3514           0 :         json_object *json = NULL;
    3515           0 :         struct zebra_vrf *zvrf = NULL;
    3516             : 
    3517           0 :         if (!is_evpn_enabled())
    3518             :                 return;
    3519             : 
    3520           0 :         zvrf = zebra_vrf_get_evpn();
    3521             : 
    3522           0 :         num_l3vnis = hashcount(zrouter.l3vni_table);
    3523           0 :         num_l2vnis = hashcount(zvrf->evpn_table);
    3524           0 :         num_vnis = num_l2vnis + num_l3vnis;
    3525             : 
    3526           0 :         if (uj) {
    3527           0 :                 json = json_object_new_object();
    3528           0 :                 json_object_string_add(json, "advertiseGatewayMacip",
    3529           0 :                                        zvrf->advertise_gw_macip ? "Yes" : "No");
    3530           0 :                 json_object_string_add(json, "advertiseSviMacip",
    3531           0 :                                        zvrf->advertise_svi_macip ? "Yes"
    3532             :                                                                  : "No");
    3533           0 :                 json_object_string_add(json, "advertiseSviMac",
    3534             :                                        zebra_evpn_mh_do_adv_svi_mac() ? "Yes"
    3535             :                                                                       : "No");
    3536           0 :                 json_object_int_add(json, "numVnis", num_vnis);
    3537           0 :                 json_object_int_add(json, "numL2Vnis", num_l2vnis);
    3538           0 :                 json_object_int_add(json, "numL3Vnis", num_l3vnis);
    3539           0 :                 if (zebra_evpn_do_dup_addr_detect(zvrf))
    3540           0 :                         json_object_boolean_true_add(json,
    3541             :                                                 "isDuplicateAddrDetection");
    3542             :                 else
    3543           0 :                         json_object_boolean_false_add(json,
    3544             :                                                 "isDuplicateAddrDetection");
    3545           0 :                 json_object_int_add(json, "maxMoves", zvrf->dad_max_moves);
    3546           0 :                 json_object_int_add(json, "detectionTime", zvrf->dad_time);
    3547           0 :                 json_object_int_add(json, "detectionFreezeTime",
    3548           0 :                                     zvrf->dad_freeze_time);
    3549           0 :                 zebra_evpn_mh_json(json);
    3550             :         } else {
    3551           0 :                 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
    3552           0 :                 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
    3553           0 :                 vty_out(vty, "Advertise gateway mac-ip: %s\n",
    3554           0 :                         zvrf->advertise_gw_macip ? "Yes" : "No");
    3555           0 :                 vty_out(vty, "Advertise svi mac-ip: %s\n",
    3556           0 :                         zvrf->advertise_svi_macip ? "Yes" : "No");
    3557           0 :                 vty_out(vty, "Advertise svi mac: %s\n",
    3558             :                         zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
    3559           0 :                 vty_out(vty, "Duplicate address detection: %s\n",
    3560           0 :                         zebra_evpn_do_dup_addr_detect(zvrf) ? "Enable"
    3561             :                                                             : "Disable");
    3562           0 :                 vty_out(vty, "  Detection max-moves %u, time %d\n",
    3563             :                         zvrf->dad_max_moves, zvrf->dad_time);
    3564           0 :                 if (zvrf->dad_freeze) {
    3565           0 :                         if (zvrf->dad_freeze_time)
    3566           0 :                                 vty_out(vty, "  Detection freeze %u\n",
    3567             :                                         zvrf->dad_freeze_time);
    3568             :                         else
    3569           0 :                                 vty_out(vty, "  Detection freeze %s\n",
    3570             :                                         "permanent");
    3571             :                 }
    3572           0 :                 zebra_evpn_mh_print(vty);
    3573             :         }
    3574             : 
    3575           0 :         if (uj)
    3576           0 :                 vty_json(vty, json);
    3577             : }
    3578             : 
    3579             : /*
    3580             :  * Display VNI hash table (VTY command handler).
    3581             :  */
    3582           0 : void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
    3583             :                             bool use_json)
    3584             : {
    3585           0 :         json_object *json = NULL;
    3586           0 :         void *args[2];
    3587             : 
    3588           0 :         if (!is_evpn_enabled())
    3589           0 :                 return;
    3590             : 
    3591           0 :         if (use_json)
    3592           0 :                 json = json_object_new_object();
    3593             :         else
    3594           0 :                 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
    3595             :                         "Type", "VxLAN IF", "# MACs", "# ARPs",
    3596             :                         "# Remote VTEPs", "Tenant VRF");
    3597             : 
    3598           0 :         args[0] = vty;
    3599           0 :         args[1] = json;
    3600             : 
    3601             :         /* Display all L2-VNIs */
    3602           0 :         hash_iterate(
    3603             :                 zvrf->evpn_table,
    3604             :                 (void (*)(struct hash_bucket *, void *))zebra_evpn_print_hash,
    3605             :                 args);
    3606             : 
    3607             :         /* Display all L3-VNIs */
    3608           0 :         hash_iterate(zrouter.l3vni_table,
    3609             :                      (void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
    3610             :                      args);
    3611             : 
    3612           0 :         if (use_json)
    3613           0 :                 vty_json(vty, json);
    3614             : }
    3615             : 
    3616           0 : void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
    3617             : {
    3618           0 :         struct stream *s;
    3619           0 :         int time = 0;
    3620           0 :         uint32_t max_moves = 0;
    3621           0 :         uint32_t freeze_time = 0;
    3622           0 :         bool dup_addr_detect = false;
    3623           0 :         bool freeze = false;
    3624           0 :         bool old_addr_detect;
    3625             : 
    3626           0 :         s = msg;
    3627           0 :         STREAM_GETL(s, dup_addr_detect);
    3628           0 :         STREAM_GETL(s, time);
    3629           0 :         STREAM_GETL(s, max_moves);
    3630           0 :         STREAM_GETL(s, freeze);
    3631           0 :         STREAM_GETL(s, freeze_time);
    3632             : 
    3633           0 :         old_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
    3634           0 :         zvrf->dup_addr_detect = dup_addr_detect;
    3635           0 :         dup_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
    3636             : 
    3637             :         /* DAD previous state was enabled, and new state is disable,
    3638             :          * clear all duplicate detected addresses.
    3639             :          */
    3640           0 :         if (old_addr_detect && !dup_addr_detect)
    3641           0 :                 zebra_vxlan_clear_dup_detect_vni_all(zvrf);
    3642             : 
    3643           0 :         zvrf->dad_time = time;
    3644           0 :         zvrf->dad_max_moves = max_moves;
    3645           0 :         zvrf->dad_freeze = freeze;
    3646           0 :         zvrf->dad_freeze_time = freeze_time;
    3647             : 
    3648           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    3649           0 :                 zlog_debug(
    3650             :                         "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
    3651             :                         vrf_id_to_name(zvrf->vrf->vrf_id),
    3652             :                         dup_addr_detect ? "enable" : "disable",
    3653             :                         zvrf->dad_max_moves, zvrf->dad_time,
    3654             :                         zvrf->dad_freeze ? "enable" : "disable",
    3655             :                         zvrf->dad_freeze_time);
    3656             : 
    3657           0 : stream_failure:
    3658           0 :         return;
    3659             : }
    3660             : 
    3661             : /*
    3662             :  * Display VNI hash table in detail(VTY command handler).
    3663             :  */
    3664           0 : void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
    3665             :                                    bool use_json)
    3666             : {
    3667           0 :         json_object *json_array = NULL;
    3668           0 :         struct zebra_ns *zns = NULL;
    3669           0 :         struct zebra_evpn_show zes;
    3670             : 
    3671           0 :         if (!is_evpn_enabled())
    3672           0 :                 return;
    3673             : 
    3674           0 :         zns = zebra_ns_lookup(NS_DEFAULT);
    3675           0 :         if (!zns)
    3676             :                 return;
    3677             : 
    3678           0 :         if (use_json)
    3679           0 :                 json_array = json_object_new_array();
    3680             : 
    3681           0 :         zes.vty = vty;
    3682           0 :         zes.json = json_array;
    3683           0 :         zes.zvrf = zvrf;
    3684           0 :         zes.use_json = use_json;
    3685             : 
    3686             :         /* Display all L2-VNIs */
    3687           0 :         hash_iterate(zvrf->evpn_table,
    3688             :                      (void (*)(struct hash_bucket *,
    3689             :                                void *))zebra_evpn_print_hash_detail,
    3690             :                      &zes);
    3691             : 
    3692             :         /* Display all L3-VNIs */
    3693           0 :         hash_iterate(zrouter.l3vni_table,
    3694             :                      (void (*)(struct hash_bucket *,
    3695             :                                void *))zl3vni_print_hash_detail,
    3696             :                      &zes);
    3697             : 
    3698           0 :         if (use_json)
    3699           0 :                 vty_json(vty, json_array);
    3700             : }
    3701             : 
    3702             : /*
    3703             :  * Handle neighbor delete notification from the kernel (on a VLAN device
    3704             :  * / L3 interface). This may result in either the neighbor getting deleted
    3705             :  * from our database or being re-added to the kernel (if it is a valid
    3706             :  * remote neighbor).
    3707             :  */
    3708           0 : int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
    3709             :                                         struct interface *link_if,
    3710             :                                         struct ipaddr *ip)
    3711             : {
    3712           0 :         struct zebra_evpn *zevpn = NULL;
    3713           0 :         struct zebra_l3vni *zl3vni = NULL;
    3714             : 
    3715             :         /* check if this is a remote neigh entry corresponding to remote
    3716             :          * next-hop
    3717             :          */
    3718           0 :         zl3vni = zl3vni_from_svi(ifp, link_if);
    3719           0 :         if (zl3vni)
    3720           0 :                 return zl3vni_local_nh_del(zl3vni, ip);
    3721             : 
    3722             :         /* We are only interested in neighbors on an SVI that resides on top
    3723             :          * of a VxLAN bridge.
    3724             :          */
    3725           0 :         zevpn = zebra_evpn_from_svi(ifp, link_if);
    3726           0 :         if (!zevpn) {
    3727           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    3728           0 :                         zlog_debug(
    3729             :                                 "%s: Del neighbor %pIA EVPN is not present for interface %s",
    3730             :                                 __func__, ip, ifp->name);
    3731           0 :                 return 0;
    3732             :         }
    3733             : 
    3734           0 :         if (!zevpn->vxlan_if) {
    3735           0 :                 zlog_debug(
    3736             :                         "VNI %u hash %p doesn't have intf upon local neighbor DEL",
    3737             :                         zevpn->vni, zevpn);
    3738           0 :                 return -1;
    3739             :         }
    3740             : 
    3741           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    3742           0 :                 zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
    3743             :                            ip, ifp->name, ifp->ifindex, zevpn->vni);
    3744             : 
    3745           0 :         return zebra_evpn_neigh_del_ip(zevpn, ip);
    3746             : }
    3747             : 
    3748             : /*
    3749             :  * Handle neighbor add or update notification from the kernel (on a VLAN
    3750             :  * device / L3 interface). This is typically for a local neighbor but can
    3751             :  * also be for a remote neighbor (e.g., ageout notification). It could
    3752             :  * also be a "move" scenario.
    3753             :  */
    3754           0 : int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
    3755             :                                            struct interface *link_if,
    3756             :                                            struct ipaddr *ip,
    3757             :                                            struct ethaddr *macaddr,
    3758             :                                            uint16_t state,
    3759             :                                            bool is_ext,
    3760             :                                            bool is_router,
    3761             :                                            bool local_inactive, bool dp_static)
    3762             : {
    3763           0 :         struct zebra_evpn *zevpn = NULL;
    3764           0 :         struct zebra_l3vni *zl3vni = NULL;
    3765             : 
    3766             :         /* check if this is a remote neigh entry corresponding to remote
    3767             :          * next-hop
    3768             :          */
    3769           0 :         zl3vni = zl3vni_from_svi(ifp, link_if);
    3770           0 :         if (zl3vni)
    3771           0 :                 return zl3vni_local_nh_add_update(zl3vni, ip, state);
    3772             : 
    3773             :         /* We are only interested in neighbors on an SVI that resides on top
    3774             :          * of a VxLAN bridge.
    3775             :          */
    3776           0 :         zevpn = zebra_evpn_from_svi(ifp, link_if);
    3777           0 :         if (!zevpn)
    3778             :                 return 0;
    3779             : 
    3780           0 :         if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
    3781           0 :                 zlog_debug(
    3782             :                         "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
    3783             :                         ip, macaddr, ifp->name,
    3784             :                         ifp->ifindex, state, is_ext ? "ext-learned " : "",
    3785             :                         is_router ? "router " : "",
    3786             :                         local_inactive ? "local_inactive " : "",
    3787             :                         dp_static ? "peer_sync " : "", zevpn->vni);
    3788             : 
    3789             :         /* Is this about a local neighbor or a remote one? */
    3790           0 :         if (!is_ext)
    3791           0 :                 return zebra_evpn_local_neigh_update(zevpn, ifp, ip, macaddr,
    3792             :                                                      is_router, local_inactive,
    3793             :                                                      dp_static);
    3794             : 
    3795           0 :         return zebra_evpn_remote_neigh_update(zevpn, ifp, ip, macaddr, state);
    3796             : }
    3797             : 
    3798             : static int32_t
    3799           0 : zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni,
    3800             :                                 struct ethaddr *macaddr, uint16_t *ipa_len,
    3801             :                                 struct ipaddr *ip, struct in_addr *vtep_ip,
    3802             :                                 uint8_t *flags, uint32_t *seq, esi_t *esi)
    3803             : {
    3804           0 :         uint16_t l = 0;
    3805             : 
    3806             :         /*
    3807             :          * Obtain each remote MACIP and process.
    3808             :          * Message contains VNI, followed by MAC followed by IP (if any)
    3809             :          * followed by remote VTEP IP.
    3810             :          */
    3811           0 :         memset(ip, 0, sizeof(*ip));
    3812           0 :         STREAM_GETL(s, *vni);
    3813           0 :         STREAM_GET(macaddr->octet, s, ETH_ALEN);
    3814           0 :         STREAM_GETW(s, *ipa_len);
    3815             : 
    3816           0 :         if (*ipa_len) {
    3817           0 :                 if (*ipa_len == IPV4_MAX_BYTELEN)
    3818           0 :                         ip->ipa_type = IPADDR_V4;
    3819           0 :                 else if (*ipa_len == IPV6_MAX_BYTELEN)
    3820           0 :                         ip->ipa_type = IPADDR_V6;
    3821             :                 else {
    3822           0 :                         if (IS_ZEBRA_DEBUG_VXLAN)
    3823           0 :                                 zlog_debug(
    3824             :                                         "ipa_len *must* be %d or %d bytes in length not %d",
    3825             :                                         IPV4_MAX_BYTELEN, IPV6_MAX_BYTELEN,
    3826             :                                         *ipa_len);
    3827           0 :                         goto stream_failure;
    3828             :                 }
    3829             : 
    3830           0 :                 STREAM_GET(&ip->ip.addr, s, *ipa_len);
    3831             :         }
    3832           0 :         l += 4 + ETH_ALEN + 4 + *ipa_len;
    3833           0 :         STREAM_GET(&vtep_ip->s_addr, s, IPV4_MAX_BYTELEN);
    3834           0 :         l += IPV4_MAX_BYTELEN;
    3835             : 
    3836           0 :         if (add) {
    3837           0 :                 STREAM_GETC(s, *flags);
    3838           0 :                 STREAM_GETL(s, *seq);
    3839           0 :                 l += 5;
    3840           0 :                 STREAM_GET(esi, s, sizeof(esi_t));
    3841           0 :                 l += sizeof(esi_t);
    3842             :         }
    3843             : 
    3844           0 :         return l;
    3845             : 
    3846             : stream_failure:
    3847             :         return -1;
    3848             : }
    3849             : 
    3850             : /*
    3851             :  * Handle message from client to delete a remote MACIP for a VNI.
    3852             :  */
    3853           0 : void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
    3854             : {
    3855           0 :         struct stream *s;
    3856           0 :         vni_t vni;
    3857           0 :         struct ethaddr macaddr;
    3858           0 :         struct ipaddr ip;
    3859           0 :         struct in_addr vtep_ip;
    3860           0 :         uint16_t l = 0, ipa_len;
    3861           0 :         char buf1[INET6_ADDRSTRLEN];
    3862             : 
    3863           0 :         s = msg;
    3864             : 
    3865           0 :         while (l < hdr->length) {
    3866           0 :                 int res_length = zebra_vxlan_remote_macip_helper(
    3867             :                         false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL,
    3868             :                         NULL, NULL);
    3869             : 
    3870           0 :                 if (res_length == -1)
    3871           0 :                         goto stream_failure;
    3872             : 
    3873           0 :                 l += res_length;
    3874           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    3875           0 :                         zlog_debug(
    3876             :                                 "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
    3877             :                                 vni, &macaddr,
    3878             :                                 ipa_len ? " IP " : "",
    3879             :                                 ipa_len ?
    3880             :                                 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
    3881             :                                 &vtep_ip, zebra_route_string(client->proto));
    3882             : 
    3883             :                 /* Enqueue to workqueue for processing */
    3884           0 :                 zebra_rib_queue_evpn_rem_macip_del(vni, &macaddr, &ip, vtep_ip);
    3885             :         }
    3886             : 
    3887           0 : stream_failure:
    3888           0 :         return;
    3889             : }
    3890             : 
    3891             : /*
    3892             :  * Handle message from client to add a remote MACIP for a VNI. This
    3893             :  * could be just the add of a MAC address or the add of a neighbor
    3894             :  * (IP+MAC).
    3895             :  */
    3896           0 : void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
    3897             : {
    3898           0 :         struct stream *s;
    3899           0 :         vni_t vni;
    3900           0 :         struct ethaddr macaddr;
    3901           0 :         struct ipaddr ip;
    3902           0 :         struct in_addr vtep_ip;
    3903           0 :         uint16_t l = 0, ipa_len;
    3904           0 :         uint8_t flags = 0;
    3905           0 :         uint32_t seq;
    3906           0 :         char buf1[INET6_ADDRSTRLEN];
    3907           0 :         esi_t esi;
    3908           0 :         char esi_buf[ESI_STR_LEN];
    3909             : 
    3910           0 :         if (!EVPN_ENABLED(zvrf)) {
    3911           0 :                 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
    3912           0 :                 return;
    3913             :         }
    3914             : 
    3915             :         s = msg;
    3916             : 
    3917           0 :         while (l < hdr->length) {
    3918             : 
    3919           0 :                 int res_length = zebra_vxlan_remote_macip_helper(
    3920             :                         true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip,
    3921             :                         &flags, &seq, &esi);
    3922             : 
    3923           0 :                 if (res_length == -1)
    3924           0 :                         goto stream_failure;
    3925             : 
    3926           0 :                 l += res_length;
    3927           0 :                 if (IS_ZEBRA_DEBUG_VXLAN) {
    3928           0 :                         if (memcmp(&esi, zero_esi, sizeof(esi_t)))
    3929           0 :                                 esi_to_str(&esi, esi_buf, sizeof(esi_buf));
    3930             :                         else
    3931           0 :                                 strlcpy(esi_buf, "-", ESI_STR_LEN);
    3932           0 :                         zlog_debug(
    3933             :                                 "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
    3934             :                                 (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ?
    3935             :                                 "sync-" : "",
    3936             :                                 vni, &macaddr,
    3937             :                                 ipa_len ? " IP " : "",
    3938             :                                 ipa_len ?
    3939             :                                 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
    3940             :                                 flags, seq, &vtep_ip, esi_buf,
    3941             :                                 zebra_route_string(client->proto));
    3942             :                 }
    3943             : 
    3944             :                 /* Enqueue to workqueue for processing */
    3945           0 :                 zebra_rib_queue_evpn_rem_macip_add(vni, &macaddr, &ip, flags,
    3946             :                                                    seq, vtep_ip, &esi);
    3947             :         }
    3948             : 
    3949           0 : stream_failure:
    3950             :         return;
    3951             : }
    3952             : 
    3953             : /*
    3954             :  * Handle remote vtep delete by kernel; re-add the vtep if we have it
    3955             :  */
    3956           0 : int zebra_vxlan_check_readd_vtep(struct interface *ifp,
    3957             :                                  struct in_addr vtep_ip)
    3958             : {
    3959           0 :         struct zebra_if *zif;
    3960           0 :         struct zebra_vrf *zvrf = NULL;
    3961           0 :         struct zebra_l2info_vxlan *vxl;
    3962           0 :         vni_t vni;
    3963           0 :         struct zebra_evpn *zevpn = NULL;
    3964           0 :         struct zebra_vtep *zvtep = NULL;
    3965             : 
    3966           0 :         zif = ifp->info;
    3967           0 :         assert(zif);
    3968           0 :         vxl = &zif->l2info.vxl;
    3969           0 :         vni = vxl->vni;
    3970             : 
    3971             :         /* If EVPN is not enabled, nothing to do. */
    3972           0 :         if (!is_evpn_enabled())
    3973             :                 return 0;
    3974             : 
    3975             :         /* Locate VRF corresponding to interface. */
    3976           0 :         zvrf = ifp->vrf->info;
    3977           0 :         if (!zvrf)
    3978             :                 return -1;
    3979             : 
    3980             :         /* Locate hash entry; it is expected to exist. */
    3981           0 :         zevpn = zebra_evpn_lookup(vni);
    3982           0 :         if (!zevpn)
    3983             :                 return 0;
    3984             : 
    3985             :         /* If the remote vtep entry doesn't exists nothing to do */
    3986           0 :         zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
    3987           0 :         if (!zvtep)
    3988             :                 return 0;
    3989             : 
    3990           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    3991           0 :                 zlog_debug(
    3992             :                         "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
    3993             :                         &vtep_ip, ifp->name, ifp->ifindex, vni);
    3994             : 
    3995           0 :         zebra_evpn_vtep_install(zevpn, zvtep);
    3996           0 :         return 0;
    3997             : }
    3998             : 
    3999             : /*
    4000             :  * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
    4001             :  * us, this must involve a multihoming scenario. Treat this as implicit delete
    4002             :  * of any prior local MAC.
    4003             :  */
    4004           0 : static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
    4005             :                                            struct interface *br_if,
    4006             :                                            struct ethaddr *macaddr,
    4007             :                                            vlanid_t vid)
    4008             : {
    4009           0 :         struct zebra_if *zif;
    4010           0 :         struct zebra_l2info_vxlan *vxl;
    4011           0 :         vni_t vni;
    4012           0 :         struct zebra_evpn *zevpn;
    4013           0 :         struct zebra_mac *mac;
    4014             : 
    4015           0 :         zif = ifp->info;
    4016           0 :         assert(zif);
    4017           0 :         vxl = &zif->l2info.vxl;
    4018           0 :         vni = vxl->vni;
    4019             : 
    4020             :         /* Check if EVPN is enabled. */
    4021           0 :         if (!is_evpn_enabled())
    4022             :                 return 0;
    4023             : 
    4024             :         /* Locate hash entry; it is expected to exist. */
    4025           0 :         zevpn = zebra_evpn_lookup(vni);
    4026           0 :         if (!zevpn)
    4027             :                 return 0;
    4028             : 
    4029             :         /* If entry doesn't exist, nothing to do. */
    4030           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    4031           0 :         if (!mac)
    4032             :                 return 0;
    4033             : 
    4034             :         /* Is it a local entry? */
    4035           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
    4036             :                 return 0;
    4037             : 
    4038           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    4039           0 :                 zlog_debug(
    4040             :                         "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
    4041             :                         macaddr, ifp->name, ifp->ifindex, vni, mac->flags);
    4042             : 
    4043             :         /* Remove MAC from BGP. */
    4044           0 :         zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
    4045             :                                           false /* force */);
    4046             : 
    4047             :         /*
    4048             :          * If there are no neigh associated with the mac delete the mac
    4049             :          * else mark it as AUTO for forward reference
    4050             :          */
    4051           0 :         if (!listcount(mac->neigh_list)) {
    4052           0 :                 zebra_evpn_mac_del(zevpn, mac);
    4053             :         } else {
    4054           0 :                 zebra_evpn_mac_clear_fwd_info(mac);
    4055           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
    4056           0 :                 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
    4057           0 :                 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
    4058             :         }
    4059             : 
    4060             :         return 0;
    4061             : }
    4062             : 
    4063             : /* MAC notification from the dataplane with a network dest port -
    4064             :  * 1. This can be a local MAC on a down ES (if fast-failover is not possible
    4065             :  * 2. Or it can be a remote MAC
    4066             :  */
    4067           0 : int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
    4068             :                                    struct interface *br_if,
    4069             :                                    struct ethaddr *macaddr, vlanid_t vid,
    4070             :                                    uint32_t nhg_id, bool sticky, bool dp_static)
    4071             : {
    4072           0 :         struct zebra_evpn_es *es;
    4073           0 :         struct interface *acc_ifp;
    4074             : 
    4075             :         /* If netlink message is with vid, it will have no nexthop.
    4076             :          * So skip it.
    4077             :          */
    4078           0 :         if (vid) {
    4079           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    4080           0 :                         zlog_debug("dpAdd MAC %pEA VID %u - ignore as no nhid",
    4081             :                                    macaddr, vid);
    4082           0 :                 return 0;
    4083             :         }
    4084             : 
    4085             :         /* Get vxlan's vid for netlink message has no it. */
    4086           0 :         vid = ((struct zebra_if *)ifp->info)->l2info.vxl.access_vlan;
    4087             : 
    4088             :         /* if remote mac delete the local entry */
    4089           0 :         if (!nhg_id || !zebra_evpn_nhg_is_local_es(nhg_id, &es)
    4090           0 :             || !zebra_evpn_es_local_mac_via_network_port(es)) {
    4091           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    4092           0 :                         zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr,
    4093             :                                    vid);
    4094           0 :                 return zebra_vxlan_check_del_local_mac(ifp, br_if, macaddr,
    4095             :                                                        vid);
    4096             :         }
    4097             : 
    4098             :         /* If local MAC on a down local ES translate the network-mac-add
    4099             :          * to a local-active-mac-add
    4100             :          */
    4101           0 :         if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    4102           0 :                 zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr, vid);
    4103           0 :         acc_ifp = es->zif->ifp;
    4104           0 :         return zebra_vxlan_local_mac_add_update(
    4105             :                 acc_ifp, br_if, macaddr, vid, sticky,
    4106             :                 false /* local_inactive */, dp_static);
    4107             : }
    4108             : 
    4109             : /*
    4110             :  * Handle network MAC delete by kernel -
    4111             :  * 1. readd the remote MAC if we have it
    4112             :  * 2. local MAC with does ES may also need to be re-installed
    4113             :  */
    4114           0 : int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
    4115             :                                    struct interface *br_if,
    4116             :                                    struct ethaddr *macaddr, vlanid_t vid)
    4117             : {
    4118           0 :         struct zebra_if *zif = NULL;
    4119           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    4120           0 :         vni_t vni;
    4121           0 :         struct zebra_evpn *zevpn = NULL;
    4122           0 :         struct zebra_l3vni *zl3vni = NULL;
    4123           0 :         struct zebra_mac *mac = NULL;
    4124             : 
    4125           0 :         zif = ifp->info;
    4126           0 :         assert(zif);
    4127           0 :         vxl = &zif->l2info.vxl;
    4128           0 :         vni = vxl->vni;
    4129             : 
    4130             :         /* Check if EVPN is enabled. */
    4131           0 :         if (!is_evpn_enabled())
    4132             :                 return 0;
    4133             : 
    4134             :         /* check if this is a remote RMAC and readd simillar to remote macs */
    4135           0 :         zl3vni = zl3vni_lookup(vni);
    4136           0 :         if (zl3vni)
    4137           0 :                 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
    4138             : 
    4139             :         /* Locate hash entry; it is expected to exist. */
    4140           0 :         zevpn = zebra_evpn_lookup(vni);
    4141           0 :         if (!zevpn)
    4142             :                 return 0;
    4143             : 
    4144             :         /* If entry doesn't exist, nothing to do. */
    4145           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    4146           0 :         if (!mac)
    4147             :                 return 0;
    4148             : 
    4149           0 :         if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
    4150             :                 /* If remote entry simply re-install */
    4151           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    4152           0 :                         zlog_debug(
    4153             :                                 "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
    4154             :                                 macaddr, ifp->name, ifp->ifindex, vni);
    4155           0 :                 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
    4156           0 :         } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && mac->es
    4157           0 :                    && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
    4158             :                 /* If local entry via nw-port call local-del which will
    4159             :                  * re-install entry in the dataplane is needed
    4160             :                  */
    4161           0 :                 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
    4162           0 :                         zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr,
    4163             :                                    vni);
    4164             : 
    4165           0 :                 zebra_evpn_del_local_mac(zevpn, mac, false);
    4166             :         }
    4167             : 
    4168             :         return 0;
    4169             : }
    4170             : 
    4171             : /*
    4172             :  * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
    4173             :  */
    4174           0 : int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
    4175             :                               struct ethaddr *macaddr, vlanid_t vid)
    4176             : {
    4177           0 :         struct zebra_evpn *zevpn;
    4178           0 :         struct zebra_mac *mac;
    4179             : 
    4180             :         /* We are interested in MACs only on ports or (port, VLAN) that
    4181             :          * map to a VNI.
    4182             :          */
    4183           0 :         zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
    4184           0 :         if (!zevpn)
    4185             :                 return 0;
    4186           0 :         if (!zevpn->vxlan_if) {
    4187           0 :                 zlog_debug(
    4188             :                         "VNI %u hash %p doesn't have intf upon local MAC DEL",
    4189             :                         zevpn->vni, zevpn);
    4190           0 :                 return -1;
    4191             :         }
    4192             : 
    4193             :         /* If entry doesn't exist, nothing to do. */
    4194           0 :         mac = zebra_evpn_mac_lookup(zevpn, macaddr);
    4195           0 :         if (!mac)
    4196             :                 return 0;
    4197             : 
    4198             :         /* Is it a local entry? */
    4199           0 :         if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
    4200             :                 return 0;
    4201             : 
    4202           0 :         return zebra_evpn_del_local_mac(zevpn, mac, false);
    4203             : }
    4204             : 
    4205             : /*
    4206             :  * Handle local MAC add (on a port or VLAN corresponding to this VNI).
    4207             :  */
    4208           0 : int zebra_vxlan_local_mac_add_update(struct interface *ifp,
    4209             :                                      struct interface *br_if,
    4210             :                                      struct ethaddr *macaddr, vlanid_t vid,
    4211             :                                          bool sticky, bool local_inactive,
    4212             :                                          bool dp_static)
    4213             : {
    4214           0 :         struct zebra_evpn *zevpn;
    4215           0 :         struct zebra_vrf *zvrf;
    4216             : 
    4217           0 :         assert(ifp);
    4218             : 
    4219             :         /* We are interested in MACs only on ports or (port, VLAN) that
    4220             :          * map to an EVPN.
    4221             :          */
    4222           0 :         zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
    4223           0 :         if (!zevpn) {
    4224           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4225           0 :                         zlog_debug(
    4226             :                                 "        Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
    4227             :                                 sticky ? "sticky " : "", macaddr,
    4228             :                                 ifp->name, ifp->ifindex, vid);
    4229           0 :                 return 0;
    4230             :         }
    4231             : 
    4232           0 :         if (!zevpn->vxlan_if) {
    4233           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4234           0 :                         zlog_debug(
    4235             :                                 "        VNI %u hash %p doesn't have intf upon local MAC ADD",
    4236             :                                 zevpn->vni, zevpn);
    4237           0 :                 return -1;
    4238             :         }
    4239             : 
    4240           0 :         zvrf = zebra_vrf_get_evpn();
    4241           0 :         return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid,
    4242             :                                                sticky, local_inactive,
    4243             :                                                dp_static, NULL);
    4244             : }
    4245             : 
    4246             : /*
    4247             :  * Handle message from client to delete a remote VTEP for an EVPN.
    4248             :  */
    4249           0 : void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS)
    4250             : {
    4251           0 :         struct stream *s;
    4252           0 :         unsigned short l = 0;
    4253           0 :         vni_t vni;
    4254           0 :         struct in_addr vtep_ip;
    4255             : 
    4256           0 :         if (!is_evpn_enabled()) {
    4257           0 :                 zlog_debug(
    4258             :                         "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
    4259             :                         __func__);
    4260           0 :                 return;
    4261             :         }
    4262             : 
    4263           0 :         if (!EVPN_ENABLED(zvrf)) {
    4264           0 :                 zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
    4265             :                            zvrf_id(zvrf));
    4266           0 :                 return;
    4267             :         }
    4268             : 
    4269             :         s = msg;
    4270             : 
    4271           0 :         while (l < hdr->length) {
    4272           0 :                 int flood_control __attribute__((unused));
    4273             : 
    4274             :                 /* Obtain each remote VTEP and process. */
    4275           0 :                 STREAM_GETL(s, vni);
    4276           0 :                 l += 4;
    4277           0 :                 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
    4278           0 :                 l += IPV4_MAX_BYTELEN;
    4279             : 
    4280             :                 /* Flood control is intentionally ignored right now */
    4281           0 :                 STREAM_GETL(s, flood_control);
    4282           0 :                 l += 4;
    4283             : 
    4284           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4285           0 :                         zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
    4286             :                                    &vtep_ip, vni,
    4287             :                                    zebra_route_string(client->proto));
    4288             : 
    4289             :                 /* Enqueue for processing */
    4290           0 :                 zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf), vni, vtep_ip);
    4291             :         }
    4292             : 
    4293           0 : stream_failure:
    4294             :         return;
    4295             : }
    4296             : 
    4297             : /*
    4298             :  * Handle message from client to delete a remote VTEP for an EVPN.
    4299             :  */
    4300           0 : void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
    4301             :                                  struct in_addr vtep_ip)
    4302             : {
    4303           0 :         struct zebra_evpn *zevpn;
    4304           0 :         struct zebra_vtep *zvtep;
    4305           0 :         struct interface *ifp;
    4306           0 :         struct zebra_if *zif;
    4307           0 :         struct zebra_vrf *zvrf;
    4308             : 
    4309           0 :         if (!is_evpn_enabled()) {
    4310           0 :                 zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
    4311             :                            __func__);
    4312           0 :                 return;
    4313             :         }
    4314             : 
    4315           0 :         zvrf = zebra_vrf_lookup_by_id(vrf_id);
    4316           0 :         if (!zvrf)
    4317             :                 return;
    4318             : 
    4319           0 :         if (!EVPN_ENABLED(zvrf)) {
    4320           0 :                 zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
    4321             :                            zvrf_id(zvrf));
    4322           0 :                 return;
    4323             :         }
    4324             : 
    4325             :         /* Locate VNI hash entry - expected to exist. */
    4326           0 :         zevpn = zebra_evpn_lookup(vni);
    4327           0 :         if (!zevpn) {
    4328           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4329           0 :                         zlog_debug(
    4330             :                                 "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
    4331             :                                 vni);
    4332           0 :                 return;
    4333             :         }
    4334             : 
    4335           0 :         ifp = zevpn->vxlan_if;
    4336           0 :         if (!ifp) {
    4337           0 :                 zlog_debug(
    4338             :                         "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
    4339             :                         zevpn->vni, zevpn);
    4340           0 :                 return;
    4341             :         }
    4342           0 :         zif = ifp->info;
    4343             : 
    4344             :         /* If down or not mapped to a bridge, we're done. */
    4345           0 :         if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    4346             :                 return;
    4347             : 
    4348             :         /* If the remote VTEP does not exist, there's nothing more to
    4349             :          * do.
    4350             :          * Otherwise, uninstall any remote MACs pointing to this VTEP
    4351             :          * and then, the VTEP entry itself and remove it.
    4352             :          */
    4353           0 :         zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
    4354           0 :         if (!zvtep)
    4355             :                 return;
    4356             : 
    4357           0 :         zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
    4358           0 :         zebra_evpn_vtep_del(zevpn, zvtep);
    4359             : }
    4360             : 
    4361             : /*
    4362             :  * Handle message from client to add a remote VTEP for an EVPN.
    4363             :  */
    4364           0 : void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
    4365             :                                  struct in_addr vtep_ip, int flood_control)
    4366             : {
    4367           0 :         struct zebra_evpn *zevpn;
    4368           0 :         struct interface *ifp;
    4369           0 :         struct zebra_if *zif;
    4370           0 :         struct zebra_vtep *zvtep;
    4371           0 :         struct zebra_vrf *zvrf;
    4372             : 
    4373           0 :         if (!is_evpn_enabled()) {
    4374           0 :                 zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
    4375             :                            __func__);
    4376           0 :                 return;
    4377             :         }
    4378             : 
    4379           0 :         zvrf = zebra_vrf_lookup_by_id(vrf_id);
    4380           0 :         if (!zvrf)
    4381             :                 return;
    4382             : 
    4383           0 :         if (!EVPN_ENABLED(zvrf)) {
    4384           0 :                 zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
    4385             :                            zvrf_id(zvrf));
    4386           0 :                 return;
    4387             :         }
    4388             : 
    4389             :         /* Locate VNI hash entry - expected to exist. */
    4390           0 :         zevpn = zebra_evpn_lookup(vni);
    4391           0 :         if (!zevpn) {
    4392           0 :                 flog_err(
    4393             :                         EC_ZEBRA_VTEP_ADD_FAILED,
    4394             :                         "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
    4395             :                         vni);
    4396           0 :                 return;
    4397             :         }
    4398             : 
    4399           0 :         ifp = zevpn->vxlan_if;
    4400           0 :         if (!ifp) {
    4401           0 :                 flog_err(
    4402             :                         EC_ZEBRA_VTEP_ADD_FAILED,
    4403             :                         "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
    4404             :                         zevpn->vni, zevpn);
    4405           0 :                 return;
    4406             :         }
    4407             : 
    4408           0 :         zif = ifp->info;
    4409             : 
    4410             :         /* If down or not mapped to a bridge, we're done. */
    4411           0 :         if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    4412             :                 return;
    4413             : 
    4414           0 :         zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
    4415           0 :         if (zvtep) {
    4416             :                 /* If the remote VTEP already exists check if
    4417             :                  * the flood mode has changed
    4418             :                  */
    4419           0 :                 if (zvtep->flood_control != flood_control) {
    4420           0 :                         if (zvtep->flood_control == VXLAN_FLOOD_DISABLED)
    4421             :                                 /* old mode was head-end-replication but
    4422             :                                  * is no longer; get rid of the HER fdb
    4423             :                                  * entry installed before
    4424             :                                  */
    4425           0 :                                 zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
    4426           0 :                         zvtep->flood_control = flood_control;
    4427           0 :                         zebra_evpn_vtep_install(zevpn, zvtep);
    4428             :                 }
    4429             :         } else {
    4430           0 :                 zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, flood_control);
    4431           0 :                 if (zvtep)
    4432           0 :                         zebra_evpn_vtep_install(zevpn, zvtep);
    4433             :                 else
    4434           0 :                         flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
    4435             :                                  "Failed to add remote VTEP, VNI %u zevpn %p",
    4436             :                                  vni, zevpn);
    4437             :         }
    4438             : }
    4439             : 
    4440             : /*
    4441             :  * Handle message from client to add a remote VTEP for an EVPN.
    4442             :  */
    4443           0 : void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS)
    4444             : {
    4445           0 :         struct stream *s;
    4446           0 :         unsigned short l = 0;
    4447           0 :         vni_t vni;
    4448           0 :         struct in_addr vtep_ip;
    4449           0 :         int flood_control;
    4450             : 
    4451           0 :         if (!is_evpn_enabled()) {
    4452           0 :                 zlog_debug(
    4453             :                         "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
    4454             :                         __func__);
    4455           0 :                 return;
    4456             :         }
    4457             : 
    4458           0 :         if (!EVPN_ENABLED(zvrf)) {
    4459           0 :                 zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
    4460             :                            zvrf_id(zvrf));
    4461           0 :                 return;
    4462             :         }
    4463             : 
    4464             :         s = msg;
    4465             : 
    4466           0 :         while (l < hdr->length) {
    4467             :                 /* Obtain each remote VTEP and process. */
    4468           0 :                 STREAM_GETL(s, vni);
    4469           0 :                 l += 4;
    4470           0 :                 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
    4471           0 :                 STREAM_GETL(s, flood_control);
    4472           0 :                 l += IPV4_MAX_BYTELEN + 4;
    4473             : 
    4474           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4475           0 :                         zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
    4476             :                                    &vtep_ip, vni, flood_control,
    4477             :                                    zebra_route_string(client->proto));
    4478             : 
    4479             :                 /* Enqueue for processing */
    4480           0 :                 zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf), vni, vtep_ip,
    4481             :                                                   flood_control);
    4482             :         }
    4483             : 
    4484           0 : stream_failure:
    4485             :         return;
    4486             : }
    4487             : 
    4488             : /*
    4489             :  * Add/Del gateway macip to evpn
    4490             :  * g/w can be:
    4491             :  *  1. SVI interface on a vlan aware bridge
    4492             :  *  2. SVI interface on a vlan unaware bridge
    4493             :  *  3. vrr interface (MACVLAN) associated to a SVI
    4494             :  * We advertise macip routes for an interface if it is associated to VxLan vlan
    4495             :  */
    4496          36 : int zebra_vxlan_add_del_gw_macip(struct interface *ifp, const struct prefix *p,
    4497             :                                  int add)
    4498             : {
    4499          36 :         struct ipaddr ip;
    4500          36 :         struct ethaddr macaddr;
    4501          36 :         struct zebra_evpn *zevpn = NULL;
    4502             : 
    4503          36 :         memset(&ip, 0, sizeof(ip));
    4504          36 :         memset(&macaddr, 0, sizeof(macaddr));
    4505             : 
    4506             :         /* Check if EVPN is enabled. */
    4507          36 :         if (!is_evpn_enabled())
    4508             :                 return 0;
    4509             : 
    4510           0 :         if (IS_ZEBRA_IF_MACVLAN(ifp)) {
    4511           0 :                 struct interface *svi_if =
    4512             :                         NULL; /* SVI corresponding to the MACVLAN */
    4513           0 :                 struct zebra_if *ifp_zif =
    4514             :                         NULL; /* Zebra daemon specific info for MACVLAN */
    4515           0 :                 struct zebra_if *svi_if_zif =
    4516             :                         NULL; /* Zebra daemon specific info for SVI*/
    4517             : 
    4518           0 :                 ifp_zif = ifp->info;
    4519           0 :                 if (!ifp_zif)
    4520             :                         return -1;
    4521             : 
    4522             :                 /*
    4523             :                  * for a MACVLAN interface the link represents the svi_if
    4524             :                  */
    4525           0 :                 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
    4526           0 :                                                    ifp_zif->link_ifindex);
    4527           0 :                 if (!svi_if) {
    4528           0 :                         zlog_debug("MACVLAN %s(%u) without link information",
    4529             :                                    ifp->name, ifp->ifindex);
    4530           0 :                         return -1;
    4531             :                 }
    4532             : 
    4533           0 :                 if (IS_ZEBRA_IF_VLAN(svi_if)) {
    4534             :                         /*
    4535             :                          * If it is a vlan aware bridge then the link gives the
    4536             :                          * bridge information
    4537             :                          */
    4538           0 :                         struct interface *svi_if_link = NULL;
    4539             : 
    4540           0 :                         svi_if_zif = svi_if->info;
    4541           0 :                         if (svi_if_zif) {
    4542           0 :                                 svi_if_link = if_lookup_by_index_per_ns(
    4543             :                                         zebra_ns_lookup(NS_DEFAULT),
    4544           0 :                                         svi_if_zif->link_ifindex);
    4545           0 :                                 zevpn = zebra_evpn_from_svi(svi_if,
    4546             :                                                             svi_if_link);
    4547             :                         }
    4548           0 :                 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
    4549             :                         /*
    4550             :                          * If it is a vlan unaware bridge then svi is the bridge
    4551             :                          * itself
    4552             :                          */
    4553           0 :                         zevpn = zebra_evpn_from_svi(svi_if, svi_if);
    4554             :                 }
    4555           0 :         } else if (IS_ZEBRA_IF_VLAN(ifp)) {
    4556           0 :                 struct zebra_if *svi_if_zif =
    4557             :                         NULL; /* Zebra daemon specific info for SVI */
    4558           0 :                 struct interface *svi_if_link =
    4559             :                         NULL; /* link info for the SVI = bridge info */
    4560             : 
    4561           0 :                 svi_if_zif = ifp->info;
    4562           0 :                 if (svi_if_zif) {
    4563           0 :                         svi_if_link = if_lookup_by_index_per_ns(
    4564             :                                 zebra_ns_lookup(NS_DEFAULT),
    4565           0 :                                 svi_if_zif->link_ifindex);
    4566           0 :                         if (svi_if_link)
    4567           0 :                                 zevpn = zebra_evpn_from_svi(ifp, svi_if_link);
    4568             :                 }
    4569           0 :         } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
    4570           0 :                 zevpn = zebra_evpn_from_svi(ifp, ifp);
    4571             :         }
    4572             : 
    4573           0 :         if (!zevpn)
    4574           0 :                 return 0;
    4575             : 
    4576           0 :         if (!zevpn->vxlan_if) {
    4577           0 :                 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
    4578             :                            zevpn->vni, zevpn);
    4579           0 :                 return -1;
    4580             :         }
    4581             : 
    4582             :         /* VRR IP is advertised only if gw-macip-adv-enabled */
    4583           0 :         if (IS_ZEBRA_IF_MACVLAN(ifp)) {
    4584           0 :                 if (!advertise_gw_macip_enabled(zevpn))
    4585             :                         return 0;
    4586             :         } else {
    4587             :                 /* SVI IP is advertised if gw or svi macip-adv-enabled */
    4588           0 :                 if (!advertise_svi_macip_enabled(zevpn)
    4589           0 :                     && !advertise_gw_macip_enabled(zevpn))
    4590             :                         return 0;
    4591             :         }
    4592             : 
    4593           0 :         memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
    4594             : 
    4595           0 :         if (p->family == AF_INET) {
    4596           0 :                 ip.ipa_type = IPADDR_V4;
    4597           0 :                 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
    4598             :                        sizeof(struct in_addr));
    4599           0 :         } else if (p->family == AF_INET6) {
    4600           0 :                 ip.ipa_type = IPADDR_V6;
    4601           0 :                 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
    4602             :                        sizeof(struct in6_addr));
    4603             :         }
    4604             : 
    4605             : 
    4606           0 :         if (add)
    4607           0 :                 zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip);
    4608             :         else
    4609           0 :                 zebra_evpn_gw_macip_del(ifp, zevpn, &ip);
    4610             : 
    4611             :         return 0;
    4612             : }
    4613             : 
    4614             : /*
    4615             :  * Handle SVI interface going down.
    4616             :  * SVI can be associated to either L3-VNI or L2-VNI.
    4617             :  * For L2-VNI: At this point, this is a NOP since
    4618             :  *      the kernel deletes the neighbor entries on this SVI (if any).
    4619             :  *      We only need to update the vrf corresponding to zevpn.
    4620             :  * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
    4621             :  *      from bgp
    4622             :  */
    4623           0 : int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
    4624             : {
    4625           0 :         struct zebra_l3vni *zl3vni = NULL;
    4626             : 
    4627           0 :         zl3vni = zl3vni_from_svi(ifp, link_if);
    4628           0 :         if (zl3vni) {
    4629             : 
    4630             :                 /* process l3-vni down */
    4631           0 :                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    4632             : 
    4633             :                 /* remove association with svi-if */
    4634           0 :                 zl3vni->svi_if = NULL;
    4635             :         } else {
    4636           0 :                 struct zebra_evpn *zevpn = NULL;
    4637             : 
    4638             :                 /* Unlink the SVI from the access VLAN */
    4639           0 :                 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, false);
    4640             : 
    4641             :                 /* since we dont have svi corresponding to zevpn, we associate it
    4642             :                  * to default vrf. Note: the corresponding neigh entries on the
    4643             :                  * SVI would have already been deleted */
    4644           0 :                 zevpn = zebra_evpn_from_svi(ifp, link_if);
    4645             : 
    4646           0 :                 if (zevpn) {
    4647             :                         /* remove from l3-vni list */
    4648           0 :                         zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    4649           0 :                         if (zl3vni)
    4650           0 :                                 listnode_delete(zl3vni->l2vnis, zevpn);
    4651             : 
    4652           0 :                         zevpn->svi_if = NULL;
    4653           0 :                         zevpn->vrf_id = VRF_DEFAULT;
    4654             : 
    4655             :                         /* update the tenant vrf in BGP */
    4656           0 :                         if (if_is_operative(zevpn->vxlan_if))
    4657           0 :                                 zebra_evpn_send_add_to_client(zevpn);
    4658             :                 }
    4659             :         }
    4660           0 :         return 0;
    4661             : }
    4662             : 
    4663             : /*
    4664             :  * Handle SVI interface coming up.
    4665             :  * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
    4666             :  * vxlan intf).
    4667             :  * For L2-VNI: we need to install any remote neighbors entried (used for
    4668             :  * arp-suppression)
    4669             :  * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
    4670             :  */
    4671           0 : int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
    4672             : {
    4673           0 :         struct zebra_evpn *zevpn = NULL;
    4674           0 :         struct zebra_l3vni *zl3vni = NULL;
    4675             : 
    4676           0 :         zl3vni = zl3vni_from_svi(ifp, link_if);
    4677           0 :         if (zl3vni) {
    4678             : 
    4679             :                 /* associate with svi */
    4680           0 :                 zl3vni->svi_if = ifp;
    4681             : 
    4682             :                 /* process oper-up */
    4683           0 :                 if (is_l3vni_oper_up(zl3vni))
    4684           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    4685             :         } else {
    4686             : 
    4687             :                 /* process SVI up for l2-vni */
    4688           0 :                 struct neigh_walk_ctx n_wctx;
    4689             : 
    4690           0 :                 zevpn = zebra_evpn_from_svi(ifp, link_if);
    4691           0 :                 if (!zevpn)
    4692           0 :                         return 0;
    4693             : 
    4694           0 :                 if (!zevpn->vxlan_if) {
    4695           0 :                         zlog_debug(
    4696             :                                 "VNI %u hash %p doesn't have intf upon SVI up",
    4697             :                                 zevpn->vni, zevpn);
    4698           0 :                         return -1;
    4699             :                 }
    4700             : 
    4701           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4702           0 :                         zlog_debug(
    4703             :                                 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
    4704             :                                 ifp->name, ifp->ifindex, zevpn->vni,
    4705             :                                 ifp->vrf->name);
    4706             : 
    4707             :                 /* update the vrf information for l2-vni and inform bgp */
    4708           0 :                 zevpn->svi_if = ifp;
    4709           0 :                 zevpn->vrf_id = ifp->vrf->vrf_id;
    4710             : 
    4711           0 :                 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    4712           0 :                 if (zl3vni)
    4713           0 :                         listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
    4714             : 
    4715           0 :                 if (if_is_operative(zevpn->vxlan_if))
    4716           0 :                         zebra_evpn_send_add_to_client(zevpn);
    4717             : 
    4718             :                 /* Install any remote neighbors for this VNI. */
    4719           0 :                 memset(&n_wctx, 0, sizeof(n_wctx));
    4720           0 :                 n_wctx.zevpn = zevpn;
    4721           0 :                 hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash,
    4722             :                              &n_wctx);
    4723             : 
    4724             :                 /* Link the SVI from the access VLAN */
    4725           0 :                 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, true);
    4726             : 
    4727             :                 /* Update MACIP routes created by advertise-svi-ip */
    4728           0 :                 if (advertise_svi_macip_enabled(zevpn)) {
    4729           0 :                         zebra_evpn_del_macip_for_intf(ifp, zevpn);
    4730           0 :                         zebra_evpn_add_macip_for_intf(ifp, zevpn);
    4731             :                 }
    4732             :         }
    4733             : 
    4734             :         return 0;
    4735             : }
    4736             : 
    4737             : /*
    4738             :  * Handle MAC-VLAN interface going down.
    4739             :  * L3VNI: When MAC-VLAN interface goes down,
    4740             :  * find its associated SVI and update type2/type-5 routes
    4741             :  * with SVI as RMAC
    4742             :  */
    4743           0 : void zebra_vxlan_macvlan_down(struct interface *ifp)
    4744             : {
    4745           0 :         struct zebra_l3vni *zl3vni = NULL;
    4746           0 :         struct zebra_if *zif, *link_zif;
    4747           0 :         struct interface *link_ifp, *link_if;
    4748             : 
    4749           0 :         zif = ifp->info;
    4750           0 :         assert(zif);
    4751           0 :         link_ifp = zif->link;
    4752           0 :         if (!link_ifp) {
    4753           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4754           0 :                         zlog_debug(
    4755             :                                 "macvlan parent link is not found. Parent index %d ifp %s",
    4756             :                                 zif->link_ifindex,
    4757             :                                 ifindex2ifname(zif->link_ifindex,
    4758             :                                                ifp->vrf->vrf_id));
    4759           0 :                 return;
    4760             :         }
    4761           0 :         link_zif = link_ifp->info;
    4762           0 :         assert(link_zif);
    4763             : 
    4764           0 :         link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
    4765           0 :                                             link_zif->link_ifindex);
    4766             : 
    4767           0 :         zl3vni = zl3vni_from_svi(link_ifp, link_if);
    4768           0 :         if (zl3vni) {
    4769           0 :                 zl3vni->mac_vlan_if = NULL;
    4770           0 :                 if (is_l3vni_oper_up(zl3vni))
    4771           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    4772             :         }
    4773             : }
    4774             : 
    4775             : /*
    4776             :  * Handle MAC-VLAN interface going up.
    4777             :  * L3VNI: When MAC-VLAN interface comes up,
    4778             :  * find its associated SVI and update type-2 routes
    4779             :  * with MAC-VLAN's MAC as RMAC and for type-5 routes
    4780             :  * use SVI's MAC as RMAC.
    4781             :  */
    4782           0 : void zebra_vxlan_macvlan_up(struct interface *ifp)
    4783             : {
    4784           0 :         struct zebra_l3vni *zl3vni = NULL;
    4785           0 :         struct zebra_if *zif, *link_zif;
    4786           0 :         struct interface *link_ifp, *link_if;
    4787             : 
    4788           0 :         zif = ifp->info;
    4789           0 :         assert(zif);
    4790           0 :         link_ifp = zif->link;
    4791           0 :         link_zif = link_ifp->info;
    4792           0 :         assert(link_zif);
    4793             : 
    4794           0 :         link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
    4795           0 :                                             link_zif->link_ifindex);
    4796           0 :         zl3vni = zl3vni_from_svi(link_ifp, link_if);
    4797           0 :         if (zl3vni) {
    4798             :                 /* associate with macvlan (VRR) interface */
    4799           0 :                 zl3vni->mac_vlan_if = ifp;
    4800             : 
    4801             :                 /* process oper-up */
    4802           0 :                 if (is_l3vni_oper_up(zl3vni))
    4803           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    4804             :         }
    4805           0 : }
    4806             : 
    4807             : /*
    4808             :  * Handle VxLAN interface down
    4809             :  */
    4810           0 : int zebra_vxlan_if_down(struct interface *ifp)
    4811             : {
    4812           0 :         vni_t vni;
    4813           0 :         struct zebra_if *zif = NULL;
    4814           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    4815           0 :         struct zebra_l3vni *zl3vni = NULL;
    4816           0 :         struct zebra_evpn *zevpn;
    4817             : 
    4818             :         /* Check if EVPN is enabled. */
    4819           0 :         if (!is_evpn_enabled())
    4820             :                 return 0;
    4821             : 
    4822           0 :         zif = ifp->info;
    4823           0 :         assert(zif);
    4824           0 :         vxl = &zif->l2info.vxl;
    4825           0 :         vni = vxl->vni;
    4826             : 
    4827           0 :         zl3vni = zl3vni_lookup(vni);
    4828           0 :         if (zl3vni) {
    4829             :                 /* process-if-down for l3-vni */
    4830           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4831           0 :                         zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
    4832             :                                    ifp->ifindex, vni);
    4833             : 
    4834           0 :                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    4835             :         } else {
    4836             :                 /* process if-down for l2-vni */
    4837           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4838           0 :                         zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
    4839             :                                    ifp->ifindex, vni);
    4840             : 
    4841             :                 /* Locate hash entry; it is expected to exist. */
    4842           0 :                 zevpn = zebra_evpn_lookup(vni);
    4843           0 :                 if (!zevpn) {
    4844           0 :                         zlog_debug(
    4845             :                                 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
    4846             :                                 ifp->name, ifp->ifindex, vni);
    4847           0 :                         return -1;
    4848             :                 }
    4849             : 
    4850           0 :                 assert(zevpn->vxlan_if == ifp);
    4851             : 
    4852             :                 /* remove from l3-vni list */
    4853           0 :                 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    4854           0 :                 if (zl3vni)
    4855           0 :                         listnode_delete(zl3vni->l2vnis, zevpn);
    4856             : 
    4857             :                 /* Delete this VNI from BGP. */
    4858           0 :                 zebra_evpn_send_del_to_client(zevpn);
    4859             : 
    4860             :                 /* Free up all neighbors and MACs, if any. */
    4861           0 :                 zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
    4862           0 :                 zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
    4863             : 
    4864             :                 /* Free up all remote VTEPs, if any. */
    4865           0 :                 zebra_evpn_vtep_del_all(zevpn, 1);
    4866             :         }
    4867             :         return 0;
    4868             : }
    4869             : 
    4870             : /*
    4871             :  * Handle VxLAN interface up - update BGP if required.
    4872             :  */
    4873           0 : int zebra_vxlan_if_up(struct interface *ifp)
    4874             : {
    4875           0 :         vni_t vni;
    4876           0 :         struct zebra_if *zif = NULL;
    4877           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    4878           0 :         struct zebra_evpn *zevpn = NULL;
    4879           0 :         struct zebra_l3vni *zl3vni = NULL;
    4880             : 
    4881             :         /* Check if EVPN is enabled. */
    4882           0 :         if (!is_evpn_enabled())
    4883             :                 return 0;
    4884             : 
    4885           0 :         zif = ifp->info;
    4886           0 :         assert(zif);
    4887           0 :         vxl = &zif->l2info.vxl;
    4888           0 :         vni = vxl->vni;
    4889             : 
    4890           0 :         zl3vni = zl3vni_lookup(vni);
    4891           0 :         if (zl3vni) {
    4892             :                 /* we need to associate with SVI, if any, we can associate with
    4893             :                  * svi-if only after association with vxlan-intf is complete
    4894             :                  */
    4895           0 :                 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
    4896           0 :                 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
    4897             : 
    4898           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4899           0 :                         zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
    4900             :                                 , ifp->name, ifp->ifindex, vni,
    4901             :                                 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
    4902             :                                 zl3vni->mac_vlan_if ?
    4903             :                                 zl3vni->mac_vlan_if->name : "NIL");
    4904             : 
    4905           0 :                 if (is_l3vni_oper_up(zl3vni))
    4906           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    4907             :         } else {
    4908             :                 /* Handle L2-VNI add */
    4909           0 :                 struct interface *vlan_if = NULL;
    4910             : 
    4911           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4912           0 :                         zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
    4913             :                                    ifp->ifindex, vni);
    4914             : 
    4915             :                 /* Locate hash entry; it is expected to exist. */
    4916           0 :                 zevpn = zebra_evpn_lookup(vni);
    4917           0 :                 if (!zevpn) {
    4918           0 :                         zlog_debug(
    4919             :                                 "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
    4920             :                                 ifp->name, ifp->ifindex, vni);
    4921           0 :                         return -1;
    4922             :                 }
    4923             : 
    4924           0 :                 assert(zevpn->vxlan_if == ifp);
    4925           0 :                 vlan_if = zvni_map_to_svi(vxl->access_vlan,
    4926             :                                           zif->brslave_info.br_if);
    4927           0 :                 if (vlan_if) {
    4928           0 :                         zevpn->svi_if = vlan_if;
    4929           0 :                         zevpn->vrf_id = vlan_if->vrf->vrf_id;
    4930           0 :                         zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
    4931           0 :                         if (zl3vni)
    4932           0 :                                 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
    4933             :                 }
    4934             : 
    4935             :                 /* If part of a bridge, inform BGP about this VNI. */
    4936             :                 /* Also, read and populate local MACs and neighbors. */
    4937           0 :                 if (zif->brslave_info.br_if) {
    4938           0 :                         zebra_evpn_send_add_to_client(zevpn);
    4939           0 :                         zebra_evpn_read_mac_neigh(zevpn, ifp);
    4940             :                 }
    4941             :         }
    4942             : 
    4943             :         return 0;
    4944             : }
    4945             : 
    4946             : /*
    4947             :  * Handle VxLAN interface delete. Locate and remove entry in hash table
    4948             :  * and update BGP, if required.
    4949             :  */
    4950           0 : int zebra_vxlan_if_del(struct interface *ifp)
    4951             : {
    4952           0 :         vni_t vni;
    4953           0 :         struct zebra_if *zif = NULL;
    4954           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    4955           0 :         struct zebra_evpn *zevpn = NULL;
    4956           0 :         struct zebra_l3vni *zl3vni = NULL;
    4957             : 
    4958             :         /* Check if EVPN is enabled. */
    4959           0 :         if (!is_evpn_enabled())
    4960             :                 return 0;
    4961             : 
    4962           0 :         zif = ifp->info;
    4963           0 :         assert(zif);
    4964           0 :         vxl = &zif->l2info.vxl;
    4965           0 :         vni = vxl->vni;
    4966             : 
    4967           0 :         zl3vni = zl3vni_lookup(vni);
    4968           0 :         if (zl3vni) {
    4969             : 
    4970           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4971           0 :                         zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
    4972             :                                    ifp->ifindex);
    4973             : 
    4974             :                 /* process oper-down for l3-vni */
    4975           0 :                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    4976             : 
    4977             :                 /* remove the association with vxlan_if */
    4978           0 :                 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
    4979           0 :                 zl3vni->vxlan_if = NULL;
    4980             :         } else {
    4981             : 
    4982             :                 /* process if-del for l2-vni*/
    4983           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    4984           0 :                         zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
    4985             :                                    ifp->ifindex);
    4986             : 
    4987             :                 /* Locate hash entry; it is expected to exist. */
    4988           0 :                 zevpn = zebra_evpn_lookup(vni);
    4989           0 :                 if (!zevpn) {
    4990           0 :                         zlog_debug(
    4991             :                                 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
    4992             :                                 ifp->name, ifp->ifindex, vni);
    4993           0 :                         return 0;
    4994             :                 }
    4995             : 
    4996             :                 /* remove from l3-vni list */
    4997           0 :                 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
    4998           0 :                 if (zl3vni)
    4999           0 :                         listnode_delete(zl3vni->l2vnis, zevpn);
    5000             :                 /* Delete VNI from BGP. */
    5001           0 :                 zebra_evpn_send_del_to_client(zevpn);
    5002             : 
    5003             :                 /* Free up all neighbors and MAC, if any. */
    5004           0 :                 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
    5005           0 :                 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
    5006             : 
    5007             :                 /* Free up all remote VTEPs, if any. */
    5008           0 :                 zebra_evpn_vtep_del_all(zevpn, 0);
    5009             : 
    5010             :                 /* Delete the hash entry. */
    5011           0 :                 if (zebra_evpn_vxlan_del(zevpn)) {
    5012           0 :                         flog_err(EC_ZEBRA_VNI_DEL_FAILED,
    5013             :                                  "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
    5014             :                                  zevpn, ifp->name, ifp->ifindex, zevpn->vni);
    5015           0 :                         return -1;
    5016             :                 }
    5017             :         }
    5018             :         return 0;
    5019             : }
    5020             : 
    5021             : /*
    5022             :  * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
    5023             :  */
    5024           0 : int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
    5025             : {
    5026           0 :         vni_t vni;
    5027           0 :         struct zebra_if *zif = NULL;
    5028           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    5029           0 :         struct zebra_evpn *zevpn = NULL;
    5030           0 :         struct zebra_l3vni *zl3vni = NULL;
    5031           0 :         struct interface *vlan_if = NULL;
    5032             : 
    5033             :         /* Check if EVPN is enabled. */
    5034           0 :         if (!is_evpn_enabled())
    5035             :                 return 0;
    5036             : 
    5037           0 :         zif = ifp->info;
    5038           0 :         assert(zif);
    5039           0 :         vxl = &zif->l2info.vxl;
    5040           0 :         vni = vxl->vni;
    5041             : 
    5042           0 :         zl3vni = zl3vni_lookup(vni);
    5043           0 :         if (zl3vni) {
    5044             : 
    5045           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5046           0 :                         zlog_debug(
    5047             :                                 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
    5048             :                                 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
    5049             :                                 &vxl->vtep_ip,
    5050             :                                 zif->brslave_info.bridge_ifindex, chgflags);
    5051             : 
    5052             :                 /* Removed from bridge? Cleanup and return */
    5053           0 :                 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
    5054           0 :                     && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
    5055           0 :                         zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5056           0 :                         return 0;
    5057             :                 }
    5058             : 
    5059           0 :                 if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
    5060           0 :                     && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
    5061           0 :                         zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5062           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    5063           0 :                         return 0;
    5064             :                 }
    5065             : 
    5066             :                 /* access-vlan change - process oper down, associate with new
    5067             :                  * svi_if and then process oper up again
    5068             :                  */
    5069           0 :                 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
    5070           0 :                         if (if_is_operative(ifp)) {
    5071           0 :                                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5072           0 :                                 zl3vni->svi_if = NULL;
    5073           0 :                                 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
    5074           0 :                                 zl3vni->mac_vlan_if =
    5075           0 :                                         zl3vni_map_to_mac_vlan_if(zl3vni);
    5076           0 :                                 zl3vni->local_vtep_ip = vxl->vtep_ip;
    5077           0 :                                 if (is_l3vni_oper_up(zl3vni))
    5078           0 :                                         zebra_vxlan_process_l3vni_oper_up(
    5079             :                                                 zl3vni);
    5080             :                         }
    5081             :                 }
    5082             : 
    5083             :                 /*
    5084             :                  * local-ip change - process oper down, associate with new
    5085             :                  * local-ip and then process oper up again
    5086             :                  */
    5087           0 :                 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
    5088           0 :                         if (if_is_operative(ifp)) {
    5089           0 :                                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5090           0 :                                 zl3vni->local_vtep_ip = vxl->vtep_ip;
    5091           0 :                                 if (is_l3vni_oper_up(zl3vni))
    5092           0 :                                         zebra_vxlan_process_l3vni_oper_up(
    5093             :                                                 zl3vni);
    5094             :                         }
    5095             :                 }
    5096             : 
    5097             :                 /* Update local tunnel IP. */
    5098           0 :                 zl3vni->local_vtep_ip = vxl->vtep_ip;
    5099             : 
    5100             :                 /* if we have a valid new master, process l3-vni oper up */
    5101           0 :                 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
    5102           0 :                         if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
    5103           0 :                                 zebra_vxlan_process_l3vni_oper_up(zl3vni);
    5104             :                 }
    5105             :         } else {
    5106             : 
    5107             :                 /* Update VNI hash. */
    5108           0 :                 zevpn = zebra_evpn_lookup(vni);
    5109           0 :                 if (!zevpn) {
    5110           0 :                         zlog_debug(
    5111             :                                 "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
    5112             :                                 ifp->name, ifp->ifindex, vni);
    5113           0 :                         return -1;
    5114             :                 }
    5115             : 
    5116           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5117           0 :                         zlog_debug(
    5118             :                                 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
    5119             :                                 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
    5120             :                                 &vxl->vtep_ip,
    5121             :                                 zif->brslave_info.bridge_ifindex, chgflags);
    5122             : 
    5123             :                 /* Removed from bridge? Cleanup and return */
    5124           0 :                 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
    5125           0 :                     && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
    5126             :                         /* Delete from client, remove all remote VTEPs */
    5127             :                         /* Also, free up all MACs and neighbors. */
    5128           0 :                         zevpn->svi_if = NULL;
    5129           0 :                         zebra_evpn_send_del_to_client(zevpn);
    5130           0 :                         zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
    5131           0 :                         zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
    5132           0 :                         zebra_evpn_vtep_del_all(zevpn, 1);
    5133           0 :                         return 0;
    5134             :                 }
    5135             : 
    5136             :                 /* Handle other changes. */
    5137           0 :                 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
    5138             :                         /* Remove all existing local neigh and MACs for this VNI
    5139             :                          * (including from BGP)
    5140             :                          */
    5141           0 :                         zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
    5142           0 :                         zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
    5143             :                 }
    5144             : 
    5145           0 :                 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
    5146           0 :                         zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
    5147           0 :                         zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
    5148             :                                 zevpn->mcast_grp);
    5149           0 :                         zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
    5150           0 :                         zevpn->local_vtep_ip = vxl->vtep_ip;
    5151           0 :                         zevpn->mcast_grp = vxl->mcast_grp;
    5152             :                         /* on local vtep-ip check if ES orig-ip
    5153             :                          * needs to be updated
    5154             :                          */
    5155           0 :                         zebra_evpn_es_set_base_evpn(zevpn);
    5156             :                 }
    5157           0 :                 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
    5158           0 :                 vlan_if = zvni_map_to_svi(vxl->access_vlan,
    5159             :                                           zif->brslave_info.br_if);
    5160           0 :                 if (vlan_if) {
    5161           0 :                         zevpn->svi_if = vlan_if;
    5162           0 :                         zevpn->vrf_id = vlan_if->vrf->vrf_id;
    5163           0 :                         zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
    5164           0 :                         if (zl3vni)
    5165           0 :                                 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
    5166             :                 }
    5167             : 
    5168             :                 /* Take further actions needed.
    5169             :                  * Note that if we are here, there is a change of interest.
    5170             :                  */
    5171             :                 /* If down or not mapped to a bridge, we're done. */
    5172           0 :                 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    5173             :                         return 0;
    5174             : 
    5175             :                 /* Inform BGP, if there is a change of interest. */
    5176           0 :                 if (chgflags &
    5177             :                     (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE |
    5178             :                      ZEBRA_VXLIF_MCAST_GRP_CHANGE | ZEBRA_VXLIF_VLAN_CHANGE))
    5179           0 :                         zebra_evpn_send_add_to_client(zevpn);
    5180             : 
    5181             :                 /* If there is a valid new master or a VLAN mapping change,
    5182             :                  * read and populate local MACs and neighbors.
    5183             :                  * Also, reinstall any remote MACs and neighbors
    5184             :                  * for this VNI (based on new VLAN).
    5185             :                  */
    5186           0 :                 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
    5187           0 :                         zebra_evpn_read_mac_neigh(zevpn, ifp);
    5188           0 :                 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
    5189           0 :                         struct mac_walk_ctx m_wctx;
    5190           0 :                         struct neigh_walk_ctx n_wctx;
    5191             : 
    5192           0 :                         zebra_evpn_read_mac_neigh(zevpn, ifp);
    5193             : 
    5194           0 :                         memset(&m_wctx, 0, sizeof(m_wctx));
    5195           0 :                         m_wctx.zevpn = zevpn;
    5196           0 :                         hash_iterate(zevpn->mac_table,
    5197             :                                      zebra_evpn_install_mac_hash, &m_wctx);
    5198             : 
    5199           0 :                         memset(&n_wctx, 0, sizeof(n_wctx));
    5200           0 :                         n_wctx.zevpn = zevpn;
    5201           0 :                         hash_iterate(zevpn->neigh_table,
    5202             :                                      zebra_evpn_install_neigh_hash, &n_wctx);
    5203             :                 }
    5204             :         }
    5205             : 
    5206             :         return 0;
    5207             : }
    5208             : 
    5209             : /*
    5210             :  * Handle VxLAN interface add.
    5211             :  */
    5212           0 : int zebra_vxlan_if_add(struct interface *ifp)
    5213             : {
    5214           0 :         vni_t vni;
    5215           0 :         struct zebra_if *zif = NULL;
    5216           0 :         struct zebra_l2info_vxlan *vxl = NULL;
    5217           0 :         struct zebra_evpn *zevpn = NULL;
    5218           0 :         struct zebra_l3vni *zl3vni = NULL;
    5219             : 
    5220             :         /* Check if EVPN is enabled. */
    5221           0 :         if (!is_evpn_enabled())
    5222             :                 return 0;
    5223             : 
    5224           0 :         zif = ifp->info;
    5225           0 :         assert(zif);
    5226           0 :         vxl = &zif->l2info.vxl;
    5227           0 :         vni = vxl->vni;
    5228             : 
    5229           0 :         zl3vni = zl3vni_lookup(vni);
    5230           0 :         if (zl3vni) {
    5231             : 
    5232             :                 /* process if-add for l3-vni*/
    5233           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5234           0 :                         zlog_debug(
    5235             :                                 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
    5236             :                                 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
    5237             :                                 &vxl->vtep_ip,
    5238             :                                 zif->brslave_info.bridge_ifindex);
    5239             : 
    5240             :                 /* associate with vxlan_if */
    5241           0 :                 zl3vni->local_vtep_ip = vxl->vtep_ip;
    5242           0 :                 zl3vni->vxlan_if = ifp;
    5243             : 
    5244             :                 /* Associate with SVI, if any. We can associate with svi-if only
    5245             :                  * after association with vxlan_if is complete */
    5246           0 :                 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
    5247             : 
    5248           0 :                 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
    5249             : 
    5250           0 :                 if (is_l3vni_oper_up(zl3vni))
    5251           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    5252             :         } else {
    5253             : 
    5254             :                 /* process if-add for l2-vni */
    5255           0 :                 struct interface *vlan_if = NULL;
    5256             : 
    5257             :                 /* Create or update EVPN hash. */
    5258           0 :                 zevpn = zebra_evpn_lookup(vni);
    5259           0 :                 if (!zevpn)
    5260           0 :                         zevpn = zebra_evpn_add(vni);
    5261             : 
    5262           0 :                 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
    5263           0 :                         zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
    5264           0 :                         zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
    5265             :                                 zevpn->mcast_grp);
    5266           0 :                         zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
    5267           0 :                         zevpn->local_vtep_ip = vxl->vtep_ip;
    5268           0 :                         zevpn->mcast_grp = vxl->mcast_grp;
    5269             :                         /* on local vtep-ip check if ES orig-ip
    5270             :                          * needs to be updated
    5271             :                          */
    5272           0 :                         zebra_evpn_es_set_base_evpn(zevpn);
    5273             :                 }
    5274           0 :                 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
    5275           0 :                 vlan_if = zvni_map_to_svi(vxl->access_vlan,
    5276             :                                           zif->brslave_info.br_if);
    5277           0 :                 if (vlan_if) {
    5278           0 :                         zevpn->svi_if = vlan_if;
    5279           0 :                         zevpn->vrf_id = vlan_if->vrf->vrf_id;
    5280           0 :                         zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
    5281           0 :                         if (zl3vni)
    5282           0 :                                 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
    5283             :                 }
    5284             : 
    5285           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5286           0 :                         zlog_debug(
    5287             :                                 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
    5288             :                                 vni,
    5289             :                                 vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
    5290             :                                 ifp->name, ifp->ifindex, vxl->access_vlan,
    5291             :                                 &vxl->vtep_ip, &vxl->mcast_grp,
    5292             :                                 zif->brslave_info.bridge_ifindex);
    5293             : 
    5294             :                 /* If down or not mapped to a bridge, we're done. */
    5295           0 :                 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    5296             :                         return 0;
    5297             : 
    5298             :                 /* Inform BGP */
    5299           0 :                 zebra_evpn_send_add_to_client(zevpn);
    5300             : 
    5301             :                 /* Read and populate local MACs and neighbors */
    5302           0 :                 zebra_evpn_read_mac_neigh(zevpn, ifp);
    5303             :         }
    5304             : 
    5305             :         return 0;
    5306             : }
    5307             : 
    5308           0 : int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
    5309             :                                     char *err, int err_str_sz, int filter,
    5310             :                                     int add)
    5311             : {
    5312           0 :         struct zebra_l3vni *zl3vni = NULL;
    5313           0 :         struct zebra_vrf *zvrf_evpn = NULL;
    5314             : 
    5315           0 :         zvrf_evpn = zebra_vrf_get_evpn();
    5316             : 
    5317           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    5318           0 :                 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
    5319             :                            add ? "ADD" : "DEL");
    5320             : 
    5321           0 :         if (add) {
    5322             :                 /* check if the vni is already present under zvrf */
    5323           0 :                 if (zvrf->l3vni) {
    5324           0 :                         snprintf(err, err_str_sz,
    5325             :                                  "VNI is already configured under the vrf");
    5326           0 :                         return -1;
    5327             :                 }
    5328             : 
    5329             :                 /* check if this VNI is already present in the system */
    5330           0 :                 zl3vni = zl3vni_lookup(vni);
    5331           0 :                 if (zl3vni) {
    5332           0 :                         snprintf(err, err_str_sz,
    5333             :                                  "VNI is already configured as L3-VNI");
    5334           0 :                         return -1;
    5335             :                 }
    5336             : 
    5337             :                 /* Remove L2VNI if present */
    5338           0 :                 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
    5339             : 
    5340             :                 /* add the L3-VNI to the global table */
    5341           0 :                 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
    5342             : 
    5343             :                 /* associate the vrf with vni */
    5344           0 :                 zvrf->l3vni = vni;
    5345             : 
    5346             :                 /* set the filter in l3vni to denote if we are using l3vni only
    5347             :                  * for prefix routes
    5348             :                  */
    5349           0 :                 if (filter)
    5350           0 :                         SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
    5351             : 
    5352             :                 /* associate with vxlan-intf;
    5353             :                  * we need to associate with the vxlan-intf first
    5354             :                  */
    5355           0 :                 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
    5356             : 
    5357             :                 /* associate with corresponding SVI interface, we can associate
    5358             :                  * with svi-if only after vxlan interface association is
    5359             :                  * complete
    5360             :                  */
    5361           0 :                 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
    5362             : 
    5363           0 :                 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
    5364             : 
    5365           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5366           0 :                         zlog_debug(
    5367             :                                 "%s: l3vni %u svi_if %s mac_vlan_if %s",
    5368             :                                 __func__, vni,
    5369             :                                 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
    5370             :                                 zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
    5371             :                                                     : "NIL");
    5372             : 
    5373             :                 /* formulate l2vni list */
    5374           0 :                 hash_iterate(zvrf_evpn->evpn_table, zevpn_add_to_l3vni_list,
    5375             :                              zl3vni);
    5376             : 
    5377           0 :                 if (is_l3vni_oper_up(zl3vni))
    5378           0 :                         zebra_vxlan_process_l3vni_oper_up(zl3vni);
    5379             : 
    5380             :         } else {
    5381           0 :                 zl3vni = zl3vni_lookup(vni);
    5382           0 :                 if (!zl3vni) {
    5383           0 :                         snprintf(err, err_str_sz, "VNI doesn't exist");
    5384           0 :                         return -1;
    5385             :                 }
    5386             : 
    5387           0 :                 if (zvrf->l3vni != vni) {
    5388           0 :                         snprintf(err, err_str_sz,
    5389             :                                         "VNI %d doesn't exist in VRF: %s",
    5390           0 :                                         vni, zvrf->vrf->name);
    5391           0 :                         return -1;
    5392             :                 }
    5393             : 
    5394           0 :                 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
    5395           0 :                         snprintf(err, ERR_STR_SZ,
    5396             :                                  "prefix-routes-only is not set for the vni");
    5397           0 :                         return -1;
    5398             :                 }
    5399             : 
    5400             :                 zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5401             : 
    5402             :                 /* delete and uninstall all rmacs */
    5403           0 :                 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
    5404             :                              zl3vni);
    5405             : 
    5406             :                 /* delete and uninstall all next-hops */
    5407           0 :                 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
    5408             :                              zl3vni);
    5409             : 
    5410           0 :                 zvrf->l3vni = 0;
    5411           0 :                 zl3vni_del(zl3vni);
    5412             : 
    5413             :                 /* Add L2VNI for this VNI */
    5414           0 :                 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
    5415             :         }
    5416             :         return 0;
    5417             : }
    5418             : 
    5419           4 : int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
    5420             : {
    5421           4 :         struct zebra_l3vni *zl3vni = NULL;
    5422             : 
    5423           4 :         if (zvrf->l3vni)
    5424           0 :                 zl3vni = zl3vni_lookup(zvrf->l3vni);
    5425           0 :         if (!zl3vni)
    5426           4 :                 return 0;
    5427             : 
    5428           0 :         zl3vni->vrf_id = zvrf_id(zvrf);
    5429           0 :         if (is_l3vni_oper_up(zl3vni))
    5430           0 :                 zebra_vxlan_process_l3vni_oper_up(zl3vni);
    5431             :         return 0;
    5432             : }
    5433             : 
    5434           4 : int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
    5435             : {
    5436           4 :         struct zebra_l3vni *zl3vni = NULL;
    5437             : 
    5438           4 :         if (zvrf->l3vni)
    5439           0 :                 zl3vni = zl3vni_lookup(zvrf->l3vni);
    5440           0 :         if (!zl3vni)
    5441           4 :                 return 0;
    5442             : 
    5443           0 :         zebra_vxlan_process_l3vni_oper_down(zl3vni);
    5444             : 
    5445             :         /* delete and uninstall all rmacs */
    5446           0 :         hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, zl3vni);
    5447             :         /* delete and uninstall all next-hops */
    5448           0 :         hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, zl3vni);
    5449             : 
    5450           0 :         zl3vni->vrf_id = VRF_UNKNOWN;
    5451             : 
    5452           0 :         return 0;
    5453             : }
    5454             : 
    5455           4 : int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
    5456             : {
    5457           4 :         struct zebra_l3vni *zl3vni = NULL;
    5458           4 :         vni_t vni;
    5459             : 
    5460           4 :         if (zvrf->l3vni)
    5461           0 :                 zl3vni = zl3vni_lookup(zvrf->l3vni);
    5462           0 :         if (!zl3vni)
    5463           4 :                 return 0;
    5464             : 
    5465           0 :         vni = zl3vni->vni;
    5466           0 :         zl3vni_del(zl3vni);
    5467           0 :         zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
    5468             : 
    5469           0 :         return 0;
    5470             : }
    5471             : 
    5472             : /*
    5473             :  * Handle message from client to specify the flooding mechanism for
    5474             :  * BUM packets. The default is to do head-end (ingress) replication
    5475             :  * and the other supported option is to disable it. This applies to
    5476             :  * all BUM traffic and disabling it applies to both the transmit and
    5477             :  * receive direction.
    5478             :  */
    5479           0 : void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
    5480             : {
    5481           0 :         struct stream *s;
    5482           0 :         enum vxlan_flood_control flood_ctrl;
    5483             : 
    5484           0 :         if (!EVPN_ENABLED(zvrf)) {
    5485           0 :                 zlog_err("EVPN flood control for non-EVPN VRF %u",
    5486             :                          zvrf_id(zvrf));
    5487           0 :                 return;
    5488             :         }
    5489             : 
    5490           0 :         s = msg;
    5491           0 :         STREAM_GETC(s, flood_ctrl);
    5492             : 
    5493           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    5494           0 :                 zlog_debug("EVPN flood control %u, currently %u",
    5495             :                            flood_ctrl, zvrf->vxlan_flood_ctrl);
    5496             : 
    5497           0 :         if (zvrf->vxlan_flood_ctrl == flood_ctrl)
    5498             :                 return;
    5499             : 
    5500           0 :         zvrf->vxlan_flood_ctrl = flood_ctrl;
    5501             : 
    5502             :         /* Install or uninstall flood entries corresponding to
    5503             :          * remote VTEPs.
    5504             :          */
    5505           0 :         hash_iterate(zvrf->evpn_table, zebra_evpn_handle_flooding_remote_vteps,
    5506             :                      zvrf);
    5507             : 
    5508           0 : stream_failure:
    5509             :         return;
    5510             : }
    5511             : 
    5512             : /*
    5513             :  * Handle message from client to enable/disable advertisement of svi macip
    5514             :  * routes
    5515             :  */
    5516           0 : void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
    5517             : {
    5518           0 :         struct stream *s;
    5519           0 :         int advertise;
    5520           0 :         vni_t vni = 0;
    5521           0 :         struct zebra_evpn *zevpn = NULL;
    5522           0 :         struct interface *ifp = NULL;
    5523             : 
    5524           0 :         if (!EVPN_ENABLED(zvrf)) {
    5525           0 :                 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
    5526             :                           zvrf_id(zvrf));
    5527           0 :                 return;
    5528             :         }
    5529             : 
    5530           0 :         s = msg;
    5531           0 :         STREAM_GETC(s, advertise);
    5532           0 :         STREAM_GETL(s, vni);
    5533             : 
    5534           0 :         if (!vni) {
    5535           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5536           0 :                         zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
    5537             :                                    advertise ? "enabled" : "disabled",
    5538             :                                    advertise_svi_macip_enabled(NULL)
    5539             :                                            ? "enabled"
    5540             :                                            : "disabled");
    5541             : 
    5542           0 :                 if (zvrf->advertise_svi_macip == advertise)
    5543             :                         return;
    5544             : 
    5545             : 
    5546           0 :                 if (advertise) {
    5547           0 :                         zvrf->advertise_svi_macip = advertise;
    5548           0 :                         hash_iterate(zvrf->evpn_table,
    5549             :                                      zebra_evpn_gw_macip_add_for_evpn_hash,
    5550             :                                      NULL);
    5551             :                 } else {
    5552           0 :                         hash_iterate(zvrf->evpn_table,
    5553             :                                      zebra_evpn_svi_macip_del_for_evpn_hash,
    5554             :                                      NULL);
    5555           0 :                         zvrf->advertise_svi_macip = advertise;
    5556             :                 }
    5557             : 
    5558             :         } else {
    5559           0 :                 struct zebra_if *zif = NULL;
    5560           0 :                 struct zebra_l2info_vxlan zl2_info;
    5561           0 :                 struct interface *vlan_if = NULL;
    5562           0 :                 int old_advertise;
    5563             : 
    5564           0 :                 zevpn = zebra_evpn_lookup(vni);
    5565           0 :                 if (!zevpn)
    5566           0 :                         return;
    5567             : 
    5568           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5569           0 :                         zlog_debug(
    5570             :                                 "EVPN SVI macip Adv %s on VNI %d, currently %s",
    5571             :                                 advertise ? "enabled" : "disabled", vni,
    5572             :                                 advertise_svi_macip_enabled(zevpn)
    5573             :                                         ? "enabled"
    5574             :                                         : "disabled");
    5575             : 
    5576           0 :                 old_advertise = advertise_svi_macip_enabled(zevpn);
    5577             : 
    5578             :                 /* Store flag even though SVI is not present.
    5579             :                  * Once SVI comes up triggers self MAC-IP route add.
    5580             :                  */
    5581           0 :                 zevpn->advertise_svi_macip = advertise;
    5582           0 :                 if (advertise_svi_macip_enabled(zevpn) == old_advertise)
    5583             :                         return;
    5584             : 
    5585           0 :                 ifp = zevpn->vxlan_if;
    5586           0 :                 if (!ifp)
    5587             :                         return;
    5588             : 
    5589           0 :                 zif = ifp->info;
    5590             : 
    5591             :                 /* If down or not mapped to a bridge, we're done. */
    5592           0 :                 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    5593             :                         return;
    5594             : 
    5595           0 :                 zl2_info = zif->l2info.vxl;
    5596           0 :                 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
    5597             :                                           zif->brslave_info.br_if);
    5598           0 :                 if (!vlan_if)
    5599             :                         return;
    5600             : 
    5601           0 :                 if (advertise) {
    5602             :                         /* Add primary SVI MAC-IP */
    5603           0 :                         zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
    5604             :                 } else {
    5605             :                         /* Del primary SVI MAC-IP */
    5606           0 :                         zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
    5607             :                 }
    5608             :         }
    5609             : 
    5610           0 : stream_failure:
    5611             :         return;
    5612             : }
    5613             : 
    5614             : /*
    5615             :  * Handle message from client to enable/disable advertisement of g/w macip
    5616             :  * routes
    5617             :  */
    5618           0 : void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
    5619             : {
    5620           0 :         struct stream *s;
    5621           0 :         int advertise;
    5622           0 :         vni_t vni = 0;
    5623           0 :         struct zebra_evpn *zevpn = NULL;
    5624           0 :         struct interface *ifp = NULL;
    5625           0 :         struct zebra_if *zif = NULL;
    5626           0 :         struct zebra_l2info_vxlan zl2_info;
    5627           0 :         struct interface *vlan_if = NULL;
    5628             : 
    5629           0 :         if (!EVPN_ENABLED(zvrf)) {
    5630           0 :                 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
    5631             :                           zvrf_id(zvrf));
    5632           0 :                 return;
    5633             :         }
    5634             : 
    5635           0 :         s = msg;
    5636           0 :         STREAM_GETC(s, advertise);
    5637           0 :         STREAM_GET(&vni, s, 3);
    5638             : 
    5639           0 :         zevpn = zebra_evpn_lookup(vni);
    5640           0 :         if (!zevpn)
    5641             :                 return;
    5642             : 
    5643           0 :         if (zevpn->advertise_subnet == advertise)
    5644             :                 return;
    5645             : 
    5646           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    5647           0 :                 zlog_debug("EVPN subnet Adv %s on VNI %d, currently %s",
    5648             :                            advertise ? "enabled" : "disabled", vni,
    5649             :                            zevpn->advertise_subnet ? "enabled" : "disabled");
    5650             : 
    5651             : 
    5652           0 :         zevpn->advertise_subnet = advertise;
    5653             : 
    5654           0 :         ifp = zevpn->vxlan_if;
    5655           0 :         if (!ifp)
    5656             :                 return;
    5657             : 
    5658           0 :         zif = ifp->info;
    5659             : 
    5660             :         /* If down or not mapped to a bridge, we're done. */
    5661           0 :         if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    5662             :                 return;
    5663             : 
    5664           0 :         zl2_info = zif->l2info.vxl;
    5665             : 
    5666           0 :         vlan_if =
    5667           0 :                 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
    5668           0 :         if (!vlan_if)
    5669             :                 return;
    5670             : 
    5671           0 :         if (zevpn->advertise_subnet)
    5672           0 :                 zebra_evpn_advertise_subnet(zevpn, vlan_if, 1);
    5673             :         else
    5674           0 :                 zebra_evpn_advertise_subnet(zevpn, vlan_if, 0);
    5675             : 
    5676           0 : stream_failure:
    5677             :         return;
    5678             : }
    5679             : 
    5680             : /*
    5681             :  * Handle message from client to enable/disable advertisement of g/w macip
    5682             :  * routes
    5683             :  */
    5684           0 : void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
    5685             : {
    5686           0 :         struct stream *s;
    5687           0 :         int advertise;
    5688           0 :         vni_t vni = 0;
    5689           0 :         struct zebra_evpn *zevpn = NULL;
    5690           0 :         struct interface *ifp = NULL;
    5691             : 
    5692           0 :         if (!EVPN_ENABLED(zvrf)) {
    5693           0 :                 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
    5694             :                            zvrf_id(zvrf));
    5695           0 :                 return;
    5696             :         }
    5697             : 
    5698           0 :         s = msg;
    5699           0 :         STREAM_GETC(s, advertise);
    5700           0 :         STREAM_GETL(s, vni);
    5701             : 
    5702           0 :         if (!vni) {
    5703           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5704           0 :                         zlog_debug("EVPN gateway macip Adv %s, currently %s",
    5705             :                                    advertise ? "enabled" : "disabled",
    5706             :                                    advertise_gw_macip_enabled(NULL)
    5707             :                                            ? "enabled"
    5708             :                                            : "disabled");
    5709             : 
    5710           0 :                 if (zvrf->advertise_gw_macip == advertise)
    5711             :                         return;
    5712             : 
    5713           0 :                 zvrf->advertise_gw_macip = advertise;
    5714             : 
    5715           0 :                 if (advertise_gw_macip_enabled(zevpn))
    5716           0 :                         hash_iterate(zvrf->evpn_table,
    5717             :                                      zebra_evpn_gw_macip_add_for_evpn_hash,
    5718             :                                      NULL);
    5719             :                 else
    5720           0 :                         hash_iterate(zvrf->evpn_table,
    5721             :                                      zebra_evpn_gw_macip_del_for_evpn_hash,
    5722             :                                      NULL);
    5723             : 
    5724             :         } else {
    5725           0 :                 struct zebra_if *zif = NULL;
    5726           0 :                 struct zebra_l2info_vxlan zl2_info;
    5727           0 :                 struct interface *vlan_if = NULL;
    5728           0 :                 struct interface *vrr_if = NULL;
    5729           0 :                 int old_advertise;
    5730             : 
    5731           0 :                 zevpn = zebra_evpn_lookup(vni);
    5732           0 :                 if (!zevpn)
    5733           0 :                         return;
    5734             : 
    5735           0 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    5736           0 :                         zlog_debug(
    5737             :                                 "EVPN gateway macip Adv %s on VNI %d, currently %s",
    5738             :                                 advertise ? "enabled" : "disabled", vni,
    5739             :                                 advertise_gw_macip_enabled(zevpn) ? "enabled"
    5740             :                                                                   : "disabled");
    5741             : 
    5742           0 :                 old_advertise = advertise_gw_macip_enabled(zevpn);
    5743             : 
    5744           0 :                 zevpn->advertise_gw_macip = advertise;
    5745           0 :                 if (advertise_gw_macip_enabled(zevpn) == old_advertise)
    5746             :                         return;
    5747             : 
    5748           0 :                 ifp = zevpn->vxlan_if;
    5749           0 :                 if (!ifp)
    5750             :                         return;
    5751             : 
    5752           0 :                 zif = ifp->info;
    5753             : 
    5754             :                 /* If down or not mapped to a bridge, we're done. */
    5755           0 :                 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
    5756             :                         return;
    5757             : 
    5758           0 :                 zl2_info = zif->l2info.vxl;
    5759             : 
    5760           0 :                 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
    5761             :                                           zif->brslave_info.br_if);
    5762           0 :                 if (!vlan_if)
    5763             :                         return;
    5764             : 
    5765           0 :                 if (advertise_gw_macip_enabled(zevpn)) {
    5766             :                         /* Add primary SVI MAC-IP */
    5767           0 :                         zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
    5768             : 
    5769             :                         /* Add VRR MAC-IP - if any*/
    5770           0 :                         vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
    5771           0 :                         if (vrr_if)
    5772           0 :                                 zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
    5773             :                 } else {
    5774             :                         /* Del primary MAC-IP */
    5775           0 :                         zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
    5776             : 
    5777             :                         /* Del VRR MAC-IP - if any*/
    5778           0 :                         vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
    5779           0 :                         if (vrr_if)
    5780           0 :                                 zebra_evpn_del_macip_for_intf(vrr_if, zevpn);
    5781             :                 }
    5782             :         }
    5783             : 
    5784           0 : stream_failure:
    5785             :         return;
    5786             : }
    5787             : 
    5788           0 : static int macfdb_read_ns(struct ns *ns,
    5789             :                           void *_in_param __attribute__((unused)),
    5790             :                           void **out_param __attribute__((unused)))
    5791             : {
    5792           0 :         struct zebra_ns *zns = ns->info;
    5793             : 
    5794           0 :         macfdb_read(zns);
    5795           0 :         return NS_WALK_CONTINUE;
    5796             : }
    5797             : 
    5798           0 : static int neigh_read_ns(struct ns *ns,
    5799             :                          void *_in_param __attribute__((unused)),
    5800             :                          void **out_param __attribute__((unused)))
    5801             : {
    5802           0 :         struct zebra_ns *zns = ns->info;
    5803             : 
    5804           0 :         neigh_read(zns);
    5805           0 :         return NS_WALK_CONTINUE;
    5806             : }
    5807             : 
    5808             : /*
    5809             :  * Handle message from client to learn (or stop learning) about VNIs and MACs.
    5810             :  * When enabled, the VNI hash table will be built and MAC FDB table read;
    5811             :  * when disabled, the entries should be deleted and remote VTEPs and MACs
    5812             :  * uninstalled from the kernel.
    5813             :  * This also informs the setting for BUM handling at the time this change
    5814             :  * occurs; it is relevant only when specifying "learn".
    5815             :  */
    5816           0 : void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
    5817             : {
    5818           0 :         struct stream *s = NULL;
    5819           0 :         int advertise = 0;
    5820           0 :         enum vxlan_flood_control flood_ctrl;
    5821             : 
    5822             :         /* Mismatch between EVPN VRF and current VRF (should be prevented by
    5823             :          * bgpd's cli) */
    5824           0 :         if (is_evpn_enabled() && !EVPN_ENABLED(zvrf))
    5825             :                 return;
    5826             : 
    5827           0 :         s = msg;
    5828           0 :         STREAM_GETC(s, advertise);
    5829           0 :         STREAM_GETC(s, flood_ctrl);
    5830             : 
    5831           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    5832           0 :                 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
    5833             :                            zvrf_name(zvrf), zvrf_id(zvrf),
    5834             :                            advertise ? "enabled" : "disabled",
    5835             :                            is_evpn_enabled() ? "enabled" : "disabled",
    5836             :                            flood_ctrl);
    5837             : 
    5838           0 :         if (zvrf->advertise_all_vni == advertise)
    5839             :                 return;
    5840             : 
    5841           0 :         zvrf->advertise_all_vni = advertise;
    5842           0 :         if (EVPN_ENABLED(zvrf)) {
    5843           0 :                 zrouter.evpn_vrf = zvrf;
    5844             : 
    5845             :                 /* Note BUM handling */
    5846           0 :                 zvrf->vxlan_flood_ctrl = flood_ctrl;
    5847             : 
    5848             :                 /* Replay all ESs */
    5849           0 :                 zebra_evpn_es_send_all_to_client(true /* add */);
    5850             : 
    5851             :                 /* Build EVPN hash table and inform BGP. */
    5852           0 :                 zevpn_build_hash_table();
    5853             : 
    5854             :                 /* Add all SVI (L3 GW) MACs to BGP*/
    5855           0 :                 hash_iterate(zvrf->evpn_table,
    5856             :                              zebra_evpn_gw_macip_add_for_evpn_hash, NULL);
    5857             : 
    5858             :                 /* Read the MAC FDB */
    5859           0 :                 ns_walk_func(macfdb_read_ns, NULL, NULL);
    5860             : 
    5861             :                 /* Read neighbors */
    5862           0 :                 ns_walk_func(neigh_read_ns, NULL, NULL);
    5863             :         } else {
    5864             :                 /* Cleanup VTEPs for all EVPNs - uninstall from
    5865             :                  * kernel and free entries.
    5866             :                  */
    5867           0 :                 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all,
    5868             :                              zvrf);
    5869             : 
    5870             :                 /* Delete all ESs in BGP */
    5871           0 :                 zebra_evpn_es_send_all_to_client(false /* add */);
    5872             : 
    5873             :                 /* cleanup all l3vnis */
    5874           0 :                 hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
    5875             : 
    5876             :                 /* Mark as "no EVPN VRF" */
    5877           0 :                 zrouter.evpn_vrf = NULL;
    5878             :         }
    5879             : 
    5880           0 : stream_failure:
    5881             :         return;
    5882             : }
    5883             : 
    5884             : /*
    5885             :  * Allocate EVPN hash table for this VRF and do other initialization.
    5886             :  * NOTE: Currently supported only for default VRF.
    5887             :  */
    5888           4 : void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
    5889             : {
    5890           4 :         char buffer[80];
    5891             : 
    5892           4 :         if (!zvrf)
    5893           0 :                 return;
    5894             : 
    5895           4 :         snprintf(buffer, sizeof(buffer), "Zebra VRF EVPN Table: %s",
    5896           4 :                  zvrf->vrf->name);
    5897           4 :         zvrf->evpn_table = hash_create_size(8, zebra_evpn_hash_keymake,
    5898             :                                             zebra_evpn_hash_cmp, buffer);
    5899             : 
    5900           4 :         snprintf(buffer, sizeof(buffer), "Zebra VxLAN SG Table: %s",
    5901           4 :                  zvrf->vrf->name);
    5902           4 :         zvrf->vxlan_sg_table = hash_create_size(8, zebra_vxlan_sg_hash_key_make,
    5903             :                                                 zebra_vxlan_sg_hash_eq, buffer);
    5904             : }
    5905             : 
    5906             : /* Cleanup EVPN info, but don't free the table. */
    5907           4 : void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
    5908             : {
    5909           4 :         struct zebra_vrf *evpn_zvrf = zebra_vrf_get_evpn();
    5910             : 
    5911           4 :         hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
    5912           4 :         zebra_vxlan_cleanup_sg_table(zvrf);
    5913             : 
    5914           4 :         if (zvrf == evpn_zvrf)
    5915           4 :                 zebra_evpn_es_cleanup();
    5916           4 : }
    5917             : 
    5918             : /* Close all EVPN handling */
    5919           4 : void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
    5920             : {
    5921           4 :         if (!zvrf)
    5922             :                 return;
    5923           4 :         hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
    5924           4 :         hash_free(zvrf->evpn_table);
    5925           4 :         if (zvrf->vxlan_sg_table) {
    5926           4 :                 zebra_vxlan_cleanup_sg_table(zvrf);
    5927           4 :                 hash_free(zvrf->vxlan_sg_table);
    5928           4 :                 zvrf->vxlan_sg_table = NULL;
    5929             :         }
    5930             : }
    5931             : 
    5932             : /* init the l3vni table */
    5933           4 : void zebra_vxlan_init(void)
    5934             : {
    5935           4 :         zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
    5936             :                                           "Zebra VRF L3 VNI table");
    5937           4 :         zrouter.evpn_vrf = NULL;
    5938           4 :         zebra_evpn_mh_init();
    5939           4 : }
    5940             : 
    5941             : /* free l3vni table */
    5942           4 : void zebra_vxlan_disable(void)
    5943             : {
    5944           4 :         hash_free(zrouter.l3vni_table);
    5945           4 :         zebra_evpn_mh_terminate();
    5946           4 : }
    5947             : 
    5948             : /* get the l3vni svi ifindex */
    5949           0 : ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
    5950             : {
    5951           0 :         struct zebra_l3vni *zl3vni = NULL;
    5952             : 
    5953           0 :         zl3vni = zl3vni_from_vrf(vrf_id);
    5954           0 :         if (!zl3vni || !is_l3vni_oper_up(zl3vni))
    5955           0 :                 return 0;
    5956             : 
    5957           0 :         return zl3vni->svi_if->ifindex;
    5958             : }
    5959             : 
    5960             : /************************** vxlan SG cache management ************************/
    5961             : /* Inform PIM about the mcast group */
    5962           0 : static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
    5963             :                 struct prefix_sg *sg,
    5964             :                 char *sg_str, uint16_t cmd)
    5965             : {
    5966           0 :         struct zserv *client = NULL;
    5967           0 :         struct stream *s = NULL;
    5968             : 
    5969           0 :         client = zserv_find_client(ZEBRA_ROUTE_PIM, 0);
    5970           0 :         if (!client)
    5971             :                 return 0;
    5972             : 
    5973           0 :         if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG))
    5974             :                 return 0;
    5975             : 
    5976           0 :         s = stream_new(ZEBRA_MAX_PACKET_SIZ);
    5977             : 
    5978           0 :         zclient_create_header(s, cmd, VRF_DEFAULT);
    5979           0 :         stream_putl(s, IPV4_MAX_BYTELEN);
    5980           0 :         stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
    5981           0 :         stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);
    5982             : 
    5983             :         /* Write packet size. */
    5984           0 :         stream_putw_at(s, 0, stream_get_endp(s));
    5985             : 
    5986           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    5987           0 :                 zlog_debug(
    5988             :                         "Send %s %s to %s",
    5989             :                         (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", sg_str,
    5990             :                         zebra_route_string(client->proto));
    5991             : 
    5992           0 :         if (cmd == ZEBRA_VXLAN_SG_ADD)
    5993           0 :                 client->vxlan_sg_add_cnt++;
    5994             :         else
    5995           0 :                 client->vxlan_sg_del_cnt++;
    5996             : 
    5997           0 :         return zserv_send_message(client, s);
    5998             : }
    5999             : 
    6000           0 : static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
    6001             : {
    6002           0 :         const struct zebra_vxlan_sg *vxlan_sg = p;
    6003             : 
    6004           0 :         return (jhash_2words(vxlan_sg->sg.src.s_addr,
    6005           0 :                                 vxlan_sg->sg.grp.s_addr, 0));
    6006             : }
    6007             : 
    6008           0 : static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
    6009             : {
    6010           0 :         const struct zebra_vxlan_sg *sg1 = p1;
    6011           0 :         const struct zebra_vxlan_sg *sg2 = p2;
    6012             : 
    6013           0 :         return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
    6014           0 :                 && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
    6015             : }
    6016             : 
    6017           0 : static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
    6018             :                                                  struct prefix_sg *sg)
    6019             : {
    6020           0 :         struct zebra_vxlan_sg *vxlan_sg;
    6021             : 
    6022           0 :         vxlan_sg = XCALLOC(MTYPE_ZVXLAN_SG, sizeof(*vxlan_sg));
    6023             : 
    6024           0 :         vxlan_sg->zvrf = zvrf;
    6025           0 :         vxlan_sg->sg = *sg;
    6026           0 :         prefix_sg2str(sg, vxlan_sg->sg_str);
    6027             : 
    6028           0 :         vxlan_sg = hash_get(zvrf->vxlan_sg_table, vxlan_sg, hash_alloc_intern);
    6029             : 
    6030           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    6031           0 :                 zlog_debug("vxlan SG %s created", vxlan_sg->sg_str);
    6032             : 
    6033           0 :         return vxlan_sg;
    6034             : }
    6035             : 
    6036           0 : static struct zebra_vxlan_sg *zebra_vxlan_sg_find(struct zebra_vrf *zvrf,
    6037             :                                                   struct prefix_sg *sg)
    6038             : {
    6039           0 :         struct zebra_vxlan_sg lookup;
    6040             : 
    6041           0 :         lookup.sg = *sg;
    6042           0 :         return hash_lookup(zvrf->vxlan_sg_table, &lookup);
    6043             : }
    6044             : 
    6045           0 : static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
    6046             :                                                  struct prefix_sg *sg)
    6047             : {
    6048           0 :         struct zebra_vxlan_sg *vxlan_sg;
    6049           0 :         struct zebra_vxlan_sg *parent = NULL;
    6050           0 :         struct in_addr sip;
    6051             : 
    6052           0 :         vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
    6053           0 :         if (vxlan_sg)
    6054             :                 return vxlan_sg;
    6055             : 
    6056             :         /* create a *G entry for every BUM group implicitly -
    6057             :          * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
    6058             :          * 2. the XG entry is used by pimd to setup the
    6059             :          * vxlan-termination-mroute
    6060             :          */
    6061           0 :         if (sg->src.s_addr != INADDR_ANY) {
    6062           0 :                 memset(&sip, 0, sizeof(sip));
    6063           0 :                 parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
    6064           0 :                 if (!parent)
    6065             :                         return NULL;
    6066             :         }
    6067             : 
    6068           0 :         vxlan_sg = zebra_vxlan_sg_new(zvrf, sg);
    6069             : 
    6070           0 :         zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str,
    6071             :                         ZEBRA_VXLAN_SG_ADD);
    6072             : 
    6073           0 :         return vxlan_sg;
    6074             : }
    6075             : 
    6076           0 : static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
    6077             : {
    6078           0 :         struct in_addr sip;
    6079           0 :         struct zebra_vrf *zvrf;
    6080             : 
    6081           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    6082           0 :         if (!zvrf)
    6083           0 :                 return;
    6084             : 
    6085             :         /* On SG entry deletion remove the reference to its parent XG
    6086             :          * entry
    6087             :          */
    6088           0 :         if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
    6089           0 :                 memset(&sip, 0, sizeof(sip));
    6090           0 :                 zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
    6091             :         }
    6092             : 
    6093           0 :         zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
    6094           0 :                         vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
    6095             : 
    6096           0 :         hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
    6097             : 
    6098           0 :         if (IS_ZEBRA_DEBUG_VXLAN)
    6099           0 :                 zlog_debug("VXLAN SG %s deleted", vxlan_sg->sg_str);
    6100             : 
    6101           0 :         XFREE(MTYPE_ZVXLAN_SG, vxlan_sg);
    6102             : }
    6103             : 
    6104           0 : static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
    6105             :                 struct in_addr sip, struct in_addr mcast_grp)
    6106             : {
    6107           0 :         struct zebra_vxlan_sg *vxlan_sg;
    6108           0 :         struct prefix_sg sg;
    6109             : 
    6110           0 :         sg.family = AF_INET;
    6111           0 :         sg.prefixlen = IPV4_MAX_BYTELEN;
    6112           0 :         sg.src = sip;
    6113           0 :         sg.grp = mcast_grp;
    6114           0 :         vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
    6115           0 :         if (!vxlan_sg)
    6116           0 :                 return;
    6117             : 
    6118           0 :         if (vxlan_sg->ref_cnt)
    6119           0 :                 --vxlan_sg->ref_cnt;
    6120             : 
    6121           0 :         if (!vxlan_sg->ref_cnt)
    6122           0 :                 zebra_vxlan_sg_del(vxlan_sg);
    6123             : }
    6124             : 
    6125           0 : static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
    6126             :                                                     struct in_addr sip,
    6127             :                                                     struct in_addr mcast_grp)
    6128             : {
    6129           0 :         struct zebra_vxlan_sg *vxlan_sg;
    6130           0 :         struct prefix_sg sg;
    6131             : 
    6132           0 :         sg.family = AF_INET;
    6133           0 :         sg.prefixlen = IPV4_MAX_BYTELEN;
    6134           0 :         sg.src = sip;
    6135           0 :         sg.grp = mcast_grp;
    6136           0 :         vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
    6137           0 :         if (vxlan_sg)
    6138           0 :                 ++vxlan_sg->ref_cnt;
    6139             : 
    6140           0 :         return vxlan_sg;
    6141             : }
    6142             : 
    6143           0 : static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
    6144             :                 struct in_addr mcast_grp)
    6145             : {
    6146           0 :         struct zebra_vrf *zvrf;
    6147             : 
    6148           0 :         if (local_vtep_ip.s_addr == INADDR_ANY
    6149           0 :             || mcast_grp.s_addr == INADDR_ANY)
    6150             :                 return;
    6151             : 
    6152           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    6153           0 :         if (!zvrf)
    6154             :                 return;
    6155             : 
    6156           0 :         zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
    6157             : }
    6158             : 
    6159           0 : static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
    6160             :                                 struct in_addr mcast_grp)
    6161             : {
    6162           0 :         struct zebra_vrf *zvrf;
    6163             : 
    6164           0 :         if (local_vtep_ip.s_addr == INADDR_ANY
    6165           0 :             || mcast_grp.s_addr == INADDR_ANY)
    6166             :                 return;
    6167             : 
    6168           0 :         zvrf = vrf_info_lookup(VRF_DEFAULT);
    6169           0 :         if (!zvrf)
    6170             :                 return;
    6171           0 :         zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
    6172             : }
    6173             : 
    6174           0 : static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
    6175             : {
    6176           0 :         struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
    6177             : 
    6178             :         /* increment the ref count against (*,G) to prevent them from being
    6179             :          * deleted
    6180             :          */
    6181           0 :         if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
    6182           0 :                 ++vxlan_sg->ref_cnt;
    6183           0 : }
    6184             : 
    6185           0 : static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
    6186             : {
    6187           0 :         struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
    6188             : 
    6189             :         /* decrement the dummy ref count against (*,G) to delete them */
    6190           0 :         if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
    6191           0 :                 if (vxlan_sg->ref_cnt)
    6192           0 :                         --vxlan_sg->ref_cnt;
    6193           0 :                 if (!vxlan_sg->ref_cnt)
    6194           0 :                         zebra_vxlan_sg_del(vxlan_sg);
    6195             :         }
    6196           0 : }
    6197             : 
    6198           0 : static void zebra_vxlan_sg_cleanup(struct hash_bucket *bucket, void *arg)
    6199             : {
    6200           0 :         struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
    6201             : 
    6202           0 :         zebra_vxlan_sg_del(vxlan_sg);
    6203           0 : }
    6204             : 
    6205           8 : static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf)
    6206             : {
    6207             :         /* increment the ref count against (*,G) to prevent them from being
    6208             :          * deleted
    6209             :          */
    6210           8 :         hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_pre_cleanup, NULL);
    6211             : 
    6212           8 :         hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL);
    6213             : 
    6214             :         /* decrement the dummy ref count against the XG entries */
    6215           8 :         hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_post_cleanup, NULL);
    6216           8 : }
    6217             : 
    6218           0 : static void zebra_vxlan_sg_replay_send(struct hash_bucket *bucket, void *arg)
    6219             : {
    6220           0 :         struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
    6221             : 
    6222           0 :         zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg,
    6223           0 :                         vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD);
    6224           0 : }
    6225             : 
    6226             : /* Handle message from client to replay vxlan SG entries */
    6227           4 : void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS)
    6228             : {
    6229           4 :         if (IS_ZEBRA_DEBUG_VXLAN)
    6230           0 :                 zlog_debug("VxLAN SG updates to PIM, start");
    6231             : 
    6232           4 :         SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
    6233             : 
    6234           4 :         if (!EVPN_ENABLED(zvrf)) {
    6235           4 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    6236           0 :                         zlog_debug("VxLAN SG replay request on unexpected vrf %d",
    6237             :                                    zvrf->vrf->vrf_id);
    6238           4 :                 return;
    6239             :         }
    6240             : 
    6241           0 :         hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL);
    6242             : }
    6243             : 
    6244             : 
    6245             : /* Cleanup EVPN configuration of a specific VRF */
    6246           0 : static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
    6247             : {
    6248           0 :         struct zebra_l3vni *zl3vni = NULL;
    6249             : 
    6250           0 :         zvrf->advertise_all_vni = 0;
    6251           0 :         zvrf->advertise_gw_macip = 0;
    6252           0 :         zvrf->advertise_svi_macip = 0;
    6253           0 :         zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
    6254             : 
    6255           0 :         hash_iterate(zvrf->evpn_table, zebra_evpn_cfg_cleanup, NULL);
    6256             : 
    6257           0 :         if (zvrf->l3vni)
    6258           0 :                 zl3vni = zl3vni_lookup(zvrf->l3vni);
    6259           0 :         if (zl3vni) {
    6260             :                 /* delete and uninstall all rmacs */
    6261           0 :                 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
    6262             :                              zl3vni);
    6263             :                 /* delete and uninstall all next-hops */
    6264           0 :                 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
    6265             :                              zl3vni);
    6266             :         }
    6267           0 : }
    6268             : 
    6269             : /* Cleanup BGP EVPN configuration upon client disconnect */
    6270           0 : static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client)
    6271             : {
    6272           0 :         struct vrf *vrf;
    6273           0 :         struct zebra_vrf *zvrf;
    6274             : 
    6275           0 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
    6276           0 :                 zvrf = vrf->info;
    6277           0 :                 if (zvrf)
    6278           0 :                         zebra_evpn_vrf_cfg_cleanup(zvrf);
    6279             :         }
    6280             : 
    6281           0 :         return 0;
    6282             : }
    6283             : 
    6284           4 : static int zebra_evpn_pim_cfg_clean_up(struct zserv *client)
    6285             : {
    6286           4 :         struct zebra_vrf *zvrf = zebra_vrf_get_evpn();
    6287             : 
    6288           4 :         if (CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) {
    6289           4 :                 if (IS_ZEBRA_DEBUG_VXLAN)
    6290           0 :                         zlog_debug("VxLAN SG updates to PIM, stop");
    6291           4 :                 UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
    6292             :         }
    6293             : 
    6294           4 :         return 0;
    6295             : }
    6296             : 
    6297          12 : static int zebra_evpn_cfg_clean_up(struct zserv *client)
    6298             : {
    6299          12 :         if (client->proto == ZEBRA_ROUTE_BGP)
    6300           0 :                 return zebra_evpn_bgp_cfg_clean_up(client);
    6301             : 
    6302          12 :         if (client->proto == ZEBRA_ROUTE_PIM)
    6303           4 :                 return zebra_evpn_pim_cfg_clean_up(client);
    6304             : 
    6305             :         return 0;
    6306             : }
    6307             : 
    6308             : /*
    6309             :  * Handle results for vxlan dataplane operations.
    6310             :  */
    6311           0 : extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
    6312             : {
    6313           0 :         return;
    6314             : }
    6315             : 
    6316             : /* Config knob for accepting lower sequence numbers */
    6317           0 : void zebra_vxlan_set_accept_bgp_seq(bool set)
    6318             : {
    6319           0 :         accept_bgp_seq = set;
    6320           0 : }
    6321             : 
    6322           0 : bool zebra_vxlan_get_accept_bgp_seq(void)
    6323             : {
    6324           0 :         return accept_bgp_seq;
    6325             : }
    6326             : 
    6327             : /* Cleanup BGP EVPN configuration upon client disconnect */
    6328           4 : extern void zebra_evpn_init(void)
    6329             : {
    6330           4 :         hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
    6331           4 : }

Generated by: LCOV version v1.16-topotato