back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_evpn_vty.c (source / functions) Hit Total Coverage
Test: test_bgp_distance_change.py::BGPDistanceChange Lines: 104 3388 3.1 %
Date: 2023-02-24 18:37:13 Functions: 1 147 0.7 %

          Line data    Source code
       1             : /* Ethernet-VPN Packet and vty Processing File
       2             :  * Copyright (C) 2017 6WIND
       3             :  *
       4             :  * This file is part of FRRouting
       5             :  *
       6             :  * FRRouting is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * FRRouting is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : #include "command.h"
      23             : #include "prefix.h"
      24             : #include "lib/json.h"
      25             : #include "lib/printfrr.h"
      26             : #include "lib/vxlan.h"
      27             : #include "stream.h"
      28             : 
      29             : #include "bgpd/bgpd.h"
      30             : #include "bgpd/bgp_table.h"
      31             : #include "bgpd/bgp_attr.h"
      32             : #include "bgpd/bgp_route.h"
      33             : #include "bgpd/bgp_mplsvpn.h"
      34             : #include "bgpd/bgp_vpn.h"
      35             : #include "bgpd/bgp_evpn_vty.h"
      36             : #include "bgpd/bgp_evpn.h"
      37             : #include "bgpd/bgp_evpn_private.h"
      38             : #include "bgpd/bgp_evpn_mh.h"
      39             : #include "bgpd/bgp_zebra.h"
      40             : #include "bgpd/bgp_vty.h"
      41             : #include "bgpd/bgp_errors.h"
      42             : #include "bgpd/bgp_ecommunity.h"
      43             : #include "bgpd/bgp_lcommunity.h"
      44             : #include "bgpd/bgp_community.h"
      45             : 
      46             : #define SHOW_DISPLAY_STANDARD 0
      47             : #define SHOW_DISPLAY_TAGS 1
      48             : #define SHOW_DISPLAY_OVERLAY 2
      49             : #define VNI_STR_LEN 32
      50             : 
      51             : /*
      52             :  * Context for VNI hash walk - used by callbacks.
      53             :  */
      54             : struct vni_walk_ctx {
      55             :         struct bgp *bgp;
      56             :         struct vty *vty;
      57             :         struct in_addr vtep_ip;
      58             :         json_object *json;
      59             :         int detail;
      60             :         int type;
      61             :         bool mac_table;
      62             : };
      63             : 
      64           0 : int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx,
      65             :                                 enum overlay_index_type *oly)
      66             : {
      67           0 :         *oly = OVERLAY_INDEX_TYPE_NONE;
      68           0 :         if (argv_find(argv, argc, "gateway-ip", oly_idx))
      69           0 :                 *oly = OVERLAY_INDEX_GATEWAY_IP;
      70           0 :         return 1;
      71             : }
      72             : 
      73           0 : static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
      74             :                                   json_object *json)
      75             : {
      76           0 :         const uint8_t *pnt;
      77           0 :         uint8_t type, sub_type;
      78           0 :         struct ecommunity_as eas;
      79           0 :         struct ecommunity_ip eip;
      80           0 :         struct listnode *node, *nnode;
      81           0 :         struct bgp *tmp_bgp_vrf = NULL;
      82           0 :         json_object *json_rt = NULL;
      83           0 :         json_object *json_vrfs = NULL;
      84           0 :         char rt_buf[RT_ADDRSTRLEN];
      85             : 
      86           0 :         if (json) {
      87           0 :                 json_rt = json_object_new_object();
      88           0 :                 json_vrfs = json_object_new_array();
      89             :         }
      90             : 
      91           0 :         pnt = (uint8_t *)&irt->rt.val;
      92           0 :         type = *pnt++;
      93           0 :         sub_type = *pnt++;
      94           0 :         if (sub_type != ECOMMUNITY_ROUTE_TARGET)
      95           0 :                 return;
      96             : 
      97           0 :         memset(&eas, 0, sizeof(eas));
      98           0 :         switch (type) {
      99           0 :         case ECOMMUNITY_ENCODE_AS:
     100           0 :                 eas.as = (*pnt++ << 8);
     101           0 :                 eas.as |= (*pnt++);
     102           0 :                 ptr_get_be32(pnt, &eas.val);
     103             : 
     104           0 :                 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
     105             : 
     106           0 :                 if (json)
     107           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     108             :                 else
     109           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     110             : 
     111             :                 break;
     112             : 
     113           0 :         case ECOMMUNITY_ENCODE_IP:
     114           0 :                 memcpy(&eip.ip, pnt, 4);
     115           0 :                 pnt += 4;
     116           0 :                 eip.val = (*pnt++ << 8);
     117           0 :                 eip.val |= (*pnt++);
     118             : 
     119           0 :                 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
     120             : 
     121           0 :                 if (json)
     122           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     123             :                 else
     124           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     125             : 
     126             :                 break;
     127             : 
     128             :         case ECOMMUNITY_ENCODE_AS4:
     129           0 :                 pnt = ptr_get_be32(pnt, &eas.val);
     130           0 :                 eas.val = (*pnt++ << 8);
     131           0 :                 eas.val |= (*pnt++);
     132             : 
     133           0 :                 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
     134             : 
     135           0 :                 if (json)
     136           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     137             :                 else
     138           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     139             : 
     140             :                 break;
     141             : 
     142             :         default:
     143             :                 return;
     144             :         }
     145             : 
     146           0 :         if (!json) {
     147           0 :                 vty_out(vty,
     148             :                         "\nList of VRFs importing routes with this route-target:\n");
     149             :         }
     150             : 
     151           0 :         for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
     152           0 :                 if (json)
     153           0 :                         json_object_array_add(
     154             :                                 json_vrfs,
     155             :                                 json_object_new_string(
     156             :                                         vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
     157             :                 else
     158           0 :                         vty_out(vty, "  %s\n",
     159             :                                 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
     160             :         }
     161             : 
     162           0 :         if (json) {
     163           0 :                 json_object_object_add(json_rt, "vrfs", json_vrfs);
     164           0 :                 json_object_object_add(json, rt_buf, json_rt);
     165             :         }
     166             : }
     167             : 
     168           0 : static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
     169             : {
     170           0 :         json_object *json = NULL;
     171           0 :         struct vty *vty = NULL;
     172           0 :         struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
     173             : 
     174           0 :         vty = (struct vty *)args[0];
     175           0 :         json = (struct json_object *)args[1];
     176             : 
     177           0 :         display_vrf_import_rt(vty, irt, json);
     178           0 : }
     179             : 
     180           0 : static void display_import_rt(struct vty *vty, struct irt_node *irt,
     181             :                               json_object *json)
     182             : {
     183           0 :         const uint8_t *pnt;
     184           0 :         uint8_t type, sub_type;
     185           0 :         struct ecommunity_as eas;
     186           0 :         struct ecommunity_ip eip;
     187           0 :         struct listnode *node, *nnode;
     188           0 :         struct bgpevpn *tmp_vpn;
     189           0 :         json_object *json_rt = NULL;
     190           0 :         json_object *json_vnis = NULL;
     191           0 :         char rt_buf[RT_ADDRSTRLEN];
     192             : 
     193           0 :         if (json) {
     194           0 :                 json_rt = json_object_new_object();
     195           0 :                 json_vnis = json_object_new_array();
     196             :         }
     197             : 
     198             :         /* TODO: This needs to go into a function */
     199             : 
     200           0 :         pnt = (uint8_t *)&irt->rt.val;
     201           0 :         type = *pnt++;
     202           0 :         sub_type = *pnt++;
     203           0 :         if (sub_type != ECOMMUNITY_ROUTE_TARGET)
     204           0 :                 return;
     205             : 
     206           0 :         memset(&eas, 0, sizeof(eas));
     207           0 :         switch (type) {
     208           0 :         case ECOMMUNITY_ENCODE_AS:
     209           0 :                 eas.as = (*pnt++ << 8);
     210           0 :                 eas.as |= (*pnt++);
     211           0 :                 ptr_get_be32(pnt, &eas.val);
     212             : 
     213           0 :                 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
     214             : 
     215           0 :                 if (json)
     216           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     217             :                 else
     218           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     219             : 
     220             :                 break;
     221             : 
     222           0 :         case ECOMMUNITY_ENCODE_IP:
     223           0 :                 memcpy(&eip.ip, pnt, 4);
     224           0 :                 pnt += 4;
     225           0 :                 eip.val = (*pnt++ << 8);
     226           0 :                 eip.val |= (*pnt++);
     227             : 
     228           0 :                 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
     229             : 
     230           0 :                 if (json)
     231           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     232             :                 else
     233           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     234             : 
     235             :                 break;
     236             : 
     237             :         case ECOMMUNITY_ENCODE_AS4:
     238           0 :                 pnt = ptr_get_be32(pnt, &eas.val);
     239           0 :                 eas.val = (*pnt++ << 8);
     240           0 :                 eas.val |= (*pnt++);
     241             : 
     242           0 :                 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
     243             : 
     244           0 :                 if (json)
     245           0 :                         json_object_string_add(json_rt, "rt", rt_buf);
     246             :                 else
     247           0 :                         vty_out(vty, "Route-target: %s", rt_buf);
     248             : 
     249             :                 break;
     250             : 
     251             :         default:
     252             :                 return;
     253             :         }
     254             : 
     255           0 :         if (!json) {
     256           0 :                 vty_out(vty,
     257             :                         "\nList of VNIs importing routes with this route-target:\n");
     258             :         }
     259             : 
     260           0 :         for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
     261           0 :                 if (json)
     262           0 :                         json_object_array_add(
     263           0 :                                 json_vnis, json_object_new_int(tmp_vpn->vni));
     264             :                 else
     265           0 :                         vty_out(vty, "  %u\n", tmp_vpn->vni);
     266             :         }
     267             : 
     268           0 :         if (json) {
     269           0 :                 json_object_object_add(json_rt, "vnis", json_vnis);
     270           0 :                 json_object_object_add(json, rt_buf, json_rt);
     271             :         }
     272             : }
     273             : 
     274           0 : static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
     275             : {
     276           0 :         json_object *json = NULL;
     277           0 :         struct vty *vty = NULL;
     278           0 :         struct irt_node *irt = (struct irt_node *)bucket->data;
     279             : 
     280           0 :         vty = args[0];
     281           0 :         json = args[1];
     282             : 
     283           0 :         display_import_rt(vty, irt, json);
     284             : 
     285           0 :         return;
     286             : }
     287             : 
     288           0 : static void bgp_evpn_show_route_rd_header(struct vty *vty,
     289             :                                           struct bgp_dest *rd_dest,
     290             :                                           json_object *json, char *rd_str,
     291             :                                           int len)
     292             : {
     293           0 :         uint16_t type;
     294           0 :         struct rd_as rd_as;
     295           0 :         struct rd_ip rd_ip;
     296           0 :         const uint8_t *pnt;
     297           0 :         const struct prefix *p = bgp_dest_get_prefix(rd_dest);
     298             : 
     299           0 :         pnt = p->u.val;
     300             : 
     301             :         /* Decode RD type. */
     302           0 :         type = decode_rd_type(pnt);
     303             : 
     304           0 :         if (!json)
     305           0 :                 vty_out(vty, "Route Distinguisher: ");
     306             : 
     307           0 :         switch (type) {
     308           0 :         case RD_TYPE_AS:
     309           0 :                 decode_rd_as(pnt + 2, &rd_as);
     310           0 :                 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
     311           0 :                 if (json)
     312           0 :                         json_object_string_add(json, "rd", rd_str);
     313             :                 else
     314           0 :                         vty_out(vty, "%s\n", rd_str);
     315             :                 break;
     316             : 
     317           0 :         case RD_TYPE_AS4:
     318           0 :                 decode_rd_as4(pnt + 2, &rd_as);
     319           0 :                 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
     320           0 :                 if (json)
     321           0 :                         json_object_string_add(json, "rd", rd_str);
     322             :                 else
     323           0 :                         vty_out(vty, "%s\n", rd_str);
     324             :                 break;
     325             : 
     326           0 :         case RD_TYPE_IP:
     327           0 :                 decode_rd_ip(pnt + 2, &rd_ip);
     328           0 :                 snprintfrr(rd_str, len, "%pI4:%d", &rd_ip.ip, rd_ip.val);
     329           0 :                 if (json)
     330           0 :                         json_object_string_add(json, "rd", rd_str);
     331             :                 else
     332           0 :                         vty_out(vty, "%s\n", rd_str);
     333             :                 break;
     334             : 
     335           0 :         default:
     336           0 :                 if (json) {
     337           0 :                         snprintf(rd_str, len, "Unknown");
     338           0 :                         json_object_string_add(json, "rd", rd_str);
     339             :                 } else {
     340           0 :                         snprintf(rd_str, len, "Unknown RD type");
     341           0 :                         vty_out(vty, "%s\n", rd_str);
     342             :                 }
     343             :                 break;
     344             :         }
     345           0 : }
     346             : 
     347           0 : static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
     348             :                                        uint64_t tbl_ver, json_object *json)
     349             : {
     350           0 :         char ri_header[] =
     351             :                 "   Network          Next Hop            Metric LocPrf Weight Path\n";
     352             : 
     353           0 :         if (json)
     354           0 :                 return;
     355             : 
     356           0 :         vty_out(vty,
     357             :                 "BGP table version is %" PRIu64 ", local router ID is %pI4\n",
     358             :                 tbl_ver, &bgp->router_id);
     359           0 :         vty_out(vty,
     360             :                 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
     361           0 :         vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
     362           0 :         vty_out(vty,
     363             :                 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
     364           0 :         vty_out(vty,
     365             :                 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
     366           0 :         vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
     367           0 :         vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
     368           0 :         vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
     369           0 :         vty_out(vty, "%s", ri_header);
     370             : }
     371             : 
     372           0 : static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
     373             :                           json_object *json)
     374             : {
     375           0 :         char *ecom_str;
     376           0 :         struct listnode *node, *nnode;
     377           0 :         struct vrf_route_target *l3rt;
     378           0 :         json_object *json_import_rtl = NULL;
     379           0 :         json_object *json_export_rtl = NULL;
     380           0 :         char buf2[ETHER_ADDR_STRLEN];
     381             : 
     382           0 :         json_import_rtl = json_export_rtl = 0;
     383             : 
     384           0 :         if (json) {
     385           0 :                 json_import_rtl = json_object_new_array();
     386           0 :                 json_export_rtl = json_object_new_array();
     387           0 :                 json_object_int_add(json, "vni", bgp_vrf->l3vni);
     388           0 :                 json_object_string_add(json, "type", "L3");
     389           0 :                 json_object_string_add(json, "inKernel", "True");
     390           0 :                 json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
     391           0 :                 json_object_string_addf(json, "originatorIp", "%pI4",
     392             :                                         &bgp_vrf->originator_ip);
     393           0 :                 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
     394           0 :                 json_object_string_add(json, "advertiseSviMacIp", "n/a");
     395           0 :                 json_object_string_add(json, "advertisePip",
     396           0 :                                        bgp_vrf->evpn_info->advertise_pip ?
     397             :                                        "Enabled" : "Disabled");
     398           0 :                 json_object_string_addf(json, "sysIP", "%pI4",
     399           0 :                                         &bgp_vrf->evpn_info->pip_ip);
     400           0 :                 json_object_string_add(json, "sysMac",
     401           0 :                                 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
     402             :                                                buf2, sizeof(buf2)));
     403           0 :                 json_object_string_add(json, "rmac",
     404           0 :                                 prefix_mac2str(&bgp_vrf->rmac,
     405             :                                                buf2, sizeof(buf2)));
     406             :         } else {
     407           0 :                 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
     408           0 :                 vty_out(vty, " (known to the kernel)");
     409           0 :                 vty_out(vty, "\n");
     410             : 
     411           0 :                 vty_out(vty, "  Type: %s\n", "L3");
     412           0 :                 vty_out(vty, "  Tenant VRF: %s\n",
     413             :                         vrf_id_to_name(bgp_vrf->vrf_id));
     414           0 :                 vty_out(vty, "  RD: %pRD\n", &bgp_vrf->vrf_prd);
     415           0 :                 vty_out(vty, "  Originator IP: %pI4\n",
     416             :                         &bgp_vrf->originator_ip);
     417           0 :                 vty_out(vty, "  Advertise-gw-macip : %s\n", "n/a");
     418           0 :                 vty_out(vty, "  Advertise-svi-macip : %s\n", "n/a");
     419           0 :                 vty_out(vty, "  Advertise-pip: %s\n",
     420           0 :                         bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
     421           0 :                 vty_out(vty, "  System-IP: %pI4\n",
     422           0 :                         &bgp_vrf->evpn_info->pip_ip);
     423           0 :                 vty_out(vty, "  System-MAC: %s\n",
     424           0 :                                 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
     425             :                                                buf2, sizeof(buf2)));
     426           0 :                 vty_out(vty, "  Router-MAC: %s\n",
     427           0 :                                 prefix_mac2str(&bgp_vrf->rmac,
     428             :                                                buf2, sizeof(buf2)));
     429             :         }
     430             : 
     431           0 :         if (!json)
     432           0 :                 vty_out(vty, "  Import Route Target:\n");
     433             : 
     434           0 :         for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt)) {
     435           0 :                 ecom_str = ecommunity_ecom2str(l3rt->ecom,
     436             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
     437             : 
     438           0 :                 if (json)
     439           0 :                         json_object_array_add(json_import_rtl,
     440             :                                               json_object_new_string(ecom_str));
     441             :                 else
     442           0 :                         vty_out(vty, "    %s\n", ecom_str);
     443             : 
     444           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
     445             :         }
     446             : 
     447           0 :         if (json)
     448           0 :                 json_object_object_add(json, "importRts", json_import_rtl);
     449             :         else
     450           0 :                 vty_out(vty, "  Export Route Target:\n");
     451             : 
     452           0 :         for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, l3rt)) {
     453           0 :                 ecom_str = ecommunity_ecom2str(l3rt->ecom,
     454             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
     455             : 
     456           0 :                 if (json)
     457           0 :                         json_object_array_add(json_export_rtl,
     458             :                                               json_object_new_string(ecom_str));
     459             :                 else
     460           0 :                         vty_out(vty, "    %s\n", ecom_str);
     461             : 
     462           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
     463             :         }
     464             : 
     465           0 :         if (json)
     466           0 :                 json_object_object_add(json, "exportRts", json_export_rtl);
     467           0 : }
     468             : 
     469           0 : static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
     470             : {
     471           0 :         char *ecom_str;
     472           0 :         struct listnode *node, *nnode;
     473           0 :         struct ecommunity *ecom;
     474           0 :         json_object *json_import_rtl = NULL;
     475           0 :         json_object *json_export_rtl = NULL;
     476           0 :         struct bgp *bgp_evpn;
     477             : 
     478           0 :         bgp_evpn = bgp_get_evpn();
     479             : 
     480           0 :         if (json) {
     481           0 :                 json_import_rtl = json_object_new_array();
     482           0 :                 json_export_rtl = json_object_new_array();
     483           0 :                 json_object_int_add(json, "vni", vpn->vni);
     484           0 :                 json_object_string_add(json, "type", "L2");
     485           0 :                 json_object_string_add(json, "inKernel",
     486           0 :                                        is_vni_live(vpn) ? "True" : "False");
     487           0 :                 json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
     488           0 :                 json_object_string_addf(json, "originatorIp", "%pI4",
     489             :                                         &vpn->originator_ip);
     490           0 :                 json_object_string_addf(json, "mcastGroup", "%pI4",
     491             :                                         &vpn->mcast_grp);
     492             :                 /* per vni knob is enabled -- Enabled
     493             :                  * Global knob is enabled  -- Active
     494             :                  * default  -- Disabled
     495             :                  */
     496           0 :                 if (!vpn->advertise_gw_macip &&
     497           0 :                     bgp_evpn && bgp_evpn->advertise_gw_macip)
     498           0 :                         json_object_string_add(json, "advertiseGatewayMacip",
     499             :                                                "Active");
     500           0 :                 else if (vpn->advertise_gw_macip)
     501           0 :                         json_object_string_add(json, "advertiseGatewayMacip",
     502             :                                                "Enabled");
     503             :                 else
     504           0 :                         json_object_string_add(json, "advertiseGatewayMacip",
     505             :                                                "Disabled");
     506           0 :                 if (!vpn->advertise_svi_macip && bgp_evpn &&
     507           0 :                     bgp_evpn->evpn_info->advertise_svi_macip)
     508           0 :                         json_object_string_add(json, "advertiseSviMacIp",
     509             :                                                "Active");
     510           0 :                 else if (vpn->advertise_svi_macip)
     511           0 :                         json_object_string_add(json, "advertiseSviMacIp",
     512             :                                                "Enabled");
     513             :                 else
     514           0 :                         json_object_string_add(json, "advertiseSviMacIp",
     515             :                                                "Disabled");
     516           0 :                 json_object_string_add(
     517             :                         json, "sviInterface",
     518             :                         ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
     519             :         } else {
     520           0 :                 vty_out(vty, "VNI: %u", vpn->vni);
     521           0 :                 if (is_vni_live(vpn))
     522           0 :                         vty_out(vty, " (known to the kernel)");
     523           0 :                 vty_out(vty, "\n");
     524             : 
     525           0 :                 vty_out(vty, "  Type: %s\n", "L2");
     526           0 :                 vty_out(vty, "  Tenant-Vrf: %s\n",
     527             :                         vrf_id_to_name(vpn->tenant_vrf_id));
     528           0 :                 vty_out(vty, "  RD: %pRD\n", &vpn->prd);
     529           0 :                 vty_out(vty, "  Originator IP: %pI4\n", &vpn->originator_ip);
     530           0 :                 vty_out(vty, "  Mcast group: %pI4\n", &vpn->mcast_grp);
     531           0 :                 if (!vpn->advertise_gw_macip &&
     532           0 :                     bgp_evpn && bgp_evpn->advertise_gw_macip)
     533           0 :                         vty_out(vty, "  Advertise-gw-macip : %s\n",
     534             :                                 "Active");
     535           0 :                 else if (vpn->advertise_gw_macip)
     536           0 :                         vty_out(vty, "  Advertise-gw-macip : %s\n",
     537             :                                 "Enabled");
     538             :                 else
     539           0 :                         vty_out(vty, "  Advertise-gw-macip : %s\n",
     540             :                                 "Disabled");
     541           0 :                 if (!vpn->advertise_svi_macip && bgp_evpn &&
     542           0 :                     bgp_evpn->evpn_info->advertise_svi_macip)
     543           0 :                         vty_out(vty, "  Advertise-svi-macip : %s\n",
     544             :                                 "Active");
     545           0 :                 else if (vpn->advertise_svi_macip)
     546           0 :                         vty_out(vty, "  Advertise-svi-macip : %s\n",
     547             :                                 "Enabled");
     548             :                 else
     549           0 :                         vty_out(vty, "  Advertise-svi-macip : %s\n",
     550             :                                 "Disabled");
     551           0 :                 vty_out(vty, "  SVI interface : %s\n",
     552             :                         ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
     553             :         }
     554             : 
     555           0 :         if (!json)
     556           0 :                 vty_out(vty, "  Import Route Target:\n");
     557             : 
     558           0 :         for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
     559           0 :                 ecom_str = ecommunity_ecom2str(ecom,
     560             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
     561             : 
     562           0 :                 if (json)
     563           0 :                         json_object_array_add(json_import_rtl,
     564             :                                               json_object_new_string(ecom_str));
     565             :                 else
     566           0 :                         vty_out(vty, "    %s\n", ecom_str);
     567             : 
     568           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
     569             :         }
     570             : 
     571           0 :         if (json)
     572           0 :                 json_object_object_add(json, "importRts", json_import_rtl);
     573             :         else
     574           0 :                 vty_out(vty, "  Export Route Target:\n");
     575             : 
     576           0 :         for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
     577           0 :                 ecom_str = ecommunity_ecom2str(ecom,
     578             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
     579             : 
     580           0 :                 if (json)
     581           0 :                         json_object_array_add(json_export_rtl,
     582             :                                               json_object_new_string(ecom_str));
     583             :                 else
     584           0 :                         vty_out(vty, "    %s\n", ecom_str);
     585             : 
     586           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
     587             :         }
     588             : 
     589           0 :         if (json)
     590           0 :                 json_object_object_add(json, "exportRts", json_export_rtl);
     591           0 : }
     592             : 
     593           0 : static void show_esi_routes(struct bgp *bgp,
     594             :                             struct bgp_evpn_es *es,
     595             :                             struct vty *vty,
     596             :                             json_object *json)
     597             : {
     598           0 :         int header = 1;
     599           0 :         struct bgp_dest *dest;
     600           0 :         struct bgp_path_info *pi;
     601           0 :         uint32_t prefix_cnt, path_cnt;
     602           0 :         uint64_t tbl_ver;
     603             : 
     604           0 :         prefix_cnt = path_cnt = 0;
     605             : 
     606           0 :         tbl_ver = es->route_table->version;
     607           0 :         for (dest = bgp_table_top(es->route_table); dest;
     608           0 :              dest = bgp_route_next(dest)) {
     609           0 :                 int add_prefix_to_json = 0;
     610           0 :                 json_object *json_paths = NULL;
     611           0 :                 json_object *json_prefix = NULL;
     612           0 :                 const struct prefix *p = bgp_dest_get_prefix(dest);
     613             : 
     614           0 :                 if (json)
     615           0 :                         json_prefix = json_object_new_object();
     616             : 
     617           0 :                 pi = bgp_dest_get_bgp_path_info(dest);
     618           0 :                 if (pi) {
     619             :                         /* Overall header/legend displayed once. */
     620           0 :                         if (header) {
     621           0 :                                 bgp_evpn_show_route_header(vty, bgp,
     622             :                                                            tbl_ver, json);
     623           0 :                                 header = 0;
     624             :                         }
     625             : 
     626           0 :                         prefix_cnt++;
     627             :                 }
     628             : 
     629           0 :                 if (json)
     630           0 :                         json_paths = json_object_new_array();
     631             : 
     632             :                 /* For EVPN, the prefix is displayed for each path (to fit in
     633             :                  * with code that already exists).
     634             :                  */
     635           0 :                 for (; pi; pi = pi->next) {
     636           0 :                         json_object *json_path = NULL;
     637             : 
     638           0 :                         if (json)
     639           0 :                                 json_path = json_object_new_array();
     640             : 
     641           0 :                         route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path,
     642             :                                       false);
     643             : 
     644           0 :                         if (json)
     645           0 :                                 json_object_array_add(json_paths, json_path);
     646             : 
     647           0 :                         path_cnt++;
     648           0 :                         add_prefix_to_json = 1;
     649             :                 }
     650             : 
     651           0 :                 if (json) {
     652           0 :                         if (add_prefix_to_json) {
     653           0 :                                 json_object_string_addf(json_prefix, "prefix",
     654             :                                                         "%pFX", p);
     655           0 :                                 json_object_int_add(json_prefix, "prefixLen",
     656           0 :                                                     p->prefixlen);
     657           0 :                                 json_object_object_add(json_prefix, "paths",
     658             :                                                        json_paths);
     659           0 :                                 json_object_object_addf(json, json_prefix,
     660             :                                                         "%pFX", p);
     661             :                         } else {
     662           0 :                                 json_object_free(json_paths);
     663           0 :                                 json_object_free(json_prefix);
     664           0 :                                 json_paths = NULL;
     665           0 :                                 json_prefix = NULL;
     666             :                         }
     667             :                 }
     668             :         }
     669             : 
     670           0 :         if (json) {
     671           0 :                 json_object_int_add(json, "numPrefix", prefix_cnt);
     672           0 :                 json_object_int_add(json, "numPaths", path_cnt);
     673             :         } else {
     674           0 :                 if (prefix_cnt == 0)
     675           0 :                         vty_out(vty, "No EVPN prefixes exist for this ESI\n");
     676             :                 else
     677           0 :                         vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
     678             :                                 prefix_cnt, path_cnt);
     679             :         }
     680           0 : }
     681             : 
     682             : /* Display all MAC-IP VNI routes linked to an ES */
     683           0 : static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,
     684             :                                            json_object *json, int detail,
     685             :                                            bool global_table)
     686             : {
     687           0 :         struct bgp_node *rn;
     688           0 :         struct bgp_path_info *pi;
     689           0 :         int header = detail ? 0 : 1;
     690           0 :         uint32_t path_cnt;
     691           0 :         struct listnode *node;
     692           0 :         struct bgp_evpn_es *es;
     693           0 :         struct bgp_path_es_info *es_info;
     694           0 :         struct bgp *bgp = bgp_get_evpn();
     695           0 :         json_object *json_paths = NULL;
     696             : 
     697           0 :         if (!bgp)
     698             :                 return;
     699             : 
     700           0 :         path_cnt = 0;
     701             : 
     702           0 :         if (json)
     703           0 :                 json_paths = json_object_new_array();
     704             : 
     705           0 :         RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
     706           0 :                 struct list *es_list;
     707             : 
     708           0 :                 if (esi && memcmp(esi, &es->esi, sizeof(*esi)))
     709           0 :                         continue;
     710             : 
     711           0 :                 if (global_table)
     712           0 :                         es_list = es->macip_global_path_list;
     713             :                 else
     714           0 :                         es_list = es->macip_evi_path_list;
     715             : 
     716           0 :                 for (ALL_LIST_ELEMENTS_RO(es_list, node, es_info)) {
     717           0 :                         json_object *json_path = NULL;
     718             : 
     719           0 :                         pi = es_info->pi;
     720           0 :                         rn = pi->net;
     721             : 
     722           0 :                         if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
     723           0 :                                 continue;
     724             : 
     725             :                         /* Overall header/legend displayed once. */
     726           0 :                         if (header) {
     727           0 :                                 bgp_evpn_show_route_header(vty, bgp, 0, json);
     728           0 :                                 header = 0;
     729             :                         }
     730             : 
     731           0 :                         path_cnt++;
     732             : 
     733           0 :                         if (json)
     734           0 :                                 json_path = json_object_new_array();
     735             : 
     736           0 :                         if (detail)
     737           0 :                                 route_vty_out_detail(
     738             :                                         vty, bgp, rn, bgp_dest_get_prefix(rn),
     739             :                                         pi, AFI_L2VPN, SAFI_EVPN,
     740             :                                         RPKI_NOT_BEING_USED, json_path);
     741             :                         else
     742           0 :                                 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
     743             :                                               json_path, false);
     744             : 
     745           0 :                         if (json)
     746           0 :                                 json_object_array_add(json_paths, json_path);
     747             :                 }
     748             :         }
     749             : 
     750           0 :         if (json) {
     751           0 :                 json_object_object_add(json, "paths", json_paths);
     752           0 :                 json_object_int_add(json, "numPaths", path_cnt);
     753             :         } else {
     754           0 :                 if (path_cnt == 0)
     755           0 :                         vty_out(vty, "There are no MAC-IP ES paths");
     756             :                 else
     757           0 :                         vty_out(vty, "\nDisplayed %u paths\n", path_cnt);
     758           0 :                 vty_out(vty, "\n");
     759             :         }
     760             : }
     761             : 
     762           0 : static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi,
     763             :                                                json_object *json, int detail)
     764             : {
     765           0 :         bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, false);
     766             : }
     767             : 
     768           0 : static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi,
     769             :                                                   json_object *json, int detail)
     770             : {
     771           0 :         bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true);
     772             : }
     773             : 
     774           0 : static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn,
     775             :                             struct vty *vty, int type, bool mac_table,
     776             :                             struct in_addr vtep_ip, json_object *json,
     777             :                             int detail)
     778             : {
     779           0 :         struct bgp_dest *dest;
     780           0 :         struct bgp_path_info *pi;
     781           0 :         struct bgp_table *table;
     782           0 :         int header = detail ? 0 : 1;
     783           0 :         uint64_t tbl_ver;
     784           0 :         uint32_t prefix_cnt, path_cnt;
     785             : 
     786           0 :         prefix_cnt = path_cnt = 0;
     787             : 
     788           0 :         if (mac_table)
     789           0 :                 table = vpn->mac_table;
     790             :         else
     791           0 :                 table = vpn->ip_table;
     792             : 
     793           0 :         tbl_ver = table->version;
     794           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
     795           0 :                 const struct prefix_evpn *evp =
     796           0 :                         (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
     797           0 :                 int add_prefix_to_json = 0;
     798           0 :                 json_object *json_paths = NULL;
     799           0 :                 json_object *json_prefix = NULL;
     800           0 :                 const struct prefix *p = bgp_dest_get_prefix(dest);
     801             : 
     802           0 :                 if (type && evp->prefix.route_type != type)
     803           0 :                         continue;
     804             : 
     805           0 :                 if (json)
     806           0 :                         json_prefix = json_object_new_object();
     807             : 
     808           0 :                 pi = bgp_dest_get_bgp_path_info(dest);
     809           0 :                 if (pi) {
     810             :                         /* Overall header/legend displayed once. */
     811           0 :                         if (header) {
     812           0 :                                 bgp_evpn_show_route_header(vty, bgp,
     813             :                                                            tbl_ver, json);
     814           0 :                                 header = 0;
     815             :                         }
     816             : 
     817           0 :                         prefix_cnt++;
     818             :                 }
     819             : 
     820           0 :                 if (json)
     821           0 :                         json_paths = json_object_new_array();
     822             : 
     823             :                 /* For EVPN, the prefix is displayed for each path (to fit in
     824             :                  * with code that already exists).
     825             :                  */
     826           0 :                 for (; pi; pi = pi->next) {
     827           0 :                         struct prefix tmp_p;
     828           0 :                         json_object *json_path = NULL;
     829             : 
     830           0 :                         if (vtep_ip.s_addr != INADDR_ANY
     831           0 :                             && !IPV4_ADDR_SAME(&(vtep_ip),
     832             :                                                &(pi->attr->nexthop)))
     833           0 :                                 continue;
     834             : 
     835           0 :                         if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
     836             :                                 /*
     837             :                                  * VNI IP/MAC table prefixes don't have MAC/IP
     838             :                                  * respectively so make sure it's set from path
     839             :                                  * info here.
     840             :                                  */
     841           0 :                                 if (is_evpn_prefix_ipaddr_none(evp)) {
     842             :                                         /* VNI MAC -> Global */
     843           0 :                                         evpn_type2_prefix_global_copy(
     844             :                                                 (struct prefix_evpn *)&tmp_p,
     845             :                                                 evp, NULL /* mac */,
     846           0 :                                                 evpn_type2_path_info_get_ip(
     847             :                                                         pi));
     848             :                                 } else {
     849             :                                         /* VNI IP -> Global */
     850           0 :                                         evpn_type2_prefix_global_copy(
     851             :                                                 (struct prefix_evpn *)&tmp_p,
     852             :                                                 evp,
     853           0 :                                                 evpn_type2_path_info_get_mac(
     854             :                                                         pi),
     855             :                                                 NULL /* ip */);
     856             :                                 }
     857             :                         } else
     858           0 :                                 memcpy(&tmp_p, p, sizeof(tmp_p));
     859             : 
     860             : 
     861           0 :                         if (json)
     862           0 :                                 json_path = json_object_new_array();
     863             : 
     864           0 :                         if (detail)
     865           0 :                                 route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,
     866             :                                                      AFI_L2VPN, SAFI_EVPN,
     867             :                                                      RPKI_NOT_BEING_USED,
     868             :                                                      json_path);
     869             : 
     870             :                         else
     871           0 :                                 route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,
     872             :                                               json_path, false);
     873             : 
     874           0 :                         if (json)
     875           0 :                                 json_object_array_add(json_paths, json_path);
     876             : 
     877           0 :                         path_cnt++;
     878           0 :                         add_prefix_to_json = 1;
     879             :                 }
     880             : 
     881           0 :                 if (json) {
     882           0 :                         if (add_prefix_to_json) {
     883           0 :                                 json_object_string_addf(json_prefix, "prefix",
     884             :                                                         "%pFX", p);
     885           0 :                                 json_object_int_add(json_prefix, "prefixLen",
     886           0 :                                                     p->prefixlen);
     887           0 :                                 json_object_object_add(json_prefix, "paths",
     888             :                                                        json_paths);
     889           0 :                                 json_object_object_addf(json, json_prefix,
     890             :                                                         "%pFX", p);
     891             :                         } else {
     892           0 :                                 json_object_free(json_paths);
     893           0 :                                 json_object_free(json_prefix);
     894           0 :                                 json_paths = NULL;
     895           0 :                                 json_prefix = NULL;
     896             :                         }
     897             :                 }
     898             :         }
     899             : 
     900           0 :         if (json) {
     901           0 :                 json_object_int_add(json, "numPrefix", prefix_cnt);
     902           0 :                 json_object_int_add(json, "numPaths", path_cnt);
     903             :         } else {
     904           0 :                 if (prefix_cnt == 0)
     905           0 :                         vty_out(vty, "No EVPN prefixes %sexist for this VNI",
     906             :                                 type ? "(of requested type) " : "");
     907             :                 else
     908           0 :                         vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
     909             :                                 prefix_cnt, path_cnt,
     910             :                                 type ? " (of requested type)" : "");
     911           0 :                 vty_out(vty, "\n");
     912             :         }
     913           0 : }
     914             : 
     915           0 : static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
     916             : {
     917           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
     918           0 :         struct vni_walk_ctx *wctx = arg;
     919           0 :         struct vty *vty = wctx->vty;
     920           0 :         json_object *json = wctx->json;
     921           0 :         json_object *json_vni = NULL;
     922           0 :         char vni_str[VNI_STR_LEN];
     923             : 
     924           0 :         snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
     925           0 :         if (json) {
     926           0 :                 json_vni = json_object_new_object();
     927           0 :                 json_object_int_add(json_vni, "vni", vpn->vni);
     928             :         } else {
     929           0 :                 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
     930             :         }
     931             : 
     932           0 :         show_vni_routes(wctx->bgp, vpn, wctx->vty, wctx->type, wctx->mac_table,
     933             :                         wctx->vtep_ip, json_vni, wctx->detail);
     934             : 
     935           0 :         if (json)
     936           0 :                 json_object_object_add(json, vni_str, json_vni);
     937           0 : }
     938             : 
     939           0 : static void show_vni_routes_all_hash(struct hash_bucket *bucket, void *arg)
     940             : {
     941           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
     942           0 :         struct vni_walk_ctx *wctx = arg;
     943           0 :         struct vty *vty = wctx->vty;
     944           0 :         json_object *json = wctx->json;
     945           0 :         json_object *json_vni = NULL;
     946           0 :         json_object *json_vni_mac = NULL;
     947           0 :         char vni_str[VNI_STR_LEN];
     948             : 
     949           0 :         snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
     950           0 :         if (json) {
     951           0 :                 json_vni = json_object_new_object();
     952           0 :                 json_object_int_add(json_vni, "vni", vpn->vni);
     953             :         } else {
     954           0 :                 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
     955             :         }
     956             : 
     957           0 :         show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, false, wctx->vtep_ip,
     958             :                         json_vni, wctx->detail);
     959             : 
     960           0 :         if (json)
     961           0 :                 json_object_object_add(json, vni_str, json_vni);
     962             : 
     963           0 :         if (json)
     964           0 :                 json_vni_mac = json_object_new_object();
     965             :         else
     966           0 :                 vty_out(vty, "\nVNI: %u MAC Table\n\n", vpn->vni);
     967             : 
     968           0 :         show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, true, wctx->vtep_ip,
     969             :                         json_vni_mac, wctx->detail);
     970             : 
     971           0 :         if (json)
     972           0 :                 json_object_object_add(json_vni, "macTable", json_vni_mac);
     973           0 : }
     974             : 
     975           0 : static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
     976             :                              json_object *json)
     977             : {
     978           0 :         json_object *json_vni = NULL;
     979           0 :         json_object *json_import_rtl = NULL;
     980           0 :         json_object *json_export_rtl = NULL;
     981           0 :         char buf1[10];
     982           0 :         char buf2[INET6_ADDRSTRLEN];
     983           0 :         char rt_buf[25];
     984           0 :         char *ecom_str;
     985           0 :         struct listnode *node, *nnode;
     986           0 :         struct vrf_route_target *l3rt;
     987             : 
     988           0 :         if (!bgp->l3vni)
     989           0 :                 return;
     990             : 
     991           0 :         if (json) {
     992           0 :                 json_vni = json_object_new_object();
     993           0 :                 json_import_rtl = json_object_new_array();
     994           0 :                 json_export_rtl = json_object_new_array();
     995             :         }
     996             : 
     997             :         /* if an l3vni is present in bgp it is live */
     998           0 :         buf1[0] = '\0';
     999           0 :         snprintf(buf1, sizeof(buf1), "*");
    1000             : 
    1001           0 :         if (json) {
    1002           0 :                 json_object_int_add(json_vni, "vni", bgp->l3vni);
    1003           0 :                 json_object_string_add(json_vni, "type", "L3");
    1004           0 :                 json_object_string_add(json_vni, "inKernel", "True");
    1005           0 :                 json_object_string_addf(json_vni, "originatorIp", "%pI4",
    1006             :                                         &bgp->originator_ip);
    1007           0 :                 json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
    1008           0 :                 json_object_string_add(json_vni, "advertiseGatewayMacip",
    1009             :                                        "n/a");
    1010           0 :                 json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
    1011           0 :                 json_object_string_add(
    1012             :                         json_vni, "advertisePip",
    1013           0 :                         bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
    1014           0 :                 json_object_string_addf(json_vni, "sysIP", "%pI4",
    1015           0 :                                         &bgp->evpn_info->pip_ip);
    1016           0 :                 json_object_string_add(json_vni, "sysMAC",
    1017           0 :                                        prefix_mac2str(&bgp->evpn_info->pip_rmac,
    1018             :                                                       buf2, sizeof(buf2)));
    1019           0 :                 json_object_string_add(
    1020             :                         json_vni, "rmac",
    1021           0 :                         prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
    1022             :         } else {
    1023           0 :                 vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3",
    1024             :                         &bgp->vrf_prd);
    1025             :         }
    1026             : 
    1027           0 :         for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, l3rt)) {
    1028           0 :                 ecom_str = ecommunity_ecom2str(l3rt->ecom,
    1029             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1030             : 
    1031           0 :                 if (json) {
    1032           0 :                         json_object_array_add(json_import_rtl,
    1033             :                                               json_object_new_string(ecom_str));
    1034             :                 } else {
    1035           0 :                         if (listcount(bgp->vrf_import_rtl) > 1)
    1036           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
    1037             :                                          ecom_str);
    1038             :                         else
    1039           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s",
    1040             :                                          ecom_str);
    1041           0 :                         vty_out(vty, " %-25s", rt_buf);
    1042             :                 }
    1043             : 
    1044           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    1045             : 
    1046             :                 /* If there are multiple import RTs we break here and show only
    1047             :                  * one */
    1048           0 :                 if (!json)
    1049             :                         break;
    1050             :         }
    1051             : 
    1052           0 :         if (json)
    1053           0 :                 json_object_object_add(json_vni, "importRTs", json_import_rtl);
    1054             : 
    1055           0 :         for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, l3rt)) {
    1056           0 :                 ecom_str = ecommunity_ecom2str(l3rt->ecom,
    1057             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1058             : 
    1059           0 :                 if (json) {
    1060           0 :                         json_object_array_add(json_export_rtl,
    1061             :                                               json_object_new_string(ecom_str));
    1062             :                 } else {
    1063           0 :                         if (listcount(bgp->vrf_export_rtl) > 1)
    1064           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
    1065             :                                          ecom_str);
    1066             :                         else
    1067           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s",
    1068             :                                          ecom_str);
    1069           0 :                         vty_out(vty, " %-25s", rt_buf);
    1070             :                 }
    1071             : 
    1072           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    1073             : 
    1074             :                 /* If there are multiple export RTs we break here and show only
    1075             :                  * one */
    1076           0 :                 if (!json) {
    1077           0 :                         vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
    1078           0 :                         break;
    1079             :                 }
    1080             :         }
    1081             : 
    1082           0 :         if (json) {
    1083           0 :                 char vni_str[VNI_STR_LEN];
    1084             : 
    1085           0 :                 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
    1086           0 :                 snprintf(vni_str, sizeof(vni_str), "%u", bgp->l3vni);
    1087           0 :                 json_object_object_add(json, vni_str, json_vni);
    1088             :         } else {
    1089           0 :                 vty_out(vty, "\n");
    1090             :         }
    1091             : }
    1092             : 
    1093           0 : static void show_vni_entry(struct hash_bucket *bucket, void *args[])
    1094             : {
    1095           0 :         struct vty *vty;
    1096           0 :         json_object *json;
    1097           0 :         json_object *json_vni = NULL;
    1098           0 :         json_object *json_import_rtl = NULL;
    1099           0 :         json_object *json_export_rtl = NULL;
    1100           0 :         struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
    1101           0 :         char buf1[10];
    1102           0 :         char rt_buf[25];
    1103           0 :         char *ecom_str;
    1104           0 :         struct listnode *node, *nnode;
    1105           0 :         struct ecommunity *ecom;
    1106           0 :         struct bgp *bgp_evpn;
    1107             : 
    1108           0 :         vty = args[0];
    1109           0 :         json = args[1];
    1110             : 
    1111           0 :         bgp_evpn = bgp_get_evpn();
    1112             : 
    1113           0 :         if (json) {
    1114           0 :                 json_vni = json_object_new_object();
    1115           0 :                 json_import_rtl = json_object_new_array();
    1116           0 :                 json_export_rtl = json_object_new_array();
    1117             :         }
    1118             : 
    1119           0 :         buf1[0] = '\0';
    1120           0 :         if (is_vni_live(vpn))
    1121           0 :                 snprintf(buf1, sizeof(buf1), "*");
    1122             : 
    1123           0 :         if (json) {
    1124           0 :                 json_object_int_add(json_vni, "vni", vpn->vni);
    1125           0 :                 json_object_string_add(json_vni, "type", "L2");
    1126           0 :                 json_object_string_add(json_vni, "inKernel",
    1127           0 :                                        is_vni_live(vpn) ? "True" : "False");
    1128           0 :                 json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
    1129           0 :                 json_object_string_addf(json_vni, "originatorIp", "%pI4",
    1130             :                                         &vpn->originator_ip);
    1131           0 :                 json_object_string_addf(json_vni, "mcastGroup", "%pI4",
    1132             :                                         &vpn->mcast_grp);
    1133             :                 /* per vni knob is enabled -- Enabled
    1134             :                  * Global knob is enabled  -- Active
    1135             :                  * default  -- Disabled
    1136             :                  */
    1137           0 :                 if (!vpn->advertise_gw_macip && bgp_evpn
    1138           0 :                     && bgp_evpn->advertise_gw_macip)
    1139           0 :                         json_object_string_add(
    1140             :                                 json_vni, "advertiseGatewayMacip", "Active");
    1141           0 :                 else if (vpn->advertise_gw_macip)
    1142           0 :                         json_object_string_add(
    1143             :                                 json_vni, "advertiseGatewayMacip", "Enabled");
    1144             :                 else
    1145           0 :                         json_object_string_add(
    1146             :                                 json_vni, "advertiseGatewayMacip", "Disabled");
    1147           0 :                 if (!vpn->advertise_svi_macip && bgp_evpn
    1148           0 :                     && bgp_evpn->evpn_info->advertise_svi_macip)
    1149           0 :                         json_object_string_add(json_vni, "advertiseSviMacIp",
    1150             :                                                "Active");
    1151           0 :                 else if (vpn->advertise_svi_macip)
    1152           0 :                         json_object_string_add(json_vni, "advertiseSviMacIp",
    1153             :                                                "Enabled");
    1154             :                 else
    1155           0 :                         json_object_string_add(json_vni, "advertiseSviMacIp",
    1156             :                                                "Disabled");
    1157             :         } else {
    1158           0 :                 vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2",
    1159             :                         &vpn->prd);
    1160             :         }
    1161             : 
    1162           0 :         for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
    1163           0 :                 ecom_str = ecommunity_ecom2str(ecom,
    1164             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1165             : 
    1166           0 :                 if (json) {
    1167           0 :                         json_object_array_add(json_import_rtl,
    1168             :                                               json_object_new_string(ecom_str));
    1169             :                 } else {
    1170           0 :                         if (listcount(vpn->import_rtl) > 1)
    1171           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
    1172             :                                          ecom_str);
    1173             :                         else
    1174           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s",
    1175             :                                          ecom_str);
    1176           0 :                         vty_out(vty, " %-25s", rt_buf);
    1177             :                 }
    1178             : 
    1179           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    1180             : 
    1181             :                 /* If there are multiple import RTs we break here and show only
    1182             :                  * one */
    1183           0 :                 if (!json)
    1184             :                         break;
    1185             :         }
    1186             : 
    1187           0 :         if (json)
    1188           0 :                 json_object_object_add(json_vni, "importRTs", json_import_rtl);
    1189             : 
    1190           0 :         for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
    1191           0 :                 ecom_str = ecommunity_ecom2str(ecom,
    1192             :                                                ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1193             : 
    1194           0 :                 if (json) {
    1195           0 :                         json_object_array_add(json_export_rtl,
    1196             :                                               json_object_new_string(ecom_str));
    1197             :                 } else {
    1198           0 :                         if (listcount(vpn->export_rtl) > 1)
    1199           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
    1200             :                                          ecom_str);
    1201             :                         else
    1202           0 :                                 snprintf(rt_buf, sizeof(rt_buf), "%s",
    1203             :                                          ecom_str);
    1204           0 :                         vty_out(vty, " %-25s", rt_buf);
    1205             :                 }
    1206             : 
    1207           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    1208             : 
    1209             :                 /* If there are multiple export RTs we break here and show only
    1210             :                  * one */
    1211           0 :                 if (!json) {
    1212           0 :                         vty_out(vty, "%-37s",
    1213             :                                 vrf_id_to_name(vpn->tenant_vrf_id));
    1214           0 :                         break;
    1215             :                 }
    1216             :         }
    1217             : 
    1218           0 :         if (json) {
    1219           0 :                 char vni_str[VNI_STR_LEN];
    1220             : 
    1221           0 :                 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
    1222           0 :                 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
    1223           0 :                 json_object_object_add(json, vni_str, json_vni);
    1224             :         } else {
    1225           0 :                 vty_out(vty, "\n");
    1226             :         }
    1227           0 : }
    1228             : 
    1229           0 : static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
    1230             :                                  enum bgp_show_type type, void *output_arg,
    1231             :                                  int option, bool use_json)
    1232             : {
    1233           0 :         afi_t afi = AFI_L2VPN;
    1234           0 :         struct bgp *bgp;
    1235           0 :         struct bgp_table *table;
    1236           0 :         struct bgp_dest *dest;
    1237           0 :         struct bgp_dest *rm;
    1238           0 :         struct bgp_path_info *pi;
    1239           0 :         int rd_header;
    1240           0 :         int header = 1;
    1241           0 :         char rd_str[RD_ADDRSTRLEN];
    1242           0 :         int no_display;
    1243             : 
    1244           0 :         unsigned long output_count = 0;
    1245           0 :         unsigned long total_count = 0;
    1246           0 :         json_object *json = NULL;
    1247           0 :         json_object *json_array = NULL;
    1248           0 :         json_object *json_prefix_info = NULL;
    1249             : 
    1250           0 :         memset(rd_str, 0, RD_ADDRSTRLEN);
    1251             : 
    1252           0 :         bgp = bgp_get_evpn();
    1253           0 :         if (bgp == NULL) {
    1254           0 :                 if (!use_json)
    1255           0 :                         vty_out(vty, "No BGP process is configured\n");
    1256             :                 else
    1257           0 :                         vty_out(vty, "{}\n");
    1258           0 :                 return CMD_WARNING;
    1259             :         }
    1260             : 
    1261           0 :         if (use_json)
    1262           0 :                 json = json_object_new_object();
    1263             : 
    1264           0 :         for (dest = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); dest;
    1265           0 :              dest = bgp_route_next(dest)) {
    1266           0 :                 uint64_t tbl_ver;
    1267           0 :                 json_object *json_nroute = NULL;
    1268           0 :                 const struct prefix *p = bgp_dest_get_prefix(dest);
    1269             : 
    1270           0 :                 if (prd && memcmp(p->u.val, prd->val, 8) != 0)
    1271           0 :                         continue;
    1272             : 
    1273           0 :                 table = bgp_dest_get_bgp_table_info(dest);
    1274           0 :                 if (!table)
    1275           0 :                         continue;
    1276             : 
    1277           0 :                 rd_header = 1;
    1278           0 :                 tbl_ver = table->version;
    1279             : 
    1280           0 :                 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
    1281           0 :                         pi = bgp_dest_get_bgp_path_info(rm);
    1282           0 :                         if (pi == NULL)
    1283           0 :                                 continue;
    1284             : 
    1285             :                         no_display = 0;
    1286           0 :                         for (; pi; pi = pi->next) {
    1287           0 :                                 struct community *picomm = NULL;
    1288             : 
    1289           0 :                                 picomm = bgp_attr_get_community(pi->attr);
    1290             : 
    1291           0 :                                 total_count++;
    1292           0 :                                 if (type == bgp_show_type_neighbor) {
    1293           0 :                                         struct peer *peer = output_arg;
    1294             : 
    1295           0 :                                         if (peer_cmp(peer, pi->peer) != 0)
    1296           0 :                                                 continue;
    1297             :                                 }
    1298           0 :                                 if (type == bgp_show_type_lcommunity_exact) {
    1299           0 :                                         struct lcommunity *lcom = output_arg;
    1300             : 
    1301           0 :                                         if (!bgp_attr_get_lcommunity(
    1302           0 :                                                     pi->attr) ||
    1303           0 :                                             !lcommunity_cmp(
    1304           0 :                                                     bgp_attr_get_lcommunity(
    1305           0 :                                                             pi->attr),
    1306             :                                                     lcom))
    1307           0 :                                                 continue;
    1308             :                                 }
    1309           0 :                                 if (type == bgp_show_type_lcommunity) {
    1310           0 :                                         struct lcommunity *lcom = output_arg;
    1311             : 
    1312           0 :                                         if (!bgp_attr_get_lcommunity(
    1313           0 :                                                     pi->attr) ||
    1314           0 :                                             !lcommunity_match(
    1315           0 :                                                     bgp_attr_get_lcommunity(
    1316           0 :                                                             pi->attr),
    1317             :                                                     lcom))
    1318           0 :                                                 continue;
    1319             :                                 }
    1320           0 :                                 if (type == bgp_show_type_community) {
    1321           0 :                                         struct community *com = output_arg;
    1322             : 
    1323           0 :                                         if (!picomm ||
    1324           0 :                                             !community_match(picomm, com))
    1325           0 :                                                 continue;
    1326             :                                 }
    1327           0 :                                 if (type == bgp_show_type_community_exact) {
    1328           0 :                                         struct community *com = output_arg;
    1329             : 
    1330           0 :                                         if (!picomm ||
    1331           0 :                                             !community_cmp(picomm, com))
    1332           0 :                                                 continue;
    1333             :                                 }
    1334           0 :                                 if (header) {
    1335           0 :                                         if (use_json) {
    1336           0 :                                                 json_object_int_add(
    1337             :                                                         json, "bgpTableVersion",
    1338             :                                                         tbl_ver);
    1339           0 :                                                 json_object_string_addf(
    1340             :                                                         json,
    1341             :                                                         "bgpLocalRouterId",
    1342             :                                                         "%pI4",
    1343             :                                                         &bgp->router_id);
    1344           0 :                                                 json_object_int_add(
    1345             :                                                         json,
    1346             :                                                         "defaultLocPrf",
    1347           0 :                                                         bgp->default_local_pref);
    1348           0 :                                                 json_object_int_add(
    1349             :                                                         json, "localAS",
    1350           0 :                                                         bgp->as);
    1351             :                                         } else {
    1352           0 :                                                 if (option == SHOW_DISPLAY_TAGS)
    1353           0 :                                                         vty_out(vty,
    1354             :                                                                 V4_HEADER_TAG);
    1355           0 :                                                 else if (
    1356             :                                                         option
    1357             :                                                         == SHOW_DISPLAY_OVERLAY)
    1358           0 :                                                         vty_out(vty,
    1359             :                                                                 V4_HEADER_OVERLAY);
    1360             :                                                 else {
    1361           0 :                                                         bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
    1362             :                                                 }
    1363             :                                         }
    1364             :                                         header = 0;
    1365             :                                 }
    1366           0 :                                 if (rd_header) {
    1367           0 :                                         if (use_json)
    1368           0 :                                                 json_nroute =
    1369           0 :                                                        json_object_new_object();
    1370           0 :                                         bgp_evpn_show_route_rd_header(
    1371             :                                                 vty, dest, json_nroute, rd_str,
    1372             :                                                 RD_ADDRSTRLEN);
    1373           0 :                                         rd_header = 0;
    1374             :                                 }
    1375           0 :                                 if (use_json && !json_array)
    1376           0 :                                         json_array = json_object_new_array();
    1377             : 
    1378           0 :                                 if (option == SHOW_DISPLAY_TAGS)
    1379           0 :                                         route_vty_out_tag(
    1380             :                                                 vty, bgp_dest_get_prefix(rm),
    1381             :                                                 pi, no_display, SAFI_EVPN,
    1382             :                                                 json_array);
    1383           0 :                                 else if (option == SHOW_DISPLAY_OVERLAY)
    1384           0 :                                         route_vty_out_overlay(
    1385             :                                                 vty, bgp_dest_get_prefix(rm),
    1386             :                                                 pi, no_display, json_array);
    1387             :                                 else
    1388           0 :                                         route_vty_out(vty,
    1389             :                                                       bgp_dest_get_prefix(rm),
    1390             :                                                       pi, no_display, SAFI_EVPN,
    1391             :                                                       json_array, false);
    1392             :                                 no_display = 1;
    1393             :                         }
    1394             : 
    1395           0 :                         if (no_display)
    1396           0 :                                 output_count++;
    1397             : 
    1398           0 :                         if (use_json && json_array) {
    1399           0 :                                 const struct prefix *p =
    1400           0 :                                         bgp_dest_get_prefix(rm);
    1401             : 
    1402           0 :                                 json_prefix_info = json_object_new_object();
    1403             : 
    1404           0 :                                 json_object_string_addf(json_prefix_info,
    1405             :                                                         "prefix", "%pFX", p);
    1406             : 
    1407           0 :                                 json_object_int_add(json_prefix_info,
    1408           0 :                                                     "prefixLen", p->prefixlen);
    1409             : 
    1410           0 :                                 json_object_object_add(json_prefix_info,
    1411             :                                         "paths", json_array);
    1412           0 :                                 json_object_object_addf(json_nroute,
    1413             :                                                         json_prefix_info,
    1414             :                                                         "%pFX", p);
    1415           0 :                                 json_array = NULL;
    1416             :                         }
    1417             :                 }
    1418             : 
    1419           0 :                 if (use_json && json_nroute)
    1420           0 :                         json_object_object_add(json, rd_str, json_nroute);
    1421             :         }
    1422             : 
    1423           0 :         if (use_json) {
    1424           0 :                 json_object_int_add(json, "numPrefix", output_count);
    1425           0 :                 json_object_int_add(json, "totalPrefix", total_count);
    1426           0 :                 vty_json(vty, json);
    1427             :         } else {
    1428           0 :                 if (output_count == 0)
    1429           0 :                         vty_out(vty, "No prefixes displayed, %ld exist\n",
    1430             :                                 total_count);
    1431             :                 else
    1432           0 :                         vty_out(vty,
    1433             :                                 "\nDisplayed %ld out of %ld total prefixes\n",
    1434             :                                 output_count, total_count);
    1435             :         }
    1436             :         return CMD_SUCCESS;
    1437             : }
    1438             : 
    1439           0 : DEFUN(show_ip_bgp_l2vpn_evpn,
    1440             :       show_ip_bgp_l2vpn_evpn_cmd,
    1441             :       "show [ip] bgp l2vpn evpn [json]",
    1442             :       SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
    1443             : {
    1444           0 :         return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
    1445             :                                      SHOW_DISPLAY_STANDARD,
    1446           0 :                                      use_json(argc, argv));
    1447             : }
    1448             : 
    1449           0 : DEFUN(show_ip_bgp_l2vpn_evpn_rd,
    1450             :       show_ip_bgp_l2vpn_evpn_rd_cmd,
    1451             :       "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
    1452             :       SHOW_STR
    1453             :       IP_STR
    1454             :       BGP_STR
    1455             :       L2VPN_HELP_STR
    1456             :       EVPN_HELP_STR
    1457             :       "Display information for a route distinguisher\n"
    1458             :       "VPN Route Distinguisher\n"
    1459             :       "All VPN Route Distinguishers\n"
    1460             :       JSON_STR)
    1461             : {
    1462           0 :         int idx_ext_community = 0;
    1463           0 :         int ret;
    1464           0 :         struct prefix_rd prd;
    1465           0 :         int rd_all = 0;
    1466             : 
    1467           0 :         if (argv_find(argv, argc, "all", &rd_all))
    1468           0 :                 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
    1469             :                                              NULL, SHOW_DISPLAY_STANDARD,
    1470           0 :                                              use_json(argc, argv));
    1471             : 
    1472           0 :         argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
    1473           0 :         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    1474           0 :         if (!ret) {
    1475           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    1476           0 :                 return CMD_WARNING;
    1477             :         }
    1478           0 :         return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
    1479             :                                      SHOW_DISPLAY_STANDARD,
    1480           0 :                                      use_json(argc, argv));
    1481             : }
    1482             : 
    1483           0 : DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
    1484             :       show_ip_bgp_l2vpn_evpn_all_tags_cmd,
    1485             :       "show [ip] bgp l2vpn evpn all tags",
    1486             :       SHOW_STR
    1487             :       IP_STR
    1488             :       BGP_STR
    1489             :       L2VPN_HELP_STR
    1490             :       EVPN_HELP_STR
    1491             :       "Display information about all EVPN NLRIs\n"
    1492             :       "Display BGP tags for prefixes\n")
    1493             : {
    1494           0 :         return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
    1495             :                                      SHOW_DISPLAY_TAGS, 0);
    1496             : }
    1497             : 
    1498           0 : DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
    1499             :       show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
    1500             :       "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
    1501             :       SHOW_STR
    1502             :       IP_STR
    1503             :       BGP_STR
    1504             :       L2VPN_HELP_STR
    1505             :       EVPN_HELP_STR
    1506             :       "Display information for a route distinguisher\n"
    1507             :       "VPN Route Distinguisher\n"
    1508             :       "All VPN Route Distinguishers\n"
    1509             :       "Display BGP tags for prefixes\n")
    1510             : {
    1511           0 :         int idx_ext_community = 0;
    1512           0 :         int ret;
    1513           0 :         struct prefix_rd prd;
    1514           0 :         int rd_all = 0;
    1515             : 
    1516           0 :         if (argv_find(argv, argc, "all", &rd_all))
    1517           0 :                 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
    1518             :                                              NULL, SHOW_DISPLAY_TAGS, 0);
    1519             : 
    1520           0 :         argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
    1521           0 :         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    1522           0 :         if (!ret) {
    1523           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    1524           0 :                 return CMD_WARNING;
    1525             :         }
    1526           0 :         return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
    1527             :                                      SHOW_DISPLAY_TAGS, 0);
    1528             : }
    1529             : 
    1530           0 : DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
    1531             :       show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
    1532             :       "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
    1533             :       SHOW_STR
    1534             :       IP_STR
    1535             :       BGP_STR
    1536             :       L2VPN_HELP_STR
    1537             :       EVPN_HELP_STR
    1538             :       "Detailed information on TCP and BGP neighbor connections\n"
    1539             :       "IPv4 Neighbor to display information about\n"
    1540             :       "IPv6 Neighbor to display information about\n"
    1541             :       "Neighbor on BGP configured interface\n"
    1542             :       "Display routes learned from neighbor\n" JSON_STR)
    1543             : {
    1544           0 :         int idx = 0;
    1545           0 :         struct peer *peer;
    1546           0 :         char *peerstr = NULL;
    1547           0 :         bool uj = use_json(argc, argv);
    1548           0 :         afi_t afi = AFI_L2VPN;
    1549           0 :         safi_t safi = SAFI_EVPN;
    1550           0 :         struct bgp *bgp = NULL;
    1551             : 
    1552           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
    1553             :                                             &bgp, uj);
    1554           0 :         if (!idx) {
    1555           0 :                 vty_out(vty, "No index\n");
    1556           0 :                 return CMD_WARNING;
    1557             :         }
    1558             : 
    1559             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
    1560           0 :         argv_find(argv, argc, "neighbors", &idx);
    1561           0 :         peerstr = argv[++idx]->arg;
    1562             : 
    1563           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
    1564           0 :         if (!peer) {
    1565           0 :                 if (uj) {
    1566           0 :                         json_object *json_no = NULL;
    1567           0 :                         json_no = json_object_new_object();
    1568           0 :                         json_object_string_add(json_no, "warning",
    1569             :                                                "Malformed address");
    1570           0 :                         vty_out(vty, "%s\n",
    1571             :                                 json_object_to_json_string(json_no));
    1572           0 :                         json_object_free(json_no);
    1573             :                 } else
    1574           0 :                         vty_out(vty, "Malformed address: %s\n",
    1575           0 :                                 argv[idx]->arg);
    1576           0 :                 return CMD_WARNING;
    1577             :         }
    1578           0 :         if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
    1579           0 :                 if (uj) {
    1580           0 :                         json_object *json_no = NULL;
    1581           0 :                         json_no = json_object_new_object();
    1582           0 :                         json_object_string_add(
    1583             :                                 json_no, "warning",
    1584             :                                 "No such neighbor or address family");
    1585           0 :                         vty_out(vty, "%s\n",
    1586             :                                 json_object_to_json_string(json_no));
    1587           0 :                         json_object_free(json_no);
    1588             :                 } else
    1589           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
    1590           0 :                 return CMD_WARNING;
    1591             :         }
    1592             : 
    1593           0 :         return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer,
    1594             :                                      SHOW_DISPLAY_STANDARD, uj);
    1595             : }
    1596             : 
    1597           0 : DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
    1598             :       show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
    1599             :       "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
    1600             :       SHOW_STR
    1601             :       IP_STR
    1602             :       BGP_STR
    1603             :       L2VPN_HELP_STR
    1604             :       EVPN_HELP_STR
    1605             :       "Display information for a route distinguisher\n"
    1606             :       "VPN Route Distinguisher\n"
    1607             :       "All VPN Route Distinguishers\n"
    1608             :       "Detailed information on TCP and BGP neighbor connections\n"
    1609             :       "IPv4 Neighbor to display information about\n"
    1610             :       "IPv6 Neighbor to display information about\n"
    1611             :       "Neighbor on BGP configured interface\n"
    1612             :       "Display routes learned from neighbor\n" JSON_STR)
    1613             : {
    1614           0 :         int idx_ext_community = 0;
    1615           0 :         int idx = 0;
    1616           0 :         int ret;
    1617           0 :         struct peer *peer;
    1618           0 :         char *peerstr = NULL;
    1619           0 :         struct prefix_rd prd = {};
    1620           0 :         bool uj = use_json(argc, argv);
    1621           0 :         afi_t afi = AFI_L2VPN;
    1622           0 :         safi_t safi = SAFI_EVPN;
    1623           0 :         struct bgp *bgp = NULL;
    1624           0 :         int rd_all = 0;
    1625             : 
    1626           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
    1627             :                                             &bgp, uj);
    1628           0 :         if (!idx) {
    1629           0 :                 vty_out(vty, "No index\n");
    1630           0 :                 return CMD_WARNING;
    1631             :         }
    1632             : 
    1633           0 :         if (argv_find(argv, argc, "all", &rd_all)) {
    1634           0 :                 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
    1635             :                           &idx_ext_community);
    1636           0 :                 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    1637           0 :                 if (!ret) {
    1638           0 :                         if (uj) {
    1639           0 :                                 json_object *json_no = NULL;
    1640           0 :                                 json_no = json_object_new_object();
    1641           0 :                                 json_object_string_add(
    1642             :                                         json_no, "warning",
    1643             :                                         "Malformed Route Distinguisher");
    1644           0 :                                 vty_out(vty, "%s\n",
    1645             :                                         json_object_to_json_string(json_no));
    1646           0 :                                 json_object_free(json_no);
    1647             :                         } else
    1648           0 :                                 vty_out(vty,
    1649             :                                         "%% Malformed Route Distinguisher\n");
    1650           0 :                         return CMD_WARNING;
    1651             :                 }
    1652             :         }
    1653             : 
    1654             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
    1655           0 :         argv_find(argv, argc, "neighbors", &idx);
    1656           0 :         peerstr = argv[++idx]->arg;
    1657             : 
    1658           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
    1659           0 :         if (!peer) {
    1660           0 :                 if (uj) {
    1661           0 :                         json_object *json_no = NULL;
    1662           0 :                         json_no = json_object_new_object();
    1663           0 :                         json_object_string_add(json_no, "warning",
    1664             :                                                "Malformed address");
    1665           0 :                         vty_out(vty, "%s\n",
    1666             :                                 json_object_to_json_string(json_no));
    1667           0 :                         json_object_free(json_no);
    1668             :                 } else
    1669           0 :                         vty_out(vty, "Malformed address: %s\n",
    1670           0 :                                 argv[idx]->arg);
    1671           0 :                 return CMD_WARNING;
    1672             :         }
    1673           0 :         if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
    1674           0 :                 if (uj) {
    1675           0 :                         json_object *json_no = NULL;
    1676           0 :                         json_no = json_object_new_object();
    1677           0 :                         json_object_string_add(
    1678             :                                 json_no, "warning",
    1679             :                                 "No such neighbor or address family");
    1680           0 :                         vty_out(vty, "%s\n",
    1681             :                                 json_object_to_json_string(json_no));
    1682           0 :                         json_object_free(json_no);
    1683             :                 } else
    1684           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
    1685           0 :                 return CMD_WARNING;
    1686             :         }
    1687             : 
    1688             : 
    1689           0 :         if (rd_all)
    1690           0 :                 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor,
    1691             :                                              peer, SHOW_DISPLAY_STANDARD, uj);
    1692             :         else
    1693           0 :                 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor,
    1694             :                                              peer, SHOW_DISPLAY_STANDARD, uj);
    1695             : }
    1696             : 
    1697           0 : DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
    1698             :       show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
    1699             :       "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
    1700             :       SHOW_STR
    1701             :       IP_STR
    1702             :       BGP_STR
    1703             :       L2VPN_HELP_STR
    1704             :       EVPN_HELP_STR
    1705             :       "Detailed information on TCP and BGP neighbor connections\n"
    1706             :       "IPv4 Neighbor to display information about\n"
    1707             :       "IPv6 Neighbor to display information about\n"
    1708             :       "Neighbor on BGP configured interface\n"
    1709             :       "Display the routes advertised to a BGP neighbor\n" JSON_STR)
    1710             : {
    1711           0 :         int idx = 0;
    1712           0 :         struct peer *peer;
    1713           0 :         bool uj = use_json(argc, argv);
    1714           0 :         struct bgp *bgp = NULL;
    1715           0 :         afi_t afi = AFI_L2VPN;
    1716           0 :         safi_t safi = SAFI_EVPN;
    1717           0 :         char *peerstr = NULL;
    1718             : 
    1719           0 :         if (uj)
    1720           0 :                 argc--;
    1721             : 
    1722           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
    1723             :                                             &bgp, uj);
    1724           0 :         if (!idx) {
    1725           0 :                 vty_out(vty, "No index\n");
    1726           0 :                 return CMD_WARNING;
    1727             :         }
    1728             : 
    1729             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
    1730           0 :         argv_find(argv, argc, "neighbors", &idx);
    1731           0 :         peerstr = argv[++idx]->arg;
    1732             : 
    1733           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
    1734           0 :         if (!peer) {
    1735           0 :                 if (uj) {
    1736           0 :                         json_object *json_no = NULL;
    1737           0 :                         json_no = json_object_new_object();
    1738           0 :                         json_object_string_add(json_no, "warning",
    1739             :                                                "Malformed address");
    1740           0 :                         vty_out(vty, "%s\n",
    1741             :                                 json_object_to_json_string(json_no));
    1742           0 :                         json_object_free(json_no);
    1743             :                 } else
    1744           0 :                         vty_out(vty, "Malformed address: %s\n",
    1745           0 :                                 argv[idx]->arg);
    1746           0 :                 return CMD_WARNING;
    1747             :         }
    1748           0 :         if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
    1749           0 :                 if (uj) {
    1750           0 :                         json_object *json_no = NULL;
    1751           0 :                         json_no = json_object_new_object();
    1752           0 :                         json_object_string_add(
    1753             :                                 json_no, "warning",
    1754             :                                 "No such neighbor or address family");
    1755           0 :                         vty_out(vty, "%s\n",
    1756             :                                 json_object_to_json_string(json_no));
    1757           0 :                         json_object_free(json_no);
    1758             :                 } else
    1759           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
    1760           0 :                 return CMD_WARNING;
    1761             :         }
    1762             : 
    1763           0 :         return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
    1764             : }
    1765             : 
    1766           0 : DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
    1767             :       show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
    1768             :       "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
    1769             :       SHOW_STR
    1770             :       IP_STR
    1771             :       BGP_STR
    1772             :       L2VPN_HELP_STR
    1773             :       EVPN_HELP_STR
    1774             :       "Display information for a route distinguisher\n"
    1775             :       "VPN Route Distinguisher\n"
    1776             :       "All VPN Route Distinguishers\n"
    1777             :       "Detailed information on TCP and BGP neighbor connections\n"
    1778             :       "IPv4 Neighbor to display information about\n"
    1779             :       "IPv6 Neighbor to display information about\n"
    1780             :       "Neighbor on BGP configured interface\n"
    1781             :       "Display the routes advertised to a BGP neighbor\n" JSON_STR)
    1782             : {
    1783           0 :         int idx_ext_community = 0;
    1784           0 :         int idx = 0;
    1785           0 :         int ret;
    1786           0 :         struct peer *peer;
    1787           0 :         struct prefix_rd prd;
    1788           0 :         struct bgp *bgp = NULL;
    1789           0 :         bool uj = use_json(argc, argv);
    1790           0 :         char *peerstr = NULL;
    1791           0 :         afi_t afi = AFI_L2VPN;
    1792           0 :         safi_t safi = SAFI_EVPN;
    1793           0 :         int rd_all = 0;
    1794             : 
    1795           0 :         if (uj)
    1796           0 :                 argc--;
    1797             : 
    1798           0 :         if (uj)
    1799           0 :                 argc--;
    1800             : 
    1801           0 :         bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
    1802             :                                             &bgp, uj);
    1803           0 :         if (!idx) {
    1804           0 :                 vty_out(vty, "No index\n");
    1805           0 :                 return CMD_WARNING;
    1806             :         }
    1807             : 
    1808             :         /* neighbors <A.B.C.D|X:X::X:X|WORD> */
    1809           0 :         argv_find(argv, argc, "neighbors", &idx);
    1810           0 :         peerstr = argv[++idx]->arg;
    1811             : 
    1812           0 :         peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
    1813           0 :         if (!peer) {
    1814           0 :                 if (uj) {
    1815           0 :                         json_object *json_no = NULL;
    1816           0 :                         json_no = json_object_new_object();
    1817           0 :                         json_object_string_add(json_no, "warning",
    1818             :                                                "Malformed address");
    1819           0 :                         vty_out(vty, "%s\n",
    1820             :                                 json_object_to_json_string(json_no));
    1821           0 :                         json_object_free(json_no);
    1822             :                 } else
    1823           0 :                         vty_out(vty, "Malformed address: %s\n",
    1824           0 :                                 argv[idx]->arg);
    1825           0 :                 return CMD_WARNING;
    1826             :         }
    1827           0 :         if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
    1828           0 :                 if (uj) {
    1829           0 :                         json_object *json_no = NULL;
    1830           0 :                         json_no = json_object_new_object();
    1831           0 :                         json_object_string_add(
    1832             :                                 json_no, "warning",
    1833             :                                 "No such neighbor or address family");
    1834           0 :                         vty_out(vty, "%s\n",
    1835             :                                 json_object_to_json_string(json_no));
    1836           0 :                         json_object_free(json_no);
    1837             :                 } else
    1838           0 :                         vty_out(vty, "%% No such neighbor or address family\n");
    1839           0 :                 return CMD_WARNING;
    1840             :         }
    1841             : 
    1842           0 :         if (argv_find(argv, argc, "all", &rd_all))
    1843           0 :                 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN,
    1844             :                                           uj);
    1845             :         else {
    1846           0 :                 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
    1847             :                           &idx_ext_community);
    1848           0 :                 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    1849           0 :                 if (!ret) {
    1850           0 :                         if (uj) {
    1851           0 :                                 json_object *json_no = NULL;
    1852           0 :                                 json_no = json_object_new_object();
    1853           0 :                                 json_object_string_add(
    1854             :                                         json_no, "warning",
    1855             :                                         "Malformed Route Distinguisher");
    1856           0 :                                 vty_out(vty, "%s\n",
    1857             :                                         json_object_to_json_string(json_no));
    1858           0 :                                 json_object_free(json_no);
    1859             :                         } else
    1860           0 :                                 vty_out(vty,
    1861             :                                         "%% Malformed Route Distinguisher\n");
    1862           0 :                         return CMD_WARNING;
    1863             :                 }
    1864             :         }
    1865             : 
    1866           0 :         return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
    1867             : }
    1868             : 
    1869           0 : DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
    1870             :       show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
    1871             :       "show [ip] bgp l2vpn evpn all overlay [json]",
    1872             :       SHOW_STR
    1873             :       IP_STR
    1874             :       BGP_STR
    1875             :       L2VPN_HELP_STR
    1876             :       EVPN_HELP_STR
    1877             :       "Display information about all EVPN NLRIs\n"
    1878             :       "Display BGP Overlay Information for prefixes\n"
    1879             :       JSON_STR)
    1880             : {
    1881           0 :         return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
    1882             :                                      SHOW_DISPLAY_OVERLAY,
    1883           0 :                                      use_json(argc, argv));
    1884             : }
    1885             : 
    1886           0 : DEFUN(show_ip_bgp_evpn_rd_overlay,
    1887             :       show_ip_bgp_evpn_rd_overlay_cmd,
    1888             :       "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
    1889             :       SHOW_STR
    1890             :       IP_STR
    1891             :       BGP_STR
    1892             :       L2VPN_HELP_STR
    1893             :       EVPN_HELP_STR
    1894             :       "Display information for a route distinguisher\n"
    1895             :       "VPN Route Distinguisher\n"
    1896             :       "All VPN Route Distinguishers\n"
    1897             :       "Display BGP Overlay Information for prefixes\n")
    1898             : {
    1899           0 :         int idx_ext_community = 0;
    1900           0 :         int ret;
    1901           0 :         struct prefix_rd prd;
    1902           0 :         int rd_all = 0;
    1903             : 
    1904           0 :         if (argv_find(argv, argc, "all", &rd_all))
    1905           0 :                 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
    1906             :                                              NULL, SHOW_DISPLAY_OVERLAY,
    1907           0 :                                              use_json(argc, argv));
    1908             : 
    1909           0 :         argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
    1910           0 :         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    1911           0 :         if (!ret) {
    1912           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    1913           0 :                 return CMD_WARNING;
    1914             :         }
    1915           0 :         return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
    1916             :                                      SHOW_DISPLAY_OVERLAY,
    1917           0 :                                      use_json(argc, argv));
    1918             : }
    1919             : 
    1920           0 : DEFUN(show_bgp_l2vpn_evpn_com,
    1921             :       show_bgp_l2vpn_evpn_com_cmd,
    1922             :       "show bgp l2vpn evpn \
    1923             :       <community AA:NN|large-community AA:BB:CC> \
    1924             :       [exact-match] [json]",
    1925             :       SHOW_STR
    1926             :       BGP_STR
    1927             :       L2VPN_HELP_STR
    1928             :       EVPN_HELP_STR
    1929             :       "Display routes matching the community\n"
    1930             :       "Community number where AA and NN are (0-65535)\n"
    1931             :       "Display routes matching the large-community\n"
    1932             :       "List of large-community numbers\n"
    1933             :       "Exact match of the communities\n"
    1934             :       JSON_STR)
    1935             : {
    1936           0 :         int idx = 0;
    1937           0 :         int ret = 0;
    1938           0 :         const char *clist_number_or_name;
    1939           0 :         int show_type = bgp_show_type_normal;
    1940           0 :         struct community *com;
    1941           0 :         struct lcommunity *lcom;
    1942             : 
    1943           0 :         if (argv_find(argv, argc, "large-community", &idx)) {
    1944           0 :                 clist_number_or_name = argv[++idx]->arg;
    1945           0 :                 show_type = bgp_show_type_lcommunity;
    1946             : 
    1947           0 :                 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
    1948           0 :                         show_type = bgp_show_type_lcommunity_exact;
    1949             : 
    1950           0 :                 lcom = lcommunity_str2com(clist_number_or_name);
    1951           0 :                 if (!lcom) {
    1952           0 :                         vty_out(vty, "%% Large-community malformed\n");
    1953           0 :                         return CMD_WARNING;
    1954             :                 }
    1955             : 
    1956           0 :                 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
    1957             :                                             SHOW_DISPLAY_STANDARD,
    1958           0 :                                             use_json(argc, argv));
    1959             : 
    1960           0 :                 lcommunity_free(&lcom);
    1961           0 :         } else if (argv_find(argv, argc, "community", &idx)) {
    1962           0 :                 clist_number_or_name = argv[++idx]->arg;
    1963           0 :                 show_type = bgp_show_type_community;
    1964             : 
    1965           0 :                 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
    1966           0 :                         show_type = bgp_show_type_community_exact;
    1967             : 
    1968           0 :                 com = community_str2com(clist_number_or_name);
    1969             : 
    1970           0 :                 if (!com) {
    1971           0 :                         vty_out(vty, "%% Community malformed: %s\n",
    1972             :                                 clist_number_or_name);
    1973           0 :                         return CMD_WARNING;
    1974             :                 }
    1975             : 
    1976           0 :                 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
    1977             :                                             SHOW_DISPLAY_STANDARD,
    1978           0 :                                             use_json(argc, argv));
    1979           0 :                 community_free(&com);
    1980             :         }
    1981             : 
    1982             :         return ret;
    1983             : }
    1984             : 
    1985             : /* For testing purpose, static route of EVPN RT-5. */
    1986           0 : DEFUN(evpnrt5_network,
    1987             :       evpnrt5_network_cmd,
    1988             :       "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map RMAP_NAME]",
    1989             :       "Specify a network to announce via BGP\n"
    1990             :       "IP prefix\n"
    1991             :       "IPv6 prefix\n"
    1992             :       "Specify Route Distinguisher\n"
    1993             :       "VPN Route Distinguisher\n"
    1994             :       "Ethernet Tag\n"
    1995             :       "Ethernet Tag Value\n"
    1996             :       "BGP label\n"
    1997             :       "label value\n"
    1998             :       "Ethernet Segment Identifier\n"
    1999             :       "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
    2000             :       "Gateway IP\n"
    2001             :       "Gateway IP ( A.B.C.D )\n"
    2002             :       "Gateway IPv6 ( X:X::X:X )\n"
    2003             :       "Router Mac Ext Comm\n"
    2004             :       "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
    2005             :       "Route-map to modify the attributes\n"
    2006             :       "Name of the route map\n")
    2007             : {
    2008           0 :         int idx_ipv4_prefixlen = 1;
    2009           0 :         int idx_route_distinguisher = 3;
    2010           0 :         int idx_label = 7;
    2011           0 :         int idx_esi = 9;
    2012           0 :         int idx_gwip = 11;
    2013           0 :         int idx_ethtag = 5;
    2014           0 :         int idx_routermac = 13;
    2015             : 
    2016           0 :         return bgp_static_set_safi(
    2017           0 :                 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
    2018           0 :                 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
    2019           0 :                 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
    2020           0 :                 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
    2021           0 :                 argv[idx_routermac]->arg);
    2022             : }
    2023             : 
    2024             : /* For testing purpose, static route of EVPN RT-5. */
    2025           0 : DEFUN(no_evpnrt5_network,
    2026             :       no_evpnrt5_network_cmd,
    2027             :       "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
    2028             :       NO_STR
    2029             :       "Specify a network to announce via BGP\n"
    2030             :       "IP prefix\n"
    2031             :       "IPv6 prefix\n"
    2032             :       "Specify Route Distinguisher\n"
    2033             :       "VPN Route Distinguisher\n"
    2034             :       "Ethernet Tag\n"
    2035             :       "Ethernet Tag Value\n"
    2036             :       "BGP label\n"
    2037             :       "label value\n"
    2038             :       "Ethernet Segment Identifier\n"
    2039             :       "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
    2040             :       "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
    2041             : {
    2042           0 :         int idx_ipv4_prefixlen = 2;
    2043           0 :         int idx_ext_community = 4;
    2044           0 :         int idx_label = 8;
    2045           0 :         int idx_ethtag = 6;
    2046           0 :         int idx_esi = 10;
    2047           0 :         int idx_gwip = 12;
    2048           0 :         return bgp_static_unset_safi(
    2049           0 :                 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
    2050           0 :                 argv[idx_ext_community]->arg, argv[idx_label]->arg,
    2051           0 :                 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
    2052           0 :                 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
    2053             : }
    2054             : 
    2055           0 : static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
    2056             : {
    2057           0 :         evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl, false);
    2058             : }
    2059             : 
    2060           0 : static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
    2061             : {
    2062           0 :         evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl, false);
    2063             : }
    2064             : 
    2065             : /*
    2066             :  * Configure the Import RTs for a VNI (vty handler). Caller expected to
    2067             :  * check that this is a change.
    2068             :  */
    2069           0 : static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
    2070             :                                      struct ecommunity *ecomadd)
    2071             : {
    2072             :         /* If the VNI is "live", we need to uninstall routes using the current
    2073             :          * import RT(s) first before we update the import RT, and subsequently
    2074             :          * install routes.
    2075             :          */
    2076           0 :         if (is_vni_live(vpn))
    2077           0 :                 bgp_evpn_uninstall_routes(bgp, vpn);
    2078             : 
    2079             :         /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
    2080           0 :         bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
    2081             : 
    2082             :         /* If the auto route-target is in use we must remove it */
    2083           0 :         evpn_import_rt_delete_auto(bgp, vpn);
    2084             : 
    2085             :         /* Add new RT and rebuild the RT to VNI mapping */
    2086           0 :         listnode_add_sort(vpn->import_rtl, ecomadd);
    2087             : 
    2088           0 :         SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
    2089           0 :         bgp_evpn_map_vni_to_its_rts(bgp, vpn);
    2090             : 
    2091             :         /* Install routes that match new import RT */
    2092           0 :         if (is_vni_live(vpn))
    2093           0 :                 bgp_evpn_install_routes(bgp, vpn);
    2094           0 : }
    2095             : 
    2096             : /*
    2097             :  * Unconfigure Import RT(s) for a VNI (vty handler).
    2098             :  */
    2099           0 : static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
    2100             :                                        struct ecommunity *ecomdel)
    2101             : {
    2102           0 :         struct listnode *node, *nnode, *node_to_del;
    2103           0 :         struct ecommunity *ecom;
    2104             : 
    2105             :         /* Along the lines of "configure" except we have to reset to the
    2106             :          * automatic value.
    2107             :          */
    2108           0 :         if (is_vni_live(vpn))
    2109           0 :                 bgp_evpn_uninstall_routes(bgp, vpn);
    2110             : 
    2111             :         /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
    2112           0 :         bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
    2113             : 
    2114             :         /* Delete all import RTs */
    2115           0 :         if (ecomdel == NULL) {
    2116           0 :                 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
    2117           0 :                         ecommunity_free(&ecom);
    2118           0 :                         list_delete_node(vpn->import_rtl, node);
    2119             :                 }
    2120             :         }
    2121             : 
    2122             :         /* Delete a specific import RT */
    2123             :         else {
    2124           0 :                 node_to_del = NULL;
    2125             : 
    2126           0 :                 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
    2127           0 :                         if (ecommunity_match(ecom, ecomdel)) {
    2128           0 :                                 ecommunity_free(&ecom);
    2129           0 :                                 node_to_del = node;
    2130           0 :                                 break;
    2131             :                         }
    2132             :                 }
    2133             : 
    2134           0 :                 if (node_to_del)
    2135           0 :                         list_delete_node(vpn->import_rtl, node_to_del);
    2136             :         }
    2137             : 
    2138           0 :         assert(vpn->import_rtl);
    2139             :         /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
    2140           0 :         if (list_isempty(vpn->import_rtl)) {
    2141           0 :                 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
    2142           0 :                 bgp_evpn_derive_auto_rt_import(bgp, vpn);
    2143             :         }
    2144             :         /* Rebuild the RT to VNI mapping */
    2145             :         else
    2146           0 :                 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
    2147             : 
    2148             :         /* Install routes that match new import RT */
    2149           0 :         if (is_vni_live(vpn))
    2150           0 :                 bgp_evpn_install_routes(bgp, vpn);
    2151           0 : }
    2152             : 
    2153             : /*
    2154             :  * Configure the Export RT for a VNI (vty handler). Caller expected to
    2155             :  * check that this is a change. Note that only a single export RT is
    2156             :  * allowed for a VNI and any change to configuration is implemented as
    2157             :  * a "replace" (similar to other configuration).
    2158             :  */
    2159           0 : static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
    2160             :                                      struct ecommunity *ecomadd)
    2161             : {
    2162             :         /* If the auto route-target is in use we must remove it */
    2163           0 :         evpn_export_rt_delete_auto(bgp, vpn);
    2164             : 
    2165           0 :         listnode_add_sort(vpn->export_rtl, ecomadd);
    2166           0 :         SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
    2167             : 
    2168           0 :         if (is_vni_live(vpn))
    2169           0 :                 bgp_evpn_handle_export_rt_change(bgp, vpn);
    2170           0 : }
    2171             : 
    2172             : /*
    2173             :  * Unconfigure the Export RT for a VNI (vty handler)
    2174             :  */
    2175           0 : static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
    2176             :                                        struct ecommunity *ecomdel)
    2177             : {
    2178           0 :         struct listnode *node, *nnode, *node_to_del;
    2179           0 :         struct ecommunity *ecom;
    2180             : 
    2181             :         /* Delete all export RTs */
    2182           0 :         if (ecomdel == NULL) {
    2183             :                 /* Reset to default and process all routes. */
    2184           0 :                 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
    2185           0 :                         ecommunity_free(&ecom);
    2186           0 :                         list_delete_node(vpn->export_rtl, node);
    2187             :                 }
    2188             :         }
    2189             : 
    2190             :         /* Delete a specific export RT */
    2191             :         else {
    2192           0 :                 node_to_del = NULL;
    2193             : 
    2194           0 :                 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
    2195           0 :                         if (ecommunity_match(ecom, ecomdel)) {
    2196           0 :                                 ecommunity_free(&ecom);
    2197           0 :                                 node_to_del = node;
    2198           0 :                                 break;
    2199             :                         }
    2200             :                 }
    2201             : 
    2202           0 :                 if (node_to_del)
    2203           0 :                         list_delete_node(vpn->export_rtl, node_to_del);
    2204             :         }
    2205             : 
    2206           0 :         assert(vpn->export_rtl);
    2207           0 :         if (list_isempty(vpn->export_rtl)) {
    2208           0 :                 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
    2209           0 :                 bgp_evpn_derive_auto_rt_export(bgp, vpn);
    2210             :         }
    2211             : 
    2212           0 :         if (is_vni_live(vpn))
    2213           0 :                 bgp_evpn_handle_export_rt_change(bgp, vpn);
    2214           0 : }
    2215             : 
    2216             : /*
    2217             :  * Configure RD for VRF
    2218             :  */
    2219           0 : static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
    2220             : {
    2221             :         /* If we have already advertise type-5 routes with a diffrent RD, we
    2222             :          * have to delete and withdraw them firs
    2223             :          */
    2224           0 :         bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
    2225             : 
    2226             :         /* update RD */
    2227           0 :         memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
    2228           0 :         SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
    2229             : 
    2230             :         /* We have a new RD for VRF.
    2231             :          * Advertise all type-5 routes again with the new RD
    2232             :          */
    2233           0 :         bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
    2234           0 : }
    2235             : 
    2236             : /*
    2237             :  * Unconfigure RD for VRF
    2238             :  */
    2239           0 : static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
    2240             : {
    2241             :         /* If we have already advertise type-5 routes with a diffrent RD, we
    2242             :          * have to delete and withdraw them firs
    2243             :          */
    2244           0 :         bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
    2245             : 
    2246             :         /* fall back to default RD */
    2247           0 :         bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
    2248           0 :         UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
    2249             : 
    2250             :         /* We have a new RD for VRF.
    2251             :          * Advertise all type-5 routes again with the new RD
    2252             :          */
    2253           0 :         bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
    2254           0 : }
    2255             : 
    2256             : /*
    2257             :  * Configure RD for a VNI (vty handler)
    2258             :  */
    2259           0 : static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
    2260             :                               struct prefix_rd *rd)
    2261             : {
    2262             :         /* If the VNI is "live", we need to delete and withdraw this VNI's
    2263             :          * local routes with the prior RD first. Then, after updating RD,
    2264             :          * need to re-advertise.
    2265             :          */
    2266           0 :         if (is_vni_live(vpn))
    2267           0 :                 bgp_evpn_handle_rd_change(bgp, vpn, 1);
    2268             : 
    2269             :         /* update RD */
    2270           0 :         memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
    2271           0 :         SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
    2272             : 
    2273           0 :         if (is_vni_live(vpn))
    2274           0 :                 bgp_evpn_handle_rd_change(bgp, vpn, 0);
    2275           0 : }
    2276             : 
    2277             : /*
    2278             :  * Unconfigure RD for a VNI (vty handler)
    2279             :  */
    2280           0 : static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
    2281             : {
    2282             :         /* If the VNI is "live", we need to delete and withdraw this VNI's
    2283             :          * local routes with the prior RD first. Then, after resetting RD
    2284             :          * to automatic value, need to re-advertise.
    2285             :          */
    2286           0 :         if (is_vni_live(vpn))
    2287           0 :                 bgp_evpn_handle_rd_change(bgp, vpn, 1);
    2288             : 
    2289             :         /* reset RD to default */
    2290           0 :         bgp_evpn_derive_auto_rd(bgp, vpn);
    2291             : 
    2292           0 :         if (is_vni_live(vpn))
    2293           0 :                 bgp_evpn_handle_rd_change(bgp, vpn, 0);
    2294           0 : }
    2295             : 
    2296             : /*
    2297             :  * Create VNI, if not already present (VTY handler). Mark as configured.
    2298             :  */
    2299           0 : static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
    2300             : {
    2301           0 :         struct bgpevpn *vpn;
    2302           0 :         struct in_addr mcast_grp = {INADDR_ANY};
    2303             : 
    2304           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    2305           0 :         if (!vpn) {
    2306             :                 /* Check if this L2VNI is already configured as L3VNI */
    2307           0 :                 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
    2308           0 :                         flog_err(
    2309             :                                 EC_BGP_VNI,
    2310             :                                 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
    2311             :                                 bgp->vrf_id, vni);
    2312           0 :                         return NULL;
    2313             :                 }
    2314             : 
    2315             :                 /* tenant vrf will be updated when we get local_vni_add from
    2316             :                  * zebra
    2317             :                  */
    2318           0 :                 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp, 0);
    2319             :         }
    2320             : 
    2321             :         /* Mark as configured. */
    2322           0 :         SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
    2323           0 :         return vpn;
    2324             : }
    2325             : 
    2326             : /*
    2327             :  * Delete VNI. If VNI does not exist in the system (i.e., just
    2328             :  * configuration), all that is needed is to free it. Otherwise,
    2329             :  * any parameters configured for the VNI need to be reset (with
    2330             :  * appropriate action) and the VNI marked as unconfigured; the
    2331             :  * VNI will continue to exist, purely as a "learnt" entity.
    2332             :  */
    2333           0 : static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
    2334             : {
    2335           0 :         if (!is_vni_live(vpn)) {
    2336           0 :                 bgp_evpn_free(bgp, vpn);
    2337           0 :                 return;
    2338             :         }
    2339             : 
    2340             :         /* We need to take the unconfigure action for each parameter of this VNI
    2341             :          * that is configured. Some optimization is possible, but not worth the
    2342             :          * additional code for an operation that should be pretty rare.
    2343             :          */
    2344           0 :         UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
    2345             : 
    2346             :         /* First, deal with the export side - RD and export RT changes. */
    2347           0 :         if (is_rd_configured(vpn))
    2348           0 :                 evpn_unconfigure_rd(bgp, vpn);
    2349           0 :         if (is_export_rt_configured(vpn))
    2350           0 :                 evpn_unconfigure_export_rt(bgp, vpn, NULL);
    2351             : 
    2352             :         /* Next, deal with the import side. */
    2353           0 :         if (is_import_rt_configured(vpn))
    2354           0 :                 evpn_unconfigure_import_rt(bgp, vpn, NULL);
    2355             : }
    2356             : 
    2357             : /*
    2358             :  * Display import RT mapping to VRFs (vty handler)
    2359             :  * bgp_evpn: evpn bgp instance
    2360             :  */
    2361           0 : static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
    2362             :                                      json_object *json)
    2363             : {
    2364           0 :         void *args[2];
    2365             : 
    2366           0 :         args[0] = vty;
    2367           0 :         args[1] = json;
    2368             : 
    2369           0 :         hash_iterate(bgp_evpn->vrf_import_rt_hash,
    2370             :                      (void (*)(struct hash_bucket *,
    2371             :                                void *))show_vrf_import_rt_entry,
    2372             :                      args);
    2373             : }
    2374             : 
    2375             : /*
    2376             :  * Display import RT mapping to VNIs (vty handler)
    2377             :  */
    2378           0 : static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
    2379             :                                  json_object *json)
    2380             : {
    2381           0 :         void *args[2];
    2382             : 
    2383           0 :         args[0] = vty;
    2384           0 :         args[1] = json;
    2385             : 
    2386           0 :         hash_iterate(
    2387             :                 bgp->import_rt_hash,
    2388             :                 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
    2389             :                 args);
    2390             : }
    2391             : 
    2392             : /*
    2393             :  * Display EVPN routes for all VNIs - vty handler.
    2394             :  */
    2395           0 : static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, int type,
    2396             :                                      bool mac_table, struct in_addr vtep_ip,
    2397             :                                      json_object *json, int detail)
    2398             : {
    2399           0 :         uint32_t num_vnis;
    2400           0 :         struct vni_walk_ctx wctx;
    2401             : 
    2402           0 :         num_vnis = hashcount(bgp->vnihash);
    2403           0 :         if (!num_vnis)
    2404           0 :                 return;
    2405           0 :         memset(&wctx, 0, sizeof(wctx));
    2406           0 :         wctx.bgp = bgp;
    2407           0 :         wctx.vty = vty;
    2408           0 :         wctx.type = type;
    2409           0 :         wctx.mac_table = mac_table;
    2410           0 :         wctx.vtep_ip = vtep_ip;
    2411           0 :         wctx.json = json;
    2412           0 :         wctx.detail = detail;
    2413           0 :         hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
    2414             :                                              void *))show_vni_routes_hash,
    2415             :                      &wctx);
    2416             : }
    2417             : 
    2418             : /*
    2419             :  * Display EVPN routes for all VNIs & all types - vty handler.
    2420             :  */
    2421           0 : static void evpn_show_routes_vni_all_type_all(struct vty *vty, struct bgp *bgp,
    2422             :                                               struct in_addr vtep_ip,
    2423             :                                               json_object *json, int detail)
    2424             : {
    2425           0 :         uint32_t num_vnis;
    2426           0 :         struct vni_walk_ctx wctx;
    2427             : 
    2428           0 :         num_vnis = hashcount(bgp->vnihash);
    2429           0 :         if (!num_vnis)
    2430           0 :                 return;
    2431             : 
    2432           0 :         memset(&wctx, 0, sizeof(struct vni_walk_ctx));
    2433           0 :         wctx.bgp = bgp;
    2434           0 :         wctx.vty = vty;
    2435           0 :         wctx.vtep_ip = vtep_ip;
    2436           0 :         wctx.json = json;
    2437           0 :         wctx.detail = detail;
    2438           0 :         hash_iterate(bgp->vnihash,
    2439             :                      (void (*)(struct hash_bucket *,
    2440             :                                void *))show_vni_routes_all_hash,
    2441             :                      &wctx);
    2442             : }
    2443             : 
    2444             : /*
    2445             :  * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
    2446             :  */
    2447           0 : static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
    2448             :                                           vni_t vni, struct in_addr orig_ip,
    2449             :                                           json_object *json)
    2450             : {
    2451           0 :         struct bgpevpn *vpn;
    2452           0 :         struct prefix_evpn p;
    2453           0 :         struct bgp_dest *dest;
    2454           0 :         struct bgp_path_info *pi;
    2455           0 :         uint32_t path_cnt = 0;
    2456           0 :         afi_t afi;
    2457           0 :         safi_t safi;
    2458           0 :         json_object *json_paths = NULL;
    2459             : 
    2460           0 :         afi = AFI_L2VPN;
    2461           0 :         safi = SAFI_EVPN;
    2462             : 
    2463             :         /* Locate VNI. */
    2464           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    2465           0 :         if (!vpn) {
    2466           0 :                 vty_out(vty, "VNI not found\n");
    2467           0 :                 return;
    2468             :         }
    2469             : 
    2470             :         /* See if route exists. */
    2471           0 :         build_evpn_type3_prefix(&p, orig_ip);
    2472           0 :         dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
    2473           0 :         if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
    2474           0 :                 if (!json)
    2475           0 :                         vty_out(vty, "%% Network not in table\n");
    2476             : 
    2477           0 :                 if (dest)
    2478           0 :                         bgp_dest_unlock_node(dest);
    2479             : 
    2480           0 :                 return;
    2481             :         }
    2482             : 
    2483           0 :         if (json)
    2484           0 :                 json_paths = json_object_new_array();
    2485             : 
    2486             :         /* Prefix and num paths displayed once per prefix. */
    2487           0 :         route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
    2488             :                                     NULL, afi, safi, json);
    2489             : 
    2490             :         /* Display each path for this prefix. */
    2491           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    2492           0 :                 json_object *json_path = NULL;
    2493             : 
    2494           0 :                 if (json)
    2495           0 :                         json_path = json_object_new_array();
    2496             : 
    2497           0 :                 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
    2498             :                                      pi, afi, safi, RPKI_NOT_BEING_USED,
    2499             :                                      json_path);
    2500             : 
    2501           0 :                 if (json)
    2502           0 :                         json_object_array_add(json_paths, json_path);
    2503             : 
    2504           0 :                 path_cnt++;
    2505             :         }
    2506             : 
    2507           0 :         if (json) {
    2508           0 :                 if (path_cnt)
    2509           0 :                         json_object_object_add(json, "paths", json_paths);
    2510             : 
    2511           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    2512             :         } else {
    2513           0 :                 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
    2514             :                         path_cnt);
    2515             :         }
    2516             : 
    2517           0 :         bgp_dest_unlock_node(dest);
    2518             : }
    2519             : 
    2520             : /*
    2521             :  * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
    2522             :  * By definition, only matching type-2 route will be displayed.
    2523             :  */
    2524           0 : static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
    2525             :                                       vni_t vni, struct ethaddr *mac,
    2526             :                                       struct ipaddr *ip, json_object *json)
    2527             : {
    2528           0 :         struct bgpevpn *vpn;
    2529           0 :         struct prefix_evpn p;
    2530           0 :         struct prefix_evpn tmp_p;
    2531           0 :         struct bgp_dest *dest;
    2532           0 :         struct bgp_path_info *pi;
    2533           0 :         uint32_t path_cnt = 0;
    2534           0 :         afi_t afi;
    2535           0 :         safi_t safi;
    2536           0 :         json_object *json_paths = NULL;
    2537           0 :         struct ethaddr empty_mac = {};
    2538           0 :         struct ipaddr empty_ip = {};
    2539           0 :         const struct prefix_evpn *evp;
    2540             : 
    2541           0 :         afi = AFI_L2VPN;
    2542           0 :         safi = SAFI_EVPN;
    2543             : 
    2544             :         /* Locate VNI. */
    2545           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    2546           0 :         if (!vpn) {
    2547           0 :                 if (!json)
    2548           0 :                         vty_out(vty, "VNI not found\n");
    2549           0 :                 return;
    2550             :         }
    2551             : 
    2552           0 :         build_evpn_type2_prefix(&p, mac ? mac : &empty_mac,
    2553             :                                 ip ? ip : &empty_ip);
    2554             : 
    2555             :         /* See if route exists. Look for both non-sticky and sticky. */
    2556           0 :         dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
    2557           0 :         if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
    2558           0 :                 if (!json)
    2559           0 :                         vty_out(vty, "%% Network not in table\n");
    2560             : 
    2561           0 :                 if (dest)
    2562           0 :                         bgp_dest_unlock_node(dest);
    2563             : 
    2564           0 :                 return;
    2565             :         }
    2566             : 
    2567             :         /*
    2568             :          * MAC is per-path, we have to walk the path_info's and look for it
    2569             :          * first here.
    2570             :          */
    2571           0 :         if (ip && mac) {
    2572           0 :                 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    2573           0 :                         if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
    2574             :                                    sizeof(*mac)) == 0)
    2575             :                                 break;
    2576             :                 }
    2577             : 
    2578           0 :                 if (!pi) {
    2579           0 :                         if (!json)
    2580           0 :                                 vty_out(vty, "%% Network not in table\n");
    2581           0 :                         return;
    2582             :                 }
    2583             :         }
    2584             : 
    2585           0 :         if (json)
    2586           0 :                 json_paths = json_object_new_array();
    2587             : 
    2588             :         /* Prefix and num paths displayed once per prefix. */
    2589           0 :         route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
    2590             :                                     afi, safi, json);
    2591             : 
    2592           0 :         evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    2593             : 
    2594             :         /* Display each path for this prefix. */
    2595           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    2596           0 :                 json_object *json_path = NULL;
    2597             : 
    2598             :                 /* skip non-matching MACs */
    2599           0 :                 if (ip && mac &&
    2600           0 :                     memcmp(mac, evpn_type2_path_info_get_mac(pi),
    2601             :                            sizeof(*mac)) != 0)
    2602           0 :                         continue;
    2603             : 
    2604           0 :                 if (json)
    2605           0 :                         json_path = json_object_new_array();
    2606             : 
    2607             :                 /*
    2608             :                  * VNI table MAC-IP prefixes don't have MAC so
    2609             :                  * make sure it's set from path info
    2610             :                  * here.
    2611             :                  */
    2612           0 :                 if (is_evpn_prefix_ipaddr_none(evp)) {
    2613             :                         /* VNI MAC -> Global */
    2614           0 :                         evpn_type2_prefix_global_copy(
    2615             :                                 (struct prefix_evpn *)&tmp_p, evp,
    2616             :                                 NULL /* mac */,
    2617           0 :                                 evpn_type2_path_info_get_ip(pi));
    2618             :                 } else {
    2619             :                         /* VNI IP -> Global */
    2620           0 :                         evpn_type2_prefix_global_copy(
    2621             :                                 (struct prefix_evpn *)&tmp_p, evp,
    2622           0 :                                 evpn_type2_path_info_get_mac(pi),
    2623             :                                 NULL /* ip */);
    2624             :                 }
    2625             : 
    2626           0 :                 route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p,
    2627             :                                      pi, afi, safi, RPKI_NOT_BEING_USED,
    2628             :                                      json_path);
    2629             : 
    2630           0 :                 if (json)
    2631           0 :                         json_object_array_add(json_paths, json_path);
    2632             : 
    2633           0 :                 path_cnt++;
    2634             :         }
    2635             : 
    2636           0 :         if (json) {
    2637           0 :                 if (path_cnt)
    2638           0 :                         json_object_object_add(json, "paths", json_paths);
    2639             : 
    2640           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    2641             :         } else {
    2642           0 :                 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
    2643             :                         path_cnt);
    2644             :         }
    2645             : 
    2646           0 :         bgp_dest_unlock_node(dest);
    2647             : }
    2648             : 
    2649             : /* Disaplay EVPN routes for a ESI - VTY handler */
    2650           0 : static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
    2651             :                                  esi_t *esi, json_object *json)
    2652             : {
    2653           0 :         struct bgp_evpn_es *es = NULL;
    2654             : 
    2655             :         /* locate the ES */
    2656           0 :         es = bgp_evpn_es_find(esi);
    2657           0 :         if (!es) {
    2658           0 :                 if (!json)
    2659           0 :                         vty_out(vty, "ESI not found\n");
    2660           0 :                 return;
    2661             :         }
    2662             : 
    2663           0 :         show_esi_routes(bgp, es, vty, json);
    2664             : }
    2665             : 
    2666             : /*
    2667             :  * Display EVPN routes for a VNI - vty handler.
    2668             :  * If 'type' is non-zero, only routes matching that type are shown.
    2669             :  * If the vtep_ip is non zero, only routes behind that vtep are shown
    2670             :  */
    2671           0 : static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
    2672             :                                  int type, bool mac_table,
    2673             :                                  struct in_addr vtep_ip, json_object *json)
    2674             : {
    2675           0 :         struct bgpevpn *vpn;
    2676             : 
    2677             :         /* Locate VNI. */
    2678           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    2679           0 :         if (!vpn) {
    2680           0 :                 if (!json)
    2681           0 :                         vty_out(vty, "VNI not found\n");
    2682           0 :                 return;
    2683             :         }
    2684             : 
    2685             :         /* Walk this VNI's route table and display appropriate routes. */
    2686           0 :         show_vni_routes(bgp, vpn, vty, type, mac_table, vtep_ip, json, 0);
    2687             : }
    2688             : 
    2689             : /*
    2690             :  * Display BGP EVPN routing table -- for specific RD and MAC and/or
    2691             :  * IP (vty handler). By definition, only matching type-2 route will be
    2692             :  * displayed.
    2693             :  */
    2694           0 : static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
    2695             :                                      struct prefix_rd *prd, struct ethaddr *mac,
    2696             :                                      struct ipaddr *ip, json_object *json)
    2697             : {
    2698           0 :         struct prefix_evpn p;
    2699           0 :         struct bgp_dest *dest;
    2700           0 :         struct bgp_path_info *pi;
    2701           0 :         afi_t afi;
    2702           0 :         safi_t safi;
    2703           0 :         uint32_t path_cnt = 0;
    2704           0 :         json_object *json_paths = NULL;
    2705             : 
    2706           0 :         afi = AFI_L2VPN;
    2707           0 :         safi = SAFI_EVPN;
    2708             : 
    2709             :         /* See if route exists. Look for both non-sticky and sticky. */
    2710           0 :         build_evpn_type2_prefix(&p, mac, ip);
    2711           0 :         dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
    2712             :                                    (struct prefix *)&p, prd);
    2713           0 :         if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
    2714           0 :                 if (!json)
    2715           0 :                         vty_out(vty, "%% Network not in table\n");
    2716             : 
    2717           0 :                 if (dest)
    2718           0 :                         bgp_dest_unlock_node(dest);
    2719             : 
    2720           0 :                 return;
    2721             :         }
    2722             : 
    2723             :         /* Prefix and num paths displayed once per prefix. */
    2724           0 :         route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
    2725             :                                     prd, afi, safi, json);
    2726             : 
    2727           0 :         if (json)
    2728           0 :                 json_paths = json_object_new_array();
    2729             : 
    2730             :         /* Display each path for this prefix. */
    2731           0 :         for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
    2732           0 :                 json_object *json_path = NULL;
    2733             : 
    2734           0 :                 if (json)
    2735           0 :                         json_path = json_object_new_array();
    2736             : 
    2737           0 :                 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
    2738             :                                      pi, afi, safi, RPKI_NOT_BEING_USED,
    2739             :                                      json_path);
    2740             : 
    2741           0 :                 if (json)
    2742           0 :                         json_object_array_add(json_paths, json_path);
    2743             : 
    2744           0 :                 path_cnt++;
    2745             :         }
    2746             : 
    2747           0 :         if (json && path_cnt) {
    2748           0 :                 if (path_cnt)
    2749           0 :                         json_object_object_addf(json, json_paths, "%pFX", &p);
    2750           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    2751             :         } else {
    2752           0 :                 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
    2753             :                         path_cnt);
    2754             :         }
    2755             : 
    2756           0 :         bgp_dest_unlock_node(dest);
    2757             : }
    2758             : 
    2759             : /*
    2760             :  * Display BGP EVPN routing table -- for specific RD (vty handler)
    2761             :  * If 'type' is non-zero, only routes matching that type are shown.
    2762             :  */
    2763           0 : static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
    2764             :                                struct prefix_rd *prd, int type,
    2765             :                                json_object *json)
    2766             : {
    2767           0 :         struct bgp_dest *rd_dest;
    2768           0 :         struct bgp_table *table;
    2769           0 :         struct bgp_dest *dest;
    2770           0 :         struct bgp_path_info *pi;
    2771           0 :         int rd_header = 1;
    2772           0 :         afi_t afi;
    2773           0 :         safi_t safi;
    2774           0 :         uint32_t prefix_cnt, path_cnt;
    2775           0 :         json_object *json_rd = NULL;
    2776           0 :         int add_rd_to_json = 0;
    2777             : 
    2778           0 :         afi = AFI_L2VPN;
    2779           0 :         safi = SAFI_EVPN;
    2780           0 :         prefix_cnt = path_cnt = 0;
    2781             : 
    2782           0 :         rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
    2783           0 :         if (!rd_dest)
    2784             :                 return;
    2785             : 
    2786           0 :         table = bgp_dest_get_bgp_table_info(rd_dest);
    2787           0 :         if (table == NULL) {
    2788           0 :                 bgp_dest_unlock_node(rd_dest);
    2789           0 :                 return;
    2790             :         }
    2791             : 
    2792           0 :         if (json) {
    2793           0 :                 json_rd = json_object_new_object();
    2794           0 :                 json_object_string_addf(json_rd, "rd", "%pRD", prd);
    2795             :         }
    2796             : 
    2797           0 :         bgp_dest_unlock_node(rd_dest);
    2798             : 
    2799             :         /* Display all prefixes with this RD. */
    2800           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
    2801           0 :                 const struct prefix_evpn *evp =
    2802           0 :                         (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
    2803           0 :                 json_object *json_prefix = NULL;
    2804           0 :                 json_object *json_paths = NULL;
    2805           0 :                 int add_prefix_to_json = 0;
    2806             : 
    2807           0 :                 if (type && evp->prefix.route_type != type)
    2808           0 :                         continue;
    2809             : 
    2810           0 :                 if (json)
    2811           0 :                         json_prefix = json_object_new_object();
    2812             : 
    2813           0 :                 pi = bgp_dest_get_bgp_path_info(dest);
    2814           0 :                 if (pi) {
    2815             :                         /* RD header and legend - once overall. */
    2816           0 :                         if (rd_header && !json) {
    2817           0 :                                 vty_out(vty,
    2818             :                                         "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
    2819           0 :                                 vty_out(vty,
    2820             :                                         "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
    2821           0 :                                 vty_out(vty,
    2822             :                                         "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
    2823           0 :                                 vty_out(vty,
    2824             :                                         "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
    2825           0 :                                 vty_out(vty,
    2826             :                                         "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
    2827           0 :                                 rd_header = 0;
    2828             :                         }
    2829             : 
    2830             :                         /* Prefix and num paths displayed once per prefix. */
    2831           0 :                         route_vty_out_detail_header(
    2832             :                                 vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
    2833             :                                 afi, safi, json_prefix);
    2834             : 
    2835           0 :                         prefix_cnt++;
    2836             :                 }
    2837             : 
    2838           0 :                 if (json)
    2839           0 :                         json_paths = json_object_new_array();
    2840             : 
    2841             :                 /* Display each path for this prefix. */
    2842           0 :                 for (; pi; pi = pi->next) {
    2843           0 :                         json_object *json_path = NULL;
    2844             : 
    2845           0 :                         if (json)
    2846           0 :                                 json_path = json_object_new_array();
    2847             : 
    2848           0 :                         route_vty_out_detail(
    2849             :                                 vty, bgp, dest, bgp_dest_get_prefix(dest), pi,
    2850             :                                 afi, safi, RPKI_NOT_BEING_USED, json_path);
    2851             : 
    2852           0 :                         if (json)
    2853           0 :                                 json_object_array_add(json_paths, json_path);
    2854             : 
    2855           0 :                         path_cnt++;
    2856           0 :                         add_prefix_to_json = 1;
    2857           0 :                         add_rd_to_json = 1;
    2858             :                 }
    2859             : 
    2860           0 :                 if (json) {
    2861           0 :                         if (add_prefix_to_json) {
    2862           0 :                                 json_object_object_add(json_prefix, "paths",
    2863             :                                                        json_paths);
    2864           0 :                                 json_object_object_addf(json_rd, json_prefix,
    2865             :                                                         "%pFX", evp);
    2866             :                         } else {
    2867           0 :                                 json_object_free(json_paths);
    2868           0 :                                 json_object_free(json_prefix);
    2869           0 :                                 json_paths = NULL;
    2870           0 :                                 json_prefix = NULL;
    2871             :                         }
    2872             :                 }
    2873             :         }
    2874             : 
    2875           0 :         if (json) {
    2876           0 :                 if (add_rd_to_json)
    2877           0 :                         json_object_object_addf(json, json_rd, "%pRD", prd);
    2878             :                 else {
    2879           0 :                         json_object_free(json_rd);
    2880           0 :                         json_rd = NULL;
    2881             :                 }
    2882             : 
    2883           0 :                 json_object_int_add(json, "numPrefix", prefix_cnt);
    2884           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    2885             :         } else {
    2886           0 :                 if (prefix_cnt == 0)
    2887           0 :                         vty_out(vty, "No prefixes exist with this RD%s\n",
    2888             :                                 type ? " (of requested type)" : "");
    2889             :                 else
    2890           0 :                         vty_out(vty,
    2891             :                                 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
    2892             :                                 prefix_cnt, path_cnt,
    2893             :                                 type ? " (of requested type)" : "");
    2894             :         }
    2895             : }
    2896             : 
    2897             : /*
    2898             :  * Display BGP EVPN routing table -- all RDs and MAC and/or IP
    2899             :  * (vty handler).  Only matching type-2 routes will be displayed.
    2900             :  */
    2901           0 : static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
    2902             :                                          struct ethaddr *mac, struct ipaddr *ip,
    2903             :                                          json_object *json)
    2904             : {
    2905           0 :         struct bgp_dest *rd_dest;
    2906           0 :         struct bgp_table *table;
    2907           0 :         struct bgp_dest *dest;
    2908           0 :         struct bgp_path_info *pi;
    2909           0 :         afi_t afi = AFI_L2VPN;
    2910           0 :         safi_t safi = SAFI_EVPN;
    2911           0 :         uint32_t prefix_cnt, path_cnt;
    2912           0 :         prefix_cnt = path_cnt = 0;
    2913             : 
    2914             :         /* EVPN routing table is a 2-level table with the first level being
    2915             :          * the RD. We need to look in every RD we know about.
    2916             :          */
    2917           0 :         for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
    2918           0 :              rd_dest = bgp_route_next(rd_dest)) {
    2919           0 :                 json_object *json_paths = NULL;  /* paths array for prefix */
    2920           0 :                 json_object *json_prefix = NULL; /* prefix within an RD */
    2921           0 :                 json_object *json_rd = NULL;     /* holds all prefixes for RD */
    2922           0 :                 char rd_str[RD_ADDRSTRLEN];
    2923           0 :                 int add_rd_to_json = 0;
    2924           0 :                 struct prefix_evpn ep;
    2925           0 :                 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
    2926             : 
    2927           0 :                 table = bgp_dest_get_bgp_table_info(rd_dest);
    2928           0 :                 if (table == NULL)
    2929           0 :                         continue;
    2930             : 
    2931           0 :                 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
    2932             :                               sizeof(rd_str));
    2933             : 
    2934             :                 /* Construct an RT-2 from the user-supplied mac(ip),
    2935             :                  * then search the l2vpn evpn table for it.
    2936             :                  */
    2937           0 :                 build_evpn_type2_prefix(&ep, mac, ip);
    2938           0 :                 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
    2939             :                                            (struct prefix *)&ep,
    2940             :                                            (struct prefix_rd *)rd_destp);
    2941           0 :                 if (!dest)
    2942           0 :                         continue;
    2943             : 
    2944           0 :                 if (json)
    2945           0 :                         json_rd = json_object_new_object();
    2946             : 
    2947           0 :                 const struct prefix *p = bgp_dest_get_prefix(dest);
    2948             : 
    2949           0 :                 pi = bgp_dest_get_bgp_path_info(dest);
    2950           0 :                 if (pi) {
    2951             :                         /* RD header - per RD. */
    2952           0 :                         bgp_evpn_show_route_rd_header(vty, rd_dest, json_rd,
    2953             :                                                       rd_str, RD_ADDRSTRLEN);
    2954           0 :                         prefix_cnt++;
    2955             :                 }
    2956             : 
    2957           0 :                 if (json) {
    2958           0 :                         json_prefix = json_object_new_object();
    2959           0 :                         json_paths = json_object_new_array();
    2960           0 :                         json_object_string_addf(json_prefix, "prefix", "%pFX",
    2961             :                                                 p);
    2962           0 :                         json_object_int_add(json_prefix, "prefixLen",
    2963           0 :                                             p->prefixlen);
    2964             :                 } else
    2965             :                         /* Prefix and num paths displayed once per prefix. */
    2966           0 :                         route_vty_out_detail_header(
    2967             :                                 vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
    2968             :                                 AFI_L2VPN, SAFI_EVPN, json_prefix);
    2969             : 
    2970             :                 /* For EVPN, the prefix is displayed for each path (to
    2971             :                  * fit in with code that already exists).
    2972             :                  */
    2973           0 :                 for (; pi; pi = pi->next) {
    2974           0 :                         json_object *json_path = NULL;
    2975             : 
    2976           0 :                         add_rd_to_json = 1;
    2977           0 :                         path_cnt++;
    2978             : 
    2979           0 :                         if (json)
    2980           0 :                                 json_path = json_object_new_array();
    2981             : 
    2982           0 :                         route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,
    2983             :                                              SAFI_EVPN, RPKI_NOT_BEING_USED,
    2984             :                                              json_path);
    2985             : 
    2986           0 :                         if (json)
    2987           0 :                                 json_object_array_add(json_paths, json_path);
    2988             :                         else
    2989           0 :                                 vty_out(vty, "\n");
    2990             :                 }
    2991             : 
    2992           0 :                 if (json) {
    2993           0 :                         json_object_object_add(json_prefix, "paths",
    2994             :                                                json_paths);
    2995           0 :                         json_object_object_addf(json_rd, json_prefix, "%pFX",
    2996             :                                                 p);
    2997           0 :                         if (add_rd_to_json)
    2998           0 :                                 json_object_object_add(json, rd_str, json_rd);
    2999             :                         else {
    3000           0 :                                 json_object_free(json_rd);
    3001           0 :                                 json_rd = NULL;
    3002             :                         }
    3003             :                 }
    3004             : 
    3005           0 :                 bgp_dest_unlock_node(dest);
    3006             :         }
    3007             : 
    3008           0 :         if (json) {
    3009           0 :                 json_object_int_add(json, "numPrefix", prefix_cnt);
    3010           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    3011             :         } else {
    3012           0 :                 if (prefix_cnt == 0) {
    3013           0 :                         vty_out(vty, "No Matching EVPN prefixes exist\n");
    3014             :                 } else {
    3015           0 :                         vty_out(vty, "Displayed %u prefixes (%u paths)\n",
    3016             :                                 prefix_cnt, path_cnt);
    3017             :                 }
    3018             :         }
    3019           0 : }
    3020             : 
    3021             : /*
    3022             :  * Display BGP EVPN routing table - all routes (vty handler).
    3023             :  * If 'type' is non-zero, only routes matching that type are shown.
    3024             :  */
    3025           0 : static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
    3026             :                                  json_object *json, int detail)
    3027             : {
    3028           0 :         struct bgp_dest *rd_dest;
    3029           0 :         struct bgp_table *table;
    3030           0 :         struct bgp_dest *dest;
    3031           0 :         struct bgp_path_info *pi;
    3032           0 :         int header = detail ? 0 : 1;
    3033           0 :         int rd_header;
    3034           0 :         afi_t afi;
    3035           0 :         safi_t safi;
    3036           0 :         uint32_t prefix_cnt, path_cnt;
    3037             : 
    3038           0 :         afi = AFI_L2VPN;
    3039           0 :         safi = SAFI_EVPN;
    3040           0 :         prefix_cnt = path_cnt = 0;
    3041             : 
    3042             :         /* EVPN routing table is a 2-level table with the first level being
    3043             :          * the RD.
    3044             :          */
    3045           0 :         for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
    3046           0 :              rd_dest = bgp_route_next(rd_dest)) {
    3047           0 :                 char rd_str[RD_ADDRSTRLEN];
    3048           0 :                 json_object *json_rd = NULL; /* contains routes for an RD */
    3049           0 :                 int add_rd_to_json = 0;
    3050           0 :                 uint64_t tbl_ver;
    3051           0 :                 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
    3052             : 
    3053           0 :                 table = bgp_dest_get_bgp_table_info(rd_dest);
    3054           0 :                 if (table == NULL)
    3055           0 :                         continue;
    3056             : 
    3057           0 :                 tbl_ver = table->version;
    3058           0 :                 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
    3059             :                               sizeof(rd_str));
    3060             : 
    3061           0 :                 if (json)
    3062           0 :                         json_rd = json_object_new_object();
    3063             : 
    3064           0 :                 rd_header = 1;
    3065             : 
    3066             :                 /* Display all prefixes for an RD */
    3067           0 :                 for (dest = bgp_table_top(table); dest;
    3068           0 :                      dest = bgp_route_next(dest)) {
    3069           0 :                         json_object *json_prefix =
    3070             :                                 NULL; /* contains prefix under a RD */
    3071           0 :                         json_object *json_paths =
    3072             :                                 NULL; /* array of paths under a prefix*/
    3073           0 :                         const struct prefix_evpn *evp =
    3074           0 :                                 (const struct prefix_evpn *)bgp_dest_get_prefix(
    3075             :                                         dest);
    3076           0 :                         int add_prefix_to_json = 0;
    3077           0 :                         const struct prefix *p = bgp_dest_get_prefix(dest);
    3078             : 
    3079           0 :                         if (type && evp->prefix.route_type != type)
    3080           0 :                                 continue;
    3081             : 
    3082           0 :                         pi = bgp_dest_get_bgp_path_info(dest);
    3083           0 :                         if (pi) {
    3084             :                                 /* Overall header/legend displayed once. */
    3085           0 :                                 if (header) {
    3086           0 :                                         bgp_evpn_show_route_header(vty, bgp,
    3087             :                                                                    tbl_ver,
    3088             :                                                                    json);
    3089           0 :                                         if (!json)
    3090           0 :                                                 vty_out(vty,
    3091             :                                                         "%19s Extended Community\n"
    3092             :                                                         , " ");
    3093             :                                         header = 0;
    3094             :                                 }
    3095             : 
    3096             :                                 /* RD header - per RD. */
    3097           0 :                                 if (rd_header) {
    3098           0 :                                         bgp_evpn_show_route_rd_header(
    3099             :                                                 vty, rd_dest, json_rd, rd_str,
    3100             :                                                 RD_ADDRSTRLEN);
    3101           0 :                                         rd_header = 0;
    3102             :                                 }
    3103             : 
    3104           0 :                                 prefix_cnt++;
    3105             :                         }
    3106             : 
    3107           0 :                         if (json) {
    3108           0 :                                 json_prefix = json_object_new_object();
    3109           0 :                                 json_paths = json_object_new_array();
    3110           0 :                                 json_object_string_addf(json_prefix, "prefix",
    3111             :                                                         "%pFX", p);
    3112           0 :                                 json_object_int_add(json_prefix, "prefixLen",
    3113           0 :                                                     p->prefixlen);
    3114             :                         }
    3115             : 
    3116             :                         /* Prefix and num paths displayed once per prefix. */
    3117           0 :                         if (detail)
    3118           0 :                                 route_vty_out_detail_header(
    3119             :                                         vty, bgp, dest,
    3120             :                                         bgp_dest_get_prefix(dest),
    3121             :                                         (struct prefix_rd *)rd_destp, AFI_L2VPN,
    3122             :                                         SAFI_EVPN, json_prefix);
    3123             : 
    3124             :                         /* For EVPN, the prefix is displayed for each path (to
    3125             :                          * fit in
    3126             :                          * with code that already exists).
    3127             :                          */
    3128           0 :                         for (; pi; pi = pi->next) {
    3129           0 :                                 json_object *json_path = NULL;
    3130             : 
    3131           0 :                                 path_cnt++;
    3132           0 :                                 add_prefix_to_json = 1;
    3133           0 :                                 add_rd_to_json = 1;
    3134             : 
    3135           0 :                                 if (json)
    3136           0 :                                         json_path = json_object_new_array();
    3137             : 
    3138           0 :                                 if (detail) {
    3139           0 :                                         route_vty_out_detail(
    3140             :                                                 vty, bgp, dest,
    3141             :                                                 bgp_dest_get_prefix(dest), pi,
    3142             :                                                 AFI_L2VPN, SAFI_EVPN,
    3143             :                                                 RPKI_NOT_BEING_USED, json_path);
    3144             :                                 } else
    3145           0 :                                         route_vty_out(vty, p, pi, 0, SAFI_EVPN,
    3146             :                                                       json_path, false);
    3147             : 
    3148           0 :                                 if (json)
    3149           0 :                                         json_object_array_add(json_paths,
    3150             :                                                               json_path);
    3151             :                         }
    3152             : 
    3153           0 :                         if (json) {
    3154           0 :                                 if (add_prefix_to_json) {
    3155           0 :                                         json_object_object_add(json_prefix,
    3156             :                                                                "paths",
    3157             :                                                                json_paths);
    3158           0 :                                         json_object_object_addf(json_rd,
    3159             :                                                                 json_prefix,
    3160             :                                                                 "%pFX", p);
    3161             :                                 } else {
    3162           0 :                                         json_object_free(json_prefix);
    3163           0 :                                         json_object_free(json_paths);
    3164           0 :                                         json_prefix = NULL;
    3165           0 :                                         json_paths = NULL;
    3166             :                                 }
    3167             :                         }
    3168             :                 }
    3169             : 
    3170           0 :                 if (json) {
    3171           0 :                         if (add_rd_to_json)
    3172           0 :                                 json_object_object_add(json, rd_str, json_rd);
    3173             :                         else {
    3174           0 :                                 json_object_free(json_rd);
    3175           0 :                                 json_rd = NULL;
    3176             :                         }
    3177             :                 }
    3178             :         }
    3179             : 
    3180           0 :         if (json) {
    3181           0 :                 json_object_int_add(json, "numPrefix", prefix_cnt);
    3182           0 :                 json_object_int_add(json, "numPaths", path_cnt);
    3183             :         } else {
    3184           0 :                 if (prefix_cnt == 0) {
    3185           0 :                         vty_out(vty, "No EVPN prefixes %sexist\n",
    3186             :                                 type ? "(of requested type) " : "");
    3187             :                 } else {
    3188           0 :                         vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
    3189             :                                 prefix_cnt, path_cnt,
    3190             :                                 type ? " (of requested type)" : "");
    3191             :                 }
    3192             :         }
    3193           0 : }
    3194             : 
    3195           0 : int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
    3196             :                              bool use_json, int detail)
    3197             : {
    3198           0 :         json_object *json = NULL;
    3199             : 
    3200           0 :         if (use_json)
    3201           0 :                 json = json_object_new_object();
    3202             : 
    3203           0 :         evpn_show_all_routes(vty, bgp, type, json, detail);
    3204             : 
    3205           0 :         if (use_json)
    3206           0 :                 vty_json(vty, json);
    3207           0 :         return CMD_SUCCESS;
    3208             : }
    3209             : 
    3210             : /*
    3211             :  * Display specified VNI (vty handler)
    3212             :  */
    3213           0 : static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
    3214             :                           json_object *json)
    3215             : {
    3216           0 :         uint8_t found = 0;
    3217           0 :         struct bgpevpn *vpn;
    3218             : 
    3219           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    3220           0 :         if (vpn) {
    3221           0 :                 found = 1;
    3222           0 :                 display_vni(vty, vpn, json);
    3223             :         } else {
    3224           0 :                 struct bgp *bgp_temp;
    3225           0 :                 struct listnode *node = NULL;
    3226             : 
    3227           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
    3228           0 :                         if (bgp_temp->l3vni == vni) {
    3229           0 :                                 found = 1;
    3230           0 :                                 display_l3vni(vty, bgp_temp, json);
    3231             :                         }
    3232             :                 }
    3233             :         }
    3234             : 
    3235           0 :         if (!found) {
    3236           0 :                 if (json) {
    3237           0 :                         vty_out(vty, "{}\n");
    3238             :                 } else {
    3239           0 :                         vty_out(vty, "VNI not found\n");
    3240           0 :                         return;
    3241             :                 }
    3242             :         }
    3243             : }
    3244             : 
    3245             : /*
    3246             :  * Display a VNI (upon user query).
    3247             :  */
    3248           0 : static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
    3249             :                                json_object *json)
    3250             : {
    3251           0 :         void *args[2];
    3252           0 :         struct bgp *bgp_temp = NULL;
    3253           0 :         struct listnode *node;
    3254             : 
    3255             : 
    3256           0 :         if (!json) {
    3257           0 :                 vty_out(vty, "Flags: * - Kernel\n");
    3258           0 :                 vty_out(vty, "  %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
    3259             :                         "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
    3260             :         }
    3261             : 
    3262             :         /* print all L2 VNIS */
    3263           0 :         args[0] = vty;
    3264           0 :         args[1] = json;
    3265           0 :         hash_iterate(bgp->vnihash,
    3266             :                      (void (*)(struct hash_bucket *, void *))show_vni_entry,
    3267             :                      args);
    3268             : 
    3269             :         /* print all L3 VNIs */
    3270           0 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
    3271           0 :                 show_l3vni_entry(vty, bgp_temp, json);
    3272           0 : }
    3273             : 
    3274             : /*
    3275             :  * evpn - enable advertisement of svi MAC-IP
    3276             :  */
    3277           0 : static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
    3278             :                                          uint32_t set)
    3279             : {
    3280           0 :         if (!vpn) {
    3281           0 :                 if (set && bgp->evpn_info->advertise_svi_macip)
    3282             :                         return;
    3283           0 :                 else if (!set && !bgp->evpn_info->advertise_svi_macip)
    3284             :                         return;
    3285             : 
    3286           0 :                 bgp->evpn_info->advertise_svi_macip = set;
    3287           0 :                 bgp_zebra_advertise_svi_macip(bgp,
    3288             :                                         bgp->evpn_info->advertise_svi_macip, 0);
    3289             :         } else {
    3290           0 :                 if (set && vpn->advertise_svi_macip)
    3291             :                         return;
    3292           0 :                 else if (!set && !vpn->advertise_svi_macip)
    3293             :                         return;
    3294             : 
    3295           0 :                 vpn->advertise_svi_macip = set;
    3296           0 :                 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
    3297             :                                               vpn->vni);
    3298             :         }
    3299             : }
    3300             : 
    3301             : /*
    3302             :  * evpn - enable advertisement of default g/w
    3303             :  */
    3304           0 : static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
    3305             : {
    3306           0 :         if (!vpn) {
    3307           0 :                 if (bgp->advertise_gw_macip)
    3308             :                         return;
    3309             : 
    3310           0 :                 bgp->advertise_gw_macip = 1;
    3311           0 :                 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
    3312             :         } else {
    3313           0 :                 if (vpn->advertise_gw_macip)
    3314             :                         return;
    3315             : 
    3316           0 :                 vpn->advertise_gw_macip = 1;
    3317           0 :                 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
    3318             :                                              vpn->vni);
    3319             :         }
    3320             :         return;
    3321             : }
    3322             : 
    3323             : /*
    3324             :  * evpn - disable advertisement of default g/w
    3325             :  */
    3326           0 : static void evpn_unset_advertise_default_gw(struct bgp *bgp,
    3327             :                                             struct bgpevpn *vpn)
    3328             : {
    3329           0 :         if (!vpn) {
    3330           0 :                 if (!bgp->advertise_gw_macip)
    3331             :                         return;
    3332             : 
    3333           0 :                 bgp->advertise_gw_macip = 0;
    3334           0 :                 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
    3335             :         } else {
    3336           0 :                 if (!vpn->advertise_gw_macip)
    3337             :                         return;
    3338             : 
    3339           0 :                 vpn->advertise_gw_macip = 0;
    3340           0 :                 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
    3341             :                                              vpn->vni);
    3342             :         }
    3343             :         return;
    3344             : }
    3345             : 
    3346             : /*
    3347             :  * evpn - enable advertisement of default g/w
    3348             :  */
    3349           0 : static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
    3350             :                                                afi_t afi, bool add)
    3351             : {
    3352           0 :         safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
    3353             : 
    3354           0 :         if (add) {
    3355             :                 /* bail if we are already advertising default route */
    3356           0 :                 if (evpn_default_originate_set(bgp_vrf, afi, safi))
    3357             :                         return;
    3358             : 
    3359           0 :                 if (afi == AFI_IP)
    3360           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    3361             :                                  BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
    3362           0 :                 else if (afi == AFI_IP6)
    3363           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    3364             :                                  BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
    3365             :         } else {
    3366             :                 /* bail out if we havent advertised the default route */
    3367           0 :                 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
    3368             :                         return;
    3369           0 :                 if (afi == AFI_IP)
    3370           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    3371             :                                    BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
    3372           0 :                 else if (afi == AFI_IP6)
    3373           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    3374             :                                    BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
    3375             :         }
    3376             : 
    3377           0 :         bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
    3378             : }
    3379             : 
    3380             : /*
    3381             :  * evpn - enable advertisement of default g/w
    3382             :  */
    3383           0 : static void evpn_set_advertise_subnet(struct bgp *bgp,
    3384             :                                       struct bgpevpn *vpn)
    3385             : {
    3386           0 :         if (vpn->advertise_subnet)
    3387             :                 return;
    3388             : 
    3389           0 :         vpn->advertise_subnet = 1;
    3390           0 :         bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
    3391             : }
    3392             : 
    3393             : /*
    3394             :  * evpn - disable advertisement of default g/w
    3395             :  */
    3396           0 : static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
    3397             : {
    3398           0 :         if (!vpn->advertise_subnet)
    3399             :                 return;
    3400             : 
    3401           0 :         vpn->advertise_subnet = 0;
    3402           0 :         bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
    3403             : }
    3404             : 
    3405             : /*
    3406             :  * EVPN (VNI advertisement) enabled. Register with zebra.
    3407             :  */
    3408           0 : static void evpn_set_advertise_all_vni(struct bgp *bgp)
    3409             : {
    3410           0 :         bgp->advertise_all_vni = 1;
    3411           0 :         bgp_set_evpn(bgp);
    3412           0 :         bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
    3413           0 : }
    3414             : 
    3415             : /*
    3416             :  * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
    3417             :  * cache, EVPN routes (delete and withdraw from peers).
    3418             :  */
    3419           0 : static void evpn_unset_advertise_all_vni(struct bgp *bgp)
    3420             : {
    3421           0 :         bgp->advertise_all_vni = 0;
    3422           0 :         bgp_set_evpn(bgp_get_default());
    3423           0 :         bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
    3424           0 :         bgp_evpn_cleanup_on_disable(bgp);
    3425           0 : }
    3426             : 
    3427             : /* Set resolve overlay index flag */
    3428           0 : static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
    3429             : {
    3430           0 :         if (set == bgp->resolve_overlay_index)
    3431             :                 return;
    3432             : 
    3433           0 :         if (set) {
    3434           0 :                 bgp->resolve_overlay_index = true;
    3435           0 :                 hash_iterate(bgp->vnihash,
    3436             :                              (void (*)(struct hash_bucket *, void *))
    3437             :                                      bgp_evpn_handle_resolve_overlay_index_set,
    3438             :                              NULL);
    3439             :         } else {
    3440           0 :                 hash_iterate(
    3441             :                         bgp->vnihash,
    3442             :                         (void (*)(struct hash_bucket *, void *))
    3443             :                                 bgp_evpn_handle_resolve_overlay_index_unset,
    3444             :                         NULL);
    3445           0 :                 bgp->resolve_overlay_index = false;
    3446             :         }
    3447             : }
    3448             : 
    3449             : /*
    3450             :  * EVPN - use RFC8365 to auto-derive RT
    3451             :  */
    3452           0 : static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
    3453             : {
    3454           0 :         bgp->advertise_autort_rfc8365 = 1;
    3455           0 :         bgp_evpn_handle_autort_change(bgp);
    3456             : }
    3457             : 
    3458             : /*
    3459             :  * EVPN - don't use RFC8365 to auto-derive RT
    3460             :  */
    3461           0 : static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
    3462             : {
    3463           0 :         bgp->advertise_autort_rfc8365 = 0;
    3464           0 :         bgp_evpn_handle_autort_change(bgp);
    3465             : }
    3466             : 
    3467           0 : static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
    3468             : {
    3469           0 :         char *ecom_str;
    3470           0 :         struct listnode *node, *nnode;
    3471           0 :         struct ecommunity *ecom;
    3472             : 
    3473           0 :         if (is_vni_configured(vpn)) {
    3474           0 :                 vty_out(vty, "  vni %u\n", vpn->vni);
    3475           0 :                 if (is_rd_configured(vpn))
    3476           0 :                         vty_out(vty, "   rd %pRD\n", &vpn->prd);
    3477             : 
    3478           0 :                 if (is_import_rt_configured(vpn)) {
    3479           0 :                         for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
    3480             :                                                ecom)) {
    3481           0 :                                 ecom_str = ecommunity_ecom2str(
    3482             :                                         ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    3483           0 :                                 vty_out(vty, "   route-target import %s\n",
    3484             :                                         ecom_str);
    3485           0 :                                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    3486             :                         }
    3487             :                 }
    3488             : 
    3489           0 :                 if (is_export_rt_configured(vpn)) {
    3490           0 :                         for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
    3491             :                                                ecom)) {
    3492           0 :                                 ecom_str = ecommunity_ecom2str(
    3493             :                                         ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    3494           0 :                                 vty_out(vty, "   route-target export %s\n",
    3495             :                                         ecom_str);
    3496           0 :                                 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    3497             :                         }
    3498             :                 }
    3499             : 
    3500           0 :                 if (vpn->advertise_gw_macip)
    3501           0 :                         vty_out(vty, "   advertise-default-gw\n");
    3502             : 
    3503           0 :                 if (vpn->advertise_svi_macip)
    3504           0 :                         vty_out(vty, "   advertise-svi-ip\n");
    3505             : 
    3506           0 :                 if (vpn->advertise_subnet)
    3507           0 :                         vty_out(vty, "   advertise-subnet\n");
    3508             : 
    3509           0 :                 vty_out(vty, "  exit-vni\n");
    3510             :         }
    3511           0 : }
    3512             : 
    3513             : #include "bgpd/bgp_evpn_vty_clippy.c"
    3514             : 
    3515           0 : DEFPY(bgp_evpn_flood_control,
    3516             :       bgp_evpn_flood_control_cmd,
    3517             :       "[no$no] flooding <disable$disable|head-end-replication$her>",
    3518             :       NO_STR
    3519             :       "Specify handling for BUM packets\n"
    3520             :       "Do not flood any BUM packets\n"
    3521             :       "Flood BUM packets using head-end replication\n")
    3522             : {
    3523           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3524           0 :         enum vxlan_flood_control flood_ctrl;
    3525             : 
    3526           0 :         if (!bgp)
    3527             :                 return CMD_WARNING;
    3528             : 
    3529           0 :         if (disable && !no)
    3530             :                 flood_ctrl = VXLAN_FLOOD_DISABLED;
    3531           0 :         else if (her || no)
    3532             :                 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
    3533             :         else
    3534             :                 return CMD_WARNING;
    3535             : 
    3536           0 :         if (bgp->vxlan_flood_ctrl == flood_ctrl)
    3537             :                 return CMD_SUCCESS;
    3538             : 
    3539           0 :         bgp->vxlan_flood_ctrl = flood_ctrl;
    3540           0 :         bgp_evpn_flood_control_change(bgp);
    3541             : 
    3542           0 :         return CMD_SUCCESS;
    3543             : }
    3544             : 
    3545           0 : DEFUN (bgp_evpn_advertise_default_gw_vni,
    3546             :        bgp_evpn_advertise_default_gw_vni_cmd,
    3547             :        "advertise-default-gw",
    3548             :        "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
    3549             : {
    3550           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3551           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    3552             : 
    3553           0 :         if (!bgp)
    3554             :                 return CMD_WARNING;
    3555             : 
    3556           0 :         evpn_set_advertise_default_gw(bgp, vpn);
    3557             : 
    3558           0 :         return CMD_SUCCESS;
    3559             : }
    3560             : 
    3561           0 : DEFUN (no_bgp_evpn_advertise_default_vni_gw,
    3562             :        no_bgp_evpn_advertise_default_gw_vni_cmd,
    3563             :        "no advertise-default-gw",
    3564             :        NO_STR
    3565             :        "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
    3566             : {
    3567           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3568           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    3569             : 
    3570           0 :         if (!bgp)
    3571             :                 return CMD_WARNING;
    3572             : 
    3573           0 :         evpn_unset_advertise_default_gw(bgp, vpn);
    3574             : 
    3575           0 :         return CMD_SUCCESS;
    3576             : }
    3577             : 
    3578             : 
    3579           0 : DEFUN (bgp_evpn_advertise_default_gw,
    3580             :        bgp_evpn_advertise_default_gw_cmd,
    3581             :        "advertise-default-gw",
    3582             :        "Advertise All default g/w mac-ip routes in EVPN\n")
    3583             : {
    3584           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3585             : 
    3586           0 :         if (!bgp)
    3587             :                 return CMD_WARNING;
    3588             : 
    3589           0 :         if (!EVPN_ENABLED(bgp)) {
    3590           0 :                 vty_out(vty,
    3591             :                         "This command is only supported under the EVPN VRF\n");
    3592           0 :                 return CMD_WARNING;
    3593             :         }
    3594             : 
    3595           0 :         evpn_set_advertise_default_gw(bgp, NULL);
    3596             : 
    3597           0 :         return CMD_SUCCESS;
    3598             : }
    3599             : 
    3600           0 : DEFUN (no_bgp_evpn_advertise_default_gw,
    3601             :        no_bgp_evpn_advertise_default_gw_cmd,
    3602             :        "no advertise-default-gw",
    3603             :        NO_STR
    3604             :        "Withdraw All default g/w mac-ip routes from EVPN\n")
    3605             : {
    3606           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3607             : 
    3608           0 :         if (!bgp)
    3609             :                 return CMD_WARNING;
    3610             : 
    3611           0 :         evpn_unset_advertise_default_gw(bgp, NULL);
    3612             : 
    3613           0 :         return CMD_SUCCESS;
    3614             : }
    3615             : 
    3616           0 : DEFUN (bgp_evpn_advertise_all_vni,
    3617             :        bgp_evpn_advertise_all_vni_cmd,
    3618             :        "advertise-all-vni",
    3619             :        "Advertise All local VNIs\n")
    3620             : {
    3621           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3622           0 :         struct bgp *bgp_evpn = NULL;
    3623             : 
    3624           0 :         if (!bgp)
    3625             :                 return CMD_WARNING;
    3626             : 
    3627           0 :         bgp_evpn = bgp_get_evpn();
    3628           0 :         if (bgp_evpn && bgp_evpn != bgp) {
    3629           0 :                 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
    3630             :                         bgp_evpn->name_pretty);
    3631           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3632             :         }
    3633             : 
    3634           0 :         evpn_set_advertise_all_vni(bgp);
    3635           0 :         return CMD_SUCCESS;
    3636             : }
    3637             : 
    3638           0 : DEFUN (no_bgp_evpn_advertise_all_vni,
    3639             :        no_bgp_evpn_advertise_all_vni_cmd,
    3640             :        "no advertise-all-vni",
    3641             :        NO_STR
    3642             :        "Advertise All local VNIs\n")
    3643             : {
    3644           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3645             : 
    3646           0 :         if (!bgp)
    3647             :                 return CMD_WARNING;
    3648           0 :         evpn_unset_advertise_all_vni(bgp);
    3649           0 :         return CMD_SUCCESS;
    3650             : }
    3651             : 
    3652           0 : DEFUN (bgp_evpn_advertise_autort_rfc8365,
    3653             :        bgp_evpn_advertise_autort_rfc8365_cmd,
    3654             :        "autort rfc8365-compatible",
    3655             :        "Auto-derivation of RT\n"
    3656             :        "Auto-derivation of RT using RFC8365\n")
    3657             : {
    3658           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3659             : 
    3660           0 :         if (!bgp)
    3661             :                 return CMD_WARNING;
    3662           0 :         evpn_set_advertise_autort_rfc8365(bgp);
    3663           0 :         return CMD_SUCCESS;
    3664             : }
    3665             : 
    3666           0 : DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
    3667             :        no_bgp_evpn_advertise_autort_rfc8365_cmd,
    3668             :        "no autort rfc8365-compatible",
    3669             :        NO_STR
    3670             :        "Auto-derivation of RT\n"
    3671             :        "Auto-derivation of RT using RFC8365\n")
    3672             : {
    3673           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3674             : 
    3675           0 :         if (!bgp)
    3676             :                 return CMD_WARNING;
    3677           0 :         evpn_unset_advertise_autort_rfc8365(bgp);
    3678           0 :         return CMD_SUCCESS;
    3679             : }
    3680             : 
    3681           0 : DEFUN (bgp_evpn_default_originate,
    3682             :        bgp_evpn_default_originate_cmd,
    3683             :        "default-originate <ipv4 | ipv6>",
    3684             :        "originate a default route\n"
    3685             :        "ipv4 address family\n"
    3686             :        "ipv6 address family\n")
    3687             : {
    3688           0 :         afi_t afi = 0;
    3689           0 :         int idx_afi = 0;
    3690           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    3691             : 
    3692           0 :         if (!bgp_vrf)
    3693             :                 return CMD_WARNING;
    3694           0 :         argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
    3695           0 :         evpn_process_default_originate_cmd(bgp_vrf, afi, true);
    3696           0 :         return CMD_SUCCESS;
    3697             : }
    3698             : 
    3699           0 : DEFUN (no_bgp_evpn_default_originate,
    3700             :        no_bgp_evpn_default_originate_cmd,
    3701             :        "no default-originate <ipv4 | ipv6>",
    3702             :        NO_STR
    3703             :        "withdraw a default route\n"
    3704             :        "ipv4 address family\n"
    3705             :        "ipv6 address family\n")
    3706             : {
    3707           0 :         afi_t afi = 0;
    3708           0 :         int idx_afi = 0;
    3709           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    3710             : 
    3711           0 :         if (!bgp_vrf)
    3712             :                 return CMD_WARNING;
    3713           0 :         argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
    3714           0 :         evpn_process_default_originate_cmd(bgp_vrf, afi, false);
    3715           0 :         return CMD_SUCCESS;
    3716             : }
    3717             : 
    3718           0 : DEFPY (dup_addr_detection,
    3719             :        dup_addr_detection_cmd,
    3720             :        "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
    3721             :        "Duplicate address detection\n"
    3722             :        "Max allowed moves before address detected as duplicate\n"
    3723             :        "Num of max allowed moves (2-1000) default 5\n"
    3724             :        "Duplicate address detection time\n"
    3725             :        "Time in seconds (2-1800) default 180\n")
    3726             : {
    3727           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    3728             : 
    3729           0 :         if (!bgp_vrf)
    3730             :                 return CMD_WARNING;
    3731             : 
    3732           0 :         if (!EVPN_ENABLED(bgp_vrf)) {
    3733           0 :                 vty_out(vty,
    3734             :                         "This command is only supported under the EVPN VRF\n");
    3735           0 :                 return CMD_WARNING;
    3736             :         }
    3737             : 
    3738           0 :         bgp_vrf->evpn_info->dup_addr_detect = true;
    3739             : 
    3740           0 :         if (time_val)
    3741           0 :                 bgp_vrf->evpn_info->dad_time = time_val;
    3742           0 :         if (max_moves_val)
    3743           0 :                 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
    3744             : 
    3745           0 :         bgp_zebra_dup_addr_detection(bgp_vrf);
    3746             : 
    3747           0 :         return CMD_SUCCESS;
    3748             : }
    3749             : 
    3750           0 : DEFPY (dup_addr_detection_auto_recovery,
    3751             :        dup_addr_detection_auto_recovery_cmd,
    3752             :        "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
    3753             :        "Duplicate address detection\n"
    3754             :        "Duplicate address detection freeze\n"
    3755             :        "Duplicate address detection permanent freeze\n"
    3756             :        "Duplicate address detection freeze time (30-3600)\n")
    3757             : {
    3758           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    3759           0 :         uint32_t freeze_time = freeze_time_val;
    3760             : 
    3761           0 :         if (!bgp_vrf)
    3762             :                 return CMD_WARNING;
    3763             : 
    3764           0 :         if (!EVPN_ENABLED(bgp_vrf)) {
    3765           0 :                 vty_out(vty,
    3766             :                         "This command is only supported under the EVPN VRF\n");
    3767           0 :                 return CMD_WARNING;
    3768             :         }
    3769             : 
    3770           0 :         bgp_vrf->evpn_info->dup_addr_detect = true;
    3771           0 :         bgp_vrf->evpn_info->dad_freeze = true;
    3772           0 :         bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
    3773             : 
    3774           0 :         bgp_zebra_dup_addr_detection(bgp_vrf);
    3775             : 
    3776           0 :         return CMD_SUCCESS;
    3777             : }
    3778             : 
    3779           0 : DEFPY (no_dup_addr_detection,
    3780             :        no_dup_addr_detection_cmd,
    3781             :        "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
    3782             :        NO_STR
    3783             :        "Duplicate address detection\n"
    3784             :        "Max allowed moves before address detected as duplicate\n"
    3785             :        "Num of max allowed moves (2-1000) default 5\n"
    3786             :        "Duplicate address detection time\n"
    3787             :        "Time in seconds (2-1800) default 180\n"
    3788             :        "Duplicate address detection freeze\n"
    3789             :        "Duplicate address detection permanent freeze\n"
    3790             :        "Duplicate address detection freeze time (30-3600)\n")
    3791             : {
    3792           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    3793           0 :         uint32_t max_moves = (uint32_t)max_moves_val;
    3794           0 :         uint32_t freeze_time = (uint32_t)freeze_time_val;
    3795             : 
    3796           0 :         if (!bgp_vrf)
    3797             :                 return CMD_WARNING;
    3798             : 
    3799           0 :         if (!EVPN_ENABLED(bgp_vrf)) {
    3800           0 :                 vty_out(vty,
    3801             :                         "This command is only supported under the EVPN VRF\n");
    3802           0 :                 return CMD_WARNING;
    3803             :         }
    3804             : 
    3805           0 :         if (argc == 2) {
    3806           0 :                 if (!bgp_vrf->evpn_info->dup_addr_detect)
    3807             :                         return CMD_SUCCESS;
    3808             :                 /* Reset all parameters to default. */
    3809           0 :                 bgp_vrf->evpn_info->dup_addr_detect = false;
    3810           0 :                 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
    3811           0 :                 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
    3812           0 :                 bgp_vrf->evpn_info->dad_freeze = false;
    3813           0 :                 bgp_vrf->evpn_info->dad_freeze_time = 0;
    3814             :         } else {
    3815           0 :                 if (max_moves) {
    3816           0 :                         if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
    3817           0 :                                 vty_out(vty,
    3818             :                                 "%% Value does not match with config\n");
    3819           0 :                                 return CMD_SUCCESS;
    3820             :                         }
    3821           0 :                         bgp_vrf->evpn_info->dad_max_moves =
    3822             :                                 EVPN_DAD_DEFAULT_MAX_MOVES;
    3823             :                 }
    3824             : 
    3825           0 :                 if (time_val) {
    3826           0 :                         if (bgp_vrf->evpn_info->dad_time != time_val) {
    3827           0 :                                 vty_out(vty,
    3828             :                                 "%% Value does not match with config\n");
    3829           0 :                                 return CMD_SUCCESS;
    3830             :                         }
    3831           0 :                         bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
    3832             :                 }
    3833             : 
    3834           0 :                 if (freeze_time) {
    3835           0 :                         if (bgp_vrf->evpn_info->dad_freeze_time
    3836             :                             != freeze_time) {
    3837           0 :                                 vty_out(vty,
    3838             :                                 "%% Value does not match with config\n");
    3839           0 :                                 return CMD_SUCCESS;
    3840             :                         }
    3841           0 :                         bgp_vrf->evpn_info->dad_freeze_time = 0;
    3842           0 :                         bgp_vrf->evpn_info->dad_freeze = false;
    3843             :                 }
    3844             : 
    3845           0 :                 if (permanent_val) {
    3846           0 :                         if (bgp_vrf->evpn_info->dad_freeze_time) {
    3847           0 :                                 vty_out(vty,
    3848             :                                 "%% Value does not match with config\n");
    3849           0 :                                 return CMD_SUCCESS;
    3850             :                         }
    3851           0 :                         bgp_vrf->evpn_info->dad_freeze = false;
    3852             :                 }
    3853             :         }
    3854             : 
    3855           0 :         bgp_zebra_dup_addr_detection(bgp_vrf);
    3856             : 
    3857           0 :         return CMD_SUCCESS;
    3858             : }
    3859             : 
    3860           0 : DEFPY(bgp_evpn_advertise_svi_ip,
    3861             :       bgp_evpn_advertise_svi_ip_cmd,
    3862             :       "[no$no] advertise-svi-ip",
    3863             :       NO_STR
    3864             :       "Advertise svi mac-ip routes in EVPN\n")
    3865             : {
    3866           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3867             : 
    3868           0 :         if (!bgp)
    3869             :                 return CMD_WARNING;
    3870             : 
    3871           0 :         if (no)
    3872           0 :                 evpn_set_advertise_svi_macip(bgp, NULL, 0);
    3873             :         else {
    3874           0 :                 if (!EVPN_ENABLED(bgp)) {
    3875           0 :                         vty_out(vty,
    3876             :                                 "This command is only supported under EVPN VRF\n");
    3877           0 :                         return CMD_WARNING;
    3878             :                 }
    3879           0 :                 evpn_set_advertise_svi_macip(bgp, NULL, 1);
    3880             :         }
    3881             : 
    3882             :         return CMD_SUCCESS;
    3883             : }
    3884             : 
    3885           0 : DEFPY(bgp_evpn_advertise_svi_ip_vni,
    3886             :       bgp_evpn_advertise_svi_ip_vni_cmd,
    3887             :       "[no$no] advertise-svi-ip",
    3888             :       NO_STR
    3889             :       "Advertise svi mac-ip routes in EVPN for a VNI\n")
    3890             : {
    3891           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3892           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    3893             : 
    3894           0 :         if (!bgp)
    3895             :                 return CMD_WARNING;
    3896             : 
    3897           0 :         if (no)
    3898           0 :                 evpn_set_advertise_svi_macip(bgp, vpn, 0);
    3899             :         else
    3900           0 :                 evpn_set_advertise_svi_macip(bgp, vpn, 1);
    3901             : 
    3902             :         return CMD_SUCCESS;
    3903             : }
    3904             : 
    3905           0 : DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
    3906             :               bgp_evpn_advertise_vni_subnet_cmd,
    3907             :               "advertise-subnet",
    3908             :               "Advertise the subnet corresponding to VNI\n")
    3909             : {
    3910           0 :         struct bgp *bgp_vrf = NULL;
    3911           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3912           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    3913             : 
    3914           0 :         if (!bgp)
    3915             :                 return CMD_WARNING;
    3916             : 
    3917           0 :         bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
    3918           0 :         if (!bgp_vrf)
    3919             :                 return CMD_WARNING;
    3920             : 
    3921           0 :         evpn_set_advertise_subnet(bgp, vpn);
    3922           0 :         return CMD_SUCCESS;
    3923             : }
    3924             : 
    3925           0 : DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
    3926             :               no_bgp_evpn_advertise_vni_subnet_cmd,
    3927             :               "no advertise-subnet",
    3928             :               NO_STR
    3929             :               "Advertise All local VNIs\n")
    3930             : {
    3931           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    3932           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    3933             : 
    3934           0 :         if (!bgp)
    3935             :                 return CMD_WARNING;
    3936             : 
    3937           0 :         evpn_unset_advertise_subnet(bgp, vpn);
    3938           0 :         return CMD_SUCCESS;
    3939             : }
    3940             : 
    3941           0 : DEFUN (bgp_evpn_advertise_type5,
    3942             :        bgp_evpn_advertise_type5_cmd,
    3943             :        "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
    3944             :        "Advertise prefix routes\n"
    3945             :        BGP_AFI_HELP_STR
    3946             :        BGP_SAFI_HELP_STR
    3947             :        "advertise gateway IP overlay index\n"
    3948             :        "route-map for filtering specific routes\n"
    3949             :        "Name of the route map\n")
    3950             : {
    3951           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
    3952           0 :         int idx_afi = 0;
    3953           0 :         int idx_safi = 0;
    3954           0 :         int idx_rmap = 0;
    3955           0 :         afi_t afi = 0;
    3956           0 :         safi_t safi = 0;
    3957           0 :         int ret = 0;
    3958           0 :         int rmap_changed = 0;
    3959           0 :         enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
    3960           0 :         int idx_oly = 0;
    3961           0 :         bool adv_flag_changed = false;
    3962             : 
    3963           0 :         argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
    3964           0 :         argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
    3965           0 :         argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
    3966             : 
    3967           0 :         ret = argv_find(argv, argc, "route-map", &idx_rmap);
    3968           0 :         if (ret) {
    3969           0 :                 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
    3970             :                         rmap_changed = 1;
    3971           0 :                 else if (strcmp(argv[idx_rmap + 1]->arg,
    3972             :                                 bgp_vrf->adv_cmd_rmap[afi][safi].name)
    3973             :                          != 0)
    3974           0 :                         rmap_changed = 1;
    3975           0 :         } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
    3976           0 :                 rmap_changed = 1;
    3977             :         }
    3978             : 
    3979           0 :         if (!(afi == AFI_IP || afi == AFI_IP6)) {
    3980           0 :                 vty_out(vty,
    3981             :                         "%% Only ipv4 or ipv6 address families are supported\n");
    3982           0 :                 return CMD_WARNING;
    3983             :         }
    3984             : 
    3985           0 :         if (safi != SAFI_UNICAST) {
    3986           0 :                 vty_out(vty,
    3987             :                         "%% Only ipv4 unicast or ipv6 unicast are supported\n");
    3988           0 :                 return CMD_WARNING;
    3989             :         }
    3990             : 
    3991           0 :         if ((oly != OVERLAY_INDEX_TYPE_NONE)
    3992           0 :             && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
    3993           0 :                 vty_out(vty, "%% Unknown overlay-index type specified\n");
    3994           0 :                 return CMD_WARNING;
    3995             :         }
    3996             : 
    3997           0 :         if (afi == AFI_IP) {
    3998           0 :                 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    3999             :                                  BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
    4000             :                     && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4001             :                                     BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
    4002             : 
    4003             :                         /*
    4004             :                          * this is the case for first time ever configuration
    4005             :                          * adv ipv4 unicast is enabled for the first time.
    4006             :                          * So no need to reset any flag
    4007             :                          */
    4008           0 :                         if (oly == OVERLAY_INDEX_TYPE_NONE)
    4009           0 :                                 SET_FLAG(
    4010             :                                         bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4011             :                                         BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
    4012           0 :                         else if (oly == OVERLAY_INDEX_GATEWAY_IP)
    4013           0 :                                 SET_FLAG(
    4014             :                                         bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4015             :                                         BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
    4016           0 :                 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
    4017           0 :                            && (!CHECK_FLAG(
    4018             :                                       bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4019             :                                       BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
    4020             : 
    4021             :                         /*
    4022             :                          * This is modify case from gateway-ip
    4023             :                          * to no overlay index
    4024             :                          */
    4025           0 :                         adv_flag_changed = true;
    4026           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4027             :                                    BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
    4028           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4029             :                                  BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
    4030           0 :                 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
    4031           0 :                            && (!CHECK_FLAG(
    4032             :                                       bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4033             :                                       BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
    4034             : 
    4035             :                         /*
    4036             :                          * This is modify case from no overlay index
    4037             :                          * to gateway-ip
    4038             :                          */
    4039           0 :                         adv_flag_changed = true;
    4040           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4041             :                                    BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
    4042           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4043             :                                  BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
    4044             :                 } else {
    4045             : 
    4046             :                         /*
    4047             :                          * Command is issued with the same option
    4048             :                          * (no overlay index or gateway-ip) which was
    4049             :                          * already configured. So nothing to do.
    4050             :                          * However, route-map may have been modified.
    4051             :                          * check if route-map has been modified.
    4052             :                          * If not, return an error
    4053             :                          */
    4054           0 :                         if (!rmap_changed)
    4055             :                                 return CMD_WARNING;
    4056             :                 }
    4057             :         } else {
    4058           0 :                 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4059             :                                  BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
    4060             :                     && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4061             :                                     BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
    4062             : 
    4063             :                         /*
    4064             :                          * this is the case for first time ever configuration
    4065             :                          * adv ipv6 unicast is enabled for the first time.
    4066             :                          * So no need to reset any flag
    4067             :                          */
    4068           0 :                         if (oly == OVERLAY_INDEX_TYPE_NONE)
    4069           0 :                                 SET_FLAG(
    4070             :                                         bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4071             :                                         BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
    4072           0 :                         else if (oly == OVERLAY_INDEX_GATEWAY_IP)
    4073           0 :                                 SET_FLAG(
    4074             :                                         bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4075             :                                         BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
    4076           0 :                 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
    4077           0 :                            && (!CHECK_FLAG(
    4078             :                                       bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4079             :                                       BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
    4080             : 
    4081             :                         /*
    4082             :                          * This is modify case from gateway-ip
    4083             :                          * to no overlay index
    4084             :                          */
    4085           0 :                         adv_flag_changed = true;
    4086           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4087             :                                    BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
    4088           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4089             :                                  BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
    4090           0 :                 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
    4091           0 :                            && (!CHECK_FLAG(
    4092             :                                       bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4093             :                                       BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
    4094             : 
    4095             :                         /*
    4096             :                          * This is modify case from no overlay index
    4097             :                          * to gateway-ip
    4098             :                          */
    4099           0 :                         adv_flag_changed = true;
    4100           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4101             :                                    BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
    4102           0 :                         SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4103             :                                  BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
    4104             :                 } else {
    4105             : 
    4106             :                         /*
    4107             :                          * Command is issued with the same option
    4108             :                          * (no overlay index or gateway-ip) which was
    4109             :                          * already configured. So nothing to do.
    4110             :                          * However, route-map may have been modified.
    4111             :                          * check if route-map has been modified.
    4112             :                          * If not, return an error
    4113             :                          */
    4114           0 :                         if (!rmap_changed)
    4115             :                                 return CMD_WARNING;
    4116             :                 }
    4117             :         }
    4118             : 
    4119           0 :         if ((rmap_changed) || (adv_flag_changed)) {
    4120             : 
    4121             :                 /* If either of these are changed, then FRR needs to
    4122             :                  * withdraw already advertised type5 routes.
    4123             :                  */
    4124           0 :                 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
    4125           0 :                 if (rmap_changed) {
    4126           0 :                         if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
    4127           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    4128             :                                       bgp_vrf->adv_cmd_rmap[afi][safi].name);
    4129           0 :                                 route_map_counter_decrement(
    4130             :                                         bgp_vrf->adv_cmd_rmap[afi][safi].map);
    4131           0 :                                 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
    4132           0 :                                 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
    4133             :                         }
    4134             :                 }
    4135             :         }
    4136             : 
    4137             :         /* set the route-map for advertise command */
    4138           0 :         if (ret && argv[idx_rmap + 1]->arg) {
    4139           0 :                 bgp_vrf->adv_cmd_rmap[afi][safi].name =
    4140           0 :                         XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
    4141           0 :                 bgp_vrf->adv_cmd_rmap[afi][safi].map =
    4142           0 :                         route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
    4143           0 :                 route_map_counter_increment(
    4144             :                                 bgp_vrf->adv_cmd_rmap[afi][safi].map);
    4145             :         }
    4146             : 
    4147             :         /* advertise type-5 routes */
    4148           0 :         if (advertise_type5_routes(bgp_vrf, afi))
    4149           0 :                 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
    4150             :         return CMD_SUCCESS;
    4151             : }
    4152             : 
    4153           0 : DEFUN (no_bgp_evpn_advertise_type5,
    4154             :        no_bgp_evpn_advertise_type5_cmd,
    4155             :        "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
    4156             :        NO_STR
    4157             :        "Advertise prefix routes\n"
    4158             :        BGP_AFI_HELP_STR
    4159             :        BGP_SAFI_HELP_STR
    4160             :        "route-map for filtering specific routes\n"
    4161             :        "Name of the route map\n")
    4162             : {
    4163           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
    4164           0 :         int idx_afi = 0;
    4165           0 :         int idx_safi = 0;
    4166           0 :         afi_t afi = 0;
    4167           0 :         safi_t safi = 0;
    4168             : 
    4169           0 :         if (!bgp_vrf)
    4170             :                 return CMD_WARNING;
    4171             : 
    4172           0 :         argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
    4173           0 :         argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
    4174             : 
    4175           0 :         if (!(afi == AFI_IP || afi == AFI_IP6)) {
    4176           0 :                 vty_out(vty,
    4177             :                         "%% Only ipv4 or ipv6 address families are supported\n");
    4178           0 :                 return CMD_WARNING;
    4179             :         }
    4180             : 
    4181           0 :         if (safi != SAFI_UNICAST) {
    4182           0 :                 vty_out(vty,
    4183             :                         "%% Only ipv4 unicast or ipv6 unicast are supported\n");
    4184           0 :                 return CMD_WARNING;
    4185             :         }
    4186             : 
    4187           0 :         if (afi == AFI_IP) {
    4188             : 
    4189             :                 /* if we are not advertising ipv4 prefix as type-5
    4190             :                  * nothing to do
    4191             :                  */
    4192           0 :                 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4193             :                                 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
    4194             :                     (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4195             :                                 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
    4196           0 :                         bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
    4197           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4198             :                                    BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
    4199           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4200             :                                    BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
    4201             :                 }
    4202             :         } else {
    4203             : 
    4204             :                 /* if we are not advertising ipv6 prefix as type-5
    4205             :                  * nothing to do
    4206             :                  */
    4207           0 :                 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4208             :                                 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
    4209             :                     (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4210             :                                 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
    4211           0 :                         bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
    4212           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4213             :                                    BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
    4214           0 :                         UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
    4215             :                                    BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
    4216             :                 }
    4217             :         }
    4218             : 
    4219             :         /* clear the route-map information for advertise ipv4/ipv6 unicast */
    4220           0 :         if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
    4221           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME,
    4222             :                       bgp_vrf->adv_cmd_rmap[afi][safi].name);
    4223           0 :                 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
    4224           0 :                 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
    4225             :         }
    4226             : 
    4227             :         return CMD_SUCCESS;
    4228             : }
    4229             : 
    4230           0 : DEFPY (bgp_evpn_use_es_l3nhg,
    4231             :        bgp_evpn_use_es_l3nhg_cmd,
    4232             :        "[no$no] use-es-l3nhg",
    4233             :        NO_STR
    4234             :        "use L3 nexthop group for host routes with ES destination\n")
    4235             : {
    4236           0 :         bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
    4237           0 :         return CMD_SUCCESS;
    4238             : }
    4239             : 
    4240           0 : DEFPY (bgp_evpn_ead_evi_rx_disable,
    4241             :        bgp_evpn_ead_evi_rx_disable_cmd,
    4242             :        "[no$no] disable-ead-evi-rx",
    4243             :        NO_STR
    4244             :        "Activate PE on EAD-ES even if EAD-EVI is not received\n")
    4245             : {
    4246           0 :         bool ead_evi_rx = no? true :false;
    4247             : 
    4248           0 :         if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
    4249           0 :                 bgp_mh_info->ead_evi_rx = ead_evi_rx;
    4250           0 :                 bgp_evpn_switch_ead_evi_rx();
    4251             :         }
    4252           0 :         return CMD_SUCCESS;
    4253             : }
    4254             : 
    4255           0 : DEFPY (bgp_evpn_ead_evi_tx_disable,
    4256             :        bgp_evpn_ead_evi_tx_disable_cmd,
    4257             :        "[no$no] disable-ead-evi-tx",
    4258             :        NO_STR
    4259             :        "Don't advertise EAD-EVI for local ESs\n")
    4260             : {
    4261           0 :         bgp_mh_info->ead_evi_tx = no? true :false;
    4262           0 :         return CMD_SUCCESS;
    4263             : }
    4264             : 
    4265           0 : DEFPY (bgp_evpn_enable_resolve_overlay_index,
    4266             :        bgp_evpn_enable_resolve_overlay_index_cmd,
    4267             :        "[no$no] enable-resolve-overlay-index",
    4268             :        NO_STR
    4269             :        "Enable Recursive Resolution of type-5 route overlay index\n")
    4270             : {
    4271           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    4272             : 
    4273           0 :         if (bgp != bgp_get_evpn()) {
    4274           0 :                 vty_out(vty, "This command is only supported under EVPN VRF\n");
    4275           0 :                 return CMD_WARNING;
    4276             :         }
    4277             : 
    4278           0 :         bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
    4279           0 :         return CMD_SUCCESS;
    4280             : }
    4281             : 
    4282           0 : DEFPY (bgp_evpn_advertise_pip_ip_mac,
    4283             :        bgp_evpn_advertise_pip_ip_mac_cmd,
    4284             :        "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
    4285             :        NO_STR
    4286             :        "evpn system primary IP\n"
    4287             :        IP_STR
    4288             :        "ip address\n"
    4289             :        MAC_STR MAC_STR MAC_STR)
    4290             : {
    4291           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
    4292           0 :         struct bgp *bgp_evpn = NULL;
    4293             : 
    4294           0 :         if (EVPN_ENABLED(bgp_vrf)) {
    4295           0 :                 vty_out(vty,
    4296             :                         "This command is supported under L3VNI BGP EVPN VRF\n");
    4297           0 :                 return CMD_WARNING_CONFIG_FAILED;
    4298             :         }
    4299           0 :         bgp_evpn = bgp_get_evpn();
    4300             : 
    4301           0 :         if (!no) {
    4302             :                 /* pip is already enabled */
    4303           0 :                 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
    4304             :                         return CMD_SUCCESS;
    4305             : 
    4306           0 :                 bgp_vrf->evpn_info->advertise_pip = true;
    4307           0 :                 if (ip.s_addr != INADDR_ANY) {
    4308             :                         /* Already configured with same IP */
    4309           0 :                         if (IPV4_ADDR_SAME(&ip,
    4310             :                                         &bgp_vrf->evpn_info->pip_ip_static))
    4311             :                                 return CMD_SUCCESS;
    4312             : 
    4313           0 :                         bgp_vrf->evpn_info->pip_ip_static = ip;
    4314           0 :                         bgp_vrf->evpn_info->pip_ip = ip;
    4315             :                 } else {
    4316           0 :                         bgp_vrf->evpn_info->pip_ip_static.s_addr
    4317           0 :                                 = INADDR_ANY;
    4318             :                         /* default instance router-id assignemt */
    4319           0 :                         if (bgp_evpn)
    4320           0 :                                 bgp_vrf->evpn_info->pip_ip =
    4321             :                                         bgp_evpn->router_id;
    4322             :                 }
    4323             :                 /* parse sys mac */
    4324           0 :                 if (!is_zero_mac(&mac->eth_addr)) {
    4325             :                         /* Already configured with same MAC */
    4326           0 :                         if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
    4327             :                                    &mac->eth_addr, ETH_ALEN) == 0)
    4328             :                                 return CMD_SUCCESS;
    4329             : 
    4330           0 :                         memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
    4331             :                                &mac->eth_addr, ETH_ALEN);
    4332           0 :                         memcpy(&bgp_vrf->evpn_info->pip_rmac,
    4333           0 :                                &bgp_vrf->evpn_info->pip_rmac_static,
    4334             :                                ETH_ALEN);
    4335             :                 } else {
    4336             :                         /* Copy zebra sys mac */
    4337           0 :                         if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
    4338           0 :                                 memcpy(&bgp_vrf->evpn_info->pip_rmac,
    4339           0 :                                        &bgp_vrf->evpn_info->pip_rmac_zebra,
    4340             :                                        ETH_ALEN);
    4341             :                 }
    4342             :         } else {
    4343           0 :                 if (argc == 2) {
    4344           0 :                         if (!bgp_vrf->evpn_info->advertise_pip)
    4345             :                                 return CMD_SUCCESS;
    4346             :                         /* Disable PIP feature */
    4347           0 :                         bgp_vrf->evpn_info->advertise_pip = false;
    4348             :                         /* copy anycast mac */
    4349           0 :                         memcpy(&bgp_vrf->evpn_info->pip_rmac,
    4350           0 :                                &bgp_vrf->rmac, ETH_ALEN);
    4351             :                 } else {
    4352             :                         /* remove MAC-IP option retain PIP knob. */
    4353           0 :                         if ((ip.s_addr != INADDR_ANY) &&
    4354           0 :                             !IPV4_ADDR_SAME(&ip,
    4355             :                                         &bgp_vrf->evpn_info->pip_ip_static)) {
    4356           0 :                                 vty_out(vty,
    4357             :                                         "%% BGP EVPN PIP IP does not match\n");
    4358           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    4359             :                         }
    4360             : 
    4361           0 :                         if (!is_zero_mac(&mac->eth_addr) &&
    4362           0 :                             memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
    4363             :                                    &mac->eth_addr, ETH_ALEN) != 0) {
    4364           0 :                                 vty_out(vty,
    4365             :                                         "%% BGP EVPN PIP MAC does not match\n");
    4366           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    4367             :                         }
    4368             :                         /* pip_rmac can carry vrr_rmac reset only if it matches
    4369             :                          * with static value.
    4370             :                          */
    4371           0 :                         if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
    4372           0 :                                    &bgp_vrf->evpn_info->pip_rmac_static,
    4373             :                                    ETH_ALEN) == 0) {
    4374             :                                 /* Copy zebra sys mac */
    4375           0 :                                 if (!is_zero_mac(
    4376           0 :                                         &bgp_vrf->evpn_info->pip_rmac_zebra))
    4377           0 :                                         memcpy(&bgp_vrf->evpn_info->pip_rmac,
    4378           0 :                                         &bgp_vrf->evpn_info->pip_rmac_zebra,
    4379             :                                                ETH_ALEN);
    4380             :                                 else {
    4381             :                                         /* copy anycast mac */
    4382           0 :                                         memcpy(&bgp_vrf->evpn_info->pip_rmac,
    4383           0 :                                                &bgp_vrf->rmac, ETH_ALEN);
    4384             :                                 }
    4385             :                         }
    4386             :                 }
    4387             :                 /* reset user configured sys MAC */
    4388           0 :                 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
    4389             :                 /* reset user configured sys IP */
    4390           0 :                 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
    4391             :                 /* Assign default PIP IP (bgp instance router-id) */
    4392           0 :                 if (bgp_evpn)
    4393           0 :                         bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
    4394             :                 else
    4395           0 :                         bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
    4396             :         }
    4397             : 
    4398           0 :         if (is_evpn_enabled()) {
    4399           0 :                 struct listnode *node = NULL;
    4400           0 :                 struct bgpevpn *vpn = NULL;
    4401             : 
    4402             :                 /*
    4403             :                  * At this point if bgp_evpn is NULL and evpn is enabled
    4404             :                  * something stupid has gone wrong
    4405             :                  */
    4406           0 :                 assert(bgp_evpn);
    4407             : 
    4408           0 :                 update_advertise_vrf_routes(bgp_vrf);
    4409             : 
    4410             :                 /* Update (svi) type-2 routes */
    4411           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
    4412           0 :                         if (!bgp_evpn_is_svi_macip_enabled(vpn))
    4413           0 :                                 continue;
    4414           0 :                         update_routes_for_vni(bgp_evpn, vpn);
    4415             :                 }
    4416             :         }
    4417             : 
    4418             :         return CMD_SUCCESS;
    4419             : }
    4420             : 
    4421             : /*
    4422             :  * Display VNI information - for all or a specific VNI
    4423             :  */
    4424           0 : DEFUN(show_bgp_l2vpn_evpn_vni,
    4425             :       show_bgp_l2vpn_evpn_vni_cmd,
    4426             :       "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
    4427             :       SHOW_STR
    4428             :       BGP_STR
    4429             :       L2VPN_HELP_STR
    4430             :       EVPN_HELP_STR
    4431             :       "Show VNI\n"
    4432             :       "VNI number\n"
    4433             :       JSON_STR)
    4434             : {
    4435           0 :         struct bgp *bgp_evpn;
    4436           0 :         vni_t vni;
    4437           0 :         int idx = 0;
    4438           0 :         bool uj = false;
    4439           0 :         json_object *json = NULL;
    4440           0 :         uint32_t num_l2vnis = 0;
    4441           0 :         uint32_t num_l3vnis = 0;
    4442           0 :         uint32_t num_vnis = 0;
    4443           0 :         struct listnode *node = NULL;
    4444           0 :         struct bgp *bgp_temp = NULL;
    4445             : 
    4446           0 :         uj = use_json(argc, argv);
    4447             : 
    4448           0 :         bgp_evpn = bgp_get_evpn();
    4449           0 :         if (!bgp_evpn)
    4450             :                 return CMD_WARNING;
    4451             : 
    4452           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    4453             :                 return CMD_WARNING;
    4454             : 
    4455           0 :         if (uj)
    4456           0 :                 json = json_object_new_object();
    4457             : 
    4458           0 :         if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
    4459             : 
    4460           0 :                 num_l2vnis = hashcount(bgp_evpn->vnihash);
    4461             : 
    4462           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
    4463           0 :                         if (bgp_temp->l3vni)
    4464           0 :                                 num_l3vnis++;
    4465             :                 }
    4466           0 :                 num_vnis = num_l2vnis + num_l3vnis;
    4467           0 :                 if (uj) {
    4468           0 :                         json_object_string_add(json, "advertiseGatewayMacip",
    4469           0 :                                                bgp_evpn->advertise_gw_macip
    4470             :                                                        ? "Enabled"
    4471             :                                                        : "Disabled");
    4472           0 :                         json_object_string_add(json, "advertiseSviMacIp",
    4473           0 :                                         bgp_evpn->evpn_info->advertise_svi_macip
    4474             :                                         ? "Enabled" : "Disabled");
    4475           0 :                         json_object_string_add(json, "advertiseAllVnis",
    4476           0 :                                                is_evpn_enabled() ? "Enabled"
    4477             :                                                                  : "Disabled");
    4478           0 :                         json_object_string_add(
    4479             :                                 json, "flooding",
    4480           0 :                                 bgp_evpn->vxlan_flood_ctrl ==
    4481             :                                                 VXLAN_FLOOD_HEAD_END_REPL
    4482             :                                         ? "Head-end replication"
    4483             :                                         : "Disabled");
    4484           0 :                         json_object_string_add(
    4485             :                                 json, "vxlanFlooding",
    4486           0 :                                 bgp_evpn->vxlan_flood_ctrl ==
    4487             :                                                 VXLAN_FLOOD_HEAD_END_REPL
    4488             :                                         ? "Enabled"
    4489             :                                         : "Disabled");
    4490           0 :                         json_object_int_add(json, "numVnis", num_vnis);
    4491           0 :                         json_object_int_add(json, "numL2Vnis", num_l2vnis);
    4492           0 :                         json_object_int_add(json, "numL3Vnis", num_l3vnis);
    4493             :                 } else {
    4494           0 :                         vty_out(vty, "Advertise Gateway Macip: %s\n",
    4495           0 :                                 bgp_evpn->advertise_gw_macip ? "Enabled"
    4496             :                                                             : "Disabled");
    4497           0 :                         vty_out(vty, "Advertise SVI Macip: %s\n",
    4498           0 :                                 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
    4499             :                                                         : "Disabled");
    4500           0 :                         vty_out(vty, "Advertise All VNI flag: %s\n",
    4501           0 :                                 is_evpn_enabled() ? "Enabled" : "Disabled");
    4502           0 :                         vty_out(vty, "BUM flooding: %s\n",
    4503           0 :                                 bgp_evpn->vxlan_flood_ctrl ==
    4504             :                                                 VXLAN_FLOOD_HEAD_END_REPL
    4505             :                                         ? "Head-end replication"
    4506             :                                         : "Disabled");
    4507           0 :                         vty_out(vty, "VXLAN flooding: %s\n",
    4508           0 :                                 bgp_evpn->vxlan_flood_ctrl ==
    4509             :                                                 VXLAN_FLOOD_HEAD_END_REPL
    4510             :                                         ? "Enabled"
    4511             :                                         : "Disabled");
    4512           0 :                         vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
    4513           0 :                         vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
    4514             :                 }
    4515           0 :                 evpn_show_all_vnis(vty, bgp_evpn, json);
    4516             :         } else {
    4517           0 :                 int vni_idx = 0;
    4518             : 
    4519           0 :                 if (!argv_find(argv, argc, "vni", &vni_idx))
    4520           0 :                         return CMD_WARNING;
    4521             : 
    4522             :                 /* Display specific VNI */
    4523           0 :                 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
    4524           0 :                 evpn_show_vni(vty, bgp_evpn, vni, json);
    4525             :         }
    4526             : 
    4527           0 :         if (uj)
    4528           0 :                 vty_json(vty, json);
    4529             : 
    4530             :         return CMD_SUCCESS;
    4531             : }
    4532             : 
    4533           0 : DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
    4534             :              show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
    4535             :              "show bgp l2vpn evpn vni remote-ip-hash",
    4536             :              SHOW_STR
    4537             :              BGP_STR
    4538             :              L2VPN_HELP_STR
    4539             :              EVPN_HELP_STR
    4540             :              "Show VNI\n"
    4541             :              "Remote IP hash\n")
    4542             : {
    4543           0 :         struct bgp *bgp_evpn;
    4544           0 :         int idx = 0;
    4545             : 
    4546           0 :         bgp_evpn = bgp_get_evpn();
    4547           0 :         if (!bgp_evpn)
    4548             :                 return CMD_WARNING;
    4549             : 
    4550           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    4551             :                 return CMD_WARNING;
    4552             : 
    4553           0 :         hash_iterate(bgp_evpn->vnihash,
    4554             :                      (void (*)(struct hash_bucket *,
    4555             :                                void *))bgp_evpn_show_remote_ip_hash,
    4556             :                      vty);
    4557             : 
    4558           0 :         return CMD_SUCCESS;
    4559             : }
    4560             : 
    4561           0 : DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
    4562             :              show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
    4563             :              "show bgp l2vpn evpn vni-svi-hash",
    4564             :              SHOW_STR
    4565             :              BGP_STR
    4566             :              L2VPN_HELP_STR
    4567             :              EVPN_HELP_STR
    4568             :              "Show vni-svi-hash\n")
    4569             : {
    4570           0 :         struct bgp *bgp_evpn;
    4571           0 :         int idx = 0;
    4572             : 
    4573           0 :         bgp_evpn = bgp_get_evpn();
    4574           0 :         if (!bgp_evpn)
    4575             :                 return CMD_WARNING;
    4576             : 
    4577           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    4578             :                 return CMD_WARNING;
    4579             : 
    4580           0 :         hash_iterate(bgp_evpn->vni_svi_hash,
    4581             :                      (void (*)(struct hash_bucket *,
    4582             :                                void *))bgp_evpn_show_vni_svi_hash,
    4583             :                      vty);
    4584             : 
    4585           0 :         return CMD_SUCCESS;
    4586             : }
    4587             : 
    4588           0 : DEFPY(show_bgp_l2vpn_evpn_es_evi,
    4589             :       show_bgp_l2vpn_evpn_es_evi_cmd,
    4590             :       "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
    4591             :       SHOW_STR
    4592             :       BGP_STR
    4593             :       L2VPN_HELP_STR
    4594             :       EVPN_HELP_STR
    4595             :       "ES per EVI\n"
    4596             :       "VxLAN Network Identifier\n"
    4597             :       "VNI\n"
    4598             :       JSON_STR
    4599             :       "Detailed information\n")
    4600             : {
    4601           0 :         if (vni)
    4602           0 :                 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
    4603             :         else
    4604           0 :                 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
    4605             : 
    4606           0 :         return CMD_SUCCESS;
    4607             : }
    4608             : 
    4609           0 : DEFPY(show_bgp_l2vpn_evpn_es,
    4610             :       show_bgp_l2vpn_evpn_es_cmd,
    4611             :       "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
    4612             :       SHOW_STR
    4613             :       BGP_STR
    4614             :       L2VPN_HELP_STR
    4615             :       EVPN_HELP_STR
    4616             :       "Ethernet Segment\n"
    4617             :       "ES ID\n"
    4618             :       "Detailed information\n"
    4619             :       JSON_STR)
    4620             : {
    4621           0 :         esi_t esi;
    4622             : 
    4623           0 :         if (esi_str) {
    4624           0 :                 if (!str_to_esi(esi_str, &esi)) {
    4625           0 :                         vty_out(vty, "%% Malformed ESI\n");
    4626           0 :                         return CMD_WARNING;
    4627             :                 }
    4628           0 :                 bgp_evpn_es_show_esi(vty, &esi, uj);
    4629             :         } else {
    4630             : 
    4631           0 :                 bgp_evpn_es_show(vty, uj, !!detail);
    4632             :         }
    4633             : 
    4634             :         return CMD_SUCCESS;
    4635             : }
    4636             : 
    4637           0 : DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
    4638             :       "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
    4639             :       SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
    4640             :       "Ethernet Segment\n"
    4641             :       "ES ID\n" JSON_STR)
    4642             : {
    4643           0 :         esi_t esi;
    4644             : 
    4645           0 :         if (esi_str) {
    4646           0 :                 if (!str_to_esi(esi_str, &esi)) {
    4647           0 :                         vty_out(vty, "%% Malformed ESI\n");
    4648           0 :                         return CMD_WARNING;
    4649             :                 }
    4650           0 :                 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
    4651             :         } else {
    4652             : 
    4653           0 :                 bgp_evpn_es_vrf_show(vty, uj, NULL);
    4654             :         }
    4655             : 
    4656             :         return CMD_SUCCESS;
    4657             : }
    4658             : 
    4659           0 : DEFPY(show_bgp_l2vpn_evpn_nh,
    4660             :       show_bgp_l2vpn_evpn_nh_cmd,
    4661             :       "show bgp l2vpn evpn next-hops [json$uj]",
    4662             :       SHOW_STR
    4663             :       BGP_STR
    4664             :       L2VPN_HELP_STR
    4665             :       EVPN_HELP_STR
    4666             :       "Nexthops\n"
    4667             :       JSON_STR)
    4668             : {
    4669           0 :         bgp_evpn_nh_show(vty, uj);
    4670             : 
    4671           0 :         return CMD_SUCCESS;
    4672             : }
    4673             : 
    4674             : /*
    4675             :  * Display EVPN neighbor summary.
    4676             :  */
    4677           0 : DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
    4678             :       "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
    4679             :       SHOW_STR BGP_STR
    4680             :       "bgp vrf\n"
    4681             :       "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
    4682             :       "Summary of BGP neighbor status\n"
    4683             :       "Show only sessions in Established state\n"
    4684             :       "Show only sessions not in Established state\n"
    4685             :       "Show only the specified neighbor session\n"
    4686             :       "Neighbor to display information about\n"
    4687             :       "Neighbor to display information about\n"
    4688             :       "Neighbor on BGP configured interface\n"
    4689             :       "Show only the specified remote AS sessions\n"
    4690             :       "AS number\n"
    4691             :       "Internal (iBGP) AS sessions\n"
    4692             :       "External (eBGP) AS sessions\n"
    4693             :       "Shorten the information on BGP instances\n"
    4694             :       "Increase table width for longer output\n" JSON_STR)
    4695             : {
    4696           0 :         int idx_vrf = 0;
    4697           0 :         int idx = 0;
    4698           0 :         char *vrf = NULL;
    4699           0 :         char *neighbor = NULL;
    4700           0 :         as_t as = 0; /* 0 means AS filter not set */
    4701           0 :         int as_type = AS_UNSPECIFIED;
    4702           0 :         uint16_t show_flags = 0;
    4703             : 
    4704           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
    4705           0 :                 vrf = argv[++idx_vrf]->arg;
    4706             : 
    4707           0 :         if (argv_find(argv, argc, "failed", &idx))
    4708           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
    4709             : 
    4710           0 :         if (argv_find(argv, argc, "established", &idx))
    4711           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
    4712             : 
    4713             : 
    4714           0 :         if (argv_find(argv, argc, "neighbor", &idx))
    4715           0 :                 neighbor = argv[idx + 1]->arg;
    4716             : 
    4717           0 :         if (argv_find(argv, argc, "remote-as", &idx)) {
    4718           0 :                 if (argv[idx + 1]->arg[0] == 'i')
    4719             :                         as_type = AS_INTERNAL;
    4720           0 :                 else if (argv[idx + 1]->arg[0] == 'e')
    4721             :                         as_type = AS_EXTERNAL;
    4722             :                 else
    4723           0 :                         as = (as_t)atoi(argv[idx + 1]->arg);
    4724             :         }
    4725             : 
    4726           0 :         if (argv_find(argv, argc, "terse", &idx))
    4727           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
    4728             : 
    4729           0 :         if (argv_find(argv, argc, "wide", &idx))
    4730           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
    4731             : 
    4732           0 :         if (use_json(argc, argv))
    4733           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
    4734             : 
    4735           0 :         return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
    4736             :                                     as_type, as, show_flags);
    4737             : }
    4738             : 
    4739           0 : static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
    4740             : {
    4741           0 :         if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
    4742           0 :                 *type = BGP_EVPN_MAC_IP_ROUTE;
    4743           0 :         else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
    4744           0 :                 *type = BGP_EVPN_IMET_ROUTE;
    4745           0 :         else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
    4746           0 :                 *type = BGP_EVPN_ES_ROUTE;
    4747           0 :         else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
    4748           0 :                 *type = BGP_EVPN_AD_ROUTE;
    4749           0 :         else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
    4750           0 :                 *type = BGP_EVPN_IP_PREFIX_ROUTE;
    4751             :         else
    4752             :                 return -1;
    4753             : 
    4754             :         return 0;
    4755             : }
    4756             : 
    4757           0 : int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
    4758             : {
    4759           0 :         int type_idx = 0;
    4760             : 
    4761           0 :         if (argv_find(argv, argc, "type", &type_idx)) {
    4762             :                 /* Specific type is requested */
    4763           0 :                 if (bgp_evpn_cli_parse_type_cmp(type,
    4764           0 :                                                 argv[type_idx + 1]->arg) != 0)
    4765             :                         return -1;
    4766             :         }
    4767             : 
    4768             :         return 0;
    4769             : }
    4770             : 
    4771             : /*
    4772             :  * Display global EVPN routing table.
    4773             :  */
    4774           0 : DEFUN(show_bgp_l2vpn_evpn_route,
    4775             :       show_bgp_l2vpn_evpn_route_cmd,
    4776             :       "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
    4777             :       SHOW_STR
    4778             :       BGP_STR
    4779             :       L2VPN_HELP_STR
    4780             :       EVPN_HELP_STR
    4781             :       EVPN_RT_HELP_STR
    4782             :       "Display Detailed Information\n"
    4783             :       EVPN_TYPE_HELP_STR
    4784             :       EVPN_TYPE_ALL_LIST_HELP_STR
    4785             :       JSON_STR)
    4786             : {
    4787           0 :         struct bgp *bgp;
    4788           0 :         int detail = 0;
    4789           0 :         int type = 0;
    4790           0 :         bool uj = false;
    4791           0 :         json_object *json = NULL;
    4792             : 
    4793           0 :         uj = use_json(argc, argv);
    4794             : 
    4795           0 :         bgp = bgp_get_evpn();
    4796           0 :         if (!bgp)
    4797             :                 return CMD_WARNING;
    4798             : 
    4799           0 :         if (uj)
    4800           0 :                 json = json_object_new_object();
    4801             : 
    4802           0 :         if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
    4803             :                 return CMD_WARNING;
    4804             : 
    4805           0 :         if (argv_find(argv, argc, "detail", &detail))
    4806           0 :                 detail = 1;
    4807             : 
    4808           0 :         evpn_show_all_routes(vty, bgp, type, json, detail);
    4809             : 
    4810             :         /*
    4811             :          * This is an extremely expensive operation at scale
    4812             :          * and as such we need to save as much time as is
    4813             :          * possible.
    4814             :          */
    4815           0 :         if (uj)
    4816           0 :                 vty_json_no_pretty(vty, json);
    4817             : 
    4818             :         return CMD_SUCCESS;
    4819             : }
    4820             : 
    4821             : /*
    4822             :  * Display global EVPN routing table for specific RD.
    4823             :  */
    4824           0 : DEFUN(show_bgp_l2vpn_evpn_route_rd,
    4825             :       show_bgp_l2vpn_evpn_route_rd_cmd,
    4826             :       "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
    4827             :       SHOW_STR
    4828             :       BGP_STR
    4829             :       L2VPN_HELP_STR
    4830             :       EVPN_HELP_STR
    4831             :       EVPN_RT_HELP_STR
    4832             :       EVPN_RT_DIST_HELP_STR
    4833             :       EVPN_ASN_IP_HELP_STR
    4834             :       "All VPN Route Distinguishers\n"
    4835             :       EVPN_TYPE_HELP_STR
    4836             :       EVPN_TYPE_ALL_LIST_HELP_STR
    4837             :       JSON_STR)
    4838             : {
    4839           0 :         struct bgp *bgp;
    4840           0 :         int ret = 0;
    4841           0 :         struct prefix_rd prd;
    4842           0 :         int type = 0;
    4843           0 :         bool uj = false;
    4844           0 :         json_object *json = NULL;
    4845           0 :         int idx_ext_community = 0;
    4846           0 :         int rd_all = 0;
    4847             : 
    4848           0 :         bgp = bgp_get_evpn();
    4849           0 :         if (!bgp)
    4850             :                 return CMD_WARNING;
    4851             : 
    4852             :         /* check if we need json output */
    4853           0 :         uj = use_json(argc, argv);
    4854           0 :         if (uj)
    4855           0 :                 json = json_object_new_object();
    4856             : 
    4857           0 :         if (!argv_find(argv, argc, "all", &rd_all)) {
    4858             :                 /* get the RD */
    4859           0 :                 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
    4860             :                               &idx_ext_community)) {
    4861           0 :                         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    4862           0 :                         if (!ret) {
    4863           0 :                                 vty_out(vty,
    4864             :                                         "%% Malformed Route Distinguisher\n");
    4865           0 :                                 return CMD_WARNING;
    4866             :                         }
    4867             :                 }
    4868             :         }
    4869             : 
    4870           0 :         if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
    4871             :                 return CMD_WARNING;
    4872             : 
    4873           0 :         if (rd_all)
    4874           0 :                 evpn_show_all_routes(vty, bgp, type, json, 1);
    4875             :         else
    4876           0 :                 evpn_show_route_rd(vty, bgp, &prd, type, json);
    4877             : 
    4878           0 :         if (uj)
    4879           0 :                 vty_json(vty, json);
    4880             : 
    4881             :         return CMD_SUCCESS;
    4882             : }
    4883             : 
    4884             : /*
    4885             :  * Display global EVPN routing table for specific RD and MACIP.
    4886             :  */
    4887           0 : DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
    4888             :       show_bgp_l2vpn_evpn_route_rd_macip_cmd,
    4889             :       "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
    4890             :       SHOW_STR
    4891             :       BGP_STR
    4892             :       L2VPN_HELP_STR
    4893             :       EVPN_HELP_STR
    4894             :       EVPN_RT_HELP_STR
    4895             :       EVPN_RT_DIST_HELP_STR
    4896             :       EVPN_ASN_IP_HELP_STR
    4897             :       "All VPN Route Distinguishers\n"
    4898             :       "MAC\n"
    4899             :       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
    4900             :       "IP\n"
    4901             :       "IP address (IPv4 or IPv6)\n"
    4902             :       JSON_STR)
    4903             : {
    4904           0 :         struct bgp *bgp;
    4905           0 :         int ret = 0;
    4906           0 :         struct prefix_rd prd;
    4907           0 :         struct ethaddr mac;
    4908           0 :         struct ipaddr ip;
    4909           0 :         int idx_ext_community = 0;
    4910           0 :         int mac_idx = 0;
    4911           0 :         int ip_idx = 0;
    4912           0 :         bool uj = false;
    4913           0 :         json_object *json = NULL;
    4914           0 :         int rd_all = 0;
    4915             : 
    4916           0 :         memset(&mac, 0, sizeof(struct ethaddr));
    4917           0 :         memset(&ip, 0, sizeof(struct ipaddr));
    4918             : 
    4919           0 :         bgp = bgp_get_evpn();
    4920           0 :         if (!bgp)
    4921             :                 return CMD_WARNING;
    4922             : 
    4923             :         /* check if we need json output */
    4924           0 :         uj = use_json(argc, argv);
    4925           0 :         if (uj)
    4926           0 :                 json = json_object_new_object();
    4927             : 
    4928             :         /* get the prd */
    4929           0 :         if (!argv_find(argv, argc, "all", &rd_all)) {
    4930           0 :                 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
    4931             :                               &idx_ext_community)) {
    4932           0 :                         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    4933           0 :                         if (!ret) {
    4934           0 :                                 vty_out(vty,
    4935             :                                         "%% Malformed Route Distinguisher\n");
    4936           0 :                                 return CMD_WARNING;
    4937             :                         }
    4938             :                 }
    4939             :         }
    4940             : 
    4941             :         /* get the mac */
    4942           0 :         if (argv_find(argv, argc, "mac", &mac_idx)) {
    4943           0 :                 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
    4944           0 :                         vty_out(vty, "%% Malformed MAC address\n");
    4945           0 :                         return CMD_WARNING;
    4946             :                 }
    4947             :         }
    4948             : 
    4949             :         /* get the ip if specified */
    4950           0 :         if (argv_find(argv, argc, "ip", &ip_idx)) {
    4951           0 :                 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
    4952           0 :                         vty_out(vty, "%% Malformed IP address\n");
    4953           0 :                         return CMD_WARNING;
    4954             :                 }
    4955             :         }
    4956             : 
    4957           0 :         if (rd_all)
    4958           0 :                 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
    4959             :         else
    4960           0 :                 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
    4961             : 
    4962           0 :         if (uj)
    4963           0 :                 vty_json(vty, json);
    4964             : 
    4965             :         return CMD_SUCCESS;
    4966             : }
    4967             : 
    4968             : /* Display per ESI routing table */
    4969           0 : DEFUN(show_bgp_l2vpn_evpn_route_esi,
    4970             :       show_bgp_l2vpn_evpn_route_esi_cmd,
    4971             :       "show bgp l2vpn evpn route esi ESI [json]",
    4972             :       SHOW_STR
    4973             :       BGP_STR
    4974             :       L2VPN_HELP_STR
    4975             :       EVPN_HELP_STR
    4976             :       EVPN_RT_HELP_STR
    4977             :       "Ethernet Segment Identifier\n"
    4978             :       "ESI ID\n"
    4979             :       JSON_STR)
    4980             : {
    4981           0 :         bool uj = false;
    4982           0 :         esi_t esi;
    4983           0 :         struct bgp *bgp = NULL;
    4984           0 :         json_object *json = NULL;
    4985             : 
    4986           0 :         memset(&esi, 0, sizeof(esi));
    4987           0 :         bgp = bgp_get_evpn();
    4988           0 :         if (!bgp)
    4989             :                 return CMD_WARNING;
    4990             : 
    4991           0 :         uj = use_json(argc, argv);
    4992           0 :         if (uj)
    4993           0 :                 json = json_object_new_object();
    4994             : 
    4995             :         /* get the ESI - ESI-ID is at argv[6] */
    4996           0 :         if (!str_to_esi(argv[6]->arg, &esi)) {
    4997           0 :                 vty_out(vty, "%% Malformed ESI\n");
    4998           0 :                 return CMD_WARNING;
    4999             :         }
    5000             : 
    5001           0 :         evpn_show_routes_esi(vty, bgp, &esi, json);
    5002             : 
    5003           0 :         if (uj)
    5004           0 :                 vty_json(vty, json);
    5005             : 
    5006             :         return CMD_SUCCESS;
    5007             : }
    5008             : 
    5009             : 
    5010             : /*
    5011             :  * Display per-VNI EVPN routing table.
    5012             :  */
    5013           0 : DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
    5014             :       "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
    5015             :       SHOW_STR
    5016             :       BGP_STR
    5017             :       L2VPN_HELP_STR
    5018             :       EVPN_HELP_STR
    5019             :       EVPN_RT_HELP_STR
    5020             :       "VXLAN Network Identifier\n"
    5021             :       "VNI number\n"
    5022             :       EVPN_TYPE_HELP_STR
    5023             :       EVPN_TYPE_1_HELP_STR
    5024             :       EVPN_TYPE_1_HELP_STR
    5025             :       EVPN_TYPE_2_HELP_STR
    5026             :       EVPN_TYPE_2_HELP_STR
    5027             :       EVPN_TYPE_3_HELP_STR
    5028             :       EVPN_TYPE_3_HELP_STR
    5029             :       "Remote VTEP\n"
    5030             :       "Remote VTEP IP address\n"
    5031             :       JSON_STR)
    5032             : {
    5033           0 :         vni_t vni;
    5034           0 :         struct bgp *bgp;
    5035           0 :         struct in_addr vtep_ip;
    5036           0 :         int type = 0;
    5037           0 :         int idx = 0;
    5038           0 :         int vtep_idx = 0;
    5039           0 :         bool uj = false;
    5040           0 :         json_object *json = NULL;
    5041             : 
    5042           0 :         bgp = bgp_get_evpn();
    5043           0 :         if (!bgp)
    5044             :                 return CMD_WARNING;
    5045             : 
    5046             :         /* check if we need json output */
    5047           0 :         uj = use_json(argc, argv);
    5048           0 :         if (uj)
    5049           0 :                 json = json_object_new_object();
    5050             : 
    5051           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    5052             :                 return CMD_WARNING;
    5053             : 
    5054           0 :         vtep_ip.s_addr = 0;
    5055             : 
    5056           0 :         vni = strtoul(argv[idx + 3]->arg, NULL, 10);
    5057             : 
    5058           0 :         if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
    5059             :                 return CMD_WARNING;
    5060             : 
    5061           0 :         if (argv_find(argv, argc, "vtep", &vtep_idx)) {
    5062           0 :                 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
    5063           0 :                         vty_out(vty, "%% Malformed VTEP IP address\n");
    5064           0 :                         return CMD_WARNING;
    5065             :                 }
    5066             :         }
    5067             : 
    5068           0 :         evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
    5069             : 
    5070           0 :         if (uj)
    5071           0 :                 vty_json(vty, json);
    5072             : 
    5073             :         return CMD_SUCCESS;
    5074             : }
    5075             : 
    5076             : /*
    5077             :  * Display per-VNI EVPN routing table for specific MACIP.
    5078             :  */
    5079           0 : DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
    5080             :       show_bgp_l2vpn_evpn_route_vni_macip_cmd,
    5081             :       "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
    5082             :       SHOW_STR
    5083             :       BGP_STR
    5084             :       L2VPN_HELP_STR
    5085             :       EVPN_HELP_STR
    5086             :       EVPN_RT_HELP_STR
    5087             :       "VXLAN Network Identifier\n"
    5088             :       "VNI number\n"
    5089             :       "MAC\n"
    5090             :       "MAC address (e.g., 00:e0:ec:20:12:62)\n"
    5091             :       "IP\n"
    5092             :       "IP address (IPv4 or IPv6)\n"
    5093             :       JSON_STR)
    5094             : {
    5095           0 :         vni_t vni;
    5096           0 :         struct bgp *bgp;
    5097           0 :         struct ethaddr mac;
    5098           0 :         struct ipaddr ip;
    5099           0 :         int idx = 0;
    5100           0 :         bool uj = false;
    5101           0 :         json_object *json = NULL;
    5102             : 
    5103           0 :         bgp = bgp_get_evpn();
    5104           0 :         if (!bgp)
    5105             :                 return CMD_WARNING;
    5106             : 
    5107             :         /* check if we need json output */
    5108           0 :         uj = use_json(argc, argv);
    5109           0 :         if (uj)
    5110           0 :                 json = json_object_new_object();
    5111             : 
    5112           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    5113             :                 return CMD_WARNING;
    5114             : 
    5115             :         /* get the VNI */
    5116           0 :         vni = strtoul(argv[idx + 3]->arg, NULL, 10);
    5117             : 
    5118             :         /* get the mac */
    5119           0 :         if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
    5120           0 :                 vty_out(vty, "%% Malformed MAC address\n");
    5121           0 :                 return CMD_WARNING;
    5122             :         }
    5123             : 
    5124             :         /* get the ip */
    5125           0 :         memset(&ip, 0, sizeof(ip));
    5126           0 :         if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
    5127             :             || (uj
    5128           0 :                 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
    5129           0 :                 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
    5130           0 :                         vty_out(vty, "%% Malformed IP address\n");
    5131           0 :                         return CMD_WARNING;
    5132             :                 }
    5133             :         }
    5134             : 
    5135           0 :         evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
    5136             : 
    5137           0 :         if (uj)
    5138           0 :                 vty_json(vty, json);
    5139             : 
    5140             :         return CMD_SUCCESS;
    5141             : }
    5142             : 
    5143             : /*
    5144             :  * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
    5145             :  */
    5146           0 : DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
    5147             :       show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
    5148             :       "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
    5149             :       SHOW_STR
    5150             :       BGP_STR
    5151             :       L2VPN_HELP_STR
    5152             :       EVPN_HELP_STR
    5153             :       EVPN_RT_HELP_STR
    5154             :       "VXLAN Network Identifier\n"
    5155             :       "VNI number\n"
    5156             :       EVPN_TYPE_3_HELP_STR
    5157             :       "Originating Router IP address\n"
    5158             :       JSON_STR)
    5159             : {
    5160           0 :         vni_t vni;
    5161           0 :         struct bgp *bgp;
    5162           0 :         int ret;
    5163           0 :         struct in_addr orig_ip;
    5164           0 :         int idx = 0;
    5165           0 :         bool uj = false;
    5166           0 :         json_object *json = NULL;
    5167             : 
    5168           0 :         bgp = bgp_get_evpn();
    5169           0 :         if (!bgp)
    5170             :                 return CMD_WARNING;
    5171             : 
    5172             :         /* check if we need json output */
    5173           0 :         uj = use_json(argc, argv);
    5174           0 :         if (uj)
    5175           0 :                 json = json_object_new_object();
    5176             : 
    5177           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    5178             :                 return CMD_WARNING;
    5179             : 
    5180             :         /* get the VNI */
    5181           0 :         vni = strtoul(argv[idx + 3]->arg, NULL, 10);
    5182             : 
    5183             :         /* get the ip */
    5184           0 :         ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
    5185           0 :         if (!ret) {
    5186           0 :                 vty_out(vty, "%% Malformed Originating Router IP address\n");
    5187           0 :                 return CMD_WARNING;
    5188             :         }
    5189             : 
    5190           0 :         evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
    5191             : 
    5192           0 :         if (uj)
    5193           0 :                 vty_json(vty, json);
    5194             : 
    5195             :         return CMD_SUCCESS;
    5196             : }
    5197             : 
    5198             : /*
    5199             :  * Display per-VNI EVPN routing table - for all VNIs.
    5200             :  */
    5201           0 : DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
    5202             :       show_bgp_l2vpn_evpn_route_vni_all_cmd,
    5203             :       "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
    5204             :       SHOW_STR
    5205             :       BGP_STR
    5206             :       L2VPN_HELP_STR
    5207             :       EVPN_HELP_STR
    5208             :       EVPN_RT_HELP_STR
    5209             :       "VXLAN Network Identifier\n"
    5210             :       "All VNIs\n"
    5211             :       "Print Detailed Output\n"
    5212             :       "Remote VTEP\n"
    5213             :       "Remote VTEP IP address\n"
    5214             :       JSON_STR)
    5215             : {
    5216           0 :         struct bgp *bgp;
    5217           0 :         struct in_addr vtep_ip;
    5218           0 :         int idx = 0;
    5219           0 :         bool uj = false;
    5220           0 :         json_object *json = NULL;
    5221             :         /* Detail Adjust. Adjust indexes according to detail option */
    5222           0 :         int da = 0;
    5223             : 
    5224           0 :         bgp = bgp_get_evpn();
    5225           0 :         if (!bgp)
    5226             :                 return CMD_WARNING;
    5227             : 
    5228             :         /* check if we need json output */
    5229           0 :         uj = use_json(argc, argv);
    5230           0 :         if (uj)
    5231           0 :                 json = json_object_new_object();
    5232             : 
    5233           0 :         if (!argv_find(argv, argc, "evpn", &idx))
    5234             :                 return CMD_WARNING;
    5235             : 
    5236           0 :         if (argv_find(argv, argc, "detail", &da))
    5237           0 :                 da = 1;
    5238             : 
    5239             :         /* vtep-ip position depends on detail option */
    5240           0 :         vtep_ip.s_addr = 0;
    5241           0 :         if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
    5242             :             || (uj
    5243           0 :                 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
    5244           0 :                 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
    5245           0 :                         vty_out(vty, "%% Malformed VTEP IP address\n");
    5246           0 :                         return CMD_WARNING;
    5247             :                 }
    5248             :         }
    5249             : 
    5250           0 :         evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
    5251             : 
    5252           0 :         if (uj) {
    5253           0 :                 vty_json(vty, json);
    5254           0 :                 json_object_free(json);
    5255             :         }
    5256             : 
    5257             :         return CMD_SUCCESS;
    5258             : }
    5259             : 
    5260             : /*
    5261             :  * Display per-VNI EVPN ALL routing tables - for all VNIs.
    5262             :  */
    5263           0 : DEFPY(show_bgp_vni_all,
    5264             :       show_bgp_vni_all_cmd,
    5265             :       "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
    5266             :       SHOW_STR
    5267             :       BGP_STR
    5268             :       VNI_HELP_STR
    5269             :       VNI_ALL_HELP_STR
    5270             :       VTEP_HELP_STR
    5271             :       VTEP_IP_HELP_STR
    5272             :       DETAIL_HELP_STR
    5273             :       JSON_STR)
    5274             : {
    5275           0 :         struct bgp *bgp;
    5276           0 :         json_object *json = NULL;
    5277             : 
    5278           0 :         bgp = bgp_get_evpn();
    5279           0 :         if (!bgp)
    5280             :                 return CMD_WARNING;
    5281             : 
    5282             :         /* check if we need json output */
    5283           0 :         if (uj)
    5284           0 :                 json = json_object_new_object();
    5285             : 
    5286           0 :         evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
    5287             : 
    5288           0 :         if (uj)
    5289           0 :                 vty_json(vty, json);
    5290             : 
    5291             :         return CMD_SUCCESS;
    5292             : }
    5293             : 
    5294             : /*
    5295             :  * Display per-VNI EVPN EAD routing table - for all VNIs.
    5296             :  */
    5297           0 : DEFPY(show_bgp_vni_all_ead,
    5298             :       show_bgp_vni_all_ead_cmd,
    5299             :       "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
    5300             :       SHOW_STR
    5301             :       BGP_STR
    5302             :       VNI_HELP_STR
    5303             :       VNI_ALL_HELP_STR
    5304             :       EVPN_TYPE_HELP_STR
    5305             :       EVPN_TYPE_1_HELP_STR
    5306             :       EVPN_TYPE_1_HELP_STR
    5307             :       VTEP_HELP_STR
    5308             :       VTEP_IP_HELP_STR
    5309             :       DETAIL_HELP_STR
    5310             :       JSON_STR)
    5311             : {
    5312           0 :         struct bgp *bgp;
    5313           0 :         json_object *json = NULL;
    5314             : 
    5315           0 :         bgp = bgp_get_evpn();
    5316           0 :         if (!bgp)
    5317             :                 return CMD_WARNING;
    5318             : 
    5319             :         /* check if we need json output */
    5320           0 :         if (uj)
    5321           0 :                 json = json_object_new_object();
    5322             : 
    5323           0 :         evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
    5324             :                                  !!detail);
    5325             : 
    5326           0 :         if (uj)
    5327           0 :                 vty_json(vty, json);
    5328             : 
    5329             :         return CMD_SUCCESS;
    5330             : }
    5331             : 
    5332             : /*
    5333             :  * Display per-VNI EVPN MAC routing table - for all VNIs.
    5334             :  */
    5335           0 : DEFPY(show_bgp_vni_all_macip_mac,
    5336             :       show_bgp_vni_all_macip_mac_cmd,
    5337             :       "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
    5338             :       SHOW_STR
    5339             :       BGP_STR
    5340             :       VNI_HELP_STR
    5341             :       VNI_ALL_HELP_STR
    5342             :       EVPN_TYPE_HELP_STR
    5343             :       EVPN_TYPE_2_HELP_STR
    5344             :       EVPN_TYPE_2_HELP_STR
    5345             :       "MAC Table\n"
    5346             :       VTEP_HELP_STR
    5347             :       VTEP_IP_HELP_STR
    5348             :       DETAIL_HELP_STR
    5349             :       JSON_STR)
    5350             : {
    5351           0 :         struct bgp *bgp;
    5352           0 :         json_object *json = NULL;
    5353             : 
    5354           0 :         bgp = bgp_get_evpn();
    5355           0 :         if (!bgp)
    5356             :                 return CMD_WARNING;
    5357             : 
    5358             :         /* check if we need json output */
    5359           0 :         if (uj)
    5360           0 :                 json = json_object_new_object();
    5361             : 
    5362           0 :         evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
    5363             :                                  json, !!detail);
    5364             : 
    5365           0 :         if (uj)
    5366           0 :                 vty_json(vty, json);
    5367             : 
    5368             :         return CMD_SUCCESS;
    5369             : }
    5370             : 
    5371             : /*
    5372             :  * Display per-VNI EVPN IP routing table - for all VNIs.
    5373             :  */
    5374           0 : DEFPY(show_bgp_vni_all_macip_ip,
    5375             :       show_bgp_vni_all_macip_ip_cmd,
    5376             :       "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
    5377             :       SHOW_STR
    5378             :       BGP_STR
    5379             :       VNI_HELP_STR
    5380             :       VNI_ALL_HELP_STR
    5381             :       EVPN_TYPE_HELP_STR
    5382             :       EVPN_TYPE_2_HELP_STR
    5383             :       EVPN_TYPE_2_HELP_STR
    5384             :       "IP Table\n"
    5385             :       VTEP_HELP_STR
    5386             :       VTEP_IP_HELP_STR
    5387             :       DETAIL_HELP_STR
    5388             :       JSON_STR)
    5389             : {
    5390           0 :         struct bgp *bgp;
    5391           0 :         json_object *json = NULL;
    5392             : 
    5393           0 :         bgp = bgp_get_evpn();
    5394           0 :         if (!bgp)
    5395             :                 return CMD_WARNING;
    5396             : 
    5397             :         /* check if we need json output */
    5398           0 :         if (uj)
    5399           0 :                 json = json_object_new_object();
    5400             : 
    5401           0 :         evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
    5402             :                                  json, !!detail);
    5403             : 
    5404           0 :         if (uj)
    5405           0 :                 vty_json(vty, json);
    5406             : 
    5407             :         return CMD_SUCCESS;
    5408             : }
    5409             : 
    5410             : /*
    5411             :  * Display per-VNI EVPN Multicast routing table - for all VNIs.
    5412             :  */
    5413           0 : DEFPY(show_bgp_vni_all_imet,
    5414             :       show_bgp_vni_all_imet_cmd,
    5415             :       "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
    5416             :       SHOW_STR
    5417             :       BGP_STR
    5418             :       VNI_HELP_STR
    5419             :       VNI_ALL_HELP_STR
    5420             :       EVPN_TYPE_HELP_STR
    5421             :       EVPN_TYPE_3_HELP_STR
    5422             :       EVPN_TYPE_3_HELP_STR
    5423             :       VTEP_HELP_STR
    5424             :       VTEP_IP_HELP_STR
    5425             :       DETAIL_HELP_STR
    5426             :       JSON_STR)
    5427             : {
    5428           0 :         struct bgp *bgp;
    5429           0 :         json_object *json = NULL;
    5430             : 
    5431           0 :         bgp = bgp_get_evpn();
    5432           0 :         if (!bgp)
    5433             :                 return CMD_WARNING;
    5434             : 
    5435             :         /* check if we need json output */
    5436           0 :         if (uj)
    5437           0 :                 json = json_object_new_object();
    5438             : 
    5439           0 :         evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
    5440             :                                  json, !!detail);
    5441             : 
    5442           0 :         if (uj)
    5443           0 :                 vty_json(vty, json);
    5444             : 
    5445             :         return CMD_SUCCESS;
    5446             : }
    5447             : 
    5448             : /*
    5449             :  * Display per-VNI EVPN ALL routing tables - for select VNI
    5450             :  */
    5451           0 : DEFPY(show_bgp_vni,
    5452             :       show_bgp_vni_cmd,
    5453             :       "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
    5454             :       SHOW_STR
    5455             :       BGP_STR
    5456             :       VNI_HELP_STR
    5457             :       VNI_NUM_HELP_STR
    5458             :       VTEP_HELP_STR
    5459             :       VTEP_IP_HELP_STR
    5460             :       JSON_STR)
    5461             : {
    5462           0 :         struct bgp *bgp;
    5463           0 :         json_object *json = NULL;
    5464           0 :         json_object *json_mac = NULL;
    5465             : 
    5466           0 :         bgp = bgp_get_evpn();
    5467           0 :         if (!bgp)
    5468             :                 return CMD_WARNING;
    5469             : 
    5470             :         /* check if we need json output */
    5471           0 :         if (uj) {
    5472           0 :                 json = json_object_new_object();
    5473           0 :                 json_mac = json_object_new_object();
    5474             :         }
    5475             : 
    5476           0 :         evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
    5477             : 
    5478           0 :         if (!uj)
    5479           0 :                 vty_out(vty, "\n\nMAC Table:\n\n");
    5480             : 
    5481           0 :         evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
    5482             : 
    5483           0 :         if (uj) {
    5484           0 :                 json_object_object_add(json, "macTable", json_mac);
    5485           0 :                 vty_json(vty, json);
    5486             :         }
    5487             : 
    5488             :         return CMD_SUCCESS;
    5489             : }
    5490             : 
    5491             : /*
    5492             :  * Display per-VNI EVPN EAD routing table - for select VNI
    5493             :  */
    5494           0 : DEFPY(show_bgp_vni_ead,
    5495             :       show_bgp_vni_ead_cmd,
    5496             :       "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
    5497             :       SHOW_STR
    5498             :       BGP_STR
    5499             :       VNI_HELP_STR
    5500             :       VNI_NUM_HELP_STR
    5501             :       EVPN_TYPE_HELP_STR
    5502             :       EVPN_TYPE_1_HELP_STR
    5503             :       EVPN_TYPE_1_HELP_STR
    5504             :       VTEP_HELP_STR
    5505             :       VTEP_IP_HELP_STR
    5506             :       JSON_STR)
    5507             : {
    5508           0 :         struct bgp *bgp;
    5509           0 :         json_object *json = NULL;
    5510             : 
    5511           0 :         bgp = bgp_get_evpn();
    5512           0 :         if (!bgp)
    5513             :                 return CMD_WARNING;
    5514             : 
    5515             :         /* check if we need json output */
    5516           0 :         if (uj)
    5517           0 :                 json = json_object_new_object();
    5518             : 
    5519           0 :         evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
    5520             :                              json);
    5521             : 
    5522           0 :         if (uj)
    5523           0 :                 vty_json(vty, json);
    5524             : 
    5525             :         return CMD_SUCCESS;
    5526             : }
    5527             : 
    5528             : /*
    5529             :  * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
    5530             :  */
    5531           0 : DEFPY(show_bgp_vni_macip_mac,
    5532             :       show_bgp_vni_macip_mac_cmd,
    5533             :       "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
    5534             :       SHOW_STR
    5535             :       BGP_STR
    5536             :       VNI_HELP_STR
    5537             :       VNI_NUM_HELP_STR
    5538             :       EVPN_TYPE_HELP_STR
    5539             :       EVPN_TYPE_2_HELP_STR
    5540             :       EVPN_TYPE_2_HELP_STR
    5541             :       "MAC Table\n"
    5542             :       VTEP_HELP_STR
    5543             :       VTEP_IP_HELP_STR
    5544             :       JSON_STR)
    5545             : {
    5546           0 :         struct bgp *bgp;
    5547           0 :         json_object *json = NULL;
    5548             : 
    5549           0 :         bgp = bgp_get_evpn();
    5550           0 :         if (!bgp)
    5551             :                 return CMD_WARNING;
    5552             : 
    5553             :         /* check if we need json output */
    5554           0 :         if (uj)
    5555           0 :                 json = json_object_new_object();
    5556             : 
    5557           0 :         evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
    5558             :                              json);
    5559             : 
    5560           0 :         if (uj)
    5561           0 :                 vty_json(vty, json);
    5562             : 
    5563             :         return CMD_SUCCESS;
    5564             : }
    5565             : 
    5566             : /*
    5567             :  * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
    5568             :  */
    5569           0 : DEFPY(show_bgp_vni_macip_ip,
    5570             :       show_bgp_vni_macip_ip_cmd,
    5571             :       "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
    5572             :       SHOW_STR
    5573             :       BGP_STR
    5574             :       VNI_HELP_STR
    5575             :       VNI_NUM_HELP_STR
    5576             :       EVPN_TYPE_HELP_STR
    5577             :       EVPN_TYPE_2_HELP_STR
    5578             :       EVPN_TYPE_2_HELP_STR
    5579             :       "IP Table\n"
    5580             :       VTEP_HELP_STR
    5581             :       VTEP_IP_HELP_STR
    5582             :       JSON_STR)
    5583             : {
    5584           0 :         struct bgp *bgp;
    5585           0 :         json_object *json = NULL;
    5586             : 
    5587           0 :         bgp = bgp_get_evpn();
    5588           0 :         if (!bgp)
    5589             :                 return CMD_WARNING;
    5590             : 
    5591             :         /* check if we need json output */
    5592           0 :         if (uj)
    5593           0 :                 json = json_object_new_object();
    5594             : 
    5595           0 :         evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
    5596             :                              json);
    5597             : 
    5598           0 :         if (uj)
    5599           0 :                 vty_json(vty, json);
    5600             : 
    5601             :         return CMD_SUCCESS;
    5602             : }
    5603             : 
    5604             : /*
    5605             :  * Display per-VNI EVPN Multicast routing table - for select VNI
    5606             :  */
    5607           0 : DEFPY(show_bgp_vni_imet,
    5608             :       show_bgp_vni_imet_cmd,
    5609             :       "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
    5610             :       SHOW_STR
    5611             :       BGP_STR
    5612             :       VNI_HELP_STR
    5613             :       VNI_NUM_HELP_STR
    5614             :       EVPN_TYPE_HELP_STR
    5615             :       EVPN_TYPE_3_HELP_STR
    5616             :       EVPN_TYPE_3_HELP_STR
    5617             :       VTEP_HELP_STR
    5618             :       VTEP_IP_HELP_STR
    5619             :       JSON_STR)
    5620             : {
    5621           0 :         struct bgp *bgp;
    5622           0 :         json_object *json = NULL;
    5623             : 
    5624           0 :         bgp = bgp_get_evpn();
    5625           0 :         if (!bgp)
    5626             :                 return CMD_WARNING;
    5627             : 
    5628             :         /* check if we need json output */
    5629           0 :         if (uj)
    5630           0 :                 json = json_object_new_object();
    5631             : 
    5632           0 :         evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
    5633             :                              json);
    5634             : 
    5635           0 :         if (uj)
    5636           0 :                 vty_json(vty, json);
    5637             : 
    5638             :         return CMD_SUCCESS;
    5639             : }
    5640             : 
    5641             : /*
    5642             :  * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
    5643             :  */
    5644           0 : DEFPY(show_bgp_vni_macip_mac_addr,
    5645             :       show_bgp_vni_macip_mac_addr_cmd,
    5646             :       "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
    5647             :       SHOW_STR
    5648             :       BGP_STR
    5649             :       VNI_HELP_STR
    5650             :       VNI_NUM_HELP_STR
    5651             :       EVPN_TYPE_HELP_STR
    5652             :       EVPN_TYPE_2_HELP_STR
    5653             :       EVPN_TYPE_2_HELP_STR
    5654             :       "MAC Table\n"
    5655             :       MAC_STR
    5656             :       JSON_STR)
    5657             : {
    5658           0 :         struct bgp *bgp;
    5659           0 :         json_object *json = NULL;
    5660             : 
    5661           0 :         bgp = bgp_get_evpn();
    5662           0 :         if (!bgp)
    5663             :                 return CMD_WARNING;
    5664             : 
    5665             :         /* check if we need json output */
    5666           0 :         if (uj)
    5667           0 :                 json = json_object_new_object();
    5668             : 
    5669           0 :         evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
    5670             : 
    5671           0 :         if (uj)
    5672           0 :                 vty_json(vty, json);
    5673             : 
    5674             :         return CMD_SUCCESS;
    5675             : }
    5676             : 
    5677             : /*
    5678             :  * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
    5679             :  */
    5680           0 : DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
    5681             :       "show bgp vni " CMD_VNI_RANGE
    5682             :       "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
    5683             :       SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
    5684             :               EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
    5685             :       "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
    5686             : {
    5687           0 :         struct bgp *bgp;
    5688           0 :         json_object *json = NULL;
    5689           0 :         struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
    5690             : 
    5691           0 :         bgp = bgp_get_evpn();
    5692           0 :         if (!bgp)
    5693             :                 return CMD_WARNING;
    5694             : 
    5695             :         /* check if we need json output */
    5696           0 :         if (uj)
    5697           0 :                 json = json_object_new_object();
    5698             : 
    5699           0 :         if (sockunion_family(ip) == AF_INET) {
    5700           0 :                 ip_addr.ipa_type = IPADDR_V4;
    5701           0 :                 ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
    5702             :         } else {
    5703           0 :                 ip_addr.ipa_type = IPADDR_V6;
    5704           0 :                 memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
    5705             :                        sizeof(struct in6_addr));
    5706             :         }
    5707           0 :         evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
    5708             : 
    5709           0 :         if (uj)
    5710           0 :                 vty_json(vty, json);
    5711             : 
    5712             :         return CMD_SUCCESS;
    5713             : }
    5714             : 
    5715           0 : DEFPY_HIDDEN(
    5716             :         show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
    5717             :         show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
    5718             :         "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
    5719             :         SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
    5720             :         "EVPN route information\n"
    5721             :         "MAC IP routes in the EVI tables linked to the ES\n"
    5722             :         "ES ID\n"
    5723             :         "Detailed information\n" JSON_STR)
    5724             : {
    5725           0 :         esi_t esi;
    5726           0 :         esi_t *esi_p;
    5727           0 :         json_object *json = NULL;
    5728             : 
    5729           0 :         if (esi_str) {
    5730           0 :                 if (!str_to_esi(esi_str, &esi)) {
    5731           0 :                         vty_out(vty, "%% Malformed ESI\n");
    5732           0 :                         return CMD_WARNING;
    5733             :                 }
    5734             :                 esi_p = &esi;
    5735             :         } else {
    5736             :                 esi_p = NULL;
    5737             :         }
    5738             : 
    5739           0 :         if (uj)
    5740           0 :                 json = json_object_new_object();
    5741           0 :         bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
    5742           0 :         if (uj)
    5743           0 :                 vty_json(vty, json);
    5744             : 
    5745             :         return CMD_SUCCESS;
    5746             : }
    5747             : 
    5748           0 : DEFPY_HIDDEN(
    5749             :         show_bgp_l2vpn_evpn_route_mac_ip_global_es,
    5750             :         show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
    5751             :         "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
    5752             :         SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
    5753             :         "EVPN route information\n"
    5754             :         "MAC IP routes in the global table linked to the ES\n"
    5755             :         "ES ID\n"
    5756             :         "Detailed information\n" JSON_STR)
    5757             : {
    5758           0 :         esi_t esi;
    5759           0 :         esi_t *esi_p;
    5760           0 :         json_object *json = NULL;
    5761             : 
    5762           0 :         if (esi_str) {
    5763           0 :                 if (!str_to_esi(esi_str, &esi)) {
    5764           0 :                         vty_out(vty, "%% Malformed ESI\n");
    5765           0 :                         return CMD_WARNING;
    5766             :                 }
    5767             :                 esi_p = &esi;
    5768             :         } else {
    5769             :                 esi_p = NULL;
    5770             :         }
    5771             : 
    5772           0 :         if (uj)
    5773           0 :                 json = json_object_new_object();
    5774           0 :         bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
    5775           0 :         if (uj)
    5776           0 :                 vty_json(vty, json);
    5777             : 
    5778             :         return CMD_SUCCESS;
    5779             : }
    5780             : 
    5781             : /*
    5782             :  * Display EVPN import route-target hash table
    5783             :  */
    5784           0 : DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
    5785             :       show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
    5786             :       "show bgp l2vpn evpn vrf-import-rt [json]",
    5787             :       SHOW_STR
    5788             :       BGP_STR
    5789             :       L2VPN_HELP_STR
    5790             :       EVPN_HELP_STR
    5791             :       "Show vrf import route target\n"
    5792             :       JSON_STR)
    5793             : {
    5794           0 :         bool uj = false;
    5795           0 :         struct bgp *bgp_evpn = NULL;
    5796           0 :         json_object *json = NULL;
    5797             : 
    5798           0 :         bgp_evpn = bgp_get_evpn();
    5799           0 :         if (!bgp_evpn)
    5800             :                 return CMD_WARNING;
    5801             : 
    5802           0 :         uj = use_json(argc, argv);
    5803           0 :         if (uj)
    5804           0 :                 json = json_object_new_object();
    5805             : 
    5806           0 :         evpn_show_vrf_import_rts(vty, bgp_evpn, json);
    5807             : 
    5808           0 :         if (uj)
    5809           0 :                 vty_json(vty, json);
    5810             : 
    5811             :         return CMD_SUCCESS;
    5812             : }
    5813             : 
    5814             : /*
    5815             :  * Display EVPN import route-target hash table
    5816             :  */
    5817           0 : DEFUN(show_bgp_l2vpn_evpn_import_rt,
    5818             :       show_bgp_l2vpn_evpn_import_rt_cmd,
    5819             :       "show bgp l2vpn evpn import-rt [json]",
    5820             :       SHOW_STR
    5821             :       BGP_STR
    5822             :       L2VPN_HELP_STR
    5823             :       EVPN_HELP_STR
    5824             :       "Show import route target\n"
    5825             :       JSON_STR)
    5826             : {
    5827           0 :         struct bgp *bgp;
    5828           0 :         bool uj = false;
    5829           0 :         json_object *json = NULL;
    5830             : 
    5831           0 :         bgp = bgp_get_evpn();
    5832           0 :         if (!bgp)
    5833             :                 return CMD_WARNING;
    5834             : 
    5835           0 :         uj = use_json(argc, argv);
    5836           0 :         if (uj)
    5837           0 :                 json = json_object_new_object();
    5838             : 
    5839           0 :         evpn_show_import_rts(vty, bgp, json);
    5840             : 
    5841           0 :         if (uj)
    5842           0 :                 vty_json(vty, json);
    5843             : 
    5844             :         return CMD_SUCCESS;
    5845             : }
    5846             : 
    5847           0 : DEFPY_HIDDEN(test_es_add,
    5848             :       test_es_add_cmd,
    5849             :       "[no$no] test es NAME$esi_str [state NAME$state_str]",
    5850             :       NO_STR
    5851             :       "Test\n"
    5852             :       "Ethernet-segment\n"
    5853             :       "Ethernet-Segment Identifier\n"
    5854             :       "ES link state\n"
    5855             :       "up|down\n"
    5856             : )
    5857             : {
    5858           0 :         int ret = 0;
    5859           0 :         esi_t esi;
    5860           0 :         struct bgp *bgp;
    5861           0 :         struct in_addr vtep_ip;
    5862           0 :         bool oper_up;
    5863             : 
    5864           0 :         bgp = bgp_get_evpn();
    5865           0 :         if (!bgp) {
    5866           0 :                 vty_out(vty, "%% EVPN BGP instance not yet created\n");
    5867           0 :                 return CMD_WARNING;
    5868             :         }
    5869             : 
    5870           0 :         if (!str_to_esi(esi_str, &esi)) {
    5871           0 :                 vty_out(vty, "%% Malformed ESI\n");
    5872           0 :                 return CMD_WARNING;
    5873             :         }
    5874             : 
    5875           0 :         if (no) {
    5876           0 :                 ret = bgp_evpn_local_es_del(bgp, &esi);
    5877           0 :                 if (ret == -1) {
    5878           0 :                         vty_out(vty, "%% Failed to delete ES\n");
    5879           0 :                         return CMD_WARNING;
    5880             :                 }
    5881             :         } else {
    5882           0 :                 if (state_str && !strcmp(state_str, "up"))
    5883             :                         oper_up = true;
    5884             :                 else
    5885           0 :                         oper_up = false;
    5886           0 :                 vtep_ip = bgp->router_id;
    5887             : 
    5888           0 :                 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
    5889             :                                             EVPN_MH_DF_PREF_MIN, false);
    5890           0 :                 if (ret == -1) {
    5891           0 :                         vty_out(vty, "%% Failed to add ES\n");
    5892           0 :                         return CMD_WARNING;
    5893             :                 }
    5894             :         }
    5895             :         return CMD_SUCCESS;
    5896             : }
    5897             : 
    5898           0 : DEFPY_HIDDEN(test_es_vni_add,
    5899             :       test_es_vni_add_cmd,
    5900             :       "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
    5901             :       NO_STR
    5902             :       "Test\n"
    5903             :       "Ethernet-segment\n"
    5904             :       "Ethernet-Segment Identifier\n"
    5905             :       "VNI\n"
    5906             :       "1-16777215\n"
    5907             : )
    5908             : {
    5909           0 :         int ret = 0;
    5910           0 :         esi_t esi;
    5911           0 :         struct bgp *bgp;
    5912             : 
    5913           0 :         bgp = bgp_get_evpn();
    5914           0 :         if (!bgp) {
    5915           0 :                 vty_out(vty, "%% EVPN BGP instance not yet created\n");
    5916           0 :                 return CMD_WARNING;
    5917             :         }
    5918             : 
    5919           0 :         if (!str_to_esi(esi_str, &esi)) {
    5920           0 :                 vty_out(vty, "%% Malformed ESI\n");
    5921           0 :                 return CMD_WARNING;
    5922             :         }
    5923             : 
    5924           0 :         if (no) {
    5925           0 :                 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
    5926           0 :                 if (ret == -1) {
    5927           0 :                         vty_out(vty, "%% Failed to deref ES VNI\n");
    5928           0 :                         return CMD_WARNING;
    5929             :                 }
    5930             :         } else {
    5931           0 :                 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
    5932           0 :                 if (ret == -1) {
    5933           0 :                         vty_out(vty, "%% Failed to ref ES VNI\n");
    5934           0 :                         return CMD_WARNING;
    5935             :                 }
    5936             :         }
    5937             :         return CMD_SUCCESS;
    5938             : }
    5939             : 
    5940             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
    5941             :              "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
    5942             :              "Show VNI\n"
    5943             :              "VNI number\n")
    5944             : 
    5945             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
    5946             :              "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
    5947             :              "Summary of BGP neighbor status\n" JSON_STR)
    5948             : 
    5949             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
    5950             :              "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
    5951             :              SHOW_STR BGP_STR EVPN_HELP_STR
    5952             :              EVPN_RT_HELP_STR
    5953             :              "Display Detailed Information\n"
    5954             :              EVPN_TYPE_HELP_STR
    5955             :              EVPN_TYPE_2_HELP_STR
    5956             :              EVPN_TYPE_2_HELP_STR
    5957             :              EVPN_TYPE_3_HELP_STR
    5958             :              EVPN_TYPE_3_HELP_STR)
    5959             : 
    5960             : ALIAS_HIDDEN(
    5961             :         show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
    5962             :         "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
    5963             :         SHOW_STR BGP_STR EVPN_HELP_STR
    5964             :         EVPN_RT_HELP_STR
    5965             :         EVPN_RT_DIST_HELP_STR
    5966             :         EVPN_ASN_IP_HELP_STR
    5967             :         EVPN_TYPE_HELP_STR
    5968             :         EVPN_TYPE_2_HELP_STR
    5969             :         EVPN_TYPE_2_HELP_STR
    5970             :         EVPN_TYPE_3_HELP_STR
    5971             :         EVPN_TYPE_3_HELP_STR)
    5972             : 
    5973             : ALIAS_HIDDEN(
    5974             :         show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
    5975             :         "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
    5976             :         SHOW_STR BGP_STR EVPN_HELP_STR
    5977             :         EVPN_RT_HELP_STR
    5978             :         EVPN_RT_DIST_HELP_STR
    5979             :         EVPN_ASN_IP_HELP_STR
    5980             :         "MAC\n"
    5981             :         "MAC address (e.g., 00:e0:ec:20:12:62)\n"
    5982             :         "IP\n"
    5983             :         "IP address (IPv4 or IPv6)\n")
    5984             : 
    5985             : ALIAS_HIDDEN(
    5986             :         show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
    5987             :         "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
    5988             :         SHOW_STR BGP_STR EVPN_HELP_STR
    5989             :         EVPN_RT_HELP_STR
    5990             :         "VXLAN Network Identifier\n"
    5991             :         "VNI number\n"
    5992             :         EVPN_TYPE_HELP_STR
    5993             :         EVPN_TYPE_2_HELP_STR
    5994             :         EVPN_TYPE_2_HELP_STR
    5995             :         EVPN_TYPE_3_HELP_STR
    5996             :         EVPN_TYPE_3_HELP_STR
    5997             :         "Remote VTEP\n"
    5998             :         "Remote VTEP IP address\n")
    5999             : 
    6000             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
    6001             :              show_bgp_evpn_route_vni_macip_cmd,
    6002             :              "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
    6003             :              SHOW_STR BGP_STR EVPN_HELP_STR
    6004             :              EVPN_RT_HELP_STR
    6005             :              "VXLAN Network Identifier\n"
    6006             :              "VNI number\n"
    6007             :              "MAC\n"
    6008             :              "MAC address (e.g., 00:e0:ec:20:12:62)\n"
    6009             :              "IP\n"
    6010             :              "IP address (IPv4 or IPv6)\n")
    6011             : 
    6012             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
    6013             :              show_bgp_evpn_route_vni_multicast_cmd,
    6014             :              "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
    6015             :              SHOW_STR BGP_STR EVPN_HELP_STR
    6016             :              EVPN_RT_HELP_STR
    6017             :              "VXLAN Network Identifier\n"
    6018             :              "VNI number\n"
    6019             :              EVPN_TYPE_3_HELP_STR
    6020             :              "Originating Router IP address\n")
    6021             : 
    6022             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
    6023             :              "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
    6024             :              SHOW_STR BGP_STR EVPN_HELP_STR
    6025             :              EVPN_RT_HELP_STR
    6026             :              "VXLAN Network Identifier\n"
    6027             :              "All VNIs\n"
    6028             :              "Print Detailed Output\n"
    6029             :              "Remote VTEP\n"
    6030             :              "Remote VTEP IP address\n")
    6031             : 
    6032             : ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
    6033             :              "show bgp evpn import-rt",
    6034             :              SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
    6035             : 
    6036           0 : DEFUN_NOSH (bgp_evpn_vni,
    6037             :             bgp_evpn_vni_cmd,
    6038             :             "vni " CMD_VNI_RANGE,
    6039             :             "VXLAN Network Identifier\n"
    6040             :             "VNI number\n")
    6041             : {
    6042           0 :         vni_t vni;
    6043           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6044           0 :         struct bgpevpn *vpn;
    6045             : 
    6046           0 :         if (!bgp)
    6047             :                 return CMD_WARNING;
    6048             : 
    6049           0 :         vni = strtoul(argv[1]->arg, NULL, 10);
    6050             : 
    6051             :         /* Create VNI, or mark as configured. */
    6052           0 :         vpn = evpn_create_update_vni(bgp, vni);
    6053           0 :         if (!vpn) {
    6054           0 :                 vty_out(vty, "%% Failed to create VNI \n");
    6055           0 :                 return CMD_WARNING;
    6056             :         }
    6057             : 
    6058           0 :         VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
    6059           0 :         return CMD_SUCCESS;
    6060             : }
    6061             : 
    6062           0 : DEFUN (no_bgp_evpn_vni,
    6063             :        no_bgp_evpn_vni_cmd,
    6064             :        "no vni " CMD_VNI_RANGE,
    6065             :        NO_STR
    6066             :        "VXLAN Network Identifier\n"
    6067             :        "VNI number\n")
    6068             : {
    6069           0 :         vni_t vni;
    6070           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6071           0 :         struct bgpevpn *vpn;
    6072             : 
    6073           0 :         if (!bgp)
    6074             :                 return CMD_WARNING;
    6075             : 
    6076           0 :         vni = strtoul(argv[2]->arg, NULL, 10);
    6077             : 
    6078             :         /* Check if we should disallow. */
    6079           0 :         vpn = bgp_evpn_lookup_vni(bgp, vni);
    6080           0 :         if (!vpn) {
    6081           0 :                 vty_out(vty, "%% Specified VNI does not exist\n");
    6082           0 :                 return CMD_WARNING;
    6083             :         }
    6084           0 :         if (!is_vni_configured(vpn)) {
    6085           0 :                 vty_out(vty, "%% Specified VNI is not configured\n");
    6086           0 :                 return CMD_WARNING;
    6087             :         }
    6088             : 
    6089           0 :         evpn_delete_vni(bgp, vpn);
    6090           0 :         return CMD_SUCCESS;
    6091             : }
    6092             : 
    6093           0 : DEFUN_NOSH (exit_vni,
    6094             :             exit_vni_cmd,
    6095             :             "exit-vni",
    6096             :             "Exit from VNI mode\n")
    6097             : {
    6098           0 :         if (vty->node == BGP_EVPN_VNI_NODE)
    6099           0 :                 vty->node = BGP_EVPN_NODE;
    6100           0 :         return CMD_SUCCESS;
    6101             : }
    6102             : 
    6103           0 : DEFUN (bgp_evpn_vrf_rd,
    6104             :        bgp_evpn_vrf_rd_cmd,
    6105             :        "rd ASN:NN_OR_IP-ADDRESS:NN",
    6106             :        EVPN_RT_DIST_HELP_STR
    6107             :        EVPN_ASN_IP_HELP_STR)
    6108             : {
    6109           0 :         int ret;
    6110           0 :         struct prefix_rd prd;
    6111           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    6112             : 
    6113           0 :         if (!bgp_vrf)
    6114             :                 return CMD_WARNING;
    6115             : 
    6116           0 :         ret = str2prefix_rd(argv[1]->arg, &prd);
    6117           0 :         if (!ret) {
    6118           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    6119           0 :                 return CMD_WARNING;
    6120             :         }
    6121             : 
    6122             :         /* If same as existing value, there is nothing more to do. */
    6123           0 :         if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
    6124             :                 return CMD_SUCCESS;
    6125             : 
    6126             :         /* Configure or update the RD. */
    6127           0 :         evpn_configure_vrf_rd(bgp_vrf, &prd);
    6128           0 :         return CMD_SUCCESS;
    6129             : }
    6130             : 
    6131           0 : DEFUN (no_bgp_evpn_vrf_rd,
    6132             :        no_bgp_evpn_vrf_rd_cmd,
    6133             :        "no rd ASN:NN_OR_IP-ADDRESS:NN",
    6134             :        NO_STR
    6135             :        EVPN_RT_DIST_HELP_STR
    6136             :        EVPN_ASN_IP_HELP_STR)
    6137             : {
    6138           0 :         int ret;
    6139           0 :         struct prefix_rd prd;
    6140           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    6141             : 
    6142           0 :         if (!bgp_vrf)
    6143             :                 return CMD_WARNING;
    6144             : 
    6145           0 :         ret = str2prefix_rd(argv[2]->arg, &prd);
    6146           0 :         if (!ret) {
    6147           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    6148           0 :                 return CMD_WARNING;
    6149             :         }
    6150             : 
    6151             :         /* Check if we should disallow. */
    6152           0 :         if (!is_vrf_rd_configured(bgp_vrf)) {
    6153           0 :                 vty_out(vty, "%% RD is not configured for this VRF\n");
    6154           0 :                 return CMD_WARNING;
    6155             :         }
    6156             : 
    6157           0 :         if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
    6158           0 :                 vty_out(vty,
    6159             :                         "%% RD specified does not match configuration for this VRF\n");
    6160           0 :                 return CMD_WARNING;
    6161             :         }
    6162             : 
    6163           0 :         evpn_unconfigure_vrf_rd(bgp_vrf);
    6164           0 :         return CMD_SUCCESS;
    6165             : }
    6166             : 
    6167           0 : DEFUN (no_bgp_evpn_vrf_rd_without_val,
    6168             :        no_bgp_evpn_vrf_rd_without_val_cmd,
    6169             :        "no rd",
    6170             :        NO_STR
    6171             :        EVPN_RT_DIST_HELP_STR)
    6172             : {
    6173           0 :         struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
    6174             : 
    6175           0 :         if (!bgp_vrf)
    6176             :                 return CMD_WARNING;
    6177             : 
    6178             :         /* Check if we should disallow. */
    6179           0 :         if (!is_vrf_rd_configured(bgp_vrf)) {
    6180           0 :                 vty_out(vty, "%% RD is not configured for this VRF\n");
    6181           0 :                 return CMD_WARNING;
    6182             :         }
    6183             : 
    6184           0 :         evpn_unconfigure_vrf_rd(bgp_vrf);
    6185           0 :         return CMD_SUCCESS;
    6186             : }
    6187             : 
    6188           0 : DEFUN (bgp_evpn_vni_rd,
    6189             :        bgp_evpn_vni_rd_cmd,
    6190             :        "rd ASN:NN_OR_IP-ADDRESS:NN",
    6191             :        EVPN_RT_DIST_HELP_STR
    6192             :        EVPN_ASN_IP_HELP_STR)
    6193             : {
    6194           0 :         struct prefix_rd prd;
    6195           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6196           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    6197           0 :         int ret;
    6198             : 
    6199           0 :         if (!bgp)
    6200             :                 return CMD_WARNING;
    6201             : 
    6202           0 :         if (!EVPN_ENABLED(bgp)) {
    6203           0 :                 vty_out(vty,
    6204             :                         "This command is only supported under EVPN VRF\n");
    6205           0 :                 return CMD_WARNING;
    6206             :         }
    6207             : 
    6208           0 :         ret = str2prefix_rd(argv[1]->arg, &prd);
    6209           0 :         if (!ret) {
    6210           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    6211           0 :                 return CMD_WARNING;
    6212             :         }
    6213             : 
    6214             :         /* If same as existing value, there is nothing more to do. */
    6215           0 :         if (bgp_evpn_rd_matches_existing(vpn, &prd))
    6216             :                 return CMD_SUCCESS;
    6217             : 
    6218             :         /* Configure or update the RD. */
    6219           0 :         evpn_configure_rd(bgp, vpn, &prd);
    6220           0 :         return CMD_SUCCESS;
    6221             : }
    6222             : 
    6223           0 : DEFUN (no_bgp_evpn_vni_rd,
    6224             :        no_bgp_evpn_vni_rd_cmd,
    6225             :        "no rd ASN:NN_OR_IP-ADDRESS:NN",
    6226             :        NO_STR
    6227             :        EVPN_RT_DIST_HELP_STR
    6228             :        EVPN_ASN_IP_HELP_STR)
    6229             : {
    6230           0 :         struct prefix_rd prd;
    6231           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6232           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    6233           0 :         int ret;
    6234             : 
    6235           0 :         if (!bgp)
    6236             :                 return CMD_WARNING;
    6237             : 
    6238           0 :         if (!EVPN_ENABLED(bgp)) {
    6239           0 :                 vty_out(vty,
    6240             :                         "This command is only supported under EVPN VRF\n");
    6241           0 :                 return CMD_WARNING;
    6242             :         }
    6243             : 
    6244           0 :         ret = str2prefix_rd(argv[2]->arg, &prd);
    6245           0 :         if (!ret) {
    6246           0 :                 vty_out(vty, "%% Malformed Route Distinguisher\n");
    6247           0 :                 return CMD_WARNING;
    6248             :         }
    6249             : 
    6250             :         /* Check if we should disallow. */
    6251           0 :         if (!is_rd_configured(vpn)) {
    6252           0 :                 vty_out(vty, "%% RD is not configured for this VNI\n");
    6253           0 :                 return CMD_WARNING;
    6254             :         }
    6255             : 
    6256           0 :         if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
    6257           0 :                 vty_out(vty,
    6258             :                         "%% RD specified does not match configuration for this VNI\n");
    6259           0 :                 return CMD_WARNING;
    6260             :         }
    6261             : 
    6262           0 :         evpn_unconfigure_rd(bgp, vpn);
    6263           0 :         return CMD_SUCCESS;
    6264             : }
    6265             : 
    6266           0 : DEFUN (no_bgp_evpn_vni_rd_without_val,
    6267             :        no_bgp_evpn_vni_rd_without_val_cmd,
    6268             :        "no rd",
    6269             :        NO_STR
    6270             :        EVPN_RT_DIST_HELP_STR)
    6271             : {
    6272           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6273           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    6274             : 
    6275           0 :         if (!bgp)
    6276             :                 return CMD_WARNING;
    6277             : 
    6278           0 :         if (!EVPN_ENABLED(bgp)) {
    6279           0 :                 vty_out(vty,
    6280             :                         "This command is only supported under EVPN VRF\n");
    6281           0 :                 return CMD_WARNING;
    6282             :         }
    6283             : 
    6284             :         /* Check if we should disallow. */
    6285           0 :         if (!is_rd_configured(vpn)) {
    6286           0 :                 vty_out(vty, "%% RD is not configured for this VNI\n");
    6287           0 :                 return CMD_WARNING;
    6288             :         }
    6289             : 
    6290           0 :         evpn_unconfigure_rd(bgp, vpn);
    6291           0 :         return CMD_SUCCESS;
    6292             : }
    6293             : 
    6294             : /*
    6295             :  * Loop over all extended-communities in the route-target list rtl and
    6296             :  * return 1 if we find ecomtarget
    6297             :  */
    6298           0 : static bool bgp_evpn_rt_matches_existing(struct list *rtl,
    6299             :                                          struct ecommunity *ecomtarget)
    6300             : {
    6301           0 :         struct listnode *node;
    6302           0 :         struct ecommunity *ecom;
    6303             : 
    6304           0 :         for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
    6305           0 :                 if (ecommunity_match(ecom, ecomtarget))
    6306             :                         return true;
    6307             :         }
    6308             : 
    6309             :         return false;
    6310             : }
    6311             : 
    6312             : /*
    6313             :  * L3 RT version of above.
    6314             :  */
    6315           0 : static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
    6316             :                                              struct ecommunity *ecomtarget)
    6317             : {
    6318           0 :         struct listnode *node;
    6319           0 :         struct vrf_route_target *l3rt;
    6320             : 
    6321           0 :         for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
    6322           0 :                 if (ecommunity_match(l3rt->ecom, ecomtarget))
    6323             :                         return true;
    6324             :         }
    6325             : 
    6326             :         return false;
    6327             : }
    6328             : 
    6329             : /* display L3VNI related info for a VRF instance */
    6330           0 : DEFUN (show_bgp_vrf_l3vni_info,
    6331             :        show_bgp_vrf_l3vni_info_cmd,
    6332             :        "show bgp vrf VRFNAME vni [json]",
    6333             :        SHOW_STR
    6334             :        BGP_STR
    6335             :        "show bgp vrf\n"
    6336             :        "VRF Name\n"
    6337             :        "L3-VNI\n"
    6338             :        JSON_STR)
    6339             : {
    6340           0 :         char buf[ETHER_ADDR_STRLEN];
    6341           0 :         int idx_vrf = 3;
    6342           0 :         const char *name = NULL;
    6343           0 :         struct bgp *bgp = NULL;
    6344           0 :         struct listnode *node = NULL;
    6345           0 :         struct bgpevpn *vpn = NULL;
    6346           0 :         struct vrf_route_target *l3rt;
    6347           0 :         json_object *json = NULL;
    6348           0 :         json_object *json_vnis = NULL;
    6349           0 :         json_object *json_export_rts = NULL;
    6350           0 :         json_object *json_import_rts = NULL;
    6351           0 :         bool uj = use_json(argc, argv);
    6352             : 
    6353           0 :         if (uj) {
    6354           0 :                 json = json_object_new_object();
    6355           0 :                 json_vnis = json_object_new_array();
    6356           0 :                 json_export_rts = json_object_new_array();
    6357           0 :                 json_import_rts = json_object_new_array();
    6358             :         }
    6359             : 
    6360           0 :         name = argv[idx_vrf]->arg;
    6361           0 :         bgp = bgp_lookup_by_name(name);
    6362           0 :         if (strmatch(name, VRF_DEFAULT_NAME))
    6363           0 :                 bgp = bgp_get_default();
    6364             : 
    6365           0 :         if (!bgp) {
    6366           0 :                 if (!uj)
    6367           0 :                         vty_out(vty, "BGP instance for VRF %s not found\n",
    6368             :                                 name);
    6369             :                 else {
    6370           0 :                         json_object_string_add(json, "warning",
    6371             :                                                "BGP instance not found");
    6372           0 :                         vty_out(vty, "%s\n", json_object_to_json_string(json));
    6373           0 :                         json_object_free(json);
    6374             :                 }
    6375           0 :                 return CMD_WARNING;
    6376             :         }
    6377             : 
    6378           0 :         if (!json) {
    6379           0 :                 vty_out(vty, "BGP VRF: %s\n", name);
    6380           0 :                 vty_out(vty, "  Local-Ip: %pI4\n", &bgp->originator_ip);
    6381           0 :                 vty_out(vty, "  L3-VNI: %u\n", bgp->l3vni);
    6382           0 :                 vty_out(vty, "  Rmac: %s\n",
    6383           0 :                         prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
    6384           0 :                 vty_out(vty, "  VNI Filter: %s\n",
    6385           0 :                         CHECK_FLAG(bgp->vrf_flags,
    6386             :                                    BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
    6387             :                                 ? "prefix-routes-only"
    6388             :                                 : "none");
    6389           0 :                 vty_out(vty, "  L2-VNI List:\n");
    6390           0 :                 vty_out(vty, "    ");
    6391           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
    6392           0 :                         vty_out(vty, "%u  ", vpn->vni);
    6393           0 :                 vty_out(vty, "\n");
    6394           0 :                 vty_out(vty, "  Export-RTs:\n");
    6395           0 :                 vty_out(vty, "    ");
    6396           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
    6397           0 :                         vty_out(vty, "%s  ", ecommunity_str(l3rt->ecom));
    6398           0 :                 vty_out(vty, "\n");
    6399           0 :                 vty_out(vty, "  Import-RTs:\n");
    6400           0 :                 vty_out(vty, "    ");
    6401           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
    6402           0 :                         vty_out(vty, "%s  ", ecommunity_str(l3rt->ecom));
    6403           0 :                 vty_out(vty, "\n");
    6404           0 :                 vty_out(vty, "  RD: %pRD\n", &bgp->vrf_prd);
    6405             :         } else {
    6406           0 :                 json_object_string_add(json, "vrf", name);
    6407           0 :                 json_object_string_addf(json, "local-ip", "%pI4",
    6408             :                                         &bgp->originator_ip);
    6409           0 :                 json_object_int_add(json, "l3vni", bgp->l3vni);
    6410           0 :                 json_object_string_add(
    6411             :                         json, "rmac",
    6412           0 :                         prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
    6413           0 :                 json_object_string_add(
    6414             :                         json, "vniFilter",
    6415           0 :                         CHECK_FLAG(bgp->vrf_flags,
    6416             :                                    BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
    6417             :                                 ? "prefix-routes-only"
    6418             :                                 : "none");
    6419             :                 /* list of l2vnis */
    6420           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
    6421           0 :                         json_object_array_add(json_vnis,
    6422           0 :                                               json_object_new_int(vpn->vni));
    6423           0 :                 json_object_object_add(json, "l2vnis", json_vnis);
    6424             : 
    6425             :                 /* export rts */
    6426           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
    6427           0 :                         json_object_array_add(
    6428             :                                 json_export_rts,
    6429             :                                 json_object_new_string(
    6430           0 :                                         ecommunity_str(l3rt->ecom)));
    6431           0 :                 json_object_object_add(json, "export-rts", json_export_rts);
    6432             : 
    6433             :                 /* import rts */
    6434           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
    6435           0 :                         json_object_array_add(
    6436             :                                 json_import_rts,
    6437             :                                 json_object_new_string(
    6438           0 :                                         ecommunity_str(l3rt->ecom)));
    6439           0 :                 json_object_object_add(json, "import-rts", json_import_rts);
    6440           0 :                 json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
    6441             :         }
    6442             : 
    6443           0 :         if (uj)
    6444           0 :                 vty_json(vty, json);
    6445             :         return CMD_SUCCESS;
    6446             : }
    6447             : 
    6448           0 : static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
    6449             :                   bool is_wildcard)
    6450             : {
    6451             :         /* Do nothing if we already have this route-target */
    6452           0 :         if (is_import) {
    6453           0 :                 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
    6454             :                                                       ecom))
    6455           0 :                         bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
    6456             :                                                              is_wildcard);
    6457             :                 else
    6458             :                         return -1;
    6459             :         } else {
    6460           0 :                 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
    6461             :                                                       ecom))
    6462           0 :                         bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
    6463             :                 else
    6464             :                         return -1;
    6465             :         }
    6466             : 
    6467             :         return 0;
    6468             : }
    6469             : 
    6470           0 : static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
    6471             : {
    6472             :         /* Verify we already have this route-target */
    6473           0 :         if (is_import) {
    6474           0 :                 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
    6475             :                                                       ecom))
    6476             :                         return -1;
    6477             : 
    6478           0 :                 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
    6479             :         } else {
    6480           0 :                 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
    6481             :                                                       ecom))
    6482             :                         return -1;
    6483             : 
    6484           0 :                 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
    6485             :         }
    6486             : 
    6487             :         return 0;
    6488             : }
    6489             : 
    6490           0 : static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
    6491             :                         struct cmd_token **argv, int rt_idx, bool is_add,
    6492             :                         bool is_import)
    6493             : {
    6494           0 :         int ret = CMD_SUCCESS;
    6495           0 :         bool is_wildcard = false;
    6496           0 :         struct ecommunity *ecom = NULL;
    6497             : 
    6498           0 :         for (int i = rt_idx; i < argc; i++) {
    6499           0 :                 is_wildcard = false;
    6500             : 
    6501             :                 /*
    6502             :                  * Special handling for wildcard '*' here.
    6503             :                  *
    6504             :                  * Let's just convert it to 0 here so we dont have to modify
    6505             :                  * the ecommunity parser.
    6506             :                  */
    6507           0 :                 if ((argv[i]->arg)[0] == '*') {
    6508           0 :                         (argv[i]->arg)[0] = '0';
    6509           0 :                         is_wildcard = true;
    6510             :                 }
    6511             : 
    6512           0 :                 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
    6513             :                                           0);
    6514             : 
    6515             :                 /* Put it back as was */
    6516           0 :                 if (is_wildcard)
    6517           0 :                         (argv[i]->arg)[0] = '*';
    6518             : 
    6519           0 :                 if (!ecom) {
    6520           0 :                         vty_out(vty, "%% Malformed Route Target list\n");
    6521           0 :                         ret = CMD_WARNING;
    6522           0 :                         continue;
    6523             :                 }
    6524             : 
    6525           0 :                 ecommunity_str(ecom);
    6526             : 
    6527           0 :                 if (is_add) {
    6528           0 :                         if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
    6529           0 :                                 vty_out(vty,
    6530             :                                         "%% RT specified already configured for this VRF: %s\n",
    6531           0 :                                         argv[i]->arg);
    6532           0 :                                 ecommunity_free(&ecom);
    6533           0 :                                 ret = CMD_WARNING;
    6534             :                         }
    6535             : 
    6536             :                 } else {
    6537           0 :                         if (del_rt(bgp, ecom, is_import) != 0) {
    6538           0 :                                 vty_out(vty,
    6539             :                                         "%% RT specified does not match configuration for this VRF: %s\n",
    6540           0 :                                         argv[i]->arg);
    6541           0 :                                 ret = CMD_WARNING;
    6542             :                         }
    6543             : 
    6544           0 :                         ecommunity_free(&ecom);
    6545             :                 }
    6546             :         }
    6547             : 
    6548           0 :         return ret;
    6549             : }
    6550             : 
    6551             : /* import/export rt for l3vni-vrf */
    6552           0 : DEFUN (bgp_evpn_vrf_rt,
    6553             :        bgp_evpn_vrf_rt_cmd,
    6554             :        "route-target <both|import|export> RTLIST...",
    6555             :        "Route Target\n"
    6556             :        "import and export\n"
    6557             :        "import\n"
    6558             :        "export\n"
    6559             :        "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
    6560             : {
    6561           0 :         int ret = CMD_SUCCESS;
    6562           0 :         int tmp_ret = CMD_SUCCESS;
    6563           0 :         int rt_type;
    6564           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6565             : 
    6566           0 :         if (!bgp)
    6567             :                 return CMD_WARNING_CONFIG_FAILED;
    6568             : 
    6569           0 :         if (!strcmp(argv[1]->arg, "import"))
    6570             :                 rt_type = RT_TYPE_IMPORT;
    6571           0 :         else if (!strcmp(argv[1]->arg, "export"))
    6572             :                 rt_type = RT_TYPE_EXPORT;
    6573           0 :         else if (!strcmp(argv[1]->arg, "both"))
    6574             :                 rt_type = RT_TYPE_BOTH;
    6575             :         else {
    6576           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6577           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6578             :         }
    6579             : 
    6580           0 :         if (strmatch(argv[2]->arg, "auto")) {
    6581           0 :                 vty_out(vty, "%% `auto` cannot be configured via list\n");
    6582           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6583             :         }
    6584             : 
    6585           0 :         if (rt_type != RT_TYPE_IMPORT) {
    6586           0 :                 for (int i = 2; i < argc; i++) {
    6587           0 :                         if ((argv[i]->arg)[0] == '*') {
    6588           0 :                                 vty_out(vty,
    6589             :                                         "%% Wildcard '*' only applicable for import\n");
    6590           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6591             :                         }
    6592             :                 }
    6593             :         }
    6594             : 
    6595             :         /* Add/update the import route-target */
    6596           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
    6597           0 :                 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
    6598             : 
    6599           0 :         if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
    6600           0 :                 ret = tmp_ret;
    6601             : 
    6602           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
    6603           0 :                 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
    6604             : 
    6605           0 :         if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
    6606           0 :                 ret = tmp_ret;
    6607             : 
    6608             :         return ret;
    6609             : }
    6610             : 
    6611           0 : DEFPY (bgp_evpn_vrf_rt_auto,
    6612             :        bgp_evpn_vrf_rt_auto_cmd,
    6613             :        "route-target <both|import|export>$type auto",
    6614             :        "Route Target\n"
    6615             :        "import and export\n"
    6616             :        "import\n"
    6617             :        "export\n"
    6618             :        "Automatically derive route target\n")
    6619             : {
    6620           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6621           0 :         int rt_type;
    6622             : 
    6623           0 :         if (!bgp)
    6624             :                 return CMD_WARNING_CONFIG_FAILED;
    6625             : 
    6626           0 :         if (strmatch(type, "import"))
    6627             :                 rt_type = RT_TYPE_IMPORT;
    6628           0 :         else if (strmatch(type, "export"))
    6629             :                 rt_type = RT_TYPE_EXPORT;
    6630           0 :         else if (strmatch(type, "both"))
    6631             :                 rt_type = RT_TYPE_BOTH;
    6632             :         else {
    6633           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6634           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6635             :         }
    6636             : 
    6637           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
    6638           0 :                 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
    6639             : 
    6640           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
    6641           0 :                 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
    6642             : 
    6643             :         return CMD_SUCCESS;
    6644             : }
    6645             : 
    6646           0 : DEFUN (no_bgp_evpn_vrf_rt,
    6647             :        no_bgp_evpn_vrf_rt_cmd,
    6648             :        "no route-target <both|import|export> RTLIST...",
    6649             :        NO_STR
    6650             :        "Route Target\n"
    6651             :        "import and export\n"
    6652             :        "import\n"
    6653             :        "export\n"
    6654             :        "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
    6655             : {
    6656           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6657           0 :         int ret = CMD_SUCCESS;
    6658           0 :         int tmp_ret = CMD_SUCCESS;
    6659           0 :         int rt_type;
    6660             : 
    6661           0 :         if (!bgp)
    6662             :                 return CMD_WARNING_CONFIG_FAILED;
    6663             : 
    6664           0 :         if (!strcmp(argv[2]->arg, "import"))
    6665             :                 rt_type = RT_TYPE_IMPORT;
    6666           0 :         else if (!strcmp(argv[2]->arg, "export"))
    6667             :                 rt_type = RT_TYPE_EXPORT;
    6668           0 :         else if (!strcmp(argv[2]->arg, "both"))
    6669             :                 rt_type = RT_TYPE_BOTH;
    6670             :         else {
    6671           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6672           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6673             :         }
    6674             : 
    6675           0 :         if (!strcmp(argv[3]->arg, "auto")) {
    6676           0 :                 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
    6677           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6678             :         }
    6679             : 
    6680           0 :         if (rt_type == RT_TYPE_IMPORT) {
    6681           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
    6682           0 :                         vty_out(vty,
    6683             :                                 "%% Import RT is not configured for this VRF\n");
    6684           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6685             :                 }
    6686           0 :         } else if (rt_type == RT_TYPE_EXPORT) {
    6687           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
    6688           0 :                         vty_out(vty,
    6689             :                                 "%% Export RT is not configured for this VRF\n");
    6690           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6691             :                 }
    6692           0 :         } else if (rt_type == RT_TYPE_BOTH) {
    6693           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
    6694           0 :                     && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
    6695           0 :                         vty_out(vty,
    6696             :                                 "%% Import/Export RT is not configured for this VRF\n");
    6697           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6698             :                 }
    6699             :         }
    6700             : 
    6701           0 :         if (rt_type != RT_TYPE_IMPORT) {
    6702           0 :                 for (int i = 3; i < argc; i++) {
    6703           0 :                         if ((argv[i]->arg)[0] == '*') {
    6704           0 :                                 vty_out(vty,
    6705             :                                         "%% Wildcard '*' only applicable for import\n");
    6706           0 :                                 return CMD_WARNING_CONFIG_FAILED;
    6707             :                         }
    6708             :                 }
    6709             :         }
    6710             : 
    6711           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
    6712           0 :                 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
    6713             : 
    6714           0 :         if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
    6715           0 :                 ret = tmp_ret;
    6716             : 
    6717           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
    6718           0 :                 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
    6719             : 
    6720           0 :         if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
    6721           0 :                 ret = tmp_ret;
    6722             : 
    6723             :         return ret;
    6724             : }
    6725             : 
    6726           0 : DEFPY (no_bgp_evpn_vrf_rt_auto,
    6727             :        no_bgp_evpn_vrf_rt_auto_cmd,
    6728             :        "no route-target <both|import|export>$type auto",
    6729             :        NO_STR
    6730             :        "Route Target\n"
    6731             :        "import and export\n"
    6732             :        "import\n"
    6733             :        "export\n"
    6734             :        "Automatically derive route target\n")
    6735             : {
    6736           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6737           0 :         int rt_type;
    6738             : 
    6739           0 :         if (!bgp)
    6740             :                 return CMD_WARNING_CONFIG_FAILED;
    6741             : 
    6742           0 :         if (strmatch(type, "import"))
    6743             :                 rt_type = RT_TYPE_IMPORT;
    6744           0 :         else if (strmatch(type, "export"))
    6745             :                 rt_type = RT_TYPE_EXPORT;
    6746           0 :         else if (strmatch(type, "both"))
    6747             :                 rt_type = RT_TYPE_BOTH;
    6748             :         else {
    6749           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6750           0 :                 return CMD_WARNING_CONFIG_FAILED;
    6751             :         }
    6752             : 
    6753           0 :         if (rt_type == RT_TYPE_IMPORT) {
    6754           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
    6755           0 :                         vty_out(vty,
    6756             :                                 "%% Import AUTO RT is not configured for this VRF\n");
    6757           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6758             :                 }
    6759           0 :         } else if (rt_type == RT_TYPE_EXPORT) {
    6760           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
    6761           0 :                         vty_out(vty,
    6762             :                                 "%% Export AUTO RT is not configured for this VRF\n");
    6763           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6764             :                 }
    6765           0 :         } else if (rt_type == RT_TYPE_BOTH) {
    6766           0 :                 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
    6767             :                     !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
    6768           0 :                         vty_out(vty,
    6769             :                                 "%% Import/Export AUTO RT is not configured for this VRF\n");
    6770           0 :                         return CMD_WARNING_CONFIG_FAILED;
    6771             :                 }
    6772             :         }
    6773             : 
    6774           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
    6775           0 :                 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
    6776             : 
    6777           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
    6778           0 :                 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
    6779             : 
    6780             :         return CMD_SUCCESS;
    6781             : }
    6782             : 
    6783           0 : DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
    6784             :       "[no$no] ead-es-frag evi-limit (1-1000)$limit",
    6785             :       NO_STR
    6786             :       "EAD ES fragment config\n"
    6787             :       "EVIs per-fragment\n"
    6788             :       "limit\n")
    6789             : {
    6790           0 :         bgp_mh_info->evi_per_es_frag =
    6791             :                 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
    6792             : 
    6793           0 :         return CMD_SUCCESS;
    6794             : }
    6795             : 
    6796           0 : DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
    6797             :       "ead-es-route-target export RT",
    6798             :       "EAD ES Route Target\n"
    6799             :       "export\n"
    6800             :       "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
    6801             : {
    6802           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6803           0 :         struct ecommunity *ecomadd = NULL;
    6804             : 
    6805           0 :         if (!bgp)
    6806             :                 return CMD_WARNING;
    6807             : 
    6808           0 :         if (!EVPN_ENABLED(bgp)) {
    6809           0 :                 vty_out(vty, "This command is only supported under EVPN VRF\n");
    6810           0 :                 return CMD_WARNING;
    6811             :         }
    6812             : 
    6813             :         /* Add/update the export route-target */
    6814           0 :         ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
    6815           0 :         if (!ecomadd) {
    6816           0 :                 vty_out(vty, "%% Malformed Route Target list\n");
    6817           0 :                 return CMD_WARNING;
    6818             :         }
    6819           0 :         ecommunity_str(ecomadd);
    6820             : 
    6821             :         /* Do nothing if we already have this export route-target */
    6822           0 :         if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
    6823             :                                           ecomadd))
    6824           0 :                 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
    6825             : 
    6826             :         return CMD_SUCCESS;
    6827             : }
    6828             : 
    6829           0 : DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
    6830             :       "no ead-es-route-target export RT",
    6831             :       NO_STR
    6832             :       "EAD ES Route Target\n"
    6833             :       "export\n" EVPN_ASN_IP_HELP_STR)
    6834             : {
    6835           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6836           0 :         struct ecommunity *ecomdel = NULL;
    6837             : 
    6838           0 :         if (!bgp)
    6839             :                 return CMD_WARNING;
    6840             : 
    6841           0 :         if (!EVPN_ENABLED(bgp)) {
    6842           0 :                 vty_out(vty, "This command is only supported under EVPN VRF\n");
    6843           0 :                 return CMD_WARNING;
    6844             :         }
    6845             : 
    6846           0 :         ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
    6847           0 :         if (!ecomdel) {
    6848           0 :                 vty_out(vty, "%% Malformed Route Target list\n");
    6849           0 :                 return CMD_WARNING;
    6850             :         }
    6851           0 :         ecommunity_str(ecomdel);
    6852             : 
    6853           0 :         if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
    6854             :                                           ecomdel)) {
    6855           0 :                 ecommunity_free(&ecomdel);
    6856           0 :                 vty_out(vty,
    6857             :                         "%% RT specified does not match EAD-ES RT configuration\n");
    6858           0 :                 return CMD_WARNING;
    6859             :         }
    6860           0 :         bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
    6861             : 
    6862           0 :         return CMD_SUCCESS;
    6863             : }
    6864             : 
    6865           0 : DEFUN (bgp_evpn_vni_rt,
    6866             :        bgp_evpn_vni_rt_cmd,
    6867             :        "route-target <both|import|export> RT",
    6868             :        "Route Target\n"
    6869             :        "import and export\n"
    6870             :        "import\n"
    6871             :        "export\n"
    6872             :        "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
    6873             : {
    6874           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6875           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    6876           0 :         int rt_type;
    6877           0 :         struct ecommunity *ecomadd = NULL;
    6878             : 
    6879           0 :         if (!bgp)
    6880             :                 return CMD_WARNING;
    6881             : 
    6882           0 :         if (!EVPN_ENABLED(bgp)) {
    6883           0 :                 vty_out(vty,
    6884             :                         "This command is only supported under EVPN VRF\n");
    6885           0 :                 return CMD_WARNING;
    6886             :         }
    6887             : 
    6888           0 :         if (!strcmp(argv[1]->text, "import"))
    6889             :                 rt_type = RT_TYPE_IMPORT;
    6890           0 :         else if (!strcmp(argv[1]->text, "export"))
    6891             :                 rt_type = RT_TYPE_EXPORT;
    6892           0 :         else if (!strcmp(argv[1]->text, "both"))
    6893             :                 rt_type = RT_TYPE_BOTH;
    6894             :         else {
    6895           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6896           0 :                 return CMD_WARNING;
    6897             :         }
    6898             : 
    6899             :         /* Add/update the import route-target */
    6900           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
    6901             :                 /* Note that first of the two RTs is created for "both" type */
    6902           0 :                 ecomadd = ecommunity_str2com(argv[2]->arg,
    6903             :                                              ECOMMUNITY_ROUTE_TARGET, 0);
    6904           0 :                 if (!ecomadd) {
    6905           0 :                         vty_out(vty, "%% Malformed Route Target list\n");
    6906           0 :                         return CMD_WARNING;
    6907             :                 }
    6908           0 :                 ecommunity_str(ecomadd);
    6909             : 
    6910             :                 /* Do nothing if we already have this import route-target */
    6911           0 :                 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
    6912           0 :                         evpn_configure_import_rt(bgp, vpn, ecomadd);
    6913             :         }
    6914             : 
    6915             :         /* Add/update the export route-target */
    6916           0 :         if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
    6917             :                 /* Note that second of the two RTs is created for "both" type */
    6918           0 :                 ecomadd = ecommunity_str2com(argv[2]->arg,
    6919             :                                              ECOMMUNITY_ROUTE_TARGET, 0);
    6920           0 :                 if (!ecomadd) {
    6921           0 :                         vty_out(vty, "%% Malformed Route Target list\n");
    6922           0 :                         return CMD_WARNING;
    6923             :                 }
    6924           0 :                 ecommunity_str(ecomadd);
    6925             : 
    6926             :                 /* Do nothing if we already have this export route-target */
    6927           0 :                 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
    6928           0 :                         evpn_configure_export_rt(bgp, vpn, ecomadd);
    6929             :         }
    6930             : 
    6931             :         return CMD_SUCCESS;
    6932             : }
    6933             : 
    6934           0 : DEFUN (no_bgp_evpn_vni_rt,
    6935             :        no_bgp_evpn_vni_rt_cmd,
    6936             :        "no route-target <both|import|export> RT",
    6937             :        NO_STR
    6938             :        "Route Target\n"
    6939             :        "import and export\n"
    6940             :        "import\n"
    6941             :        "export\n"
    6942             :        EVPN_ASN_IP_HELP_STR)
    6943             : {
    6944           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    6945           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    6946           0 :         int rt_type, found_ecomdel;
    6947           0 :         struct ecommunity *ecomdel = NULL;
    6948             : 
    6949           0 :         if (!bgp)
    6950             :                 return CMD_WARNING;
    6951             : 
    6952           0 :         if (!EVPN_ENABLED(bgp)) {
    6953           0 :                 vty_out(vty,
    6954             :                         "This command is only supported under EVPN VRF\n");
    6955           0 :                 return CMD_WARNING;
    6956             :         }
    6957             : 
    6958           0 :         if (!strcmp(argv[2]->text, "import"))
    6959             :                 rt_type = RT_TYPE_IMPORT;
    6960           0 :         else if (!strcmp(argv[2]->text, "export"))
    6961             :                 rt_type = RT_TYPE_EXPORT;
    6962           0 :         else if (!strcmp(argv[2]->text, "both"))
    6963             :                 rt_type = RT_TYPE_BOTH;
    6964             :         else {
    6965           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    6966           0 :                 return CMD_WARNING;
    6967             :         }
    6968             : 
    6969             :         /* The user did "no route-target import", check to see if there are any
    6970             :          * import route-targets configured. */
    6971           0 :         if (rt_type == RT_TYPE_IMPORT) {
    6972           0 :                 if (!is_import_rt_configured(vpn)) {
    6973           0 :                         vty_out(vty,
    6974             :                                 "%% Import RT is not configured for this VNI\n");
    6975           0 :                         return CMD_WARNING;
    6976             :                 }
    6977           0 :         } else if (rt_type == RT_TYPE_EXPORT) {
    6978           0 :                 if (!is_export_rt_configured(vpn)) {
    6979           0 :                         vty_out(vty,
    6980             :                                 "%% Export RT is not configured for this VNI\n");
    6981           0 :                         return CMD_WARNING;
    6982             :                 }
    6983           0 :         } else if (rt_type == RT_TYPE_BOTH) {
    6984           0 :                 if (!is_import_rt_configured(vpn)
    6985           0 :                     && !is_export_rt_configured(vpn)) {
    6986           0 :                         vty_out(vty,
    6987             :                                 "%% Import/Export RT is not configured for this VNI\n");
    6988           0 :                         return CMD_WARNING;
    6989             :                 }
    6990             :         }
    6991             : 
    6992           0 :         ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
    6993           0 :         if (!ecomdel) {
    6994           0 :                 vty_out(vty, "%% Malformed Route Target list\n");
    6995           0 :                 return CMD_WARNING;
    6996             :         }
    6997           0 :         ecommunity_str(ecomdel);
    6998             : 
    6999           0 :         if (rt_type == RT_TYPE_IMPORT) {
    7000           0 :                 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
    7001           0 :                         ecommunity_free(&ecomdel);
    7002           0 :                         vty_out(vty,
    7003             :                                 "%% RT specified does not match configuration for this VNI\n");
    7004           0 :                         return CMD_WARNING;
    7005             :                 }
    7006           0 :                 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
    7007           0 :         } else if (rt_type == RT_TYPE_EXPORT) {
    7008           0 :                 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
    7009           0 :                         ecommunity_free(&ecomdel);
    7010           0 :                         vty_out(vty,
    7011             :                                 "%% RT specified does not match configuration for this VNI\n");
    7012           0 :                         return CMD_WARNING;
    7013             :                 }
    7014           0 :                 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
    7015           0 :         } else if (rt_type == RT_TYPE_BOTH) {
    7016           0 :                 found_ecomdel = 0;
    7017             : 
    7018           0 :                 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
    7019           0 :                         evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
    7020           0 :                         found_ecomdel = 1;
    7021             :                 }
    7022             : 
    7023           0 :                 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
    7024           0 :                         evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
    7025           0 :                         found_ecomdel = 1;
    7026             :                 }
    7027             : 
    7028           0 :                 if (!found_ecomdel) {
    7029           0 :                         ecommunity_free(&ecomdel);
    7030           0 :                         vty_out(vty,
    7031             :                                 "%% RT specified does not match configuration for this VNI\n");
    7032           0 :                         return CMD_WARNING;
    7033             :                 }
    7034             :         }
    7035             : 
    7036             :         return CMD_SUCCESS;
    7037             : }
    7038             : 
    7039           0 : DEFUN (no_bgp_evpn_vni_rt_without_val,
    7040             :        no_bgp_evpn_vni_rt_without_val_cmd,
    7041             :        "no route-target <import|export>",
    7042             :        NO_STR
    7043             :        "Route Target\n"
    7044             :        "import\n"
    7045             :        "export\n")
    7046             : {
    7047           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
    7048           0 :         VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
    7049           0 :         int rt_type;
    7050             : 
    7051           0 :         if (!bgp)
    7052             :                 return CMD_WARNING;
    7053             : 
    7054           0 :         if (!EVPN_ENABLED(bgp)) {
    7055           0 :                 vty_out(vty,
    7056             :                         "This command is only supported under EVPN VRF\n");
    7057           0 :                 return CMD_WARNING;
    7058             :         }
    7059             : 
    7060           0 :         if (!strcmp(argv[2]->text, "import")) {
    7061             :                 rt_type = RT_TYPE_IMPORT;
    7062           0 :         } else if (!strcmp(argv[2]->text, "export")) {
    7063             :                 rt_type = RT_TYPE_EXPORT;
    7064             :         } else {
    7065           0 :                 vty_out(vty, "%% Invalid Route Target type\n");
    7066           0 :                 return CMD_WARNING;
    7067             :         }
    7068             : 
    7069             :         /* Check if we should disallow. */
    7070           0 :         if (rt_type == RT_TYPE_IMPORT) {
    7071           0 :                 if (!is_import_rt_configured(vpn)) {
    7072           0 :                         vty_out(vty,
    7073             :                                 "%% Import RT is not configured for this VNI\n");
    7074           0 :                         return CMD_WARNING;
    7075             :                 }
    7076             :         } else {
    7077           0 :                 if (!is_export_rt_configured(vpn)) {
    7078           0 :                         vty_out(vty,
    7079             :                                 "%% Export RT is not configured for this VNI\n");
    7080           0 :                         return CMD_WARNING;
    7081             :                 }
    7082             :         }
    7083             : 
    7084             :         /* Unconfigure the RT. */
    7085           0 :         if (rt_type == RT_TYPE_IMPORT)
    7086           0 :                 evpn_unconfigure_import_rt(bgp, vpn, NULL);
    7087             :         else
    7088           0 :                 evpn_unconfigure_export_rt(bgp, vpn, NULL);
    7089             :         return CMD_SUCCESS;
    7090             : }
    7091             : 
    7092           0 : static int vni_cmp(const void **a, const void **b)
    7093             : {
    7094           0 :         const struct bgpevpn *first = *a;
    7095           0 :         const struct bgpevpn *secnd = *b;
    7096             : 
    7097           0 :         return secnd->vni - first->vni;
    7098             : }
    7099             : 
    7100             : /*
    7101             :  * Output EVPN configuration information.
    7102             :  */
    7103           0 : void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
    7104             :                                 safi_t safi)
    7105             : {
    7106           0 :         if (bgp->advertise_all_vni)
    7107           0 :                 vty_out(vty, "  advertise-all-vni\n");
    7108             : 
    7109           0 :         if (hashcount(bgp->vnihash)) {
    7110           0 :                 struct list *vnilist = hash_to_list(bgp->vnihash);
    7111           0 :                 struct listnode *ln;
    7112           0 :                 struct bgpevpn *data;
    7113             : 
    7114           0 :                 list_sort(vnilist, vni_cmp);
    7115           0 :                 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
    7116           0 :                         write_vni_config(vty, data);
    7117             : 
    7118           0 :                 list_delete(&vnilist);
    7119             :         }
    7120             : 
    7121           0 :         if (bgp->advertise_autort_rfc8365)
    7122           0 :                 vty_out(vty, "  autort rfc8365-compatible\n");
    7123             : 
    7124           0 :         if (bgp->advertise_gw_macip)
    7125           0 :                 vty_out(vty, "  advertise-default-gw\n");
    7126             : 
    7127           0 :         if (bgp->evpn_info->advertise_svi_macip)
    7128           0 :                 vty_out(vty, "  advertise-svi-ip\n");
    7129             : 
    7130           0 :         if (bgp->resolve_overlay_index)
    7131           0 :                 vty_out(vty, "  enable-resolve-overlay-index\n");
    7132             : 
    7133           0 :         if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
    7134           0 :                 vty_out(vty, "  ead-es-frag evi-limit %u\n",
    7135             :                         bgp_mh_info->evi_per_es_frag);
    7136             : 
    7137           0 :         if (bgp_mh_info->host_routes_use_l3nhg !=
    7138             :                         BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
    7139           0 :                 if (bgp_mh_info->host_routes_use_l3nhg)
    7140             :                         vty_out(vty, "  use-es-l3nhg\n");
    7141             :                 else
    7142           0 :                         vty_out(vty, "  no use-es-l3nhg\n");
    7143             :         }
    7144             : 
    7145           0 :         if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
    7146           0 :                 if (bgp_mh_info->ead_evi_rx)
    7147             :                         vty_out(vty, "  no disable-ead-evi-rx\n");
    7148             :                 else
    7149           0 :                         vty_out(vty, "  disable-ead-evi-rx\n");
    7150             :         }
    7151             : 
    7152           0 :         if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
    7153           0 :                 if (bgp_mh_info->ead_evi_tx)
    7154             :                         vty_out(vty, "  no disable-ead-evi-tx\n");
    7155             :                 else
    7156           0 :                         vty_out(vty, "  disable-ead-evi-tx\n");
    7157             :         }
    7158             : 
    7159           0 :         if (!bgp->evpn_info->dup_addr_detect)
    7160           0 :                 vty_out(vty, "  no dup-addr-detection\n");
    7161             : 
    7162           0 :         if (bgp->evpn_info->dad_max_moves !=
    7163           0 :                 EVPN_DAD_DEFAULT_MAX_MOVES ||
    7164           0 :                 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
    7165           0 :                 vty_out(vty, "  dup-addr-detection max-moves %u time %u\n",
    7166             :                         bgp->evpn_info->dad_max_moves,
    7167             :                         bgp->evpn_info->dad_time);
    7168             : 
    7169           0 :         if (bgp->evpn_info->dad_freeze) {
    7170           0 :                 if (bgp->evpn_info->dad_freeze_time)
    7171           0 :                         vty_out(vty,
    7172             :                                 "  dup-addr-detection freeze %u\n",
    7173             :                                 bgp->evpn_info->dad_freeze_time);
    7174             :                 else
    7175           0 :                         vty_out(vty,
    7176             :                                 "  dup-addr-detection freeze permanent\n");
    7177             :         }
    7178             : 
    7179           0 :         if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
    7180           0 :                 vty_out(vty, "  flooding disable\n");
    7181             : 
    7182           0 :         if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7183             :                        BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
    7184           0 :                 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
    7185           0 :                         vty_out(vty, "  advertise ipv4 unicast route-map %s\n",
    7186             :                                 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
    7187             :                 else
    7188           0 :                         vty_out(vty,
    7189             :                                 "  advertise ipv4 unicast\n");
    7190           0 :         } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7191             :                    BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
    7192           0 :                 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
    7193           0 :                         vty_out(vty,
    7194             :                                 "  advertise ipv4 unicast gateway-ip route-map %s\n",
    7195             :                                 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
    7196             :                 else
    7197           0 :                         vty_out(vty, "  advertise ipv4 unicast gateway-ip\n");
    7198             :         }
    7199             : 
    7200             :         /* EAD ES export route-target */
    7201           0 :         if (listcount(bgp_mh_info->ead_es_export_rtl)) {
    7202           0 :                 struct ecommunity *ecom;
    7203           0 :                 char *ecom_str;
    7204           0 :                 struct listnode *node;
    7205             : 
    7206           0 :                 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
    7207             :                                           ecom)) {
    7208             : 
    7209           0 :                         ecom_str = ecommunity_ecom2str(
    7210             :                                 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    7211           0 :                         vty_out(vty, "  ead-es-route-target export %s\n",
    7212             :                                 ecom_str);
    7213           0 :                         XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    7214             :                 }
    7215             :         }
    7216             : 
    7217           0 :         if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7218             :                        BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
    7219           0 :                 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
    7220           0 :                         vty_out(vty,
    7221             :                                 "  advertise ipv6 unicast route-map %s\n",
    7222             :                                 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
    7223             :                 else
    7224           0 :                         vty_out(vty,
    7225             :                                 "  advertise ipv6 unicast\n");
    7226           0 :         } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7227             :                               BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
    7228           0 :                 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
    7229           0 :                         vty_out(vty,
    7230             :                                 "  advertise ipv6 unicast gateway-ip route-map %s\n",
    7231             :                                 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
    7232             :                 else
    7233           0 :                         vty_out(vty, "  advertise ipv6 unicast gateway-ip\n");
    7234             :         }
    7235             : 
    7236           0 :         if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7237             :                        BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
    7238           0 :                 vty_out(vty, "  default-originate ipv4\n");
    7239             : 
    7240           0 :         if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
    7241             :                        BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
    7242           0 :                 vty_out(vty, "  default-originate ipv6\n");
    7243             : 
    7244           0 :         if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
    7245           0 :                 if (!bgp->evpn_info->advertise_pip)
    7246           0 :                         vty_out(vty, "  no advertise-pip\n");
    7247           0 :                 if (bgp->evpn_info->advertise_pip) {
    7248           0 :                         if (bgp->evpn_info->pip_ip_static.s_addr
    7249             :                             != INADDR_ANY) {
    7250           0 :                                 vty_out(vty, "  advertise-pip ip %pI4",
    7251             :                                         &bgp->evpn_info->pip_ip_static);
    7252           0 :                                 if (!is_zero_mac(&(
    7253           0 :                                             bgp->evpn_info->pip_rmac_static))) {
    7254           0 :                                         char buf[ETHER_ADDR_STRLEN];
    7255             : 
    7256           0 :                                         vty_out(vty, " mac %s",
    7257             :                                                 prefix_mac2str(
    7258           0 :                                                         &bgp->evpn_info
    7259             :                                                                  ->pip_rmac,
    7260             :                                                         buf, sizeof(buf)));
    7261             :                                 }
    7262           0 :                                 vty_out(vty, "\n");
    7263             :                         }
    7264             :                 }
    7265             :         }
    7266           0 :         if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
    7267           0 :                 vty_out(vty, "  rd %pRD\n", &bgp->vrf_prd);
    7268             : 
    7269             :         /* import route-target */
    7270           0 :         if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
    7271           0 :                 char *ecom_str;
    7272           0 :                 struct listnode *node, *nnode;
    7273           0 :                 struct vrf_route_target *l3rt;
    7274             : 
    7275           0 :                 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
    7276             :                                        l3rt)) {
    7277             : 
    7278           0 :                         if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
    7279           0 :                                 continue;
    7280             : 
    7281           0 :                         ecom_str = ecommunity_ecom2str(
    7282             :                                 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    7283             : 
    7284           0 :                         if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
    7285           0 :                                 char *vni_str = NULL;
    7286             : 
    7287           0 :                                 vni_str = strchr(ecom_str, ':');
    7288           0 :                                 if (!vni_str) {
    7289           0 :                                         XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    7290           0 :                                         continue;
    7291             :                                 }
    7292             : 
    7293             :                                 /* Move pointer to vni */
    7294           0 :                                 vni_str += 1;
    7295             : 
    7296           0 :                                 vty_out(vty, "  route-target import *:%s\n",
    7297             :                                         vni_str);
    7298             : 
    7299             :                         } else
    7300           0 :                                 vty_out(vty, "  route-target import %s\n",
    7301             :                                         ecom_str);
    7302             : 
    7303           0 :                         XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    7304             :                 }
    7305             :         }
    7306             : 
    7307             :         /* import route-target auto */
    7308           0 :         if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
    7309           0 :                 vty_out(vty, "  route-target import auto\n");
    7310             : 
    7311             :         /* export route-target */
    7312           0 :         if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
    7313           0 :                 char *ecom_str;
    7314           0 :                 struct listnode *node, *nnode;
    7315           0 :                 struct vrf_route_target *l3rt;
    7316             : 
    7317           0 :                 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
    7318             :                                        l3rt)) {
    7319             : 
    7320           0 :                         if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
    7321           0 :                                 continue;
    7322             : 
    7323           0 :                         ecom_str = ecommunity_ecom2str(
    7324             :                                 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    7325           0 :                         vty_out(vty, "  route-target export %s\n", ecom_str);
    7326           0 :                         XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
    7327             :                 }
    7328             :         }
    7329             : 
    7330             :         /* export route-target auto */
    7331           0 :         if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
    7332           0 :                 vty_out(vty, "  route-target export auto\n");
    7333           0 : }
    7334             : 
    7335           2 : void bgp_ethernetvpn_init(void)
    7336             : {
    7337           2 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
    7338           2 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
    7339           2 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
    7340           2 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
    7341           2 :         install_element(VIEW_NODE,
    7342             :                         &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
    7343           2 :         install_element(VIEW_NODE,
    7344             :                         &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
    7345           2 :         install_element(
    7346             :                 VIEW_NODE,
    7347             :                 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
    7348           2 :         install_element(
    7349             :                 VIEW_NODE,
    7350             :                 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
    7351           2 :         install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
    7352           2 :         install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
    7353           2 :         install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
    7354           2 :         install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
    7355           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
    7356           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
    7357           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
    7358           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
    7359           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
    7360           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
    7361           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
    7362           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
    7363           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
    7364           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
    7365           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
    7366           2 :         install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
    7367           2 :         install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
    7368           2 :         install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
    7369           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
    7370           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
    7371           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
    7372           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
    7373           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
    7374           2 :         install_element(BGP_EVPN_NODE,
    7375             :                         &bgp_evpn_enable_resolve_overlay_index_cmd);
    7376             : 
    7377             :         /* test commands */
    7378           2 :         install_element(BGP_EVPN_NODE, &test_es_add_cmd);
    7379           2 :         install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
    7380             : 
    7381             :         /* "show bgp l2vpn evpn" commands. */
    7382           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
    7383           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
    7384           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
    7385           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
    7386           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
    7387           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
    7388           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
    7389           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
    7390           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
    7391           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
    7392           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
    7393           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
    7394           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
    7395           2 :         install_element(VIEW_NODE,
    7396             :                         &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
    7397           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
    7398           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
    7399           2 :         install_element(VIEW_NODE,
    7400             :                         &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
    7401           2 :         install_element(VIEW_NODE,
    7402             :                         &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
    7403           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
    7404           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
    7405             : 
    7406             :         /* "show bgp vni" commands. */
    7407           2 :         install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
    7408           2 :         install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
    7409           2 :         install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
    7410           2 :         install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
    7411           2 :         install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
    7412           2 :         install_element(VIEW_NODE, &show_bgp_vni_cmd);
    7413           2 :         install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
    7414           2 :         install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
    7415           2 :         install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
    7416           2 :         install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
    7417           2 :         install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
    7418           2 :         install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
    7419             : 
    7420             :         /* "show bgp evpn" commands. */
    7421           2 :         install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
    7422           2 :         install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
    7423           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
    7424           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
    7425           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
    7426           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
    7427           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
    7428           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
    7429           2 :         install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
    7430           2 :         install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
    7431           2 :         install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
    7432           2 :         install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
    7433             : 
    7434           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
    7435           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
    7436           2 :         install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
    7437           2 :         install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
    7438           2 :         install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
    7439           2 :         install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
    7440           2 :         install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
    7441           2 :         install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
    7442           2 :         install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
    7443           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
    7444           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
    7445           2 :         install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
    7446           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
    7447           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
    7448           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
    7449           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
    7450           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
    7451           2 :         install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
    7452           2 :         install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
    7453           2 :         install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
    7454           2 :         install_element(BGP_EVPN_VNI_NODE,
    7455             :                         &bgp_evpn_advertise_default_gw_vni_cmd);
    7456           2 :         install_element(BGP_EVPN_VNI_NODE,
    7457             :                         &no_bgp_evpn_advertise_default_gw_vni_cmd);
    7458           2 :         install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
    7459           2 :         install_element(BGP_EVPN_VNI_NODE,
    7460             :                         &no_bgp_evpn_advertise_vni_subnet_cmd);
    7461           2 : }

Generated by: LCOV version v1.16-topotato