]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
Merge pull request #7270 from donaldsharp/isis_cleanup
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
CommitLineData
784d3a42 1/* Ethernet-VPN Packet and vty Processing File
896014f4
DL
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 */
784d3a42
PG
20
21#include <zebra.h>
22#include "command.h"
23#include "prefix.h"
24#include "lib/json.h"
937652c6 25#include "stream.h"
784d3a42
PG
26
27#include "bgpd/bgpd.h"
28#include "bgpd/bgp_table.h"
29#include "bgpd/bgp_attr.h"
30#include "bgpd/bgp_route.h"
31#include "bgpd/bgp_mplsvpn.h"
32#include "bgpd/bgp_vpn.h"
33#include "bgpd/bgp_evpn_vty.h"
3da6fcd5 34#include "bgpd/bgp_evpn.h"
7724c0a1 35#include "bgpd/bgp_evpn_private.h"
185fb14a 36#include "bgpd/bgp_evpn_mh.h"
7724c0a1 37#include "bgpd/bgp_zebra.h"
520d5d76 38#include "bgpd/bgp_vty.h"
14454c9f 39#include "bgpd/bgp_errors.h"
5a0ccebf 40#include "bgpd/bgp_ecommunity.h"
7f433a5e
LK
41#include "bgpd/bgp_lcommunity.h"
42#include "bgpd/bgp_community.h"
784d3a42 43
784d3a42
PG
44#define SHOW_DISPLAY_STANDARD 0
45#define SHOW_DISPLAY_TAGS 1
46#define SHOW_DISPLAY_OVERLAY 2
60466a63 47#define VNI_STR_LEN 32
784d3a42 48
520d5d76 49/*
50 * Context for VNI hash walk - used by callbacks.
51 */
d62a17ae 52struct vni_walk_ctx {
53 struct bgp *bgp;
54 struct vty *vty;
55 struct in_addr vtep_ip;
9c92b5f7 56 json_object *json;
c7ef6cf2 57 int detail;
520d5d76 58};
59
996c9314 60static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
10ebe1ab
MK
61 json_object *json)
62{
1be1693e 63 const uint8_t *pnt;
d7c0a89a 64 uint8_t type, sub_type;
10ebe1ab
MK
65 struct ecommunity_as eas;
66 struct ecommunity_ip eip;
67 struct listnode *node, *nnode;
68 struct bgp *tmp_bgp_vrf = NULL;
69 json_object *json_rt = NULL;
70 json_object *json_vrfs = NULL;
71 char rt_buf[RT_ADDRSTRLEN];
72
73 if (json) {
74 json_rt = json_object_new_object();
75 json_vrfs = json_object_new_array();
76 }
77
d7c0a89a 78 pnt = (uint8_t *)&irt->rt.val;
10ebe1ab
MK
79 type = *pnt++;
80 sub_type = *pnt++;
81 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
82 return;
83
84 memset(&eas, 0, sizeof(eas));
85 switch (type) {
86 case ECOMMUNITY_ENCODE_AS:
87 eas.as = (*pnt++ << 8);
88 eas.as |= (*pnt++);
100cb793 89 ptr_get_be32(pnt, &eas.val);
10ebe1ab 90
772270f3 91 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
10ebe1ab
MK
92
93 if (json)
94 json_object_string_add(json_rt, "rt", rt_buf);
95 else
96 vty_out(vty, "Route-target: %s", rt_buf);
97
98 break;
99
100 case ECOMMUNITY_ENCODE_IP:
101 memcpy(&eip.ip, pnt, 4);
102 pnt += 4;
103 eip.val = (*pnt++ << 8);
104 eip.val |= (*pnt++);
105
772270f3 106 snprintf(rt_buf, sizeof(rt_buf), "%s:%u", inet_ntoa(eip.ip),
10ebe1ab
MK
107 eip.val);
108
109 if (json)
110 json_object_string_add(json_rt, "rt", rt_buf);
111 else
112 vty_out(vty, "Route-target: %s", rt_buf);
113
114 break;
115
116 case ECOMMUNITY_ENCODE_AS4:
117 pnt = ptr_get_be32(pnt, &eas.val);
118 eas.val = (*pnt++ << 8);
119 eas.val |= (*pnt++);
120
772270f3 121 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
10ebe1ab
MK
122
123 if (json)
124 json_object_string_add(json_rt, "rt", rt_buf);
125 else
126 vty_out(vty, "Route-target: %s", rt_buf);
127
128 break;
129
130 default:
131 return;
132 }
133
134 if (!json) {
135 vty_out(vty,
136 "\nList of VRFs importing routes with this route-target:\n");
137 }
138
139 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
140 if (json)
141 json_object_array_add(
142 json_vrfs,
143 json_object_new_string(
996c9314 144 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
10ebe1ab
MK
145 else
146 vty_out(vty, " %s\n",
147 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
148 }
149
150 if (json) {
151 json_object_object_add(json_rt, "vrfs", json_vrfs);
152 json_object_object_add(json, rt_buf, json_rt);
153 }
154}
155
e3b78da8 156static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
10ebe1ab
MK
157{
158 json_object *json = NULL;
159 struct vty *vty = NULL;
e3b78da8 160 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
10ebe1ab 161
181c08c6
MK
162 vty = (struct vty *)args[0];
163 json = (struct json_object *)args[1];
10ebe1ab
MK
164
165 display_vrf_import_rt(vty, irt, json);
166}
167
9c92b5f7
MK
168static void display_import_rt(struct vty *vty, struct irt_node *irt,
169 json_object *json)
d62a17ae 170{
1be1693e 171 const uint8_t *pnt;
d7c0a89a 172 uint8_t type, sub_type;
5a0ccebf
QY
173 struct ecommunity_as eas;
174 struct ecommunity_ip eip;
d62a17ae 175 struct listnode *node, *nnode;
176 struct bgpevpn *tmp_vpn;
9c92b5f7
MK
177 json_object *json_rt = NULL;
178 json_object *json_vnis = NULL;
179 char rt_buf[RT_ADDRSTRLEN];
d62a17ae 180
9c92b5f7 181 if (json) {
b682f6de 182 json_rt = json_object_new_object();
183 json_vnis = json_object_new_array();
9c92b5f7 184 }
d62a17ae 185
186 /* TODO: This needs to go into a function */
187
d7c0a89a 188 pnt = (uint8_t *)&irt->rt.val;
d62a17ae 189 type = *pnt++;
190 sub_type = *pnt++;
191 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
192 return;
193
88a837f6 194 memset(&eas, 0, sizeof(eas));
d62a17ae 195 switch (type) {
196 case ECOMMUNITY_ENCODE_AS:
197 eas.as = (*pnt++ << 8);
198 eas.as |= (*pnt++);
100cb793 199 ptr_get_be32(pnt, &eas.val);
d62a17ae 200
772270f3 201 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
9c92b5f7
MK
202
203 if (json)
204 json_object_string_add(json_rt, "rt", rt_buf);
205 else
206 vty_out(vty, "Route-target: %s", rt_buf);
207
d62a17ae 208 break;
209
210 case ECOMMUNITY_ENCODE_IP:
211 memcpy(&eip.ip, pnt, 4);
212 pnt += 4;
213 eip.val = (*pnt++ << 8);
214 eip.val |= (*pnt++);
215
772270f3 216 snprintf(rt_buf, sizeof(rt_buf), "%s:%u", inet_ntoa(eip.ip),
9c92b5f7
MK
217 eip.val);
218
219 if (json)
220 json_object_string_add(json_rt, "rt", rt_buf);
221 else
222 vty_out(vty, "Route-target: %s", rt_buf);
223
d62a17ae 224 break;
225
226 case ECOMMUNITY_ENCODE_AS4:
937652c6 227 pnt = ptr_get_be32(pnt, &eas.val);
d62a17ae 228 eas.val = (*pnt++ << 8);
229 eas.val |= (*pnt++);
230
772270f3 231 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
9c92b5f7
MK
232
233 if (json)
234 json_object_string_add(json_rt, "rt", rt_buf);
235 else
236 vty_out(vty, "Route-target: %s", rt_buf);
237
d62a17ae 238 break;
239
240 default:
241 return;
242 }
243
9c92b5f7
MK
244 if (!json) {
245 vty_out(vty,
246 "\nList of VNIs importing routes with this route-target:\n");
247 }
248
249 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
250 if (json)
251 json_object_array_add(
f00ba699 252 json_vnis, json_object_new_int(tmp_vpn->vni));
9c92b5f7
MK
253 else
254 vty_out(vty, " %u\n", tmp_vpn->vni);
255 }
256
257 if (json) {
258 json_object_object_add(json_rt, "vnis", json_vnis);
259 json_object_object_add(json, rt_buf, json_rt);
260 }
d62a17ae 261}
262
e3b78da8 263static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
520d5d76 264{
9c92b5f7
MK
265 json_object *json = NULL;
266 struct vty *vty = NULL;
e3b78da8 267 struct irt_node *irt = (struct irt_node *)bucket->data;
9c92b5f7
MK
268
269 vty = args[0];
270 json = args[1];
271
dff8f48d 272 display_import_rt(vty, irt, json);
9c92b5f7
MK
273
274 return;
d62a17ae 275}
520d5d76 276
d62a17ae 277static void bgp_evpn_show_route_rd_header(struct vty *vty,
9bcb3eef
DS
278 struct bgp_dest *rd_dest,
279 json_object *json, char *rd_str,
280 int len)
d62a17ae 281{
d7c0a89a 282 uint16_t type;
d62a17ae 283 struct rd_as rd_as;
284 struct rd_ip rd_ip;
b54892e0 285 const uint8_t *pnt;
9bcb3eef 286 const struct prefix *p = bgp_dest_get_prefix(rd_dest);
520d5d76 287
b54892e0 288 pnt = p->u.val;
520d5d76 289
d62a17ae 290 /* Decode RD type. */
291 type = decode_rd_type(pnt);
520d5d76 292
c69e79f1
LK
293 if (!json)
294 vty_out(vty, "Route Distinguisher: ");
520d5d76 295
d62a17ae 296 switch (type) {
297 case RD_TYPE_AS:
298 decode_rd_as(pnt + 2, &rd_as);
c69e79f1
LK
299 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
300 if (json)
301 json_object_string_add(json, "rd", rd_str);
302 else
527fd6de 303 vty_out(vty, "%s\n", rd_str);
c69e79f1
LK
304 break;
305
306 case RD_TYPE_AS4:
307 decode_rd_as4(pnt + 2, &rd_as);
308 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
309 if (json)
310 json_object_string_add(json, "rd", rd_str);
311 else
527fd6de 312 vty_out(vty, "%s\n", rd_str);
d62a17ae 313 break;
520d5d76 314
d62a17ae 315 case RD_TYPE_IP:
316 decode_rd_ip(pnt + 2, &rd_ip);
c69e79f1 317 snprintf(rd_str, len, "%s:%d", inet_ntoa(rd_ip.ip),
9c92b5f7 318 rd_ip.val);
c69e79f1
LK
319 if (json)
320 json_object_string_add(json, "rd", rd_str);
321 else
527fd6de 322 vty_out(vty, "%s\n", rd_str);
d62a17ae 323 break;
520d5d76 324
d62a17ae 325 default:
c69e79f1
LK
326 if (json) {
327 snprintf(rd_str, len, "Unknown");
328 json_object_string_add(json, "rd", rd_str);
329 } else {
330 snprintf(rd_str, len, "Unknown RD type");
527fd6de 331 vty_out(vty, "%s\n", rd_str);
c69e79f1 332 }
d62a17ae 333 break;
334 }
d62a17ae 335}
336
9c92b5f7 337static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
2dd32217 338 uint64_t tbl_ver, json_object *json)
d62a17ae 339{
340 char ri_header[] =
341 " Network Next Hop Metric LocPrf Weight Path\n";
520d5d76 342
9c92b5f7
MK
343 if (json)
344 return;
345
2dd32217 346 vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n",
347 tbl_ver, inet_ntoa(bgp->router_id));
d62a17ae 348 vty_out(vty,
3efd0893 349 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
d62a17ae 350 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
b5e140c8
AK
351 vty_out(vty,
352 "EVPN type-1 prefix: [1]:[ESI]:[EthTag]:[IPlen]:[VTEP-IP]\n");
d62a17ae 353 vty_out(vty,
554cd77a 354 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
b3628c70 355 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
50f74cf1 356 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
554cd77a 357 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
d62a17ae 358 vty_out(vty, "%s", ri_header);
359}
520d5d76 360
4cce389e
MK
361static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
362 json_object *json)
363{
364 char buf1[INET6_ADDRSTRLEN];
365 char *ecom_str;
366 struct listnode *node, *nnode;
367 struct ecommunity *ecom;
368 json_object *json_import_rtl = NULL;
369 json_object *json_export_rtl = NULL;
23c7421d 370 char buf2[ETHER_ADDR_STRLEN];
4cce389e
MK
371
372 json_import_rtl = json_export_rtl = 0;
373
374 if (json) {
375 json_import_rtl = json_object_new_array();
376 json_export_rtl = json_object_new_array();
377 json_object_int_add(json, "vni", bgp_vrf->l3vni);
378 json_object_string_add(json, "type", "L3");
37ae1adb 379 json_object_string_add(json, "inKernel", "True");
4cce389e
MK
380 json_object_string_add(
381 json, "rd",
382 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
383 json_object_string_add(json, "originatorIp",
384 inet_ntoa(bgp_vrf->originator_ip));
385 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
0b509723 386 json_object_string_add(json, "advertiseSviMacIp", "n/a");
cbdbb1ca
CS
387 json_object_to_json_string_ext(json,
388 JSON_C_TO_STRING_NOSLASHESCAPE);
23c7421d
CS
389 json_object_string_add(json, "advertisePip",
390 bgp_vrf->evpn_info->advertise_pip ?
391 "Enabled" : "Disabled");
392 json_object_string_add(json, "sysIP",
1c97c9fd
CS
393 inet_ntop(AF_INET,
394 &bgp_vrf->evpn_info->pip_ip,
395 buf1, INET_ADDRSTRLEN));
23c7421d
CS
396 json_object_string_add(json, "sysMac",
397 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
398 buf2, sizeof(buf2)));
399 json_object_string_add(json, "rmac",
400 prefix_mac2str(&bgp_vrf->rmac,
401 buf2, sizeof(buf2)));
4cce389e
MK
402 } else {
403 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
404 vty_out(vty, " (known to the kernel)");
405 vty_out(vty, "\n");
406
407 vty_out(vty, " Type: %s\n", "L3");
408 vty_out(vty, " Tenant VRF: %s\n",
409 vrf_id_to_name(bgp_vrf->vrf_id));
410 vty_out(vty, " RD: %s\n",
411 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
412 vty_out(vty, " Originator IP: %s\n",
413 inet_ntoa(bgp_vrf->originator_ip));
414 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
cbdbb1ca 415 vty_out(vty, " Advertise-svi-macip : %s\n", "n/a");
23c7421d
CS
416 vty_out(vty, " Advertise-pip: %s\n",
417 bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
418 vty_out(vty, " System-IP: %s\n",
1c97c9fd
CS
419 inet_ntop(AF_INET, &bgp_vrf->evpn_info->pip_ip,
420 buf1, INET_ADDRSTRLEN));
23c7421d
CS
421 vty_out(vty, " System-MAC: %s\n",
422 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
423 buf2, sizeof(buf2)));
424 vty_out(vty, " Router-MAC: %s\n",
425 prefix_mac2str(&bgp_vrf->rmac,
426 buf2, sizeof(buf2)));
4cce389e
MK
427 }
428
429 if (!json)
430 vty_out(vty, " Import Route Target:\n");
431
432 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) {
433 ecom_str = ecommunity_ecom2str(ecom,
434 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
435
436 if (json)
437 json_object_array_add(json_import_rtl,
438 json_object_new_string(ecom_str));
439 else
440 vty_out(vty, " %s\n", ecom_str);
441
442 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
443 }
444
445 if (json)
446 json_object_object_add(json, "importRts", json_import_rtl);
447 else
448 vty_out(vty, " Export Route Target:\n");
449
450 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) {
451 ecom_str = ecommunity_ecom2str(ecom,
452 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
453
454 if (json)
455 json_object_array_add(json_export_rtl,
456 json_object_new_string(ecom_str));
457 else
458 vty_out(vty, " %s\n", ecom_str);
459
460 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
461 }
462
463 if (json)
464 json_object_object_add(json, "exportRts", json_export_rtl);
465}
466
9c92b5f7 467static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
d62a17ae 468{
06b9f471 469 char buf1[RD_ADDRSTRLEN];
d62a17ae 470 char *ecom_str;
471 struct listnode *node, *nnode;
472 struct ecommunity *ecom;
f57514e1
DS
473 json_object *json_import_rtl = NULL;
474 json_object *json_export_rtl = NULL;
2c4654a1
CS
475 struct bgp *bgp_evpn;
476
477 bgp_evpn = bgp_get_evpn();
9c92b5f7
MK
478
479 if (json) {
480 json_import_rtl = json_object_new_array();
481 json_export_rtl = json_object_new_array();
482 json_object_int_add(json, "vni", vpn->vni);
4cce389e 483 json_object_string_add(json, "type", "L2");
37ae1adb
CS
484 json_object_string_add(json, "inKernel",
485 is_vni_live(vpn) ? "True" : "False");
9c92b5f7
MK
486 json_object_string_add(
487 json, "rd",
06b9f471 488 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
9c92b5f7
MK
489 json_object_string_add(json, "originatorIp",
490 inet_ntoa(vpn->originator_ip));
76d07c7a
AK
491 json_object_string_add(json, "mcastGroup",
492 inet_ntoa(vpn->mcast_grp));
2c4654a1
CS
493 /* per vni knob is enabled -- Enabled
494 * Global knob is enabled -- Active
495 * default -- Disabled
496 */
497 if (!vpn->advertise_gw_macip &&
498 bgp_evpn && bgp_evpn->advertise_gw_macip)
499 json_object_string_add(json, "advertiseGatewayMacip",
500 "Active");
501 else if (vpn->advertise_gw_macip)
502 json_object_string_add(json, "advertiseGatewayMacip",
503 "Enabled");
504 else
505 json_object_string_add(json, "advertiseGatewayMacip",
506 "Disabled");
507 if (!vpn->advertise_svi_macip && bgp_evpn &&
508 bgp_evpn->evpn_info->advertise_svi_macip)
0b509723 509 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1
CS
510 "Active");
511 else if (vpn->advertise_svi_macip)
0b509723 512 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1
CS
513 "Enabled");
514 else
0b509723 515 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1 516 "Disabled");
9c92b5f7
MK
517 } else {
518 vty_out(vty, "VNI: %d", vpn->vni);
519 if (is_vni_live(vpn))
520 vty_out(vty, " (known to the kernel)");
521 vty_out(vty, "\n");
522
4cce389e 523 vty_out(vty, " Type: %s\n", "L2");
29c53922
MK
524 vty_out(vty, " Tenant-Vrf: %s\n",
525 vrf_id_to_name(vpn->tenant_vrf_id));
9c92b5f7 526 vty_out(vty, " RD: %s\n",
06b9f471 527 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
9c92b5f7
MK
528 vty_out(vty, " Originator IP: %s\n",
529 inet_ntoa(vpn->originator_ip));
76d07c7a
AK
530 vty_out(vty, " Mcast group: %s\n",
531 inet_ntoa(vpn->mcast_grp));
2c4654a1
CS
532 if (!vpn->advertise_gw_macip &&
533 bgp_evpn && bgp_evpn->advertise_gw_macip)
534 vty_out(vty, " Advertise-gw-macip : %s\n",
535 "Active");
536 else if (vpn->advertise_gw_macip)
537 vty_out(vty, " Advertise-gw-macip : %s\n",
538 "Enabled");
539 else
540 vty_out(vty, " Advertise-gw-macip : %s\n",
541 "Disabled");
542 if (!vpn->advertise_svi_macip && bgp_evpn &&
543 bgp_evpn->evpn_info->advertise_svi_macip)
544 vty_out(vty, " Advertise-svi-macip : %s\n",
545 "Active");
546 else if (vpn->advertise_svi_macip)
547 vty_out(vty, " Advertise-svi-macip : %s\n",
548 "Enabled");
549 else
550 vty_out(vty, " Advertise-svi-macip : %s\n",
551 "Disabled");
9c92b5f7 552 }
520d5d76 553
9c92b5f7
MK
554 if (!json)
555 vty_out(vty, " Import Route Target:\n");
520d5d76 556
d62a17ae 557 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
558 ecom_str = ecommunity_ecom2str(ecom,
559 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
560
561 if (json)
562 json_object_array_add(json_import_rtl,
563 json_object_new_string(ecom_str));
564 else
565 vty_out(vty, " %s\n", ecom_str);
566
d62a17ae 567 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
568 }
520d5d76 569
9c92b5f7
MK
570 if (json)
571 json_object_object_add(json, "importRts", json_import_rtl);
572 else
573 vty_out(vty, " Export Route Target:\n");
574
d62a17ae 575 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
576 ecom_str = ecommunity_ecom2str(ecom,
577 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
578
579 if (json)
580 json_object_array_add(json_export_rtl,
581 json_object_new_string(ecom_str));
582 else
583 vty_out(vty, " %s\n", ecom_str);
584
d62a17ae 585 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
586 }
9c92b5f7
MK
587
588 if (json)
589 json_object_object_add(json, "exportRts", json_export_rtl);
520d5d76 590}
d62a17ae 591
50f74cf1 592static void show_esi_routes(struct bgp *bgp,
b5e140c8 593 struct bgp_evpn_es *es,
50f74cf1 594 struct vty *vty,
595 json_object *json)
596{
597 int header = 1;
9bcb3eef 598 struct bgp_dest *dest;
40381db7 599 struct bgp_path_info *pi;
50f74cf1 600 uint32_t prefix_cnt, path_cnt;
601 uint64_t tbl_ver;
602
603 prefix_cnt = path_cnt = 0;
604
605 tbl_ver = es->route_table->version;
9bcb3eef
DS
606 for (dest = bgp_table_top(es->route_table); dest;
607 dest = bgp_route_next(dest)) {
50f74cf1 608 int add_prefix_to_json = 0;
609 char prefix_str[BUFSIZ];
610 json_object *json_paths = NULL;
611 json_object *json_prefix = NULL;
9bcb3eef 612 const struct prefix *p = bgp_dest_get_prefix(dest);
50f74cf1 613
b54892e0 614 bgp_evpn_route2str((struct prefix_evpn *)p, prefix_str,
50f74cf1 615 sizeof(prefix_str));
616
617 if (json)
618 json_prefix = json_object_new_object();
619
9bcb3eef 620 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 621 if (pi) {
50f74cf1 622 /* Overall header/legend displayed once. */
623 if (header) {
624 bgp_evpn_show_route_header(vty, bgp,
625 tbl_ver, json);
626 header = 0;
627 }
628
629 prefix_cnt++;
630 }
631
632 if (json)
633 json_paths = json_object_new_array();
634
635 /* For EVPN, the prefix is displayed for each path (to fit in
636 * with code that already exists).
637 */
6f94b685 638 for (; pi; pi = pi->next) {
50f74cf1 639 json_object *json_path = NULL;
640
641 if (json)
642 json_path = json_object_new_array();
643
ae248832
MK
644 route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path,
645 false);
50f74cf1 646
647 if (json)
648 json_object_array_add(json_paths, json_path);
649
650 path_cnt++;
651 add_prefix_to_json = 1;
652 }
653
24882500
CS
654 if (json) {
655 if (add_prefix_to_json) {
656 json_object_string_add(json_prefix, "prefix",
657 prefix_str);
658 json_object_int_add(json_prefix, "prefixLen",
b54892e0 659 p->prefixlen);
24882500
CS
660 json_object_object_add(json_prefix, "paths",
661 json_paths);
662 json_object_object_add(json, prefix_str,
663 json_prefix);
664 } else {
665 json_object_free(json_paths);
666 json_object_free(json_prefix);
667 json_paths = NULL;
668 json_prefix = NULL;
669 }
50f74cf1 670 }
671 }
672
673 if (json) {
674 json_object_int_add(json, "numPrefix", prefix_cnt);
675 json_object_int_add(json, "numPaths", path_cnt);
676 } else {
677 if (prefix_cnt == 0)
a2a8153f 678 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
50f74cf1 679 else
680 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
681 prefix_cnt, path_cnt);
682 }
683}
684
d62a17ae 685static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
9c92b5f7 686 struct vty *vty, struct in_addr vtep_ip,
c7ef6cf2 687 json_object *json, int detail)
520d5d76 688{
9bcb3eef 689 struct bgp_dest *dest;
40381db7 690 struct bgp_path_info *pi;
2dd32217 691 struct bgp_table *table;
c7ef6cf2 692 int header = detail ? 0 : 1;
2dd32217 693 uint64_t tbl_ver;
d7c0a89a 694 uint32_t prefix_cnt, path_cnt;
d62a17ae 695
696 prefix_cnt = path_cnt = 0;
697
2dd32217 698 table = vpn->route_table;
699 tbl_ver = table->version;
9bcb3eef 700 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
b54892e0 701 const struct prefix_evpn *evp =
9bcb3eef 702 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
9c92b5f7
MK
703 int add_prefix_to_json = 0;
704 char prefix_str[BUFSIZ];
705 json_object *json_paths = NULL;
706 json_object *json_prefix = NULL;
9bcb3eef 707 const struct prefix *p = bgp_dest_get_prefix(dest);
9c92b5f7 708
9bcb3eef
DS
709 bgp_evpn_route2str(
710 (struct prefix_evpn *)bgp_dest_get_prefix(dest),
711 prefix_str, sizeof(prefix_str));
d62a17ae 712
713 if (type && evp->prefix.route_type != type)
714 continue;
715
9c92b5f7
MK
716 if (json)
717 json_prefix = json_object_new_object();
718
9bcb3eef 719 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 720 if (pi) {
d62a17ae 721 /* Overall header/legend displayed once. */
722 if (header) {
2dd32217 723 bgp_evpn_show_route_header(vty, bgp,
724 tbl_ver, json);
d62a17ae 725 header = 0;
726 }
727
728 prefix_cnt++;
729 }
730
9c92b5f7
MK
731 if (json)
732 json_paths = json_object_new_array();
733
d62a17ae 734 /* For EVPN, the prefix is displayed for each path (to fit in
735 * with code that already exists).
736 */
6f94b685 737 for (; pi; pi = pi->next) {
9c92b5f7
MK
738 json_object *json_path = NULL;
739
975a328e 740 if (vtep_ip.s_addr != INADDR_ANY
d62a17ae 741 && !IPV4_ADDR_SAME(&(vtep_ip),
40381db7 742 &(pi->attr->nexthop)))
d62a17ae 743 continue;
744
9c92b5f7
MK
745 if (json)
746 json_path = json_object_new_array();
747
c7ef6cf2 748 if (detail)
9bcb3eef 749 route_vty_out_detail(vty, bgp, dest, pi,
c7ef6cf2
NS
750 AFI_L2VPN, SAFI_EVPN,
751 json_path);
752 else
b54892e0 753 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
ae248832 754 json_path, false);
9c92b5f7
MK
755
756 if (json)
757 json_object_array_add(json_paths, json_path);
758
d62a17ae 759 path_cnt++;
9c92b5f7
MK
760 add_prefix_to_json = 1;
761 }
762
24882500
CS
763 if (json) {
764 if (add_prefix_to_json) {
765 json_object_string_add(json_prefix, "prefix",
766 prefix_str);
767 json_object_int_add(json_prefix, "prefixLen",
b54892e0 768 p->prefixlen);
24882500
CS
769 json_object_object_add(json_prefix, "paths",
770 json_paths);
771 json_object_object_add(json, prefix_str,
772 json_prefix);
773 } else {
774 json_object_free(json_paths);
775 json_object_free(json_prefix);
776 json_paths = NULL;
777 json_prefix = NULL;
778 }
d62a17ae 779 }
780 }
781
9c92b5f7
MK
782 if (json) {
783 json_object_int_add(json, "numPrefix", prefix_cnt);
784 json_object_int_add(json, "numPaths", path_cnt);
785 } else {
786 if (prefix_cnt == 0)
787 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
788 type ? "(of requested type) " : "");
789 else
50f74cf1 790 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
9c92b5f7
MK
791 prefix_cnt, path_cnt,
792 type ? " (of requested type)" : "");
c7ef6cf2 793 vty_out(vty, "\n");
9c92b5f7 794 }
520d5d76 795}
796
e3b78da8 797static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
520d5d76 798{
e3b78da8 799 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
d62a17ae 800 struct vni_walk_ctx *wctx = arg;
801 struct vty *vty = wctx->vty;
9c92b5f7
MK
802 json_object *json = wctx->json;
803 json_object *json_vni = NULL;
804 char vni_str[VNI_STR_LEN];
805
772270f3 806 snprintf(vni_str, sizeof(vni_str), "%d", vpn->vni);
9c92b5f7
MK
807 if (json) {
808 json_vni = json_object_new_object();
809 json_object_int_add(json_vni, "vni", vpn->vni);
810 } else {
811 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
812 }
813
c7ef6cf2
NS
814 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni,
815 wctx->detail);
520d5d76 816
9c92b5f7
MK
817 if (json)
818 json_object_object_add(json, vni_str, json_vni);
520d5d76 819}
820
4cce389e 821static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
996c9314 822 json_object *json)
4cce389e 823{
dcfe4716
DS
824 json_object *json_vni = NULL;
825 json_object *json_import_rtl = NULL;
826 json_object *json_export_rtl = NULL;
4cce389e
MK
827 char buf1[10];
828 char buf2[INET6_ADDRSTRLEN];
829 char rt_buf[25];
830 char *ecom_str;
831 struct listnode *node, *nnode;
832 struct ecommunity *ecom;
833
834 if (!bgp->l3vni)
835 return;
836
837 if (json) {
838 json_vni = json_object_new_object();
839 json_import_rtl = json_object_new_array();
840 json_export_rtl = json_object_new_array();
841 }
842
843 /* if an l3vni is present in bgp it is live */
844 buf1[0] = '\0';
772270f3 845 snprintf(buf1, sizeof(buf1), "*");
4cce389e
MK
846
847 if (json) {
848 json_object_int_add(json_vni, "vni", bgp->l3vni);
849 json_object_string_add(json_vni, "type", "L3");
850 json_object_string_add(json_vni, "inKernel", "True");
d4454626 851 json_object_string_add(json_vni, "originatorIp",
852 inet_ntoa(bgp->originator_ip));
4cce389e
MK
853 json_object_string_add(
854 json_vni, "rd",
855 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
7c9cb387
CS
856 json_object_string_add(json_vni, "advertiseGatewayMacip",
857 "n/a");
0b509723 858 json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
7c9cb387
CS
859 json_object_to_json_string_ext(json_vni,
860 JSON_C_TO_STRING_NOSLASHESCAPE);
861 json_object_string_add(
862 json_vni, "advertisePip",
863 bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
864 json_object_string_add(json_vni, "sysIP",
865 inet_ntoa(bgp->evpn_info->pip_ip));
866 json_object_string_add(json_vni, "sysMAC",
867 prefix_mac2str(&bgp->evpn_info->pip_rmac,
868 buf2, sizeof(buf2)));
869 json_object_string_add(
870 json_vni, "rmac",
871 prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
4cce389e 872 } else {
996c9314 873 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
4cce389e
MK
874 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
875 }
876
877 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
878 ecom_str = ecommunity_ecom2str(ecom,
879 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
880
881 if (json) {
882 json_object_array_add(json_import_rtl,
883 json_object_new_string(ecom_str));
884 } else {
885 if (listcount(bgp->vrf_import_rtl) > 1)
772270f3
QY
886 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
887 ecom_str);
4cce389e 888 else
772270f3
QY
889 snprintf(rt_buf, sizeof(rt_buf), "%s",
890 ecom_str);
4cce389e
MK
891 vty_out(vty, " %-25s", rt_buf);
892 }
893
894 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
895
896 /* If there are multiple import RTs we break here and show only
897 * one */
898 if (!json)
899 break;
900 }
901
902 if (json)
903 json_object_object_add(json_vni, "importRTs", json_import_rtl);
904
905 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) {
906 ecom_str = ecommunity_ecom2str(ecom,
907 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
908
909 if (json) {
910 json_object_array_add(json_export_rtl,
911 json_object_new_string(ecom_str));
912 } else {
913 if (listcount(bgp->vrf_export_rtl) > 1)
772270f3
QY
914 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
915 ecom_str);
4cce389e 916 else
772270f3
QY
917 snprintf(rt_buf, sizeof(rt_buf), "%s",
918 ecom_str);
4cce389e
MK
919 vty_out(vty, " %-25s", rt_buf);
920 }
921
922 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
923
924 /* If there are multiple export RTs we break here and show only
925 * one */
926 if (!json)
927 break;
928 }
929
930 if (!json)
931 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
932
933 if (json) {
934 char vni_str[VNI_STR_LEN];
935
936 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
772270f3 937 snprintf(vni_str, sizeof(vni_str), "%u", bgp->l3vni);
4cce389e
MK
938 json_object_object_add(json, vni_str, json_vni);
939 } else {
940 vty_out(vty, "\n");
941 }
942}
943
e3b78da8 944static void show_vni_entry(struct hash_bucket *bucket, void *args[])
520d5d76 945{
9c92b5f7
MK
946 struct vty *vty;
947 json_object *json;
fb8f41e4
RB
948 json_object *json_vni = NULL;
949 json_object *json_import_rtl = NULL;
950 json_object *json_export_rtl = NULL;
e3b78da8 951 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
d62a17ae 952 char buf1[10];
06b9f471 953 char buf2[RD_ADDRSTRLEN];
d62a17ae 954 char rt_buf[25];
955 char *ecom_str;
956 struct listnode *node, *nnode;
957 struct ecommunity *ecom;
7c9cb387 958 struct bgp *bgp_evpn;
520d5d76 959
9c92b5f7
MK
960 vty = args[0];
961 json = args[1];
962
7c9cb387
CS
963 bgp_evpn = bgp_get_evpn();
964
9c92b5f7
MK
965 if (json) {
966 json_vni = json_object_new_object();
967 json_import_rtl = json_object_new_array();
968 json_export_rtl = json_object_new_array();
969 }
970
d62a17ae 971 buf1[0] = '\0';
972 if (is_vni_live(vpn))
772270f3 973 snprintf(buf1, sizeof(buf1), "*");
520d5d76 974
9c92b5f7
MK
975 if (json) {
976 json_object_int_add(json_vni, "vni", vpn->vni);
4cce389e 977 json_object_string_add(json_vni, "type", "L2");
9c92b5f7
MK
978 json_object_string_add(json_vni, "inKernel",
979 is_vni_live(vpn) ? "True" : "False");
9c92b5f7
MK
980 json_object_string_add(
981 json_vni, "rd",
06b9f471 982 prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
37ae1adb
CS
983 json_object_string_add(json_vni, "originatorIp",
984 inet_ntoa(vpn->originator_ip));
7c9cb387
CS
985 json_object_string_add(json_vni, "mcastGroup",
986 inet_ntoa(vpn->mcast_grp));
987 /* per vni knob is enabled -- Enabled
988 * Global knob is enabled -- Active
989 * default -- Disabled
990 */
991 if (!vpn->advertise_gw_macip && bgp_evpn
992 && bgp_evpn->advertise_gw_macip)
993 json_object_string_add(
994 json_vni, "advertiseGatewayMacip", "Active");
995 else if (vpn->advertise_gw_macip)
996 json_object_string_add(
997 json_vni, "advertiseGatewayMacip", "Enabled");
998 else
999 json_object_string_add(
1000 json_vni, "advertiseGatewayMacip", "Disabled");
1001 if (!vpn->advertise_svi_macip && bgp_evpn
1002 && bgp_evpn->evpn_info->advertise_svi_macip)
0b509723 1003 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387
CS
1004 "Active");
1005 else if (vpn->advertise_svi_macip)
0b509723 1006 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387
CS
1007 "Enabled");
1008 else
0b509723 1009 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387 1010 "Disabled");
9c92b5f7 1011 } else {
996c9314 1012 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
29c53922 1013 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
9c92b5f7 1014 }
520d5d76 1015
d62a17ae 1016 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1017 ecom_str = ecommunity_ecom2str(ecom,
1018 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
520d5d76 1019
9c92b5f7
MK
1020 if (json) {
1021 json_object_array_add(json_import_rtl,
1022 json_object_new_string(ecom_str));
1023 } else {
1024 if (listcount(vpn->import_rtl) > 1)
772270f3
QY
1025 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1026 ecom_str);
9c92b5f7 1027 else
772270f3
QY
1028 snprintf(rt_buf, sizeof(rt_buf), "%s",
1029 ecom_str);
9c92b5f7
MK
1030 vty_out(vty, " %-25s", rt_buf);
1031 }
520d5d76 1032
d62a17ae 1033 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
1034
1035 /* If there are multiple import RTs we break here and show only
1036 * one */
1037 if (!json)
1038 break;
d62a17ae 1039 }
1040
9c92b5f7
MK
1041 if (json)
1042 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1043
d62a17ae 1044 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1045 ecom_str = ecommunity_ecom2str(ecom,
1046 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1047
9c92b5f7
MK
1048 if (json) {
1049 json_object_array_add(json_export_rtl,
1050 json_object_new_string(ecom_str));
1051 } else {
1052 if (listcount(vpn->export_rtl) > 1)
772270f3
QY
1053 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1054 ecom_str);
9c92b5f7 1055 else
772270f3
QY
1056 snprintf(rt_buf, sizeof(rt_buf), "%s",
1057 ecom_str);
9c92b5f7
MK
1058 vty_out(vty, " %-25s", rt_buf);
1059 }
d62a17ae 1060
1061 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
1062
1063 /* If there are multiple export RTs we break here and show only
1064 * one */
1065 if (!json)
1066 break;
1067 }
1068
6be9a208
MK
1069 if (!json)
1070 vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
1071
9c92b5f7
MK
1072 if (json) {
1073 char vni_str[VNI_STR_LEN];
b682f6de 1074
9c92b5f7 1075 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
772270f3 1076 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
9c92b5f7
MK
1077 json_object_object_add(json, vni_str, json_vni);
1078 } else {
1079 vty_out(vty, "\n");
d62a17ae 1080 }
520d5d76 1081}
1082
d62a17ae 1083static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1084 enum bgp_show_type type, void *output_arg,
9f049418 1085 int option, bool use_json)
784d3a42 1086{
4d0e6ece
PG
1087 afi_t afi = AFI_L2VPN;
1088 struct bgp *bgp;
1089 struct bgp_table *table;
9bcb3eef
DS
1090 struct bgp_dest *dest;
1091 struct bgp_dest *rm;
40381db7 1092 struct bgp_path_info *pi;
4d0e6ece
PG
1093 int rd_header;
1094 int header = 1;
c69e79f1 1095 char rd_str[RD_ADDRSTRLEN];
597f4b1a 1096 char buf[BUFSIZ];
0afbd728 1097 int no_display;
4d0e6ece
PG
1098
1099 unsigned long output_count = 0;
1100 unsigned long total_count = 0;
1101 json_object *json = NULL;
4d0e6ece 1102 json_object *json_array = NULL;
597f4b1a
LK
1103 json_object *json_prefix_info = NULL;
1104
c69e79f1 1105 memset(rd_str, 0, RD_ADDRSTRLEN);
4d0e6ece 1106
530db8dc 1107 bgp = bgp_get_evpn();
4d0e6ece
PG
1108 if (bgp == NULL) {
1109 if (!use_json)
d62a17ae 1110 vty_out(vty, "No BGP process is configured\n");
16307668
RW
1111 else
1112 vty_out(vty, "{}\n");
4d0e6ece
PG
1113 return CMD_WARNING;
1114 }
1115
597f4b1a 1116 if (use_json)
4d0e6ece 1117 json = json_object_new_object();
4d0e6ece 1118
9bcb3eef
DS
1119 for (dest = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); dest;
1120 dest = bgp_route_next(dest)) {
2dd32217 1121 uint64_t tbl_ver;
c69e79f1 1122 json_object *json_nroute = NULL;
9bcb3eef 1123 const struct prefix *p = bgp_dest_get_prefix(dest);
2dd32217 1124
b54892e0 1125 if (prd && memcmp(p->u.val, prd->val, 8) != 0)
4d0e6ece
PG
1126 continue;
1127
9bcb3eef 1128 table = bgp_dest_get_bgp_table_info(dest);
67009e22 1129 if (!table)
ea47320b 1130 continue;
4d0e6ece 1131
ea47320b 1132 rd_header = 1;
2dd32217 1133 tbl_ver = table->version;
4d0e6ece 1134
0ac811af 1135 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
9bcb3eef 1136 pi = bgp_dest_get_bgp_path_info(rm);
0afbd728
KA
1137 if (pi == NULL)
1138 continue;
1139
1140 no_display = 0;
0afbd728 1141 for (; pi; pi = pi->next) {
ea47320b
DL
1142 total_count++;
1143 if (type == bgp_show_type_neighbor) {
dcc1615e 1144 struct peer *peer = output_arg;
ea47320b 1145
dcc1615e 1146 if (peer_cmp(peer, pi->peer) != 0)
ea47320b
DL
1147 continue;
1148 }
7f433a5e
LK
1149 if (type == bgp_show_type_lcommunity_exact) {
1150 struct lcommunity *lcom = output_arg;
1151
1152 if (!pi->attr->lcommunity ||
1153 !lcommunity_cmp(
1154 pi->attr->lcommunity, lcom))
1155 continue;
1156 }
1157 if (type == bgp_show_type_lcommunity) {
1158 struct lcommunity *lcom = output_arg;
1159
1160 if (!pi->attr->lcommunity ||
1161 !lcommunity_match(
1162 pi->attr->lcommunity, lcom))
1163 continue;
1164 }
1165 if (type == bgp_show_type_community) {
1166 struct community *com = output_arg;
1167
1168 if (!pi->attr->community ||
1169 !community_match(
1170 pi->attr->community, com))
1171 continue;
1172 }
1173 if (type == bgp_show_type_community_exact) {
1174 struct community *com = output_arg;
1175
1176 if (!pi->attr->community ||
1177 !community_cmp(
1178 pi->attr->community, com))
1179 continue;
1180 }
597f4b1a 1181 if (header) {
ea47320b 1182 if (use_json) {
597f4b1a
LK
1183 json_object_int_add(
1184 json, "bgpTableVersion",
1185 tbl_ver);
1186 json_object_string_add(
1187 json,
1188 "bgpLocalRouterId",
1189 inet_ntoa(
1190 bgp->router_id));
1191 json_object_int_add(
1192 json,
1193 "defaultLocPrf",
1194 bgp->default_local_pref);
1195 json_object_int_add(
1196 json, "localAS",
1197 bgp->as);
ea47320b 1198 } else {
60466a63 1199 if (option == SHOW_DISPLAY_TAGS)
ea47320b
DL
1200 vty_out(vty,
1201 V4_HEADER_TAG);
1202 else if (
1203 option
1204 == SHOW_DISPLAY_OVERLAY)
1205 vty_out(vty,
1206 V4_HEADER_OVERLAY);
1207 else {
0afbd728 1208 bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
4d0e6ece 1209 }
4d0e6ece 1210 }
ea47320b 1211 header = 0;
4d0e6ece 1212 }
ea47320b 1213 if (rd_header) {
c69e79f1
LK
1214 if (use_json)
1215 json_nroute =
1216 json_object_new_object();
9bcb3eef
DS
1217 bgp_evpn_show_route_rd_header(
1218 vty, dest, json_nroute, rd_str,
c69e79f1 1219 RD_ADDRSTRLEN);
ea47320b
DL
1220 rd_header = 0;
1221 }
c69e79f1
LK
1222 if (use_json && !json_array)
1223 json_array = json_object_new_array();
0ac811af 1224
ea47320b 1225 if (option == SHOW_DISPLAY_TAGS)
b54892e0 1226 route_vty_out_tag(
9bcb3eef 1227 vty, bgp_dest_get_prefix(rm),
b54892e0
DS
1228 pi, no_display, SAFI_EVPN,
1229 json_array);
ea47320b 1230 else if (option == SHOW_DISPLAY_OVERLAY)
b54892e0 1231 route_vty_out_overlay(
9bcb3eef 1232 vty, bgp_dest_get_prefix(rm),
b54892e0 1233 pi, no_display, json_array);
ea47320b 1234 else
b54892e0 1235 route_vty_out(vty,
9bcb3eef 1236 bgp_dest_get_prefix(rm),
b54892e0 1237 pi, no_display, SAFI_EVPN,
ae248832 1238 json_array, false);
0afbd728 1239 no_display = 1;
ea47320b 1240 }
0afbd728
KA
1241
1242 if (no_display)
1243 output_count++;
1244
c69e79f1 1245 if (use_json && json_array) {
b54892e0 1246 const struct prefix *p =
9bcb3eef 1247 bgp_dest_get_prefix(rm);
b54892e0 1248
c69e79f1
LK
1249 json_prefix_info = json_object_new_object();
1250
b54892e0
DS
1251 json_object_string_add(
1252 json_prefix_info, "prefix",
1253 bgp_evpn_route2str(
1254 (struct prefix_evpn *)p, buf,
1255 BUFSIZ));
c69e79f1
LK
1256
1257 json_object_int_add(json_prefix_info,
b54892e0 1258 "prefixLen", p->prefixlen);
c69e79f1 1259
0ac811af
LK
1260 json_object_object_add(json_prefix_info,
1261 "paths", json_array);
1262 json_object_object_add(json_nroute, buf,
1263 json_prefix_info);
c69e79f1 1264 json_array = NULL;
0ac811af
LK
1265 }
1266 }
597f4b1a 1267
c69e79f1 1268 if (use_json && json_nroute)
597f4b1a 1269 json_object_object_add(json, rd_str, json_nroute);
597f4b1a
LK
1270 }
1271
1272 if (use_json) {
1273 json_object_int_add(json, "numPrefix", output_count);
1274 json_object_int_add(json, "totalPrefix", total_count);
1275 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1276 json, JSON_C_TO_STRING_PRETTY));
1277 json_object_free(json);
1278 } else {
1279 if (output_count == 0)
1280 vty_out(vty, "No prefixes displayed, %ld exist\n",
1281 total_count);
1282 else
1283 vty_out(vty,
1284 "\nDisplayed %ld out of %ld total prefixes\n",
1285 output_count, total_count);
4d0e6ece 1286 }
4d0e6ece 1287 return CMD_SUCCESS;
784d3a42
PG
1288}
1289
4d0e6ece
PG
1290DEFUN(show_ip_bgp_l2vpn_evpn,
1291 show_ip_bgp_l2vpn_evpn_cmd,
1292 "show [ip] bgp l2vpn evpn [json]",
1293 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
784d3a42 1294{
4d0e6ece
PG
1295 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
1296 use_json(argc, argv));
784d3a42
PG
1297}
1298
4d0e6ece
PG
1299DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1300 show_ip_bgp_l2vpn_evpn_rd_cmd,
d114b977 1301 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
4d0e6ece
PG
1302 SHOW_STR
1303 IP_STR
1304 BGP_STR
1305 L2VPN_HELP_STR
1306 EVPN_HELP_STR
1307 "Display information for a route distinguisher\n"
1308 "VPN Route Distinguisher\n" JSON_STR)
784d3a42 1309{
313605cb 1310 int idx_ext_community = 0;
4d0e6ece
PG
1311 int ret;
1312 struct prefix_rd prd;
1313
d114b977 1314 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
313605cb 1315
4d0e6ece
PG
1316 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1317 if (!ret) {
d62a17ae 1318 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1319 return CMD_WARNING;
1320 }
1321 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
1322 use_json(argc, argv));
784d3a42
PG
1323}
1324
4d0e6ece
PG
1325DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1326 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1327 "show [ip] bgp l2vpn evpn all tags",
1328 SHOW_STR
1329 IP_STR
1330 BGP_STR
1331 L2VPN_HELP_STR
1332 EVPN_HELP_STR
1333 "Display information about all EVPN NLRIs\n"
1334 "Display BGP tags for prefixes\n")
784d3a42 1335{
4d0e6ece
PG
1336 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
1337 0);
784d3a42
PG
1338}
1339
4d0e6ece
PG
1340DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1341 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
d114b977 1342 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
4d0e6ece
PG
1343 SHOW_STR
1344 IP_STR
1345 BGP_STR
1346 L2VPN_HELP_STR
1347 EVPN_HELP_STR
1348 "Display information for a route distinguisher\n"
1349 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
784d3a42 1350{
313605cb 1351 int idx_ext_community = 0;
4d0e6ece
PG
1352 int ret;
1353 struct prefix_rd prd;
1354
d114b977 1355 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
313605cb 1356
4d0e6ece
PG
1357 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1358 if (!ret) {
d62a17ae 1359 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1360 return CMD_WARNING;
1361 }
1362 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
1363 0);
784d3a42
PG
1364}
1365
dcc1615e
DD
1366DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1367 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1368 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
4d0e6ece
PG
1369 SHOW_STR
1370 IP_STR
1371 BGP_STR
1372 L2VPN_HELP_STR
1373 EVPN_HELP_STR
4d0e6ece 1374 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1375 "IPv4 Neighbor to display information about\n"
1376 "IPv6 Neighbor to display information about\n"
1377 "Neighbor on BGP configured interface\n"
4d0e6ece 1378 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 1379{
dcc1615e 1380 int idx = 0;
4d0e6ece 1381 struct peer *peer;
dcc1615e 1382 char *peerstr = NULL;
9f049418 1383 bool uj = use_json(argc, argv);
dcc1615e
DD
1384 afi_t afi = AFI_L2VPN;
1385 safi_t safi = SAFI_EVPN;
1386 struct bgp *bgp = NULL;
4d0e6ece 1387
dcc1615e
DD
1388 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1389 &bgp, uj);
1390 if (!idx) {
1391 vty_out(vty, "No index\n");
1392 return CMD_WARNING;
1393 }
1394
1395 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1396 argv_find(argv, argc, "neighbors", &idx);
1397 peerstr = argv[++idx]->arg;
313605cb 1398
dcc1615e
DD
1399 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1400 if (!peer) {
4d0e6ece
PG
1401 if (uj) {
1402 json_object *json_no = NULL;
1403 json_no = json_object_new_object();
1404 json_object_string_add(json_no, "warning",
1405 "Malformed address");
d62a17ae 1406 vty_out(vty, "%s\n",
96ade3ed 1407 json_object_to_json_string(json_no));
4d0e6ece
PG
1408 json_object_free(json_no);
1409 } else
d62a17ae 1410 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1411 argv[idx]->arg);
4d0e6ece
PG
1412 return CMD_WARNING;
1413 }
4d0e6ece
PG
1414 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1415 if (uj) {
1416 json_object *json_no = NULL;
1417 json_no = json_object_new_object();
d62a17ae 1418 json_object_string_add(
1419 json_no, "warning",
1420 "No such neighbor or address family");
1421 vty_out(vty, "%s\n",
96ade3ed 1422 json_object_to_json_string(json_no));
4d0e6ece
PG
1423 json_object_free(json_no);
1424 } else
d62a17ae 1425 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1426 return CMD_WARNING;
1427 }
1428
dcc1615e 1429 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer, 0,
4d0e6ece 1430 uj);
784d3a42
PG
1431}
1432
4d0e6ece
PG
1433DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1434 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
dcc1615e 1435 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
4d0e6ece
PG
1436 SHOW_STR
1437 IP_STR
1438 BGP_STR
1439 L2VPN_HELP_STR
1440 EVPN_HELP_STR
1441 "Display information for a route distinguisher\n"
1442 "VPN Route Distinguisher\n"
1443 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1444 "IPv4 Neighbor to display information about\n"
1445 "IPv6 Neighbor to display information about\n"
1446 "Neighbor on BGP configured interface\n"
4d0e6ece 1447 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 1448{
313605cb 1449 int idx_ext_community = 0;
dcc1615e 1450 int idx = 0;
4d0e6ece 1451 int ret;
4d0e6ece 1452 struct peer *peer;
dcc1615e 1453 char *peerstr = NULL;
4d0e6ece 1454 struct prefix_rd prd;
9f049418 1455 bool uj = use_json(argc, argv);
dcc1615e
DD
1456 afi_t afi = AFI_L2VPN;
1457 safi_t safi = SAFI_EVPN;
1458 struct bgp *bgp = NULL;
4d0e6ece 1459
dcc1615e
DD
1460 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1461 &bgp, uj);
1462 if (!idx) {
1463 vty_out(vty, "No index\n");
1464 return CMD_WARNING;
1465 }
313605cb 1466
dcc1615e 1467 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
4d0e6ece
PG
1468 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1469 if (!ret) {
1470 if (uj) {
1471 json_object *json_no = NULL;
1472 json_no = json_object_new_object();
1473 json_object_string_add(json_no, "warning",
1474 "Malformed Route Distinguisher");
d62a17ae 1475 vty_out(vty, "%s\n",
96ade3ed 1476 json_object_to_json_string(json_no));
4d0e6ece
PG
1477 json_object_free(json_no);
1478 } else
d62a17ae 1479 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1480 return CMD_WARNING;
1481 }
1482
dcc1615e
DD
1483 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1484 argv_find(argv, argc, "neighbors", &idx);
1485 peerstr = argv[++idx]->arg;
1486
1487 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1488 if (!peer) {
4d0e6ece
PG
1489 if (uj) {
1490 json_object *json_no = NULL;
1491 json_no = json_object_new_object();
1492 json_object_string_add(json_no, "warning",
1493 "Malformed address");
d62a17ae 1494 vty_out(vty, "%s\n",
96ade3ed 1495 json_object_to_json_string(json_no));
4d0e6ece
PG
1496 json_object_free(json_no);
1497 } else
d62a17ae 1498 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1499 argv[idx]->arg);
4d0e6ece
PG
1500 return CMD_WARNING;
1501 }
4d0e6ece
PG
1502 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1503 if (uj) {
1504 json_object *json_no = NULL;
1505 json_no = json_object_new_object();
d62a17ae 1506 json_object_string_add(
1507 json_no, "warning",
1508 "No such neighbor or address family");
1509 vty_out(vty, "%s\n",
96ade3ed 1510 json_object_to_json_string(json_no));
4d0e6ece
PG
1511 json_object_free(json_no);
1512 } else
d62a17ae 1513 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1514 return CMD_WARNING;
1515 }
1516
dcc1615e 1517 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, peer, 0,
4d0e6ece 1518 uj);
784d3a42
PG
1519}
1520
dcc1615e
DD
1521DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1522 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1523 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
4d0e6ece
PG
1524 SHOW_STR
1525 IP_STR
1526 BGP_STR
1527 L2VPN_HELP_STR
1528 EVPN_HELP_STR
4d0e6ece 1529 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1530 "IPv4 Neighbor to display information about\n"
1531 "IPv6 Neighbor to display information about\n"
1532 "Neighbor on BGP configured interface\n"
4d0e6ece 1533 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 1534{
dcc1615e 1535 int idx = 0;
4d0e6ece 1536 struct peer *peer;
9f049418 1537 bool uj = use_json(argc, argv);
dcc1615e
DD
1538 struct bgp *bgp = NULL;
1539 afi_t afi = AFI_L2VPN;
1540 safi_t safi = SAFI_EVPN;
1541 char *peerstr = NULL;
1542
1543 if (uj)
1544 argc--;
4d0e6ece 1545
dcc1615e
DD
1546 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1547 &bgp, uj);
1548 if (!idx) {
1549 vty_out(vty, "No index\n");
1550 return CMD_WARNING;
1551 }
1552
1553 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1554 argv_find(argv, argc, "neighbors", &idx);
1555 peerstr = argv[++idx]->arg;
313605cb 1556
dcc1615e
DD
1557 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1558 if (!peer) {
4d0e6ece
PG
1559 if (uj) {
1560 json_object *json_no = NULL;
1561 json_no = json_object_new_object();
1562 json_object_string_add(json_no, "warning",
1563 "Malformed address");
d62a17ae 1564 vty_out(vty, "%s\n",
96ade3ed 1565 json_object_to_json_string(json_no));
4d0e6ece
PG
1566 json_object_free(json_no);
1567 } else
d62a17ae 1568 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1569 argv[idx]->arg);
4d0e6ece
PG
1570 return CMD_WARNING;
1571 }
4d0e6ece
PG
1572 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1573 if (uj) {
1574 json_object *json_no = NULL;
1575 json_no = json_object_new_object();
d62a17ae 1576 json_object_string_add(
1577 json_no, "warning",
1578 "No such neighbor or address family");
1579 vty_out(vty, "%s\n",
96ade3ed 1580 json_object_to_json_string(json_no));
4d0e6ece
PG
1581 json_object_free(json_no);
1582 } else
d62a17ae 1583 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1584 return CMD_WARNING;
1585 }
1586
1587 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1588}
1589
4d0e6ece
PG
1590DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1591 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
dcc1615e 1592 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
4d0e6ece
PG
1593 SHOW_STR
1594 IP_STR
1595 BGP_STR
1596 L2VPN_HELP_STR
1597 EVPN_HELP_STR
1598 "Display information for a route distinguisher\n"
1599 "VPN Route Distinguisher\n"
1600 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1601 "IPv4 Neighbor to display information about\n"
1602 "IPv6 Neighbor to display information about\n"
1603 "Neighbor on BGP configured interface\n"
4d0e6ece 1604 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 1605{
313605cb 1606 int idx_ext_community = 0;
dcc1615e 1607 int idx = 0;
4d0e6ece
PG
1608 int ret;
1609 struct peer *peer;
1610 struct prefix_rd prd;
dcc1615e 1611 struct bgp *bgp = NULL;
9f049418 1612 bool uj = use_json(argc, argv);
dcc1615e
DD
1613 char *peerstr = NULL;
1614 afi_t afi = AFI_L2VPN;
1615 safi_t safi = SAFI_EVPN;
1616
1617 if (uj)
1618 argc--;
1619
1620 if (uj)
1621 argc--;
1622
1623 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1624 &bgp, uj);
1625 if (!idx) {
1626 vty_out(vty, "No index\n");
1627 return CMD_WARNING;
1628 }
4d0e6ece 1629
d114b977 1630 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
313605cb 1631
dcc1615e
DD
1632 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1633 argv_find(argv, argc, "neighbors", &idx);
1634 peerstr = argv[++idx]->arg;
1635
1636 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1637 if (!peer) {
4d0e6ece
PG
1638 if (uj) {
1639 json_object *json_no = NULL;
1640 json_no = json_object_new_object();
1641 json_object_string_add(json_no, "warning",
1642 "Malformed address");
d62a17ae 1643 vty_out(vty, "%s\n",
96ade3ed 1644 json_object_to_json_string(json_no));
4d0e6ece
PG
1645 json_object_free(json_no);
1646 } else
d62a17ae 1647 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1648 argv[idx]->arg);
4d0e6ece
PG
1649 return CMD_WARNING;
1650 }
4d0e6ece
PG
1651 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1652 if (uj) {
1653 json_object *json_no = NULL;
1654 json_no = json_object_new_object();
d62a17ae 1655 json_object_string_add(
1656 json_no, "warning",
1657 "No such neighbor or address family");
1658 vty_out(vty, "%s\n",
96ade3ed 1659 json_object_to_json_string(json_no));
4d0e6ece
PG
1660 json_object_free(json_no);
1661 } else
d62a17ae 1662 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1663 return CMD_WARNING;
1664 }
1665
1666 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1667 if (!ret) {
1668 if (uj) {
1669 json_object *json_no = NULL;
1670 json_no = json_object_new_object();
1671 json_object_string_add(json_no, "warning",
1672 "Malformed Route Distinguisher");
d62a17ae 1673 vty_out(vty, "%s\n",
96ade3ed 1674 json_object_to_json_string(json_no));
4d0e6ece
PG
1675 json_object_free(json_no);
1676 } else
d62a17ae 1677 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1678 return CMD_WARNING;
1679 }
1680
1681 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1682}
1683
4d0e6ece
PG
1684DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1685 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
14f51eba 1686 "show [ip] bgp l2vpn evpn all overlay [json]",
4d0e6ece
PG
1687 SHOW_STR
1688 IP_STR
1689 BGP_STR
1690 L2VPN_HELP_STR
1691 EVPN_HELP_STR
1692 "Display information about all EVPN NLRIs\n"
14f51eba
LK
1693 "Display BGP Overlay Information for prefixes\n"
1694 JSON_STR)
784d3a42 1695{
4d0e6ece 1696 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
d62a17ae 1697 SHOW_DISPLAY_OVERLAY,
1698 use_json(argc, argv));
784d3a42
PG
1699}
1700
4d0e6ece
PG
1701DEFUN(show_ip_bgp_evpn_rd_overlay,
1702 show_ip_bgp_evpn_rd_overlay_cmd,
d114b977 1703 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
4d0e6ece
PG
1704 SHOW_STR
1705 IP_STR
1706 BGP_STR
1707 L2VPN_HELP_STR
1708 EVPN_HELP_STR
1709 "Display information for a route distinguisher\n"
1710 "VPN Route Distinguisher\n"
1711 "Display BGP Overlay Information for prefixes\n")
784d3a42 1712{
313605cb 1713 int idx_ext_community = 0;
4d0e6ece
PG
1714 int ret;
1715 struct prefix_rd prd;
1716
d114b977 1717 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
313605cb 1718
4d0e6ece
PG
1719 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1720 if (!ret) {
d62a17ae 1721 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1722 return CMD_WARNING;
1723 }
1724 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
d62a17ae 1725 SHOW_DISPLAY_OVERLAY,
1726 use_json(argc, argv));
784d3a42
PG
1727}
1728
7f433a5e
LK
1729DEFUN(show_bgp_l2vpn_evpn_com,
1730 show_bgp_l2vpn_evpn_com_cmd,
1731 "show bgp l2vpn evpn \
1732 <community AA:NN|large-community AA:BB:CC> \
1733 [exact-match] [json]",
1734 SHOW_STR
1735 BGP_STR
1736 L2VPN_HELP_STR
1737 EVPN_HELP_STR
1738 "Display routes matching the community\n"
1739 "Community number where AA and NN are (0-65535)\n"
1740 "Display routes matching the large-community\n"
1741 "List of large-community numbers\n"
1742 "Exact match of the communities\n"
1743 JSON_STR)
1744{
1745 int idx = 0;
1746 int ret = 0;
1747 const char *clist_number_or_name;
1748 int show_type = bgp_show_type_normal;
1749 struct community *com;
1750 struct lcommunity *lcom;
1751
1752 if (argv_find(argv, argc, "large-community", &idx)) {
1753 clist_number_or_name = argv[++idx]->arg;
1754 show_type = bgp_show_type_lcommunity;
1755
1756 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1757 show_type = bgp_show_type_lcommunity_exact;
1758
1759 lcom = lcommunity_str2com(clist_number_or_name);
1760 if (!lcom) {
1761 vty_out(vty, "%% Large-community malformed\n");
1762 return CMD_WARNING;
1763 }
1764
1765 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1766 SHOW_DISPLAY_STANDARD,
1767 use_json(argc, argv));
1768
1769 lcommunity_free(&lcom);
1770 } else if (argv_find(argv, argc, "community", &idx)) {
1771 clist_number_or_name = argv[++idx]->arg;
1772 show_type = bgp_show_type_community;
1773
1774 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1775 show_type = bgp_show_type_community_exact;
1776
1777 com = community_str2com(clist_number_or_name);
1778
1779 if (!com) {
1780 vty_out(vty, "%% Community malformed: %s\n",
1781 clist_number_or_name);
1782 return CMD_WARNING;
1783 }
1784
1785 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1786 SHOW_DISPLAY_STANDARD,
1787 use_json(argc, argv));
1788 community_free(&com);
1789 }
1790
1791 return ret;
1792}
1793
dcc1615e 1794/* For testing purpose, static route of EVPN RT-5. */
4d0e6ece
PG
1795DEFUN(evpnrt5_network,
1796 evpnrt5_network_cmd,
d114b977 1797 "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 WORD]",
4d0e6ece
PG
1798 "Specify a network to announce via BGP\n"
1799 "IP prefix\n"
1800 "IPv6 prefix\n"
1801 "Specify Route Distinguisher\n"
1802 "VPN Route Distinguisher\n"
1803 "Ethernet Tag\n"
1804 "Ethernet Tag Value\n"
1805 "BGP label\n"
1806 "label value\n"
1807 "Ethernet Segment Identifier\n"
1808 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1809 "Gateway IP\n"
1810 "Gateway IP ( A.B.C.D )\n"
1811 "Gateway IPv6 ( X:X::X:X )\n"
1812 "Router Mac Ext Comm\n"
55daa605
DS
1813 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1814 "Route-map to modify the attributes\n"
1815 "Name of the route map\n")
3da6fcd5 1816{
4d0e6ece 1817 int idx_ipv4_prefixlen = 1;
197cb530
PG
1818 int idx_route_distinguisher = 3;
1819 int idx_label = 7;
4d0e6ece
PG
1820 int idx_esi = 9;
1821 int idx_gwip = 11;
1822 int idx_ethtag = 5;
1823 int idx_routermac = 13;
197cb530 1824
d62a17ae 1825 return bgp_static_set_safi(
1826 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
996c9314 1827 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
d62a17ae 1828 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1829 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1830 argv[idx_routermac]->arg);
3da6fcd5
PG
1831}
1832
dcc1615e 1833/* For testing purpose, static route of EVPN RT-5. */
4d0e6ece
PG
1834DEFUN(no_evpnrt5_network,
1835 no_evpnrt5_network_cmd,
d114b977 1836 "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>",
4d0e6ece
PG
1837 NO_STR
1838 "Specify a network to announce via BGP\n"
1839 "IP prefix\n"
1840 "IPv6 prefix\n"
1841 "Specify Route Distinguisher\n"
1842 "VPN Route Distinguisher\n"
1843 "Ethernet Tag\n"
1844 "Ethernet Tag Value\n"
1845 "BGP label\n"
1846 "label value\n"
1847 "Ethernet Segment Identifier\n"
1848 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1849 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
3da6fcd5 1850{
4d0e6ece
PG
1851 int idx_ipv4_prefixlen = 2;
1852 int idx_ext_community = 4;
1853 int idx_label = 8;
1854 int idx_ethtag = 6;
1855 int idx_esi = 10;
1856 int idx_gwip = 12;
d62a17ae 1857 return bgp_static_unset_safi(
1858 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1859 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1860 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1861 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
3da6fcd5
PG
1862}
1863
d62a17ae 1864static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1865{
c581d8b0 1866 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
90e60aa7 1867}
1868
d62a17ae 1869static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1870{
c581d8b0 1871 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl);
90e60aa7 1872}
1873
1874/*
1875 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1876 * check that this is a change.
1877 */
d62a17ae 1878static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1879 struct ecommunity *ecomadd)
90e60aa7 1880{
d62a17ae 1881 /* If the VNI is "live", we need to uninstall routes using the current
1882 * import RT(s) first before we update the import RT, and subsequently
1883 * install routes.
1884 */
1885 if (is_vni_live(vpn))
1886 bgp_evpn_uninstall_routes(bgp, vpn);
90e60aa7 1887
d62a17ae 1888 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1889 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
90e60aa7 1890
d62a17ae 1891 /* If the auto route-target is in use we must remove it */
1892 evpn_import_rt_delete_auto(bgp, vpn);
90e60aa7 1893
d62a17ae 1894 /* Add new RT and rebuild the RT to VNI mapping */
1895 listnode_add_sort(vpn->import_rtl, ecomadd);
90e60aa7 1896
d62a17ae 1897 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1898 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
90e60aa7 1899
d62a17ae 1900 /* Install routes that match new import RT */
1901 if (is_vni_live(vpn))
1902 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 1903}
1904
1905/*
1906 * Unconfigure Import RT(s) for a VNI (vty handler).
1907 */
d62a17ae 1908static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1909 struct ecommunity *ecomdel)
1910{
1911 struct listnode *node, *nnode, *node_to_del;
1912 struct ecommunity *ecom;
1913
1914 /* Along the lines of "configure" except we have to reset to the
1915 * automatic value.
1916 */
1917 if (is_vni_live(vpn))
1918 bgp_evpn_uninstall_routes(bgp, vpn);
1919
1920 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1921 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1922
1923 /* Delete all import RTs */
1924 if (ecomdel == NULL) {
1b7db1df 1925 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
d62a17ae 1926 ecommunity_free(&ecom);
1b7db1df
KA
1927 list_delete_node(vpn->import_rtl, node);
1928 }
d62a17ae 1929 }
1930
1931 /* Delete a specific import RT */
1932 else {
1933 node_to_del = NULL;
1934
1935 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1936 if (ecommunity_match(ecom, ecomdel)) {
1937 ecommunity_free(&ecom);
1938 node_to_del = node;
1939 break;
1940 }
1941 }
1942
1943 if (node_to_del)
1944 list_delete_node(vpn->import_rtl, node_to_del);
1945 }
1946
b3a4db3d 1947 assert(vpn->import_rtl);
d62a17ae 1948 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1949 if (list_isempty(vpn->import_rtl)) {
1950 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1951 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1952 }
1953 /* Rebuild the RT to VNI mapping */
1954 else
1955 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1956
1957 /* Install routes that match new import RT */
1958 if (is_vni_live(vpn))
1959 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 1960}
1961
1962/*
1963 * Configure the Export RT for a VNI (vty handler). Caller expected to
1964 * check that this is a change. Note that only a single export RT is
1965 * allowed for a VNI and any change to configuration is implemented as
1966 * a "replace" (similar to other configuration).
1967 */
d62a17ae 1968static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1969 struct ecommunity *ecomadd)
90e60aa7 1970{
d62a17ae 1971 /* If the auto route-target is in use we must remove it */
1972 evpn_export_rt_delete_auto(bgp, vpn);
90e60aa7 1973
d62a17ae 1974 listnode_add_sort(vpn->export_rtl, ecomadd);
1975 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
90e60aa7 1976
d62a17ae 1977 if (is_vni_live(vpn))
1978 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 1979}
1980
1981/*
1982 * Unconfigure the Export RT for a VNI (vty handler)
1983 */
d62a17ae 1984static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1985 struct ecommunity *ecomdel)
1986{
1987 struct listnode *node, *nnode, *node_to_del;
1988 struct ecommunity *ecom;
1989
1990 /* Delete all export RTs */
1991 if (ecomdel == NULL) {
1992 /* Reset to default and process all routes. */
1b7db1df 1993 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
d62a17ae 1994 ecommunity_free(&ecom);
1b7db1df
KA
1995 list_delete_node(vpn->export_rtl, node);
1996 }
d62a17ae 1997 }
1998
1999 /* Delete a specific export RT */
2000 else {
2001 node_to_del = NULL;
2002
2003 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2004 if (ecommunity_match(ecom, ecomdel)) {
2005 ecommunity_free(&ecom);
2006 node_to_del = node;
2007 break;
2008 }
2009 }
2010
2011 if (node_to_del)
2012 list_delete_node(vpn->export_rtl, node_to_del);
2013 }
2014
b3a4db3d 2015 assert(vpn->export_rtl);
d62a17ae 2016 if (list_isempty(vpn->export_rtl)) {
2017 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2018 bgp_evpn_derive_auto_rt_export(bgp, vpn);
2019 }
2020
2021 if (is_vni_live(vpn))
2022 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 2023}
2024
676f83b9 2025/*
2026 * Configure RD for VRF
2027 */
996c9314 2028static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
676f83b9 2029{
2030 /* If we have already advertise type-5 routes with a diffrent RD, we
523cafc4 2031 * have to delete and withdraw them firs
2032 */
06d2e8f3 2033 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
676f83b9 2034
2035 /* update RD */
2036 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
2037 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2038
2039 /* We have a new RD for VRF.
523cafc4 2040 * Advertise all type-5 routes again with the new RD
2041 */
06d2e8f3 2042 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
676f83b9 2043}
2044
2045/*
2046 * Unconfigure RD for VRF
2047 */
2048static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2049{
2050 /* If we have already advertise type-5 routes with a diffrent RD, we
523cafc4 2051 * have to delete and withdraw them firs
2052 */
06d2e8f3 2053 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
676f83b9 2054
2055 /* fall back to default RD */
2056 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
99b4e972 2057 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
676f83b9 2058
2059 /* We have a new RD for VRF.
523cafc4 2060 * Advertise all type-5 routes again with the new RD
2061 */
06d2e8f3 2062 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
676f83b9 2063}
2064
90e60aa7 2065/*
2066 * Configure RD for a VNI (vty handler)
2067 */
d62a17ae 2068static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
2069 struct prefix_rd *rd)
90e60aa7 2070{
d62a17ae 2071 /* If the VNI is "live", we need to delete and withdraw this VNI's
2072 * local routes with the prior RD first. Then, after updating RD,
2073 * need to re-advertise.
2074 */
2075 if (is_vni_live(vpn))
2076 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 2077
d62a17ae 2078 /* update RD */
2079 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
2080 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
90e60aa7 2081
d62a17ae 2082 if (is_vni_live(vpn))
2083 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 2084}
2085
2086/*
2087 * Unconfigure RD for a VNI (vty handler)
2088 */
d62a17ae 2089static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2090{
d62a17ae 2091 /* If the VNI is "live", we need to delete and withdraw this VNI's
2092 * local routes with the prior RD first. Then, after resetting RD
2093 * to automatic value, need to re-advertise.
2094 */
2095 if (is_vni_live(vpn))
2096 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 2097
d62a17ae 2098 /* reset RD to default */
2099 bgp_evpn_derive_auto_rd(bgp, vpn);
90e60aa7 2100
d62a17ae 2101 if (is_vni_live(vpn))
2102 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 2103}
2104
2105/*
2106 * Create VNI, if not already present (VTY handler). Mark as configured.
2107 */
d62a17ae 2108static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
90e60aa7 2109{
d62a17ae 2110 struct bgpevpn *vpn;
76d07c7a 2111 struct in_addr mcast_grp = {INADDR_ANY};
90e60aa7 2112
d62a17ae 2113 if (!bgp->vnihash)
2114 return NULL;
90e60aa7 2115
d62a17ae 2116 vpn = bgp_evpn_lookup_vni(bgp, vni);
2117 if (!vpn) {
7df407ed
CS
2118 /* Check if this L2VNI is already configured as L3VNI */
2119 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
1c50c1c0
QY
2120 flog_err(
2121 EC_BGP_VNI,
2122 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2123 bgp->vrf_id, vni);
7df407ed
CS
2124 return NULL;
2125 }
2126
29c53922 2127 /* tenant vrf will be updated when we get local_vni_add from
523cafc4 2128 * zebra
2129 */
76d07c7a 2130 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp);
d62a17ae 2131 if (!vpn) {
af4c2728 2132 flog_err(
e50f7cfd 2133 EC_BGP_VNI,
d62a17ae 2134 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2135 bgp->vrf_id, vni);
2136 return NULL;
2137 }
2138 }
90e60aa7 2139
d62a17ae 2140 /* Mark as configured. */
2141 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2142 return vpn;
90e60aa7 2143}
2144
2145/*
2146 * Delete VNI. If VNI does not exist in the system (i.e., just
2147 * configuration), all that is needed is to free it. Otherwise,
2148 * any parameters configured for the VNI need to be reset (with
2149 * appropriate action) and the VNI marked as unconfigured; the
2150 * VNI will continue to exist, purely as a "learnt" entity.
2151 */
3dc339cd 2152static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2153{
d62a17ae 2154 assert(bgp->vnihash);
90e60aa7 2155
d62a17ae 2156 if (!is_vni_live(vpn)) {
2157 bgp_evpn_free(bgp, vpn);
3dc339cd 2158 return;
d62a17ae 2159 }
90e60aa7 2160
d62a17ae 2161 /* We need to take the unconfigure action for each parameter of this VNI
2162 * that is configured. Some optimization is possible, but not worth the
2163 * additional code for an operation that should be pretty rare.
2164 */
2165 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
90e60aa7 2166
d62a17ae 2167 /* First, deal with the export side - RD and export RT changes. */
2168 if (is_rd_configured(vpn))
2169 evpn_unconfigure_rd(bgp, vpn);
2170 if (is_export_rt_configured(vpn))
2171 evpn_unconfigure_export_rt(bgp, vpn, NULL);
90e60aa7 2172
d62a17ae 2173 /* Next, deal with the import side. */
2174 if (is_import_rt_configured(vpn))
2175 evpn_unconfigure_import_rt(bgp, vpn, NULL);
90e60aa7 2176}
2177
10ebe1ab
MK
2178/*
2179 * Display import RT mapping to VRFs (vty handler)
5e53dce3 2180 * bgp_evpn: evpn bgp instance
10ebe1ab 2181 */
5e53dce3 2182static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
10ebe1ab
MK
2183 json_object *json)
2184{
2185 void *args[2];
2186
2187 args[0] = vty;
2188 args[1] = json;
2189
5e53dce3 2190 hash_iterate(bgp_evpn->vrf_import_rt_hash,
e3b78da8 2191 (void (*)(struct hash_bucket *,
996c9314 2192 void *))show_vrf_import_rt_entry,
10ebe1ab
MK
2193 args);
2194}
2195
520d5d76 2196/*
2197 * Display import RT mapping to VNIs (vty handler)
2198 */
9c92b5f7
MK
2199static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2200 json_object *json)
520d5d76 2201{
9c92b5f7
MK
2202 void *args[2];
2203
2204 args[0] = vty;
2205 args[1] = json;
2206
d62a17ae 2207 hash_iterate(
2208 bgp->import_rt_hash,
e3b78da8 2209 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
9c92b5f7 2210 args);
520d5d76 2211}
2212
2213/*
2214 * Display EVPN routes for all VNIs - vty handler.
2215 */
d62a17ae 2216static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
c7ef6cf2
NS
2217 struct in_addr vtep_ip, json_object *json,
2218 int detail)
520d5d76 2219{
d7c0a89a 2220 uint32_t num_vnis;
d62a17ae 2221 struct vni_walk_ctx wctx;
520d5d76 2222
d62a17ae 2223 num_vnis = hashcount(bgp->vnihash);
2224 if (!num_vnis)
2225 return;
2226 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2227 wctx.bgp = bgp;
2228 wctx.vty = vty;
2229 wctx.vtep_ip = vtep_ip;
9c92b5f7 2230 wctx.json = json;
c7ef6cf2 2231 wctx.detail = detail;
e3b78da8 2232 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
9d303b37
DL
2233 void *))show_vni_routes_hash,
2234 &wctx);
520d5d76 2235}
2236
2237/*
2238 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2239 */
d62a17ae 2240static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2241 vni_t vni, struct in_addr orig_ip,
2242 json_object *json)
d62a17ae 2243{
2244 struct bgpevpn *vpn;
2245 struct prefix_evpn p;
9bcb3eef 2246 struct bgp_dest *dest;
40381db7 2247 struct bgp_path_info *pi;
d7c0a89a 2248 uint32_t path_cnt = 0;
d62a17ae 2249 afi_t afi;
2250 safi_t safi;
9c92b5f7 2251 json_object *json_paths = NULL;
d62a17ae 2252
2253 afi = AFI_L2VPN;
2254 safi = SAFI_EVPN;
2255
2256 /* Locate VNI. */
2257 vpn = bgp_evpn_lookup_vni(bgp, vni);
2258 if (!vpn) {
2259 vty_out(vty, "VNI not found\n");
2260 return;
2261 }
2262
2263 /* See if route exists. */
2264 build_evpn_type3_prefix(&p, orig_ip);
9bcb3eef
DS
2265 dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2266 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2267 if (!json)
2268 vty_out(vty, "%% Network not in table\n");
d62a17ae 2269 return;
2270 }
2271
9c92b5f7
MK
2272 if (json)
2273 json_paths = json_object_new_array();
2274
d62a17ae 2275 /* Prefix and num paths displayed once per prefix. */
9bcb3eef 2276 route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json);
d62a17ae 2277
2278 /* Display each path for this prefix. */
9bcb3eef 2279 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2280 json_object *json_path = NULL;
2281
2282 if (json)
2283 json_path = json_object_new_array();
2284
9bcb3eef 2285 route_vty_out_detail(vty, bgp, dest, pi, afi, safi, json_path);
9c92b5f7
MK
2286
2287 if (json)
2288 json_object_array_add(json_paths, json_path);
2289
d62a17ae 2290 path_cnt++;
2291 }
2292
9c92b5f7
MK
2293 if (json) {
2294 if (path_cnt)
2295 json_object_object_add(json, "paths", json_paths);
2296
2297 json_object_int_add(json, "numPaths", path_cnt);
2298 } else {
2299 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2300 path_cnt);
2301 }
520d5d76 2302}
2303
2304/*
2305 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2306 * By definition, only matching type-2 route will be displayed.
2307 */
d62a17ae 2308static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2309 vni_t vni, struct ethaddr *mac,
9c92b5f7 2310 struct ipaddr *ip, json_object *json)
d62a17ae 2311{
2312 struct bgpevpn *vpn;
2313 struct prefix_evpn p;
9bcb3eef 2314 struct bgp_dest *dest;
40381db7 2315 struct bgp_path_info *pi;
d7c0a89a 2316 uint32_t path_cnt = 0;
d62a17ae 2317 afi_t afi;
2318 safi_t safi;
9c92b5f7 2319 json_object *json_paths = NULL;
d62a17ae 2320
2321 afi = AFI_L2VPN;
2322 safi = SAFI_EVPN;
2323
2324 /* Locate VNI. */
2325 vpn = bgp_evpn_lookup_vni(bgp, vni);
2326 if (!vpn) {
9c92b5f7
MK
2327 if (!json)
2328 vty_out(vty, "VNI not found\n");
d62a17ae 2329 return;
2330 }
2331
2332 /* See if route exists. Look for both non-sticky and sticky. */
2333 build_evpn_type2_prefix(&p, mac, ip);
9bcb3eef
DS
2334 dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2335 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2336 if (!json)
2337 vty_out(vty, "%% Network not in table\n");
d62a17ae 2338 return;
2339 }
2340
9c92b5f7
MK
2341 if (json)
2342 json_paths = json_object_new_array();
2343
d62a17ae 2344 /* Prefix and num paths displayed once per prefix. */
9bcb3eef 2345 route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json);
d62a17ae 2346
2347 /* Display each path for this prefix. */
9bcb3eef 2348 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2349 json_object *json_path = NULL;
2350
2351 if (json)
2352 json_path = json_object_new_array();
2353
9bcb3eef 2354 route_vty_out_detail(vty, bgp, dest, pi, afi, safi, json_path);
9c92b5f7
MK
2355
2356 if (json)
2357 json_object_array_add(json_paths, json_path);
2358
d62a17ae 2359 path_cnt++;
2360 }
2361
9c92b5f7
MK
2362 if (json) {
2363 if (path_cnt)
2364 json_object_object_add(json, "paths", json_paths);
2365
2366 json_object_int_add(json, "numPaths", path_cnt);
2367 } else {
2368 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2369 path_cnt);
2370 }
520d5d76 2371}
2372
50f74cf1 2373/* Disaplay EVPN routes for a ESI - VTY handler */
2374static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2375 esi_t *esi, json_object *json)
2376{
b5e140c8 2377 struct bgp_evpn_es *es = NULL;
50f74cf1 2378
2379 /* locate the ES */
b5e140c8 2380 es = bgp_evpn_es_find(esi);
50f74cf1 2381 if (!es) {
2382 if (!json)
2383 vty_out(vty, "ESI not found\n");
2384 return;
2385 }
2386
2387 show_esi_routes(bgp, es, vty, json);
2388}
2389
520d5d76 2390/*
2391 * Display EVPN routes for a VNI - vty handler.
2392 * If 'type' is non-zero, only routes matching that type are shown.
2393 * If the vtep_ip is non zero, only routes behind that vtep are shown
2394 */
d62a17ae 2395static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
9c92b5f7
MK
2396 int type, struct in_addr vtep_ip,
2397 json_object *json)
520d5d76 2398{
d62a17ae 2399 struct bgpevpn *vpn;
520d5d76 2400
d62a17ae 2401 /* Locate VNI. */
2402 vpn = bgp_evpn_lookup_vni(bgp, vni);
2403 if (!vpn) {
9c92b5f7
MK
2404 if (!json)
2405 vty_out(vty, "VNI not found\n");
d62a17ae 2406 return;
2407 }
520d5d76 2408
d62a17ae 2409 /* Walk this VNI's route table and display appropriate routes. */
c7ef6cf2 2410 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json, 0);
520d5d76 2411}
2412
2413/*
2414 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2415 * IP (vty handler). By definition, only matching type-2 route will be
2416 * displayed.
2417 */
d62a17ae 2418static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2419 struct prefix_rd *prd, struct ethaddr *mac,
9c92b5f7 2420 struct ipaddr *ip, json_object *json)
d62a17ae 2421{
2422 struct prefix_evpn p;
9bcb3eef 2423 struct bgp_dest *dest;
40381db7 2424 struct bgp_path_info *pi;
d62a17ae 2425 afi_t afi;
2426 safi_t safi;
d7c0a89a 2427 uint32_t path_cnt = 0;
9c92b5f7
MK
2428 json_object *json_paths = NULL;
2429 char prefix_str[BUFSIZ];
d62a17ae 2430
2431 afi = AFI_L2VPN;
2432 safi = SAFI_EVPN;
2433
2434 /* See if route exists. Look for both non-sticky and sticky. */
2435 build_evpn_type2_prefix(&p, mac, ip);
9bcb3eef
DS
2436 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2437 (struct prefix *)&p, prd);
2438 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2439 if (!json)
2440 vty_out(vty, "%% Network not in table\n");
d62a17ae 2441 return;
2442 }
2443
c4efd0f4 2444 bgp_evpn_route2str(&p, prefix_str, sizeof(prefix_str));
9c92b5f7 2445
d62a17ae 2446 /* Prefix and num paths displayed once per prefix. */
9bcb3eef 2447 route_vty_out_detail_header(vty, bgp, dest, prd, afi, safi, json);
9c92b5f7
MK
2448
2449 if (json)
2450 json_paths = json_object_new_array();
d62a17ae 2451
2452 /* Display each path for this prefix. */
9bcb3eef 2453 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2454 json_object *json_path = NULL;
2455
2456 if (json)
2457 json_path = json_object_new_array();
2458
9bcb3eef 2459 route_vty_out_detail(vty, bgp, dest, pi, afi, safi, json_path);
9c92b5f7
MK
2460
2461 if (json)
2462 json_object_array_add(json_paths, json_path);
2463
d62a17ae 2464 path_cnt++;
2465 }
2466
9c92b5f7
MK
2467 if (json && path_cnt) {
2468 if (path_cnt)
2469 json_object_object_add(json, prefix_str, json_paths);
2470 json_object_int_add(json, "numPaths", path_cnt);
2471 } else {
2472 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2473 path_cnt);
2474 }
520d5d76 2475}
2476
2477/*
2478 * Display BGP EVPN routing table -- for specific RD (vty handler)
2479 * If 'type' is non-zero, only routes matching that type are shown.
2480 */
d62a17ae 2481static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2482 struct prefix_rd *prd, int type,
2483 json_object *json)
d62a17ae 2484{
9bcb3eef 2485 struct bgp_dest *rd_dest;
d62a17ae 2486 struct bgp_table *table;
9bcb3eef 2487 struct bgp_dest *dest;
40381db7 2488 struct bgp_path_info *pi;
d62a17ae 2489 int rd_header = 1;
2490 afi_t afi;
2491 safi_t safi;
d7c0a89a 2492 uint32_t prefix_cnt, path_cnt;
9c92b5f7
MK
2493 char rd_str[RD_ADDRSTRLEN];
2494 json_object *json_rd = NULL;
2495 int add_rd_to_json = 0;
d62a17ae 2496
2497 afi = AFI_L2VPN;
2498 safi = SAFI_EVPN;
2499 prefix_cnt = path_cnt = 0;
2500
c4efd0f4 2501 prefix_rd2str(prd, rd_str, sizeof(rd_str));
9c92b5f7 2502
9bcb3eef
DS
2503 rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2504 if (!rd_dest)
d62a17ae 2505 return;
9c92b5f7 2506
9bcb3eef 2507 table = bgp_dest_get_bgp_table_info(rd_dest);
d62a17ae 2508 if (table == NULL)
2509 return;
2510
9c92b5f7
MK
2511 if (json) {
2512 json_rd = json_object_new_object();
2513 json_object_string_add(json_rd, "rd", rd_str);
2514 }
2515
d62a17ae 2516 /* Display all prefixes with this RD. */
9bcb3eef 2517 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
b54892e0 2518 const struct prefix_evpn *evp =
9bcb3eef 2519 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
9c92b5f7
MK
2520 json_object *json_prefix = NULL;
2521 json_object *json_paths = NULL;
2522 char prefix_str[BUFSIZ];
2523 int add_prefix_to_json = 0;
2524
b54892e0 2525 bgp_evpn_route2str((struct prefix_evpn *)evp, prefix_str,
9c92b5f7 2526 sizeof(prefix_str));
d62a17ae 2527
2528 if (type && evp->prefix.route_type != type)
2529 continue;
2530
9c92b5f7
MK
2531 if (json)
2532 json_prefix = json_object_new_object();
2533
9bcb3eef 2534 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2535 if (pi) {
d62a17ae 2536 /* RD header and legend - once overall. */
9c92b5f7 2537 if (rd_header && !json) {
d62a17ae 2538 vty_out(vty,
554cd77a 2539 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
d62a17ae 2540 vty_out(vty,
342dd0c6 2541 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2542 vty_out(vty,
554cd77a 2543 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
d62a17ae 2544 rd_header = 0;
2545 }
2546
2547 /* Prefix and num paths displayed once per prefix. */
9bcb3eef 2548 route_vty_out_detail_header(vty, bgp, dest, prd, afi,
9c92b5f7 2549 safi, json_prefix);
d62a17ae 2550
2551 prefix_cnt++;
2552 }
2553
9c92b5f7
MK
2554 if (json)
2555 json_paths = json_object_new_array();
2556
d62a17ae 2557 /* Display each path for this prefix. */
6f94b685 2558 for (; pi; pi = pi->next) {
9c92b5f7
MK
2559 json_object *json_path = NULL;
2560
2561 if (json)
2562 json_path = json_object_new_array();
2563
9bcb3eef 2564 route_vty_out_detail(vty, bgp, dest, pi, afi, safi,
9c92b5f7
MK
2565 json_path);
2566
2567 if (json)
2568 json_object_array_add(json_paths, json_path);
2569
d62a17ae 2570 path_cnt++;
9c92b5f7
MK
2571 add_prefix_to_json = 1;
2572 add_rd_to_json = 1;
2573 }
2574
a1df2ac5
CS
2575 if (json) {
2576 if (add_prefix_to_json) {
2577 json_object_object_add(json_prefix, "paths",
2578 json_paths);
2579 json_object_object_add(json_rd, prefix_str,
2580 json_prefix);
2581 } else {
2582 json_object_free(json_paths);
2583 json_object_free(json_prefix);
2584 json_paths = NULL;
2585 json_prefix = NULL;
2586 }
d62a17ae 2587 }
2588 }
2589
9c92b5f7 2590 if (json) {
a1df2ac5
CS
2591 if (add_rd_to_json)
2592 json_object_object_add(json, rd_str, json_rd);
2593 else {
2594 json_object_free(json_rd);
2595 json_rd = NULL;
2596 }
2597
9c92b5f7
MK
2598 json_object_int_add(json, "numPrefix", prefix_cnt);
2599 json_object_int_add(json, "numPaths", path_cnt);
2600 } else {
2601 if (prefix_cnt == 0)
2602 vty_out(vty, "No prefixes exist with this RD%s\n",
2603 type ? " (of requested type)" : "");
2604 else
2605 vty_out(vty,
2606 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2607 prefix_cnt, path_cnt,
2608 type ? " (of requested type)" : "");
2609 }
520d5d76 2610}
2611
2612/*
2613 * Display BGP EVPN routing table - all routes (vty handler).
2614 * If 'type' is non-zero, only routes matching that type are shown.
2615 */
9c92b5f7 2616static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
21f3551e 2617 json_object *json, int detail)
d62a17ae 2618{
9bcb3eef 2619 struct bgp_dest *rd_dest;
d62a17ae 2620 struct bgp_table *table;
9bcb3eef 2621 struct bgp_dest *dest;
40381db7 2622 struct bgp_path_info *pi;
21f3551e 2623 int header = detail ? 0 : 1;
d62a17ae 2624 int rd_header;
2625 afi_t afi;
2626 safi_t safi;
d7c0a89a 2627 uint32_t prefix_cnt, path_cnt;
d62a17ae 2628
2629 afi = AFI_L2VPN;
2630 safi = SAFI_EVPN;
2631 prefix_cnt = path_cnt = 0;
2632
2633 /* EVPN routing table is a 2-level table with the first level being
2634 * the RD.
2635 */
9bcb3eef
DS
2636 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
2637 rd_dest = bgp_route_next(rd_dest)) {
9c92b5f7
MK
2638 char rd_str[RD_ADDRSTRLEN];
2639 json_object *json_rd = NULL; /* contains routes for an RD */
2640 int add_rd_to_json = 0;
2dd32217 2641 uint64_t tbl_ver;
9bcb3eef 2642 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
9c92b5f7 2643
9bcb3eef 2644 table = bgp_dest_get_bgp_table_info(rd_dest);
d62a17ae 2645 if (table == NULL)
2646 continue;
2647
2dd32217 2648 tbl_ver = table->version;
9bcb3eef 2649 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
9c92b5f7
MK
2650 sizeof(rd_str));
2651
90c31d71 2652 if (json)
9c92b5f7 2653 json_rd = json_object_new_object();
9c92b5f7 2654
d62a17ae 2655 rd_header = 1;
2656
2657 /* Display all prefixes for an RD */
9bcb3eef
DS
2658 for (dest = bgp_table_top(table); dest;
2659 dest = bgp_route_next(dest)) {
9c92b5f7
MK
2660 json_object *json_prefix =
2661 NULL; /* contains prefix under a RD */
2662 json_object *json_paths =
2663 NULL; /* array of paths under a prefix*/
b54892e0 2664 const struct prefix_evpn *evp =
9bcb3eef
DS
2665 (const struct prefix_evpn *)bgp_dest_get_prefix(
2666 dest);
9c92b5f7
MK
2667 char prefix_str[BUFSIZ];
2668 int add_prefix_to_json = 0;
9bcb3eef 2669 const struct prefix *p = bgp_dest_get_prefix(dest);
9c92b5f7 2670
b54892e0
DS
2671 bgp_evpn_route2str((struct prefix_evpn *)p, prefix_str,
2672 sizeof(prefix_str));
d62a17ae 2673
2674 if (type && evp->prefix.route_type != type)
2675 continue;
2676
9bcb3eef 2677 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2678 if (pi) {
d62a17ae 2679 /* Overall header/legend displayed once. */
2680 if (header) {
9c92b5f7 2681 bgp_evpn_show_route_header(vty, bgp,
2dd32217 2682 tbl_ver,
9c92b5f7 2683 json);
c684d477
CS
2684 if (!json)
2685 vty_out(vty,
2686 "%19s Extended Community\n"
6f214dd3 2687 , " ");
d62a17ae 2688 header = 0;
2689 }
2690
2691 /* RD header - per RD. */
2692 if (rd_header) {
9c92b5f7 2693 bgp_evpn_show_route_rd_header(
9bcb3eef 2694 vty, rd_dest, json_rd, rd_str,
c69e79f1 2695 RD_ADDRSTRLEN);
d62a17ae 2696 rd_header = 0;
2697 }
2698
2699 prefix_cnt++;
2700 }
2701
9c92b5f7
MK
2702 if (json) {
2703 json_prefix = json_object_new_object();
2704 json_paths = json_object_new_array();
2705 json_object_string_add(json_prefix, "prefix",
2706 prefix_str);
2707 json_object_int_add(json_prefix, "prefixLen",
b54892e0 2708 p->prefixlen);
9c92b5f7
MK
2709 }
2710
21f3551e
NS
2711 /* Prefix and num paths displayed once per prefix. */
2712 if (detail)
2713 route_vty_out_detail_header(
9bcb3eef
DS
2714 vty, bgp, dest,
2715 (struct prefix_rd *)rd_destp, AFI_L2VPN,
b54892e0 2716 SAFI_EVPN, json_prefix);
21f3551e 2717
d62a17ae 2718 /* For EVPN, the prefix is displayed for each path (to
2719 * fit in
2720 * with code that already exists).
2721 */
6f94b685 2722 for (; pi; pi = pi->next) {
9c92b5f7 2723 json_object *json_path = NULL;
d62a17ae 2724 path_cnt++;
9c92b5f7
MK
2725 add_prefix_to_json = 1;
2726 add_rd_to_json = 1;
2727
2728 if (json)
2729 json_path = json_object_new_array();
2730
21f3551e
NS
2731 if (detail) {
2732 route_vty_out_detail(
9bcb3eef 2733 vty, bgp, dest, pi, AFI_L2VPN,
21f3551e
NS
2734 SAFI_EVPN, json_path);
2735 } else
b54892e0 2736 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
ae248832 2737 json_path, false);
9c92b5f7
MK
2738
2739 if (json)
2740 json_object_array_add(json_paths,
2741 json_path);
2742 }
2743
a1df2ac5
CS
2744 if (json) {
2745 if (add_prefix_to_json) {
2746 json_object_object_add(json_prefix,
2747 "paths",
2748 json_paths);
2749 json_object_object_add(json_rd,
2750 prefix_str,
2751 json_prefix);
2752 } else {
2753 json_object_free(json_prefix);
2754 json_object_free(json_paths);
2755 json_prefix = NULL;
2756 json_paths = NULL;
2757 }
d62a17ae 2758 }
2759 }
9c92b5f7 2760
a1df2ac5
CS
2761 if (json) {
2762 if (add_rd_to_json)
2763 json_object_object_add(json, rd_str, json_rd);
2764 else {
2765 json_object_free(json_rd);
2766 json_rd = NULL;
2767 }
2768 }
d62a17ae 2769 }
2770
9c92b5f7
MK
2771 if (json) {
2772 json_object_int_add(json, "numPrefix", prefix_cnt);
2773 json_object_int_add(json, "numPaths", path_cnt);
2774 } else {
2775 if (prefix_cnt == 0) {
2776 vty_out(vty, "No EVPN prefixes %sexist\n",
2777 type ? "(of requested type) " : "");
2778 } else {
2779 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2780 prefix_cnt, path_cnt,
2781 type ? " (of requested type)" : "");
2782 }
2783 }
520d5d76 2784}
2785
2786/*
2787 * Display specified VNI (vty handler)
2788 */
9c92b5f7
MK
2789static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2790 json_object *json)
520d5d76 2791{
d7c0a89a 2792 uint8_t found = 0;
d62a17ae 2793 struct bgpevpn *vpn;
520d5d76 2794
d62a17ae 2795 vpn = bgp_evpn_lookup_vni(bgp, vni);
4cce389e
MK
2796 if (vpn) {
2797 found = 1;
2798 display_vni(vty, vpn, json);
2799 } else {
2800 struct bgp *bgp_temp;
2801 struct listnode *node = NULL;
2802
2803 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2804 if (bgp_temp->l3vni == vni) {
2805 found = 1;
2806 display_l3vni(vty, bgp_temp, json);
2807 }
2808 }
2809 }
2810
2811 if (!found) {
9c92b5f7
MK
2812 if (json) {
2813 vty_out(vty, "{}\n");
2814 } else {
2815 vty_out(vty, "VNI not found\n");
2816 return;
2817 }
d62a17ae 2818 }
520d5d76 2819}
2820
2821/*
2822 * Display a VNI (upon user query).
2823 */
9c92b5f7
MK
2824static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2825 json_object *json)
520d5d76 2826{
9c92b5f7 2827 void *args[2];
4cce389e
MK
2828 struct bgp *bgp_temp = NULL;
2829 struct listnode *node;
520d5d76 2830
9c92b5f7 2831
4cce389e 2832 if (!json) {
9c92b5f7 2833 vty_out(vty, "Flags: * - Kernel\n");
4cce389e 2834 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
996c9314 2835 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
9c92b5f7
MK
2836 }
2837
4cce389e 2838 /* print all L2 VNIS */
9c92b5f7
MK
2839 args[0] = vty;
2840 args[1] = json;
d62a17ae 2841 hash_iterate(bgp->vnihash,
e3b78da8 2842 (void (*)(struct hash_bucket *, void *))show_vni_entry,
9c92b5f7 2843 args);
4cce389e
MK
2844
2845 /* print all L3 VNIs */
2846 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
2847 show_l3vni_entry(vty, bgp_temp, json);
520d5d76 2848}
2849
24864e44
CS
2850/*
2851 * evpn - enable advertisement of svi MAC-IP
2852 */
2853static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
2854 uint32_t set)
2855{
2856 if (!vpn) {
2857 if (set && bgp->evpn_info->advertise_svi_macip)
2858 return;
2859 else if (!set && !bgp->evpn_info->advertise_svi_macip)
2860 return;
2861
2862 bgp->evpn_info->advertise_svi_macip = set;
2863 bgp_zebra_advertise_svi_macip(bgp,
2864 bgp->evpn_info->advertise_svi_macip, 0);
2865 } else {
2866 if (set && vpn->advertise_svi_macip)
2867 return;
2868 else if (!set && !vpn->advertise_svi_macip)
2869 return;
2870
2871 vpn->advertise_svi_macip = set;
2872 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
2873 vpn->vni);
2874 }
2875}
2876
1a98c087
MK
2877/*
2878 * evpn - enable advertisement of default g/w
2879 */
2880static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2881{
2882 if (!vpn) {
2883 if (bgp->advertise_gw_macip)
2884 return;
2885
2886 bgp->advertise_gw_macip = 1;
2887 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2888 } else {
2889 if (vpn->advertise_gw_macip)
2890 return;
2891
2892 vpn->advertise_gw_macip = 1;
2893 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2894 vpn->vni);
2895 }
2896 return;
2897}
2898
2899/*
2900 * evpn - disable advertisement of default g/w
2901 */
2902static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2903 struct bgpevpn *vpn)
2904{
2905 if (!vpn) {
2906 if (!bgp->advertise_gw_macip)
2907 return;
2908
2909 bgp->advertise_gw_macip = 0;
2910 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2911 } else {
2912 if (!vpn->advertise_gw_macip)
2913 return;
2914
2915 vpn->advertise_gw_macip = 0;
2916 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2917 vpn->vni);
2918 }
2919 return;
2920}
2921
486456ca
MK
2922/*
2923 * evpn - enable advertisement of default g/w
2924 */
2925static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
5fd9c12b 2926 afi_t afi, bool add)
486456ca 2927{
486456ca
MK
2928 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
2929
486456ca
MK
2930 if (add) {
2931 /* bail if we are already advertising default route */
2932 if (evpn_default_originate_set(bgp_vrf, afi, safi))
2933 return;
2934
2935 if (afi == AFI_IP)
2936 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2937 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2938 else if (afi == AFI_IP6)
2939 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2940 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca
MK
2941 } else {
2942 /* bail out if we havent advertised the default route */
2943 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
2944 return;
2945 if (afi == AFI_IP)
2946 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2947 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2948 else if (afi == AFI_IP6)
2949 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2950 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca 2951 }
5fd9c12b
KA
2952
2953 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
486456ca
MK
2954}
2955
31310b25
MK
2956/*
2957 * evpn - enable advertisement of default g/w
2958 */
2959static void evpn_set_advertise_subnet(struct bgp *bgp,
2960 struct bgpevpn *vpn)
2961{
2962 if (vpn->advertise_subnet)
2963 return;
2964
2965 vpn->advertise_subnet = 1;
2966 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2967}
2968
2969/*
2970 * evpn - disable advertisement of default g/w
2971 */
996c9314 2972static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
31310b25
MK
2973{
2974 if (!vpn->advertise_subnet)
2975 return;
2976
2977 vpn->advertise_subnet = 0;
2978 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2979}
2980
7724c0a1 2981/*
2982 * EVPN (VNI advertisement) enabled. Register with zebra.
2983 */
d62a17ae 2984static void evpn_set_advertise_all_vni(struct bgp *bgp)
7724c0a1 2985{
d62a17ae 2986 bgp->advertise_all_vni = 1;
e2f3a930 2987 bgp_set_evpn(bgp);
d62a17ae 2988 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
7724c0a1 2989}
2990
2991/*
2992 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2993 * cache, EVPN routes (delete and withdraw from peers).
2994 */
d62a17ae 2995static void evpn_unset_advertise_all_vni(struct bgp *bgp)
7724c0a1 2996{
d62a17ae 2997 bgp->advertise_all_vni = 0;
e2f3a930 2998 bgp_set_evpn(bgp_get_default());
d62a17ae 2999 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3000 bgp_evpn_cleanup_on_disable(bgp);
7724c0a1 3001}
bf1061d8
VB
3002
3003/*
3004 * EVPN - use RFC8365 to auto-derive RT
3005 */
3006static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3007{
3008 bgp->advertise_autort_rfc8365 = 1;
3009 bgp_evpn_handle_autort_change(bgp);
3010}
3011
3012/*
3013 * EVPN - don't use RFC8365 to auto-derive RT
3014 */
3015static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3016{
3017 bgp->advertise_autort_rfc8365 = 0;
3018 bgp_evpn_handle_autort_change(bgp);
3019}
7724c0a1 3020
2b791107 3021static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
d62a17ae 3022{
06b9f471 3023 char buf1[RD_ADDRSTRLEN];
d62a17ae 3024 char *ecom_str;
3025 struct listnode *node, *nnode;
3026 struct ecommunity *ecom;
3027
3028 if (is_vni_configured(vpn)) {
d62a17ae 3029 vty_out(vty, " vni %d\n", vpn->vni);
3030 if (is_rd_configured(vpn))
3031 vty_out(vty, " rd %s\n",
06b9f471 3032 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
d62a17ae 3033
3034 if (is_import_rt_configured(vpn)) {
3035 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3036 ecom)) {
3037 ecom_str = ecommunity_ecom2str(
3038 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3039 vty_out(vty, " route-target import %s\n",
3040 ecom_str);
3041 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3042 }
3043 }
3044
3045 if (is_export_rt_configured(vpn)) {
3046 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3047 ecom)) {
3048 ecom_str = ecommunity_ecom2str(
3049 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 3050 vty_out(vty, " route-target export %s\n",
d62a17ae 3051 ecom_str);
3052 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3053 }
3054 }
3055
1a98c087
MK
3056 if (vpn->advertise_gw_macip)
3057 vty_out(vty, " advertise-default-gw\n");
3058
24864e44
CS
3059 if (vpn->advertise_svi_macip)
3060 vty_out(vty, " advertise-svi-ip\n");
3061
31310b25
MK
3062 if (vpn->advertise_subnet)
3063 vty_out(vty, " advertise-subnet\n");
3064
d62a17ae 3065 vty_out(vty, " exit-vni\n");
3066 }
3067}
3068
fd069644
DS
3069#ifndef VTYSH_EXTRACT_PL
3070#include "bgpd/bgp_evpn_vty_clippy.c"
3071#endif
3072
3073DEFPY(bgp_evpn_flood_control,
3074 bgp_evpn_flood_control_cmd,
3075 "[no$no] flooding <disable$disable|head-end-replication$her>",
3076 NO_STR
3077 "Specify handling for BUM packets\n"
3078 "Do not flood any BUM packets\n"
3079 "Flood BUM packets using head-end replication\n")
3080{
3081 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3082 enum vxlan_flood_control flood_ctrl;
3083
3084 if (!bgp)
3085 return CMD_WARNING;
3086
3087 if (disable && !no)
3088 flood_ctrl = VXLAN_FLOOD_DISABLED;
3089 else if (her || no)
3090 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3091 else
3092 return CMD_WARNING;
3093
3094 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3095 return CMD_SUCCESS;
3096
3097 bgp->vxlan_flood_ctrl = flood_ctrl;
3098 bgp_evpn_flood_control_change(bgp);
3099
3100 return CMD_SUCCESS;
3101}
3102
1a98c087
MK
3103DEFUN (bgp_evpn_advertise_default_gw_vni,
3104 bgp_evpn_advertise_default_gw_vni_cmd,
3105 "advertise-default-gw",
078af92e 3106 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
1a98c087
MK
3107{
3108 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3109 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3110
3111 if (!bgp)
3112 return CMD_WARNING;
3113
1a98c087
MK
3114 evpn_set_advertise_default_gw(bgp, vpn);
3115
3116 return CMD_SUCCESS;
3117}
3118
3119DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3120 no_bgp_evpn_advertise_default_gw_vni_cmd,
3121 "no advertise-default-gw",
3122 NO_STR
3123 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3124{
3125 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3126 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3127
3128 if (!bgp)
3129 return CMD_WARNING;
3130
1a98c087
MK
3131 evpn_unset_advertise_default_gw(bgp, vpn);
3132
3133 return CMD_SUCCESS;
3134}
3135
3136
3137DEFUN (bgp_evpn_advertise_default_gw,
3138 bgp_evpn_advertise_default_gw_cmd,
3139 "advertise-default-gw",
078af92e 3140 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
3141{
3142 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3143
3144 if (!bgp)
3145 return CMD_WARNING;
3146
f920dd6d 3147 if (!EVPN_ENABLED(bgp)) {
7da47d66 3148 vty_out(vty,
530db8dc 3149 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3150 return CMD_WARNING;
3151 }
3152
1a98c087
MK
3153 evpn_set_advertise_default_gw(bgp, NULL);
3154
3155 return CMD_SUCCESS;
3156}
3157
3158DEFUN (no_bgp_evpn_advertise_default_gw,
3159 no_bgp_evpn_advertise_default_gw_cmd,
3160 "no advertise-default-gw",
3161 NO_STR
3162 "Withdraw All default g/w mac-ip routes from EVPN\n")
3163{
3164 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3165
3166 if (!bgp)
3167 return CMD_WARNING;
3168
f920dd6d 3169 if (!EVPN_ENABLED(bgp)) {
7da47d66 3170 vty_out(vty,
530db8dc 3171 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3172 return CMD_WARNING;
3173 }
3174
1a98c087
MK
3175 evpn_unset_advertise_default_gw(bgp, NULL);
3176
3177 return CMD_SUCCESS;
3178}
3179
7724c0a1 3180DEFUN (bgp_evpn_advertise_all_vni,
3181 bgp_evpn_advertise_all_vni_cmd,
3182 "advertise-all-vni",
3183 "Advertise All local VNIs\n")
3184{
d62a17ae 3185 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
e2f3a930 3186 struct bgp *bgp_evpn = NULL;
7724c0a1 3187
d62a17ae 3188 if (!bgp)
3189 return CMD_WARNING;
e2f3a930
T
3190
3191 bgp_evpn = bgp_get_evpn();
3192 if (bgp_evpn && bgp_evpn != bgp) {
3193 vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n",
3194 bgp_evpn->name);
3195 return CMD_WARNING_CONFIG_FAILED;
3196 }
3197
d62a17ae 3198 evpn_set_advertise_all_vni(bgp);
3199 return CMD_SUCCESS;
7724c0a1 3200}
3201
3202DEFUN (no_bgp_evpn_advertise_all_vni,
3203 no_bgp_evpn_advertise_all_vni_cmd,
3204 "no advertise-all-vni",
3205 NO_STR
3206 "Advertise All local VNIs\n")
3207{
d62a17ae 3208 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 3209
d62a17ae 3210 if (!bgp)
3211 return CMD_WARNING;
3212 evpn_unset_advertise_all_vni(bgp);
3213 return CMD_SUCCESS;
7724c0a1 3214}
3215
bf1061d8
VB
3216DEFUN (bgp_evpn_advertise_autort_rfc8365,
3217 bgp_evpn_advertise_autort_rfc8365_cmd,
3218 "autort rfc8365-compatible",
3219 "Auto-derivation of RT\n"
3220 "Auto-derivation of RT using RFC8365\n")
3221{
3222 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3223
3224 if (!bgp)
3225 return CMD_WARNING;
3226 evpn_set_advertise_autort_rfc8365(bgp);
3227 return CMD_SUCCESS;
3228}
3229
3230DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3231 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3232 "no autort rfc8365-compatible",
3233 NO_STR
3234 "Auto-derivation of RT\n"
3235 "Auto-derivation of RT using RFC8365\n")
3236{
3237 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3238
3239 if (!bgp)
3240 return CMD_WARNING;
3241 evpn_unset_advertise_autort_rfc8365(bgp);
3242 return CMD_SUCCESS;
3243}
3244
486456ca
MK
3245DEFUN (bgp_evpn_default_originate,
3246 bgp_evpn_default_originate_cmd,
3247 "default-originate <ipv4 | ipv6>",
3248 "originate a default route\n"
3249 "ipv4 address family\n"
3250 "ipv6 address family\n")
3251{
3252 afi_t afi = 0;
3253 int idx_afi = 0;
3254 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3255
3256 if (!bgp_vrf)
3257 return CMD_WARNING;
3258 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3259 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
486456ca
MK
3260 return CMD_SUCCESS;
3261}
3262
3263DEFUN (no_bgp_evpn_default_originate,
3264 no_bgp_evpn_default_originate_cmd,
3265 "no default-originate <ipv4 | ipv6>",
3266 NO_STR
3267 "withdraw a default route\n"
3268 "ipv4 address family\n"
3269 "ipv6 address family\n")
3270{
3271 afi_t afi = 0;
3272 int idx_afi = 0;
3273 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3274
3275 if (!bgp_vrf)
3276 return CMD_WARNING;
3277 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3278 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
486456ca
MK
3279 return CMD_SUCCESS;
3280}
3281
0b9d9cd0
CS
3282DEFPY (dup_addr_detection,
3283 dup_addr_detection_cmd,
3284 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3285 "Duplicate address detection\n"
979777b2 3286 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3287 "Num of max allowed moves (2-1000) default 5\n"
3288 "Duplicate address detection time\n"
3289 "Time in seconds (2-1800) default 180\n")
3290{
3291 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3292
3293 if (!bgp_vrf)
3294 return CMD_WARNING;
3295
f920dd6d 3296 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3297 vty_out(vty,
530db8dc 3298 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3299 return CMD_WARNING;
3300 }
3301
0b9d9cd0
CS
3302 bgp_vrf->evpn_info->dup_addr_detect = true;
3303
3304 if (time_val)
3305 bgp_vrf->evpn_info->dad_time = time_val;
3306 if (max_moves_val)
3307 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3308
3309 bgp_zebra_dup_addr_detection(bgp_vrf);
3310
3311 return CMD_SUCCESS;
3312}
3313
3314DEFPY (dup_addr_detection_auto_recovery,
3315 dup_addr_detection_auto_recovery_cmd,
3316 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3317 "Duplicate address detection\n"
3318 "Duplicate address detection freeze\n"
3319 "Duplicate address detection permanent freeze\n"
3320 "Duplicate address detection freeze time (30-3600)\n")
3321{
3322 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3323 uint32_t freeze_time = freeze_time_val;
3324
3325 if (!bgp_vrf)
3326 return CMD_WARNING;
3327
f920dd6d 3328 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3329 vty_out(vty,
530db8dc 3330 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3331 return CMD_WARNING;
3332 }
3333
0b9d9cd0
CS
3334 bgp_vrf->evpn_info->dup_addr_detect = true;
3335 bgp_vrf->evpn_info->dad_freeze = true;
3336 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3337
3338 bgp_zebra_dup_addr_detection(bgp_vrf);
3339
3340 return CMD_SUCCESS;
3341}
3342
3343DEFPY (no_dup_addr_detection,
3344 no_dup_addr_detection_cmd,
3345 "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>]",
3346 NO_STR
3347 "Duplicate address detection\n"
979777b2 3348 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3349 "Num of max allowed moves (2-1000) default 5\n"
3350 "Duplicate address detection time\n"
3351 "Time in seconds (2-1800) default 180\n"
3352 "Duplicate address detection freeze\n"
3353 "Duplicate address detection permanent freeze\n"
3354 "Duplicate address detection freeze time (30-3600)\n")
3355{
3356 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3357 uint32_t max_moves = (uint32_t)max_moves_val;
3358 uint32_t freeze_time = (uint32_t)freeze_time_val;
3359
3360 if (!bgp_vrf)
3361 return CMD_WARNING;
3362
f920dd6d 3363 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3364 vty_out(vty,
530db8dc 3365 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3366 return CMD_WARNING;
3367 }
3368
0b9d9cd0
CS
3369 if (argc == 2) {
3370 if (!bgp_vrf->evpn_info->dup_addr_detect)
3371 return CMD_SUCCESS;
3372 /* Reset all parameters to default. */
3373 bgp_vrf->evpn_info->dup_addr_detect = false;
3374 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3375 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3376 bgp_vrf->evpn_info->dad_freeze = false;
3377 bgp_vrf->evpn_info->dad_freeze_time = 0;
3378 } else {
3379 if (max_moves) {
3380 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3381 vty_out(vty,
3382 "%% Value does not match with config\n");
3383 return CMD_SUCCESS;
3384 }
3385 bgp_vrf->evpn_info->dad_max_moves =
3386 EVPN_DAD_DEFAULT_MAX_MOVES;
3387 }
3388
3389 if (time_val) {
3390 if (bgp_vrf->evpn_info->dad_time != time_val) {
3391 vty_out(vty,
3392 "%% Value does not match with config\n");
3393 return CMD_SUCCESS;
3394 }
3395 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3396 }
3397
3398 if (freeze_time) {
3399 if (bgp_vrf->evpn_info->dad_freeze_time
3400 != freeze_time) {
3401 vty_out(vty,
3402 "%% Value does not match with config\n");
3403 return CMD_SUCCESS;
3404 }
3405 bgp_vrf->evpn_info->dad_freeze_time = 0;
3406 bgp_vrf->evpn_info->dad_freeze = false;
3407 }
3408
3409 if (permanent_val) {
3410 if (bgp_vrf->evpn_info->dad_freeze_time) {
3411 vty_out(vty,
3412 "%% Value does not match with config\n");
3413 return CMD_SUCCESS;
3414 }
3415 bgp_vrf->evpn_info->dad_freeze = false;
3416 }
3417 }
3418
3419 bgp_zebra_dup_addr_detection(bgp_vrf);
3420
3421 return CMD_SUCCESS;
3422}
3423
24864e44
CS
3424DEFPY(bgp_evpn_advertise_svi_ip,
3425 bgp_evpn_advertise_svi_ip_cmd,
3426 "[no$no] advertise-svi-ip",
3427 NO_STR
3428 "Advertise svi mac-ip routes in EVPN\n")
3429{
3430 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3431
3432 if (!bgp)
3433 return CMD_WARNING;
3434
f920dd6d 3435 if (!EVPN_ENABLED(bgp)) {
24864e44 3436 vty_out(vty,
530db8dc 3437 "This command is only supported under EVPN VRF\n");
24864e44
CS
3438 return CMD_WARNING;
3439 }
3440
3441 if (no)
3442 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3443 else
3444 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3445
3446 return CMD_SUCCESS;
3447}
3448
3449DEFPY(bgp_evpn_advertise_svi_ip_vni,
3450 bgp_evpn_advertise_svi_ip_vni_cmd,
3451 "[no$no] advertise-svi-ip",
3452 NO_STR
3453 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3454{
3455 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3456 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3457
3458 if (!bgp)
3459 return CMD_WARNING;
3460
24864e44
CS
3461 if (no)
3462 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3463 else
3464 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3465
3466 return CMD_SUCCESS;
3467}
3468
689b5101
MK
3469DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3470 bgp_evpn_advertise_vni_subnet_cmd,
3471 "advertise-subnet",
3472 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
3473{
3474 struct bgp *bgp_vrf = NULL;
3475 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3476 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3477
3478 if (!bgp)
3479 return CMD_WARNING;
3480
31310b25
MK
3481 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3482 if (!bgp_vrf)
3483 return CMD_WARNING;
3484
31310b25
MK
3485 evpn_set_advertise_subnet(bgp, vpn);
3486 return CMD_SUCCESS;
3487}
3488
689b5101
MK
3489DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3490 no_bgp_evpn_advertise_vni_subnet_cmd,
3491 "no advertise-subnet",
3492 NO_STR
3493 "Advertise All local VNIs\n")
31310b25
MK
3494{
3495 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3496 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3497
3498 if (!bgp)
3499 return CMD_WARNING;
3500
31310b25
MK
3501 evpn_unset_advertise_subnet(bgp, vpn);
3502 return CMD_SUCCESS;
3503}
3504
342dd0c6 3505DEFUN (bgp_evpn_advertise_type5,
3506 bgp_evpn_advertise_type5_cmd,
53c84f78 3507 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 3508 "Advertise prefix routes\n"
053905d2 3509 BGP_AFI_HELP_STR
53c84f78
MK
3510 BGP_SAFI_HELP_STR
3511 "route-map for filtering specific routes\n"
3512 "Name of the route map\n")
342dd0c6 3513{
3514 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3515 int idx_afi = 0;
3516 int idx_safi = 0;
53c84f78 3517 int idx_rmap = 0;
053905d2
MK
3518 afi_t afi = 0;
3519 safi_t safi = 0;
53c84f78
MK
3520 int ret = 0;
3521 int rmap_changed = 0;
053905d2
MK
3522
3523 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3524 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
53c84f78
MK
3525 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3526 if (ret) {
3527 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3528 rmap_changed = 1;
3529 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
3530 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3531 != 0)
53c84f78
MK
3532 rmap_changed = 1;
3533 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3534 rmap_changed = 1;
3535 }
053905d2 3536
e779dc76 3537 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3538 vty_out(vty,
3539 "%%only ipv4 or ipv6 address families are supported");
342dd0c6 3540 return CMD_WARNING;
3541 }
3542
053905d2
MK
3543 if (safi != SAFI_UNICAST) {
3544 vty_out(vty,
3545 "%%only ipv4 unicast or ipv6 unicast are supported");
3546 return CMD_WARNING;
3547 }
3548
3549 if (afi == AFI_IP) {
342dd0c6 3550
3551 /* if we are already advertising ipv4 prefix as type-5
523cafc4 3552 * nothing to do
3553 */
154faa50
MK
3554 if (!rmap_changed &&
3555 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3556 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
53c84f78 3557 return CMD_WARNING;
154faa50
MK
3558 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3559 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3560 } else {
3561
3562 /* if we are already advertising ipv6 prefix as type-5
523cafc4 3563 * nothing to do
3564 */
154faa50
MK
3565 if (!rmap_changed &&
3566 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3567 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
53c84f78 3568 return CMD_WARNING;
154faa50
MK
3569 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3570 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
53c84f78
MK
3571 }
3572
3573 if (rmap_changed) {
3574 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3575 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3576 XFREE(MTYPE_ROUTE_MAP_NAME,
3577 bgp_vrf->adv_cmd_rmap[afi][safi].name);
b4897fa5 3578 route_map_counter_decrement(
3579 bgp_vrf->adv_cmd_rmap[afi][safi].map);
53c84f78
MK
3580 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3581 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
342dd0c6 3582 }
3583 }
53c84f78
MK
3584
3585 /* set the route-map for advertise command */
3586 if (ret && argv[idx_rmap + 1]->arg) {
3587 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 3588 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
3589 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3590 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
b4897fa5 3591 route_map_counter_increment(
3592 bgp_vrf->adv_cmd_rmap[afi][safi].map);
53c84f78
MK
3593 }
3594
3595 /* advertise type-5 routes */
456a4697
AK
3596 if (advertise_type5_routes(bgp_vrf, afi))
3597 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 3598 return CMD_SUCCESS;
3599}
3600
3601DEFUN (no_bgp_evpn_advertise_type5,
3602 no_bgp_evpn_advertise_type5_cmd,
053905d2 3603 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
342dd0c6 3604 NO_STR
3605 "Advertise prefix routes\n"
053905d2
MK
3606 BGP_AFI_HELP_STR
3607 BGP_SAFI_HELP_STR)
342dd0c6 3608{
3609 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3610 int idx_afi = 0;
3611 int idx_safi = 0;
3612 afi_t afi = 0;
3613 safi_t safi = 0;
3614
3615 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3616 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3617
1ec31309 3618 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3619 vty_out(vty,
3620 "%%only ipv4 or ipv6 address families are supported");
3621 return CMD_WARNING;
3622 }
3623
3624 if (safi != SAFI_UNICAST) {
3625 vty_out(vty,
3626 "%%only ipv4 unicast or ipv6 unicast are supported");
342dd0c6 3627 return CMD_WARNING;
3628 }
3629
053905d2 3630 if (afi == AFI_IP) {
342dd0c6 3631
fdf19f06 3632 /* if we are not advertising ipv4 prefix as type-5
523cafc4 3633 * nothing to do
3634 */
154faa50
MK
3635 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3636 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
053905d2 3637 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50
MK
3638 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3639 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3640 }
3641 } else {
3642
fdf19f06 3643 /* if we are not advertising ipv6 prefix as type-5
523cafc4 3644 * nothing to do
3645 */
154faa50
MK
3646 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3647 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
053905d2 3648 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4f7497e 3649 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
154faa50 3650 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
342dd0c6 3651 }
3652 }
53c84f78
MK
3653
3654 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3655 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3656 XFREE(MTYPE_ROUTE_MAP_NAME,
3657 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3658 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3659 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3660 }
3661
342dd0c6 3662 return CMD_SUCCESS;
3663}
3664
5394a276
CS
3665DEFPY (bgp_evpn_advertise_pip_ip_mac,
3666 bgp_evpn_advertise_pip_ip_mac_cmd,
3667 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3668 NO_STR
3669 "evpn system primary IP\n"
3670 IP_STR
3671 "ip address\n"
3672 MAC_STR MAC_STR MAC_STR)
3673{
3674 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3675 struct bgp *bgp_evpn = NULL;
3676
3677 if (EVPN_ENABLED(bgp_vrf)) {
3678 vty_out(vty,
3679 "This command is supported under L3VNI BGP EVPN VRF\n");
a6e7677e 3680 return CMD_WARNING_CONFIG_FAILED;
5394a276
CS
3681 }
3682 bgp_evpn = bgp_get_evpn();
3683
3684 if (!no) {
3685 /* pip is already enabled */
3686 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
3687 return CMD_SUCCESS;
3688
3689 bgp_vrf->evpn_info->advertise_pip = true;
3690 if (ip.s_addr != INADDR_ANY) {
3691 /* Already configured with same IP */
3692 if (IPV4_ADDR_SAME(&ip,
3693 &bgp_vrf->evpn_info->pip_ip_static))
3694 return CMD_SUCCESS;
3695
3696 bgp_vrf->evpn_info->pip_ip_static = ip;
3697 bgp_vrf->evpn_info->pip_ip = ip;
3698 } else {
3699 bgp_vrf->evpn_info->pip_ip_static.s_addr
3700 = INADDR_ANY;
3701 /* default instance router-id assignemt */
3702 if (bgp_evpn)
3703 bgp_vrf->evpn_info->pip_ip =
3704 bgp_evpn->router_id;
3705 }
3706 /* parse sys mac */
3707 if (!is_zero_mac(&mac->eth_addr)) {
3708 /* Already configured with same MAC */
3709 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
3710 &mac->eth_addr, ETH_ALEN) == 0)
3711 return CMD_SUCCESS;
3712
3713 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
3714 &mac->eth_addr, ETH_ALEN);
3715 memcpy(&bgp_vrf->evpn_info->pip_rmac,
3716 &bgp_vrf->evpn_info->pip_rmac_static,
3717 ETH_ALEN);
3718 } else {
3719 /* Copy zebra sys mac */
3720 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
3721 memcpy(&bgp_vrf->evpn_info->pip_rmac,
3722 &bgp_vrf->evpn_info->pip_rmac_zebra,
3723 ETH_ALEN);
3724 }
3725 } else {
3726 if (argc == 2) {
3727 if (!bgp_vrf->evpn_info->advertise_pip)
3728 return CMD_SUCCESS;
3729 /* Disable PIP feature */
3730 bgp_vrf->evpn_info->advertise_pip = false;
3731 /* copy anycast mac */
3732 memcpy(&bgp_vrf->evpn_info->pip_rmac,
3733 &bgp_vrf->rmac, ETH_ALEN);
3734 } else {
3735 /* remove MAC-IP option retain PIP knob. */
3736 if ((ip.s_addr != INADDR_ANY) &&
3737 !IPV4_ADDR_SAME(&ip,
3738 &bgp_vrf->evpn_info->pip_ip_static)) {
3739 vty_out(vty,
3740 "%% BGP EVPN PIP IP does not match\n");
3741 return CMD_WARNING_CONFIG_FAILED;
3742 }
3743
3744 if (!is_zero_mac(&mac->eth_addr) &&
3745 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
3746 &mac->eth_addr, ETH_ALEN) != 0) {
3747 vty_out(vty,
3748 "%% BGP EVPN PIP MAC does not match\n");
3749 return CMD_WARNING_CONFIG_FAILED;
3750 }
3751 /* pip_rmac can carry vrr_rmac reset only if it matches
3752 * with static value.
3753 */
3754 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
3755 &bgp_vrf->evpn_info->pip_rmac_static,
3756 ETH_ALEN) == 0) {
3757 /* Copy zebra sys mac */
3758 if (!is_zero_mac(
3759 &bgp_vrf->evpn_info->pip_rmac_zebra))
3760 memcpy(&bgp_vrf->evpn_info->pip_rmac,
3761 &bgp_vrf->evpn_info->pip_rmac_zebra,
3762 ETH_ALEN);
3763 else {
3764 /* copy anycast mac */
3765 memcpy(&bgp_vrf->evpn_info->pip_rmac,
3766 &bgp_vrf->rmac, ETH_ALEN);
3767 }
3768 }
3769 }
3770 /* reset user configured sys MAC */
3771 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
3772 /* reset user configured sys IP */
3773 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
3774 /* Assign default PIP IP (bgp instance router-id) */
3775 if (bgp_evpn)
3776 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
3777 else
3778 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
3779 }
3780
3781 if (is_evpn_enabled()) {
0ca10580
CS
3782 struct listnode *node = NULL;
3783 struct bgpevpn *vpn = NULL;
3784
5f140efe
DS
3785 /*
3786 * At this point if bgp_evpn is NULL and evpn is enabled
3787 * something stupid has gone wrong
3788 */
3789 assert(bgp_evpn);
3790
5394a276 3791 update_advertise_vrf_routes(bgp_vrf);
0ca10580
CS
3792
3793 /* Update (svi) type-2 routes */
3794 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
3795 if (!bgp_evpn_is_svi_macip_enabled(vpn))
3796 continue;
3797 update_routes_for_vni(bgp_evpn, vpn);
3798 }
5394a276
CS
3799 }
3800
3801 return CMD_SUCCESS;
3802}
3803
f2d62262 3804/*
3805 * Display VNI information - for all or a specific VNI
3806 */
9c92b5f7
MK
3807DEFUN(show_bgp_l2vpn_evpn_vni,
3808 show_bgp_l2vpn_evpn_vni_cmd,
093e3f23 3809 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
9c92b5f7
MK
3810 SHOW_STR
3811 BGP_STR
3812 L2VPN_HELP_STR
3813 EVPN_HELP_STR
3814 "Show VNI\n"
3815 "VNI number\n"
3816 JSON_STR)
520d5d76 3817{
5e53dce3 3818 struct bgp *bgp_evpn;
f2d62262 3819 vni_t vni;
3820 int idx = 0;
9f049418 3821 bool uj = false;
9c92b5f7 3822 json_object *json = NULL;
d7c0a89a
QY
3823 uint32_t num_l2vnis = 0;
3824 uint32_t num_l3vnis = 0;
d4454626 3825 uint32_t num_vnis = 0;
4cce389e
MK
3826 struct listnode *node = NULL;
3827 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
3828
3829 uj = use_json(argc, argv);
520d5d76 3830
5e53dce3
T
3831 bgp_evpn = bgp_get_evpn();
3832 if (!bgp_evpn)
d62a17ae 3833 return CMD_WARNING;
520d5d76 3834
f2d62262 3835 if (!argv_find(argv, argc, "evpn", &idx))
3836 return CMD_WARNING;
3837
9c92b5f7
MK
3838 if (uj)
3839 json = json_object_new_object();
1a98c087 3840
9c92b5f7 3841 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e 3842
5e53dce3 3843 num_l2vnis = hashcount(bgp_evpn->vnihash);
4cce389e
MK
3844
3845 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3846 if (bgp_temp->l3vni)
3847 num_l3vnis++;
3848 }
d4454626 3849 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
3850 if (uj) {
3851 json_object_string_add(json, "advertiseGatewayMacip",
5e53dce3 3852 bgp_evpn->advertise_gw_macip
9c92b5f7
MK
3853 ? "Enabled"
3854 : "Disabled");
0b509723 3855 json_object_string_add(json, "advertiseSviMacIp",
cbdbb1ca
CS
3856 bgp_evpn->evpn_info->advertise_svi_macip
3857 ? "Enabled" : "Disabled");
9c92b5f7 3858 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
3859 is_evpn_enabled() ? "Enabled"
3860 : "Disabled");
fd069644
DS
3861 json_object_string_add(
3862 json, "flooding",
5e53dce3 3863 bgp_evpn->vxlan_flood_ctrl
fd069644
DS
3864 == VXLAN_FLOOD_HEAD_END_REPL
3865 ? "Head-end replication"
3866 : "Disabled");
d4454626 3867 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
3868 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3869 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
3870 } else {
3871 vty_out(vty, "Advertise Gateway Macip: %s\n",
5e53dce3 3872 bgp_evpn->advertise_gw_macip ? "Enabled"
996c9314 3873 : "Disabled");
24864e44 3874 vty_out(vty, "Advertise SVI Macip: %s\n",
5e53dce3 3875 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
24864e44 3876 : "Disabled");
9c92b5f7 3877 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 3878 is_evpn_enabled() ? "Enabled" : "Disabled");
fd069644 3879 vty_out(vty, "BUM flooding: %s\n",
5e53dce3 3880 bgp_evpn->vxlan_flood_ctrl
fd069644
DS
3881 == VXLAN_FLOOD_HEAD_END_REPL
3882 ? "Head-end replication"
3883 : "Disabled");
4cce389e
MK
3884 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3885 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 3886 }
5e53dce3 3887 evpn_show_all_vnis(vty, bgp_evpn, json);
f2d62262 3888 } else {
9c92b5f7
MK
3889 int vni_idx = 0;
3890
3891 if (!argv_find(argv, argc, "vni", &vni_idx))
3892 return CMD_WARNING;
3893
f2d62262 3894 /* Display specific VNI */
9c92b5f7 3895 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
5e53dce3 3896 evpn_show_vni(vty, bgp_evpn, vni, json);
9c92b5f7
MK
3897 }
3898
3899 if (uj) {
3900 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3901 json, JSON_C_TO_STRING_PRETTY));
3902 json_object_free(json);
f2d62262 3903 }
520d5d76 3904
d62a17ae 3905 return CMD_SUCCESS;
520d5d76 3906}
3907
b5e140c8
AK
3908DEFPY(show_bgp_l2vpn_evpn_es_evi,
3909 show_bgp_l2vpn_evpn_es_evi_cmd,
3910 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
3911 SHOW_STR
3912 BGP_STR
3913 L2VPN_HELP_STR
3914 EVPN_HELP_STR
3915 "ES per EVI\n"
3916 "VxLAN Network Identifier\n"
3917 "VNI\n"
3918 JSON_STR
3919 "Detailed information\n")
3920{
3921 if (vni)
3922 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
3923 else
3924 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
3925
3926 return CMD_SUCCESS;
3927}
3928
3929DEFPY(show_bgp_l2vpn_evpn_es,
50f74cf1 3930 show_bgp_l2vpn_evpn_es_cmd,
b5e140c8 3931 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
50f74cf1 3932 SHOW_STR
3933 BGP_STR
3934 L2VPN_HELP_STR
3935 EVPN_HELP_STR
b5e140c8
AK
3936 "Ethernet Segment\n"
3937 "ES ID\n"
3938 "Detailed information\n"
b482a7fd 3939 JSON_STR)
50f74cf1 3940{
6a527b2f 3941 esi_t esi;
50f74cf1 3942
b5e140c8
AK
3943 if (esi_str) {
3944 if (!str_to_esi(esi_str, &esi)) {
3945 vty_out(vty, "%%Malformed ESI\n");
50f74cf1 3946 return CMD_WARNING;
3947 }
b5e140c8
AK
3948 bgp_evpn_es_show_esi(vty, &esi, uj);
3949 } else {
50f74cf1 3950
b5e140c8 3951 bgp_evpn_es_show(vty, uj, !!detail);
50f74cf1 3952 }
3953
3954 return CMD_SUCCESS;
3955}
3956
f2d62262 3957/*
3958 * Display EVPN neighbor summary.
3959 */
9c92b5f7
MK
3960DEFUN(show_bgp_l2vpn_evpn_summary,
3961 show_bgp_l2vpn_evpn_summary_cmd,
10b49f14 3962 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [json]",
9c92b5f7
MK
3963 SHOW_STR
3964 BGP_STR
ee851c8c
MK
3965 "bgp vrf\n"
3966 "vrf name\n"
9c92b5f7
MK
3967 L2VPN_HELP_STR
3968 EVPN_HELP_STR
3969 "Summary of BGP neighbor status\n"
10b49f14 3970 "Show only sessions in Established state\n"
3577f1c5 3971 "Show only sessions not in Established state\n"
9c92b5f7 3972 JSON_STR)
520d5d76 3973{
ee851c8c 3974 int idx_vrf = 0;
9f049418 3975 bool uj = use_json(argc, argv);
ee851c8c 3976 char *vrf = NULL;
3577f1c5 3977 bool show_failed = false;
10b49f14 3978 bool show_established = false;
ee851c8c
MK
3979
3980 if (argv_find(argv, argc, "vrf", &idx_vrf))
3981 vrf = argv[++idx_vrf]->arg;
3577f1c5
DD
3982 if (argv_find(argv, argc, "failed", &idx_vrf))
3983 show_failed = true;
10b49f14
DA
3984 if (argv_find(argv, argc, "established", &idx_vrf))
3985 show_established = true;
3986
3987 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, show_failed,
3988 show_established, uj);
520d5d76 3989}
3990
f2d62262 3991/*
3992 * Display global EVPN routing table.
3993 */
60466a63
QY
3994DEFUN(show_bgp_l2vpn_evpn_route,
3995 show_bgp_l2vpn_evpn_route_cmd,
b5e140c8 3996 "show bgp l2vpn evpn route [detail] [type <ead|1|macip|2|multicast|3|es|4|prefix|5>] [json]",
9c92b5f7
MK
3997 SHOW_STR
3998 BGP_STR
3999 L2VPN_HELP_STR
4000 EVPN_HELP_STR
f5dc0b1a 4001 EVPN_RT_HELP_STR
21f3551e 4002 "Display Detailed Information\n"
f5dc0b1a
SW
4003 EVPN_TYPE_HELP_STR
4004 EVPN_TYPE_1_HELP_STR
4005 EVPN_TYPE_1_HELP_STR
4006 EVPN_TYPE_2_HELP_STR
4007 EVPN_TYPE_2_HELP_STR
4008 EVPN_TYPE_3_HELP_STR
4009 EVPN_TYPE_3_HELP_STR
4010 EVPN_TYPE_4_HELP_STR
4011 EVPN_TYPE_4_HELP_STR
4012 EVPN_TYPE_5_HELP_STR
4013 EVPN_TYPE_5_HELP_STR
9c92b5f7 4014 JSON_STR)
520d5d76 4015{
d62a17ae 4016 struct bgp *bgp;
8367c327 4017 int type_idx = 0;
21f3551e 4018 int detail = 0;
d62a17ae 4019 int type = 0;
9f049418 4020 bool uj = false;
9c92b5f7
MK
4021 json_object *json = NULL;
4022
4023 uj = use_json(argc, argv);
520d5d76 4024
530db8dc 4025 bgp = bgp_get_evpn();
d62a17ae 4026 if (!bgp)
4027 return CMD_WARNING;
520d5d76 4028
9c92b5f7
MK
4029 if (uj)
4030 json = json_object_new_object();
f2d62262 4031
9c92b5f7
MK
4032 /* get the type */
4033 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 4034 /* Specific type is requested */
8937a1e6
TA
4035 if ((strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
4036 || (strmatch(argv[type_idx + 1]->arg, "2")))
d62a17ae 4037 type = BGP_EVPN_MAC_IP_ROUTE;
8937a1e6
TA
4038 else if ((strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
4039 || (strmatch(argv[type_idx + 1]->arg, "3")))
d62a17ae 4040 type = BGP_EVPN_IMET_ROUTE;
b5e140c8 4041 else if ((strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
8937a1e6 4042 || (strmatch(argv[type_idx + 1]->arg, "4")))
50f74cf1 4043 type = BGP_EVPN_ES_ROUTE;
b5e140c8
AK
4044 else if ((strncmp(argv[type_idx + 1]->arg, "ea", 2) == 0)
4045 || (strmatch(argv[type_idx + 1]->arg, "1")))
4046 type = BGP_EVPN_AD_ROUTE;
8937a1e6
TA
4047 else if ((strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
4048 || (strmatch(argv[type_idx + 1]->arg, "5")))
47b71369 4049 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 4050 else
4051 return CMD_WARNING;
4052 }
520d5d76 4053
21f3551e
NS
4054 if (argv_find(argv, argc, "detail", &detail))
4055 detail = 1;
4056
4057 evpn_show_all_routes(vty, bgp, type, json, detail);
9c92b5f7
MK
4058
4059 if (uj) {
4060 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4061 json, JSON_C_TO_STRING_PRETTY));
4062 json_object_free(json);
4063 }
d62a17ae 4064 return CMD_SUCCESS;
520d5d76 4065}
4066
f2d62262 4067/*
4068 * Display global EVPN routing table for specific RD.
4069 */
60466a63
QY
4070DEFUN(show_bgp_l2vpn_evpn_route_rd,
4071 show_bgp_l2vpn_evpn_route_rd_cmd,
b5e140c8 4072 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <ead|macip|multicast|es|prefix>] [json]",
9c92b5f7
MK
4073 SHOW_STR
4074 BGP_STR
4075 L2VPN_HELP_STR
4076 EVPN_HELP_STR
f5dc0b1a
SW
4077 EVPN_RT_HELP_STR
4078 EVPN_RT_DIST_HELP_STR
4079 EVPN_ASN_IP_HELP_STR
4080 EVPN_TYPE_HELP_STR
4081 EVPN_TYPE_1_HELP_STR
4082 EVPN_TYPE_2_HELP_STR
4083 EVPN_TYPE_3_HELP_STR
4084 EVPN_TYPE_4_HELP_STR
4085 EVPN_TYPE_5_HELP_STR
9c92b5f7 4086 JSON_STR)
520d5d76 4087{
d62a17ae 4088 struct bgp *bgp;
4089 int ret;
4090 struct prefix_rd prd;
4091 int type = 0;
9c92b5f7
MK
4092 int rd_idx = 0;
4093 int type_idx = 0;
9f049418 4094 bool uj = false;
9c92b5f7 4095 json_object *json = NULL;
520d5d76 4096
530db8dc 4097 bgp = bgp_get_evpn();
d62a17ae 4098 if (!bgp)
4099 return CMD_WARNING;
520d5d76 4100
9c92b5f7
MK
4101 /* check if we need json output */
4102 uj = use_json(argc, argv);
4103 if (uj)
4104 json = json_object_new_object();
f2d62262 4105
9c92b5f7
MK
4106 /* get the RD */
4107 if (argv_find(argv, argc, "rd", &rd_idx)) {
4108 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
4109
4110 if (!ret) {
4111 vty_out(vty, "%% Malformed Route Distinguisher\n");
4112 return CMD_WARNING;
4113 }
d62a17ae 4114 }
520d5d76 4115
9c92b5f7
MK
4116 /* get the type */
4117 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 4118 /* Specific type is requested */
9c92b5f7 4119 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 4120 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 4121 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 4122 type = BGP_EVPN_IMET_ROUTE;
b5e140c8
AK
4123 else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
4124 type = BGP_EVPN_ES_ROUTE;
4125 else if (strncmp(argv[type_idx + 1]->arg, "ea", 2) == 0)
4126 type = BGP_EVPN_AD_ROUTE;
aa9db9e6
MK
4127 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
4128 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 4129 else
4130 return CMD_WARNING;
4131 }
520d5d76 4132
9c92b5f7
MK
4133 evpn_show_route_rd(vty, bgp, &prd, type, json);
4134
4135 if (uj) {
4136 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4137 json, JSON_C_TO_STRING_PRETTY));
4138 json_object_free(json);
4139 }
4140
d62a17ae 4141 return CMD_SUCCESS;
520d5d76 4142}
4143
f2d62262 4144/*
4145 * Display global EVPN routing table for specific RD and MACIP.
4146 */
9c92b5f7
MK
4147DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4148 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
d114b977 4149 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
9c92b5f7
MK
4150 SHOW_STR
4151 BGP_STR
4152 L2VPN_HELP_STR
4153 EVPN_HELP_STR
f5dc0b1a
SW
4154 EVPN_RT_HELP_STR
4155 EVPN_RT_DIST_HELP_STR
4156 EVPN_ASN_IP_HELP_STR
9c92b5f7
MK
4157 "MAC\n"
4158 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4159 "IP\n"
4160 "IP address (IPv4 or IPv6)\n"
4161 JSON_STR)
4162{
0291c246
MK
4163 struct bgp *bgp;
4164 int ret;
4165 struct prefix_rd prd;
4166 struct ethaddr mac;
4167 struct ipaddr ip;
4168 int rd_idx = 0;
4169 int mac_idx = 0;
4170 int ip_idx = 0;
9f049418 4171 bool uj = false;
0291c246 4172 json_object *json = NULL;
9c92b5f7
MK
4173
4174 memset(&mac, 0, sizeof(struct ethaddr));
4175 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 4176
530db8dc 4177 bgp = bgp_get_evpn();
d62a17ae 4178 if (!bgp)
4179 return CMD_WARNING;
4180
9c92b5f7
MK
4181 /* check if we need json output */
4182 uj = use_json(argc, argv);
4183 if (uj)
4184 json = json_object_new_object();
f2d62262 4185
9c92b5f7
MK
4186 /* get the prd */
4187 if (argv_find(argv, argc, "rd", &rd_idx)) {
4188 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
4189 if (!ret) {
4190 vty_out(vty, "%% Malformed Route Distinguisher\n");
4191 return CMD_WARNING;
4192 }
d62a17ae 4193 }
9c92b5f7
MK
4194
4195 /* get the mac */
4196 if (argv_find(argv, argc, "mac", &mac_idx)) {
4197 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4198 vty_out(vty, "%% Malformed MAC address\n");
4199 return CMD_WARNING;
4200 }
d62a17ae 4201 }
9c92b5f7
MK
4202
4203 /* get the ip if specified */
4204 if (argv_find(argv, argc, "ip", &ip_idx)) {
4205 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 4206 vty_out(vty, "%% Malformed IP address\n");
4207 return CMD_WARNING;
4208 }
4209 }
4210
9c92b5f7
MK
4211 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4212
4213 if (uj) {
4214 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4215 json, JSON_C_TO_STRING_PRETTY));
4216 json_object_free(json);
4217 }
4218
d62a17ae 4219 return CMD_SUCCESS;
520d5d76 4220}
4221
50f74cf1 4222/* Display per ESI routing table */
4223DEFUN(show_bgp_l2vpn_evpn_route_esi,
4224 show_bgp_l2vpn_evpn_route_esi_cmd,
4225 "show bgp l2vpn evpn route esi ESI [json]",
4226 SHOW_STR
4227 BGP_STR
4228 L2VPN_HELP_STR
4229 EVPN_HELP_STR
f5dc0b1a 4230 EVPN_RT_HELP_STR
50f74cf1 4231 "Ethernet Segment Identifier\n"
4232 "ESI ID\n"
4233 JSON_STR)
4234{
9f049418 4235 bool uj = false;
6a527b2f 4236 esi_t esi;
50f74cf1 4237 struct bgp *bgp = NULL;
4238 json_object *json = NULL;
4239
6a527b2f 4240 memset(&esi, 0, sizeof(esi));
530db8dc 4241 bgp = bgp_get_evpn();
50f74cf1 4242 if (!bgp)
4243 return CMD_WARNING;
4244
4245 uj = use_json(argc, argv);
4246 if (uj)
4247 json = json_object_new_object();
4248
4249 /* get the ESI - ESI-ID is at argv[6] */
4250 if (!str_to_esi(argv[6]->arg, &esi)) {
4251 vty_out(vty, "%% Malformed ESI\n");
4252 return CMD_WARNING;
4253 }
4254
4255 evpn_show_routes_esi(vty, bgp, &esi, json);
4256
4257 if (uj) {
4258 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4259 json, JSON_C_TO_STRING_PRETTY));
4260 json_object_free(json);
4261 }
4262
4263 return CMD_SUCCESS;
4264}
4265
4266
f2d62262 4267/*
4268 * Display per-VNI EVPN routing table.
4269 */
9c92b5f7 4270DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
b5e140c8 4271 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|macip|multicast> | vtep A.B.C.D>] [json]",
9c92b5f7
MK
4272 SHOW_STR
4273 BGP_STR
4274 L2VPN_HELP_STR
4275 EVPN_HELP_STR
f5dc0b1a 4276 EVPN_RT_HELP_STR
9c92b5f7
MK
4277 "VXLAN Network Identifier\n"
4278 "VNI number\n"
f5dc0b1a
SW
4279 EVPN_TYPE_HELP_STR
4280 EVPN_TYPE_1_HELP_STR
4281 EVPN_TYPE_2_HELP_STR
4282 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
4283 "Remote VTEP\n"
4284 "Remote VTEP IP address\n"
4285 JSON_STR)
520d5d76 4286{
d62a17ae 4287 vni_t vni;
4288 struct bgp *bgp;
4289 struct in_addr vtep_ip;
4290 int type = 0;
f2d62262 4291 int idx = 0;
9f049418 4292 bool uj = false;
9c92b5f7 4293 json_object *json = NULL;
d62a17ae 4294
530db8dc 4295 bgp = bgp_get_evpn();
d62a17ae 4296 if (!bgp)
4297 return CMD_WARNING;
4298
9c92b5f7
MK
4299 /* check if we need json output */
4300 uj = use_json(argc, argv);
4301 if (uj)
4302 json = json_object_new_object();
4303
f2d62262 4304 if (!argv_find(argv, argc, "evpn", &idx))
4305 return CMD_WARNING;
4306
d62a17ae 4307 vtep_ip.s_addr = 0;
4308
f2d62262 4309 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 4310
9c92b5f7
MK
4311 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
4312 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 4313 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
4314 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 4315 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 4316 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 4317 type = BGP_EVPN_IMET_ROUTE;
b5e140c8
AK
4318 else if (strncmp(argv[idx + 5]->arg, "ea", 2) == 0)
4319 type = BGP_EVPN_AD_ROUTE;
d62a17ae 4320 else
4321 return CMD_WARNING;
f2d62262 4322 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
4323 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 4324 vty_out(vty, "%% Malformed VTEP IP address\n");
4325 return CMD_WARNING;
4326 }
4327 } else
4328 return CMD_WARNING;
4329 }
4330
9c92b5f7
MK
4331 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
4332
4333 if (uj) {
4334 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4335 json, JSON_C_TO_STRING_PRETTY));
4336 json_object_free(json);
4337 }
4338
d62a17ae 4339 return CMD_SUCCESS;
520d5d76 4340}
4341
f2d62262 4342/*
4343 * Display per-VNI EVPN routing table for specific MACIP.
4344 */
9c92b5f7
MK
4345DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
4346 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
093e3f23 4347 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
9c92b5f7
MK
4348 SHOW_STR
4349 BGP_STR
4350 L2VPN_HELP_STR
4351 EVPN_HELP_STR
f5dc0b1a 4352 EVPN_RT_HELP_STR
9c92b5f7
MK
4353 "VXLAN Network Identifier\n"
4354 "VNI number\n"
4355 "MAC\n"
4356 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4357 "IP\n"
4358 "IP address (IPv4 or IPv6)\n"
4359 JSON_STR)
520d5d76 4360{
d62a17ae 4361 vni_t vni;
4362 struct bgp *bgp;
4363 struct ethaddr mac;
4364 struct ipaddr ip;
f2d62262 4365 int idx = 0;
9f049418 4366 bool uj = false;
9c92b5f7 4367 json_object *json = NULL;
d62a17ae 4368
530db8dc 4369 bgp = bgp_get_evpn();
d62a17ae 4370 if (!bgp)
4371 return CMD_WARNING;
4372
9c92b5f7
MK
4373 /* check if we need json output */
4374 uj = use_json(argc, argv);
4375 if (uj)
4376 json = json_object_new_object();
4377
f2d62262 4378 if (!argv_find(argv, argc, "evpn", &idx))
4379 return CMD_WARNING;
4380
9c92b5f7 4381 /* get the VNI */
f2d62262 4382 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
4383
4384 /* get the mac */
f2d62262 4385 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 4386 vty_out(vty, "%% Malformed MAC address\n");
4387 return CMD_WARNING;
4388 }
9c92b5f7
MK
4389
4390 /* get the ip */
d62a17ae 4391 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
4392 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
4393 || (uj
4394 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 4395 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 4396 vty_out(vty, "%% Malformed IP address\n");
4397 return CMD_WARNING;
4398 }
4399 }
4400
9c92b5f7
MK
4401 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
4402
4403 if (uj) {
4404 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4405 json, JSON_C_TO_STRING_PRETTY));
4406 json_object_free(json);
4407 }
4408
d62a17ae 4409 return CMD_SUCCESS;
520d5d76 4410}
4411
f2d62262 4412/*
4413 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4414 */
9c92b5f7
MK
4415DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
4416 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
093e3f23 4417 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
9c92b5f7
MK
4418 SHOW_STR
4419 BGP_STR
4420 L2VPN_HELP_STR
4421 EVPN_HELP_STR
f5dc0b1a 4422 EVPN_RT_HELP_STR
9c92b5f7
MK
4423 "VXLAN Network Identifier\n"
4424 "VNI number\n"
f5dc0b1a 4425 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
4426 "Originating Router IP address\n"
4427 JSON_STR)
520d5d76 4428{
d62a17ae 4429 vni_t vni;
4430 struct bgp *bgp;
4431 int ret;
4432 struct in_addr orig_ip;
f2d62262 4433 int idx = 0;
9f049418 4434 bool uj = false;
9c92b5f7 4435 json_object *json = NULL;
520d5d76 4436
530db8dc 4437 bgp = bgp_get_evpn();
d62a17ae 4438 if (!bgp)
4439 return CMD_WARNING;
520d5d76 4440
9c92b5f7
MK
4441 /* check if we need json output */
4442 uj = use_json(argc, argv);
4443 if (uj)
4444 json = json_object_new_object();
4445
f2d62262 4446 if (!argv_find(argv, argc, "evpn", &idx))
4447 return CMD_WARNING;
4448
9c92b5f7 4449 /* get the VNI */
f2d62262 4450 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
4451
4452 /* get the ip */
f2d62262 4453 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 4454 if (!ret) {
4455 vty_out(vty, "%% Malformed Originating Router IP address\n");
4456 return CMD_WARNING;
4457 }
520d5d76 4458
9c92b5f7
MK
4459 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
4460
4461 if (uj) {
4462 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4463 json, JSON_C_TO_STRING_PRETTY));
4464 json_object_free(json);
4465 }
4466
d62a17ae 4467 return CMD_SUCCESS;
520d5d76 4468}
4469
f2d62262 4470/*
4471 * Display per-VNI EVPN routing table - for all VNIs.
4472 */
60466a63
QY
4473DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
4474 show_bgp_l2vpn_evpn_route_vni_all_cmd,
c7ef6cf2 4475 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
9c92b5f7
MK
4476 SHOW_STR
4477 BGP_STR
4478 L2VPN_HELP_STR
4479 EVPN_HELP_STR
f5dc0b1a 4480 EVPN_RT_HELP_STR
9c92b5f7
MK
4481 "VXLAN Network Identifier\n"
4482 "All VNIs\n"
c7ef6cf2 4483 "Print Detailed Output\n"
9c92b5f7
MK
4484 "Remote VTEP\n"
4485 "Remote VTEP IP address\n"
4486 JSON_STR)
520d5d76 4487{
d62a17ae 4488 struct bgp *bgp;
4489 struct in_addr vtep_ip;
f2d62262 4490 int idx = 0;
9f049418 4491 bool uj = false;
9c92b5f7 4492 json_object *json = NULL;
c7ef6cf2
NS
4493 /* Detail Adjust. Adjust indexes according to detail option */
4494 int da = 0;
520d5d76 4495
530db8dc 4496 bgp = bgp_get_evpn();
d62a17ae 4497 if (!bgp)
4498 return CMD_WARNING;
520d5d76 4499
9c92b5f7
MK
4500 /* check if we need json output */
4501 uj = use_json(argc, argv);
4502 if (uj)
4503 json = json_object_new_object();
4504
f2d62262 4505 if (!argv_find(argv, argc, "evpn", &idx))
4506 return CMD_WARNING;
4507
c7ef6cf2
NS
4508 if (argv_find(argv, argc, "detail", &da))
4509 da = 1;
4510
4511 /* vtep-ip position depends on detail option */
d62a17ae 4512 vtep_ip.s_addr = 0;
c7ef6cf2
NS
4513 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
4514 || (uj
4515 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
4516 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
d62a17ae 4517 vty_out(vty, "%% Malformed VTEP IP address\n");
4518 return CMD_WARNING;
4519 }
4520 }
520d5d76 4521
c7ef6cf2 4522 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da);
9c92b5f7
MK
4523
4524 if (uj) {
4525 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4526 json, JSON_C_TO_STRING_PRETTY));
4527 json_object_free(json);
4528 }
4529
d62a17ae 4530 return CMD_SUCCESS;
520d5d76 4531}
4532
10ebe1ab
MK
4533/*
4534 * Display EVPN import route-target hash table
4535 */
4536DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
4537 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
4538 "show bgp l2vpn evpn vrf-import-rt [json]",
4539 SHOW_STR
4540 BGP_STR
4541 L2VPN_HELP_STR
4542 EVPN_HELP_STR
4543 "Show vrf import route target\n"
4544 JSON_STR)
4545{
9f049418 4546 bool uj = false;
5e53dce3 4547 struct bgp *bgp_evpn = NULL;
10ebe1ab
MK
4548 json_object *json = NULL;
4549
5e53dce3
T
4550 bgp_evpn = bgp_get_evpn();
4551 if (!bgp_evpn)
10ebe1ab
MK
4552 return CMD_WARNING;
4553
4554 uj = use_json(argc, argv);
4555 if (uj)
4556 json = json_object_new_object();
4557
5e53dce3 4558 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
10ebe1ab
MK
4559
4560 if (uj) {
4561 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4562 json, JSON_C_TO_STRING_PRETTY));
4563 json_object_free(json);
4564 }
4565
4566 return CMD_SUCCESS;
4567}
4568
f2d62262 4569/*
4570 * Display EVPN import route-target hash table
4571 */
60466a63
QY
4572DEFUN(show_bgp_l2vpn_evpn_import_rt,
4573 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
4574 "show bgp l2vpn evpn import-rt [json]",
4575 SHOW_STR
4576 BGP_STR
4577 L2VPN_HELP_STR
4578 EVPN_HELP_STR
4579 "Show import route target\n"
4580 JSON_STR)
520d5d76 4581{
d62a17ae 4582 struct bgp *bgp;
9f049418 4583 bool uj = false;
9c92b5f7 4584 json_object *json = NULL;
520d5d76 4585
530db8dc 4586 bgp = bgp_get_evpn();
d62a17ae 4587 if (!bgp)
4588 return CMD_WARNING;
520d5d76 4589
9c92b5f7
MK
4590 uj = use_json(argc, argv);
4591 if (uj)
4592 json = json_object_new_object();
4593
4594 evpn_show_import_rts(vty, bgp, json);
4595
4596 if (uj) {
4597 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4598 json, JSON_C_TO_STRING_PRETTY));
4599 json_object_free(json);
4600 }
4601
d62a17ae 4602 return CMD_SUCCESS;
520d5d76 4603}
4604
1673a90d 4605DEFPY_HIDDEN(test_es_add,
b5e140c8
AK
4606 test_es_add_cmd,
4607 "[no$no] test es NAME$esi_str [state NAME$state_str]",
4608 NO_STR
4609 "Test\n"
50f74cf1 4610 "Ethernet-segment\n"
b5e140c8
AK
4611 "Ethernet-Segment Identifier\n"
4612 "ES link state\n"
4613 "up|down\n"
4614)
50f74cf1 4615{
4616 int ret = 0;
4617 esi_t esi;
4618 struct bgp *bgp;
b5e140c8
AK
4619 struct in_addr vtep_ip;
4620 bool oper_up;
50f74cf1 4621
530db8dc 4622 bgp = bgp_get_evpn();
50f74cf1 4623 if (!bgp) {
530db8dc 4624 vty_out(vty, "%%EVPN BGP instance not yet created\n");
50f74cf1 4625 return CMD_WARNING;
4626 }
4627
b5e140c8 4628 if (!str_to_esi(esi_str, &esi)) {
50f74cf1 4629 vty_out(vty, "%%Malformed ESI\n");
4630 return CMD_WARNING;
4631 }
4632
b5e140c8
AK
4633 if (no) {
4634 ret = bgp_evpn_local_es_del(bgp, &esi);
4635 if (ret == -1) {
4636 vty_out(vty, "%%Failed to delete ES\n");
4637 return CMD_WARNING;
4638 }
4639 } else {
4640 if (state_str && !strcmp(state_str, "up"))
4641 oper_up = true;
4642 else
4643 oper_up = false;
4644 vtep_ip = bgp->router_id;
50f74cf1 4645
b5e140c8
AK
4646 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up);
4647 if (ret == -1) {
4648 vty_out(vty, "%%Failed to add ES\n");
4649 return CMD_WARNING;
4650 }
50f74cf1 4651 }
4652 return CMD_SUCCESS;
4653}
4654
1673a90d 4655DEFPY_HIDDEN(test_es_vni_add,
b5e140c8
AK
4656 test_es_vni_add_cmd,
4657 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
4658 NO_STR
4659 "Test\n"
50f74cf1 4660 "Ethernet-segment\n"
b5e140c8
AK
4661 "Ethernet-Segment Identifier\n"
4662 "VNI\n"
4663 "1-16777215\n"
4664)
50f74cf1 4665{
4666 int ret = 0;
4667 esi_t esi;
4668 struct bgp *bgp;
50f74cf1 4669
530db8dc 4670 bgp = bgp_get_evpn();
50f74cf1 4671 if (!bgp) {
530db8dc 4672 vty_out(vty, "%%EVPN BGP instance not yet created\n");
50f74cf1 4673 return CMD_WARNING;
4674 }
4675
b5e140c8 4676 if (!str_to_esi(esi_str, &esi)) {
50f74cf1 4677 vty_out(vty, "%%Malformed ESI\n");
4678 return CMD_WARNING;
4679 }
4680
b5e140c8
AK
4681 if (no) {
4682 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
4683 if (ret == -1) {
4684 vty_out(vty, "%%Failed to deref ES VNI\n");
4685 return CMD_WARNING;
4686 }
4687 } else {
4688 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
4689 if (ret == -1) {
4690 vty_out(vty, "%%Failed to ref ES VNI\n");
4691 return CMD_WARNING;
4692 }
50f74cf1 4693 }
4694 return CMD_SUCCESS;
4695}
4696
5014d96f 4697ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
093e3f23 4698 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5014d96f
DW
4699 "Show VNI\n"
4700 "VNI number\n")
4701
4702ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
4703 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 4704 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
4705
4706ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
21f3551e 4707 "show bgp evpn route [detail] [type <macip|multicast>]",
5014d96f 4708 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 4709 EVPN_RT_HELP_STR
21f3551e 4710 "Display Detailed Information\n"
f5dc0b1a
SW
4711 EVPN_TYPE_HELP_STR
4712 EVPN_TYPE_2_HELP_STR
4713 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
4714
4715ALIAS_HIDDEN(
4716 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
d114b977 4717 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
5014d96f 4718 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
4719 EVPN_RT_HELP_STR
4720 EVPN_RT_DIST_HELP_STR
4721 EVPN_ASN_IP_HELP_STR
4722 EVPN_TYPE_HELP_STR
4723 EVPN_TYPE_2_HELP_STR
4724 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
4725
4726ALIAS_HIDDEN(
4727 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 4728 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f 4729 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
4730 EVPN_RT_HELP_STR
4731 EVPN_RT_DIST_HELP_STR
4732 EVPN_ASN_IP_HELP_STR
5014d96f
DW
4733 "MAC\n"
4734 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4735 "IP\n"
4736 "IP address (IPv4 or IPv6)\n")
4737
4738ALIAS_HIDDEN(
4739 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
093e3f23 4740 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]",
5014d96f 4741 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 4742 EVPN_RT_HELP_STR
5014d96f
DW
4743 "VXLAN Network Identifier\n"
4744 "VNI number\n"
f5dc0b1a
SW
4745 EVPN_TYPE_HELP_STR
4746 EVPN_TYPE_2_HELP_STR
4747 EVPN_TYPE_3_HELP_STR
5014d96f
DW
4748 "Remote VTEP\n"
4749 "Remote VTEP IP address\n")
4750
4751ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4752 show_bgp_evpn_route_vni_macip_cmd,
093e3f23 4753 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
5014d96f 4754 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 4755 EVPN_RT_HELP_STR
5014d96f
DW
4756 "VXLAN Network Identifier\n"
4757 "VNI number\n"
4758 "MAC\n"
4759 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4760 "IP\n"
4761 "IP address (IPv4 or IPv6)\n")
4762
4763ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4764 show_bgp_evpn_route_vni_multicast_cmd,
093e3f23 4765 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
5014d96f 4766 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 4767 EVPN_RT_HELP_STR
5014d96f
DW
4768 "VXLAN Network Identifier\n"
4769 "VNI number\n"
f5dc0b1a 4770 EVPN_TYPE_3_HELP_STR
5014d96f
DW
4771 "Originating Router IP address\n")
4772
4773ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
c7ef6cf2 4774 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5014d96f 4775 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 4776 EVPN_RT_HELP_STR
5014d96f
DW
4777 "VXLAN Network Identifier\n"
4778 "All VNIs\n"
c7ef6cf2 4779 "Print Detailed Output\n"
5014d96f
DW
4780 "Remote VTEP\n"
4781 "Remote VTEP IP address\n")
4782
4783ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4784 "show bgp evpn import-rt",
4785 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5014d96f 4786
90e60aa7 4787DEFUN_NOSH (bgp_evpn_vni,
4788 bgp_evpn_vni_cmd,
093e3f23 4789 "vni " CMD_VNI_RANGE,
90e60aa7 4790 "VXLAN Network Identifier\n"
4791 "VNI number\n")
4792{
d62a17ae 4793 vni_t vni;
4794 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4795 struct bgpevpn *vpn;
90e60aa7 4796
d62a17ae 4797 if (!bgp)
4798 return CMD_WARNING;
90e60aa7 4799
d62a17ae 4800 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 4801
d62a17ae 4802 /* Create VNI, or mark as configured. */
4803 vpn = evpn_create_update_vni(bgp, vni);
4804 if (!vpn) {
4805 vty_out(vty, "%% Failed to create VNI \n");
4806 return CMD_WARNING;
4807 }
90e60aa7 4808
d62a17ae 4809 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4810 return CMD_SUCCESS;
90e60aa7 4811}
4812
4813DEFUN (no_bgp_evpn_vni,
4814 no_bgp_evpn_vni_cmd,
093e3f23 4815 "no vni " CMD_VNI_RANGE,
90e60aa7 4816 NO_STR
4817 "VXLAN Network Identifier\n"
4818 "VNI number\n")
4819{
d62a17ae 4820 vni_t vni;
4821 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4822 struct bgpevpn *vpn;
90e60aa7 4823
d62a17ae 4824 if (!bgp)
4825 return CMD_WARNING;
90e60aa7 4826
d62a17ae 4827 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 4828
d62a17ae 4829 /* Check if we should disallow. */
4830 vpn = bgp_evpn_lookup_vni(bgp, vni);
4831 if (!vpn) {
4832 vty_out(vty, "%% Specified VNI does not exist\n");
4833 return CMD_WARNING;
4834 }
4835 if (!is_vni_configured(vpn)) {
4836 vty_out(vty, "%% Specified VNI is not configured\n");
4837 return CMD_WARNING;
4838 }
90e60aa7 4839
d62a17ae 4840 evpn_delete_vni(bgp, vpn);
4841 return CMD_SUCCESS;
90e60aa7 4842}
4843
4844DEFUN_NOSH (exit_vni,
4845 exit_vni_cmd,
4846 "exit-vni",
4847 "Exit from VNI mode\n")
4848{
d62a17ae 4849 if (vty->node == BGP_EVPN_VNI_NODE)
4850 vty->node = BGP_EVPN_NODE;
4851 return CMD_SUCCESS;
90e60aa7 4852}
4853
676f83b9 4854DEFUN (bgp_evpn_vrf_rd,
4855 bgp_evpn_vrf_rd_cmd,
4856 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
4857 EVPN_RT_DIST_HELP_STR
4858 EVPN_ASN_IP_HELP_STR)
676f83b9 4859{
4860 int ret;
4861 struct prefix_rd prd;
4862 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4863
4864 if (!bgp_vrf)
4865 return CMD_WARNING;
4866
4867 ret = str2prefix_rd(argv[1]->arg, &prd);
4868 if (!ret) {
4869 vty_out(vty, "%% Malformed Route Distinguisher\n");
4870 return CMD_WARNING;
4871 }
4872
4873 /* If same as existing value, there is nothing more to do. */
4874 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4875 return CMD_SUCCESS;
4876
4877 /* Configure or update the RD. */
4878 evpn_configure_vrf_rd(bgp_vrf, &prd);
4879 return CMD_SUCCESS;
4880}
4881
4882DEFUN (no_bgp_evpn_vrf_rd,
4883 no_bgp_evpn_vrf_rd_cmd,
4884 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4885 NO_STR
f5dc0b1a
SW
4886 EVPN_RT_DIST_HELP_STR
4887 EVPN_ASN_IP_HELP_STR)
676f83b9 4888{
4889 int ret;
4890 struct prefix_rd prd;
4891 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4892
4893 if (!bgp_vrf)
4894 return CMD_WARNING;
4895
4896 ret = str2prefix_rd(argv[2]->arg, &prd);
4897 if (!ret) {
4898 vty_out(vty, "%% Malformed Route Distinguisher\n");
4899 return CMD_WARNING;
4900 }
4901
4902 /* Check if we should disallow. */
4903 if (!is_vrf_rd_configured(bgp_vrf)) {
4904 vty_out(vty, "%% RD is not configured for this VRF\n");
4905 return CMD_WARNING;
4906 }
4907
4908 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4909 vty_out(vty,
4910 "%% RD specified does not match configuration for this VRF\n");
4911 return CMD_WARNING;
4912 }
4913
4914 evpn_unconfigure_vrf_rd(bgp_vrf);
4915 return CMD_SUCCESS;
4916}
4917
4918DEFUN (no_bgp_evpn_vrf_rd_without_val,
4919 no_bgp_evpn_vrf_rd_without_val_cmd,
4920 "no rd",
4921 NO_STR
f5dc0b1a 4922 EVPN_RT_DIST_HELP_STR)
676f83b9 4923{
4924 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4925
4926 if (!bgp_vrf)
4927 return CMD_WARNING;
4928
4929 /* Check if we should disallow. */
4930 if (!is_vrf_rd_configured(bgp_vrf)) {
4931 vty_out(vty, "%% RD is not configured for this VRF\n");
4932 return CMD_WARNING;
4933 }
4934
4935 evpn_unconfigure_vrf_rd(bgp_vrf);
4936 return CMD_SUCCESS;
4937}
4938
90e60aa7 4939DEFUN (bgp_evpn_vni_rd,
4940 bgp_evpn_vni_rd_cmd,
d114b977 4941 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
4942 EVPN_RT_DIST_HELP_STR
4943 EVPN_ASN_IP_HELP_STR)
90e60aa7 4944{
d62a17ae 4945 struct prefix_rd prd;
4946 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4947 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4948 int ret;
90e60aa7 4949
06fe25f4 4950 if (!bgp)
d62a17ae 4951 return CMD_WARNING;
90e60aa7 4952
f920dd6d 4953 if (!EVPN_ENABLED(bgp)) {
a2a8153f 4954 vty_out(vty,
530db8dc 4955 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
4956 return CMD_WARNING;
4957 }
4958
d62a17ae 4959 ret = str2prefix_rd(argv[1]->arg, &prd);
4960 if (!ret) {
4961 vty_out(vty, "%% Malformed Route Distinguisher\n");
4962 return CMD_WARNING;
4963 }
90e60aa7 4964
d62a17ae 4965 /* If same as existing value, there is nothing more to do. */
4966 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4967 return CMD_SUCCESS;
90e60aa7 4968
d62a17ae 4969 /* Configure or update the RD. */
4970 evpn_configure_rd(bgp, vpn, &prd);
4971 return CMD_SUCCESS;
90e60aa7 4972}
4973
4974DEFUN (no_bgp_evpn_vni_rd,
4975 no_bgp_evpn_vni_rd_cmd,
d114b977 4976 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 4977 NO_STR
f5dc0b1a
SW
4978 EVPN_RT_DIST_HELP_STR
4979 EVPN_ASN_IP_HELP_STR)
90e60aa7 4980{
d62a17ae 4981 struct prefix_rd prd;
4982 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4983 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4984 int ret;
90e60aa7 4985
06fe25f4 4986 if (!bgp)
d62a17ae 4987 return CMD_WARNING;
90e60aa7 4988
f920dd6d 4989 if (!EVPN_ENABLED(bgp)) {
a2a8153f 4990 vty_out(vty,
530db8dc 4991 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
4992 return CMD_WARNING;
4993 }
4994
d62a17ae 4995 ret = str2prefix_rd(argv[2]->arg, &prd);
4996 if (!ret) {
4997 vty_out(vty, "%% Malformed Route Distinguisher\n");
4998 return CMD_WARNING;
4999 }
90e60aa7 5000
d62a17ae 5001 /* Check if we should disallow. */
5002 if (!is_rd_configured(vpn)) {
5003 vty_out(vty, "%% RD is not configured for this VNI\n");
5004 return CMD_WARNING;
5005 }
90e60aa7 5006
d62a17ae 5007 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
5008 vty_out(vty,
5009 "%% RD specified does not match configuration for this VNI\n");
5010 return CMD_WARNING;
5011 }
90e60aa7 5012
d62a17ae 5013 evpn_unconfigure_rd(bgp, vpn);
5014 return CMD_SUCCESS;
90e60aa7 5015}
5016
5017DEFUN (no_bgp_evpn_vni_rd_without_val,
5018 no_bgp_evpn_vni_rd_without_val_cmd,
5019 "no rd",
5020 NO_STR
f5dc0b1a 5021 EVPN_RT_DIST_HELP_STR)
90e60aa7 5022{
d62a17ae 5023 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5024 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 5025
06fe25f4 5026 if (!bgp)
d62a17ae 5027 return CMD_WARNING;
90e60aa7 5028
f920dd6d 5029 if (!EVPN_ENABLED(bgp)) {
a2a8153f 5030 vty_out(vty,
530db8dc 5031 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
5032 return CMD_WARNING;
5033 }
5034
d62a17ae 5035 /* Check if we should disallow. */
5036 if (!is_rd_configured(vpn)) {
5037 vty_out(vty, "%% RD is not configured for this VNI\n");
5038 return CMD_WARNING;
5039 }
90e60aa7 5040
d62a17ae 5041 evpn_unconfigure_rd(bgp, vpn);
5042 return CMD_SUCCESS;
90e60aa7 5043}
5044
5045/*
5046 * Loop over all extended-communities in the route-target list rtl and
5047 * return 1 if we find ecomtarget
5048 */
d62a17ae 5049static int bgp_evpn_rt_matches_existing(struct list *rtl,
5050 struct ecommunity *ecomtarget)
90e60aa7 5051{
d62a17ae 5052 struct listnode *node, *nnode;
5053 struct ecommunity *ecom;
90e60aa7 5054
d62a17ae 5055 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
5056 if (ecommunity_match(ecom, ecomtarget))
5057 return 1;
5058 }
90e60aa7 5059
d62a17ae 5060 return 0;
90e60aa7 5061}
5062
c581d8b0
MK
5063/* display L3VNI related info for a VRF instance */
5064DEFUN (show_bgp_vrf_l3vni_info,
5065 show_bgp_vrf_l3vni_info_cmd,
4cce389e 5066 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
5067 SHOW_STR
5068 BGP_STR
5069 "show bgp vrf\n"
5070 "VRF Name\n"
5071 "L3-VNI\n"
ceb9a921 5072 JSON_STR)
c581d8b0
MK
5073{
5074 char buf[ETHER_ADDR_STRLEN];
676f83b9 5075 char buf1[INET6_ADDRSTRLEN];
c581d8b0
MK
5076 int idx_vrf = 3;
5077 const char *name = NULL;
5078 struct bgp *bgp = NULL;
5079 struct listnode *node = NULL;
6a8657d0 5080 struct bgpevpn *vpn = NULL;
c581d8b0 5081 struct ecommunity *ecom = NULL;
ceb9a921
MK
5082 json_object *json = NULL;
5083 json_object *json_vnis = NULL;
5084 json_object *json_export_rts = NULL;
5085 json_object *json_import_rts = NULL;
9f049418 5086 bool uj = use_json(argc, argv);
ceb9a921
MK
5087
5088 if (uj) {
5089 json = json_object_new_object();
5090 json_vnis = json_object_new_array();
5091 json_export_rts = json_object_new_array();
5092 json_import_rts = json_object_new_array();
5093 }
c581d8b0
MK
5094
5095 name = argv[idx_vrf]->arg;
5096 bgp = bgp_lookup_by_name(name);
5097 if (!bgp) {
ceb9a921 5098 if (!uj)
996c9314 5099 vty_out(vty, "BGP instance for VRF %s not found", name);
ceb9a921
MK
5100 else {
5101 json_object_string_add(json, "warning",
5102 "BGP instance not found");
996c9314 5103 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
5104 json_object_free(json);
5105 }
c581d8b0
MK
5106 return CMD_WARNING;
5107 }
5108
ceb9a921
MK
5109 if (!json) {
5110 vty_out(vty, "BGP VRF: %s\n", name);
996c9314 5111 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
ceb9a921
MK
5112 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
5113 vty_out(vty, " Rmac: %s\n",
5114 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
5115 vty_out(vty, " VNI Filter: %s\n",
5116 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
5117 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
5118 ? "prefix-routes-only"
5119 : "none");
ceb9a921
MK
5120 vty_out(vty, " L2-VNI List:\n");
5121 vty_out(vty, " ");
5122 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
5123 vty_out(vty, "%u ", vpn->vni);
5124 vty_out(vty, "\n");
5125 vty_out(vty, " Export-RTs:\n");
5126 vty_out(vty, " ");
5127 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
5128 vty_out(vty, "%s ", ecommunity_str(ecom));
5129 vty_out(vty, "\n");
5130 vty_out(vty, " Import-RTs:\n");
5131 vty_out(vty, " ");
5132 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
5133 vty_out(vty, "%s ", ecommunity_str(ecom));
5134 vty_out(vty, "\n");
676f83b9 5135 vty_out(vty, " RD: %s\n",
5136 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
5137 } else {
5138 json_object_string_add(json, "vrf", name);
b67a60d2 5139 json_object_string_add(json, "local-ip",
5140 inet_ntoa(bgp->originator_ip));
ceb9a921 5141 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
5142 json_object_string_add(
5143 json, "rmac",
5144 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
5145 json_object_string_add(
5146 json, "vniFilter",
5147 CHECK_FLAG(bgp->vrf_flags,
5148 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
5149 ? "prefix-routes-only"
5150 : "none");
ceb9a921
MK
5151 /* list of l2vnis */
5152 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
5153 json_object_array_add(json_vnis,
5154 json_object_new_int(vpn->vni));
5155 json_object_object_add(json, "l2vnis", json_vnis);
5156
5157 /* export rts */
5158 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
996c9314
LB
5159 json_object_array_add(
5160 json_export_rts,
5161 json_object_new_string(ecommunity_str(ecom)));
ceb9a921
MK
5162 json_object_object_add(json, "export-rts", json_export_rts);
5163
5164 /* import rts */
5165 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
996c9314
LB
5166 json_object_array_add(
5167 json_import_rts,
5168 json_object_new_string(ecommunity_str(ecom)));
ceb9a921 5169 json_object_object_add(json, "import-rts", json_import_rts);
676f83b9 5170 json_object_string_add(
5171 json, "rd",
5172 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921 5173 }
c581d8b0 5174
ceb9a921
MK
5175 if (uj) {
5176 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5177 json, JSON_C_TO_STRING_PRETTY));
5178 json_object_free(json);
5179 }
c581d8b0
MK
5180 return CMD_SUCCESS;
5181}
5182
5183/* import/export rt for l3vni-vrf */
5184DEFUN (bgp_evpn_vrf_rt,
5185 bgp_evpn_vrf_rt_cmd,
5186 "route-target <both|import|export> RT",
5187 "Route Target\n"
5188 "import and export\n"
5189 "import\n"
5190 "export\n"
5191 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5192{
5193 int rt_type;
5194 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5195 struct ecommunity *ecomadd = NULL;
5196
5197 if (!bgp)
5198 return CMD_WARNING;
5199
5200 if (!strcmp(argv[1]->arg, "import"))
5201 rt_type = RT_TYPE_IMPORT;
5202 else if (!strcmp(argv[1]->arg, "export"))
5203 rt_type = RT_TYPE_EXPORT;
5204 else if (!strcmp(argv[1]->arg, "both"))
5205 rt_type = RT_TYPE_BOTH;
5206 else {
5207 vty_out(vty, "%% Invalid Route Target type\n");
5208 return CMD_WARNING;
5209 }
5210
5211 /* Add/update the import route-target */
5212 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5213 ecomadd = ecommunity_str2com(argv[2]->arg,
5214 ECOMMUNITY_ROUTE_TARGET, 0);
5215 if (!ecomadd) {
5216 vty_out(vty, "%% Malformed Route Target list\n");
5217 return CMD_WARNING;
5218 }
5219 ecommunity_str(ecomadd);
5220
5221 /* Do nothing if we already have this import route-target */
996c9314 5222 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
c581d8b0
MK
5223 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
5224 }
5225
5226 /* Add/update the export route-target */
5227 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5228 ecomadd = ecommunity_str2com(argv[2]->arg,
5229 ECOMMUNITY_ROUTE_TARGET, 0);
5230 if (!ecomadd) {
5231 vty_out(vty, "%% Malformed Route Target list\n");
5232 return CMD_WARNING;
5233 }
5234 ecommunity_str(ecomadd);
5235
5236 /* Do nothing if we already have this export route-target */
996c9314 5237 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
c581d8b0
MK
5238 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
5239 }
5240
5241 return CMD_SUCCESS;
5242}
5243
5244DEFUN (no_bgp_evpn_vrf_rt,
5245 no_bgp_evpn_vrf_rt_cmd,
5246 "no route-target <both|import|export> RT",
5247 NO_STR
5248 "Route Target\n"
5249 "import and export\n"
5250 "import\n"
5251 "export\n"
f5dc0b1a 5252 EVPN_ASN_IP_HELP_STR)
c581d8b0
MK
5253{
5254 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5255 int rt_type, found_ecomdel;
5256 struct ecommunity *ecomdel = NULL;
5257
5258 if (!bgp)
5259 return CMD_WARNING;
5260
5261 if (!strcmp(argv[2]->arg, "import"))
5262 rt_type = RT_TYPE_IMPORT;
5263 else if (!strcmp(argv[2]->arg, "export"))
5264 rt_type = RT_TYPE_EXPORT;
5265 else if (!strcmp(argv[2]->arg, "both"))
5266 rt_type = RT_TYPE_BOTH;
5267 else {
5268 vty_out(vty, "%% Invalid Route Target type\n");
5269 return CMD_WARNING;
5270 }
5271
5272 if (rt_type == RT_TYPE_IMPORT) {
5273 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5274 vty_out(vty,
5275 "%% Import RT is not configured for this VRF\n");
5276 return CMD_WARNING;
5277 }
5278 } else if (rt_type == RT_TYPE_EXPORT) {
5279 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5280 vty_out(vty,
5281 "%% Export RT is not configured for this VRF\n");
5282 return CMD_WARNING;
5283 }
5284 } else if (rt_type == RT_TYPE_BOTH) {
5285 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
5286 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5287 vty_out(vty,
5288 "%% Import/Export RT is not configured for this VRF\n");
5289 return CMD_WARNING;
5290 }
5291 }
5292
5293 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5294 if (!ecomdel) {
5295 vty_out(vty, "%% Malformed Route Target list\n");
5296 return CMD_WARNING;
5297 }
5298 ecommunity_str(ecomdel);
5299
5300 if (rt_type == RT_TYPE_IMPORT) {
5301 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5302 ecomdel)) {
5303 vty_out(vty,
5304 "%% RT specified does not match configuration for this VRF\n");
5305 return CMD_WARNING;
5306 }
5307 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5308 } else if (rt_type == RT_TYPE_EXPORT) {
5309 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5310 ecomdel)) {
5311 vty_out(vty,
5312 "%% RT specified does not match configuration for this VRF\n");
5313 return CMD_WARNING;
5314 }
5315 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5316 } else if (rt_type == RT_TYPE_BOTH) {
5317 found_ecomdel = 0;
5318
5319 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5320 ecomdel)) {
5321 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5322 found_ecomdel = 1;
5323 }
5324
5325 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5326 ecomdel)) {
5327 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5328 found_ecomdel = 1;
5329 }
5330
5331 if (!found_ecomdel) {
5332 vty_out(vty,
5333 "%% RT specified does not match configuration for this VRF\n");
5334 return CMD_WARNING;
5335 }
5336 }
5337
5338 return CMD_SUCCESS;
5339}
90e60aa7 5340
5341DEFUN (bgp_evpn_vni_rt,
5342 bgp_evpn_vni_rt_cmd,
5343 "route-target <both|import|export> RT",
5344 "Route Target\n"
5345 "import and export\n"
5346 "import\n"
5347 "export\n"
5348 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5349{
d62a17ae 5350 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5351 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5352 int rt_type;
5353 struct ecommunity *ecomadd = NULL;
5354
06fe25f4 5355 if (!bgp)
d62a17ae 5356 return CMD_WARNING;
5357
f920dd6d 5358 if (!EVPN_ENABLED(bgp)) {
a2a8153f 5359 vty_out(vty,
530db8dc 5360 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
5361 return CMD_WARNING;
5362 }
5363
8034beff 5364 if (!strcmp(argv[1]->text, "import"))
d62a17ae 5365 rt_type = RT_TYPE_IMPORT;
8034beff 5366 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 5367 rt_type = RT_TYPE_EXPORT;
8034beff 5368 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 5369 rt_type = RT_TYPE_BOTH;
5370 else {
5371 vty_out(vty, "%% Invalid Route Target type\n");
5372 return CMD_WARNING;
5373 }
5374
5375 /* Add/update the import route-target */
5376 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5377 ecomadd = ecommunity_str2com(argv[2]->arg,
5378 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 5379 if (!ecomadd) {
5380 vty_out(vty, "%% Malformed Route Target list\n");
5381 return CMD_WARNING;
5382 }
5bc2ed52 5383 ecommunity_str(ecomadd);
d62a17ae 5384
5385 /* Do nothing if we already have this import route-target */
5386 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
5387 evpn_configure_import_rt(bgp, vpn, ecomadd);
5388 }
5389
5390 /* Add/update the export route-target */
5391 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5392 ecomadd = ecommunity_str2com(argv[2]->arg,
5393 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 5394 if (!ecomadd) {
5395 vty_out(vty, "%% Malformed Route Target list\n");
5396 return CMD_WARNING;
5397 }
5bc2ed52 5398 ecommunity_str(ecomadd);
d62a17ae 5399
5400 /* Do nothing if we already have this export route-target */
5401 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
5402 evpn_configure_export_rt(bgp, vpn, ecomadd);
5403 }
5404
5405 return CMD_SUCCESS;
90e60aa7 5406}
5407
5408DEFUN (no_bgp_evpn_vni_rt,
5409 no_bgp_evpn_vni_rt_cmd,
5410 "no route-target <both|import|export> RT",
5411 NO_STR
5412 "Route Target\n"
5413 "import and export\n"
5414 "import\n"
5415 "export\n"
f5dc0b1a 5416 EVPN_ASN_IP_HELP_STR)
90e60aa7 5417{
d62a17ae 5418 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5419 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5420 int rt_type, found_ecomdel;
5421 struct ecommunity *ecomdel = NULL;
5422
06fe25f4 5423 if (!bgp)
d62a17ae 5424 return CMD_WARNING;
5425
f920dd6d 5426 if (!EVPN_ENABLED(bgp)) {
a2a8153f 5427 vty_out(vty,
530db8dc 5428 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
5429 return CMD_WARNING;
5430 }
5431
8034beff 5432 if (!strcmp(argv[2]->text, "import"))
d62a17ae 5433 rt_type = RT_TYPE_IMPORT;
8034beff 5434 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 5435 rt_type = RT_TYPE_EXPORT;
8034beff 5436 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 5437 rt_type = RT_TYPE_BOTH;
5438 else {
5439 vty_out(vty, "%% Invalid Route Target type\n");
5440 return CMD_WARNING;
5441 }
5442
5443 /* The user did "no route-target import", check to see if there are any
5444 * import route-targets configured. */
5445 if (rt_type == RT_TYPE_IMPORT) {
5446 if (!is_import_rt_configured(vpn)) {
5447 vty_out(vty,
5448 "%% Import RT is not configured for this VNI\n");
5449 return CMD_WARNING;
5450 }
5451 } else if (rt_type == RT_TYPE_EXPORT) {
5452 if (!is_export_rt_configured(vpn)) {
5453 vty_out(vty,
5454 "%% Export RT is not configured for this VNI\n");
5455 return CMD_WARNING;
5456 }
5457 } else if (rt_type == RT_TYPE_BOTH) {
5458 if (!is_import_rt_configured(vpn)
5459 && !is_export_rt_configured(vpn)) {
5460 vty_out(vty,
5461 "%% Import/Export RT is not configured for this VNI\n");
5462 return CMD_WARNING;
5463 }
5464 }
5465
5466 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 5467 if (!ecomdel) {
5468 vty_out(vty, "%% Malformed Route Target list\n");
5469 return CMD_WARNING;
5470 }
5bc2ed52 5471 ecommunity_str(ecomdel);
d62a17ae 5472
5473 if (rt_type == RT_TYPE_IMPORT) {
5474 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5475 vty_out(vty,
5476 "%% RT specified does not match configuration for this VNI\n");
5477 return CMD_WARNING;
5478 }
5479 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5480 } else if (rt_type == RT_TYPE_EXPORT) {
5481 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5482 vty_out(vty,
5483 "%% RT specified does not match configuration for this VNI\n");
5484 return CMD_WARNING;
5485 }
5486 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5487 } else if (rt_type == RT_TYPE_BOTH) {
5488 found_ecomdel = 0;
5489
5490 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5491 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5492 found_ecomdel = 1;
5493 }
5494
5495 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5496 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5497 found_ecomdel = 1;
5498 }
5499
5500 if (!found_ecomdel) {
5501 vty_out(vty,
5502 "%% RT specified does not match configuration for this VNI\n");
5503 return CMD_WARNING;
5504 }
5505 }
5506
5507 return CMD_SUCCESS;
90e60aa7 5508}
5509
5510DEFUN (no_bgp_evpn_vni_rt_without_val,
5511 no_bgp_evpn_vni_rt_without_val_cmd,
5512 "no route-target <import|export>",
5513 NO_STR
5514 "Route Target\n"
5515 "import\n"
5516 "export\n")
5517{
d62a17ae 5518 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5519 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5520 int rt_type;
5521
06fe25f4 5522 if (!bgp)
d62a17ae 5523 return CMD_WARNING;
5524
f920dd6d 5525 if (!EVPN_ENABLED(bgp)) {
a2a8153f 5526 vty_out(vty,
530db8dc 5527 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
5528 return CMD_WARNING;
5529 }
5530
8034beff 5531 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 5532 rt_type = RT_TYPE_IMPORT;
8034beff 5533 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 5534 rt_type = RT_TYPE_EXPORT;
5535 } else {
5536 vty_out(vty, "%% Invalid Route Target type\n");
5537 return CMD_WARNING;
5538 }
5539
5540 /* Check if we should disallow. */
5541 if (rt_type == RT_TYPE_IMPORT) {
5542 if (!is_import_rt_configured(vpn)) {
5543 vty_out(vty,
5544 "%% Import RT is not configured for this VNI\n");
5545 return CMD_WARNING;
5546 }
5547 } else {
5548 if (!is_export_rt_configured(vpn)) {
5549 vty_out(vty,
5550 "%% Export RT is not configured for this VNI\n");
5551 return CMD_WARNING;
5552 }
5553 }
5554
5555 /* Unconfigure the RT. */
5556 if (rt_type == RT_TYPE_IMPORT)
5557 evpn_unconfigure_import_rt(bgp, vpn, NULL);
5558 else
5559 evpn_unconfigure_export_rt(bgp, vpn, NULL);
5560 return CMD_SUCCESS;
90e60aa7 5561}
568b6b44
QY
5562
5563static int vni_cmp(const void **a, const void **b)
5564{
5565 const struct bgpevpn *first = *a;
5566 const struct bgpevpn *secnd = *b;
5567
5568 return secnd->vni - first->vni;
5569}
5570
90e60aa7 5571/*
5572 * Output EVPN configuration information.
5573 */
d62a17ae 5574void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 5575 safi_t safi)
d62a17ae 5576{
a75c2553 5577 char buf1[RD_ADDRSTRLEN];
1c97c9fd 5578 char buf2[INET6_ADDRSTRLEN];
a75c2553 5579
e67df34d
CS
5580 if (bgp->advertise_all_vni)
5581 vty_out(vty, " advertise-all-vni\n");
5582
568b6b44
QY
5583 if (bgp->vnihash) {
5584 struct list *vnilist = hash_to_list(bgp->vnihash);
5585 struct listnode *ln;
5586 struct bgpevpn *data;
5587
5588 list_sort(vnilist, vni_cmp);
5589 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
5590 write_vni_config(vty, data);
5591
6a154c88 5592 list_delete(&vnilist);
568b6b44 5593 }
90e60aa7 5594
bf1061d8
VB
5595 if (bgp->advertise_autort_rfc8365)
5596 vty_out(vty, " autort rfc8365-compatible\n");
5597
2b791107 5598 if (bgp->advertise_gw_macip)
1a98c087 5599 vty_out(vty, " advertise-default-gw\n");
6ee86383 5600
24864e44
CS
5601 if (bgp->evpn_info->advertise_svi_macip)
5602 vty_out(vty, " advertise-svi-ip\n");
5603
0b9d9cd0
CS
5604 if (!bgp->evpn_info->dup_addr_detect)
5605 vty_out(vty, " no dup-addr-detection\n");
5606
5607 if (bgp->evpn_info->dad_max_moves !=
5608 EVPN_DAD_DEFAULT_MAX_MOVES ||
5609 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
5610 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
5611 bgp->evpn_info->dad_max_moves,
5612 bgp->evpn_info->dad_time);
5613
5614 if (bgp->evpn_info->dad_freeze) {
5615 if (bgp->evpn_info->dad_freeze_time)
5616 vty_out(vty,
5617 " dup-addr-detection freeze %u\n",
5618 bgp->evpn_info->dad_freeze_time);
5619 else
5620 vty_out(vty,
5621 " dup-addr-detection freeze permanent\n");
5622 }
5623
fd069644
DS
5624 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
5625 vty_out(vty, " flooding disable\n");
5626
154faa50 5627 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
5628 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
5629 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
5630 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
5631 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
5632 else
5633 vty_out(vty, " advertise ipv4 unicast\n");
5634 }
6ee86383 5635
154faa50 5636 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
5637 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
5638 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
5639 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
5640 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
5641 else
5642 vty_out(vty, " advertise ipv6 unicast\n");
5643 }
486456ca
MK
5644
5645 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5646 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
5647 vty_out(vty, " default-originate ipv4\n");
5648
5649 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5650 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
5651 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 5652
5394a276
CS
5653 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
5654 if (!bgp->evpn_info->advertise_pip)
5655 vty_out(vty, " no advertise-pip\n");
5656 if (bgp->evpn_info->advertise_pip) {
0137a3d8
CS
5657 if (bgp->evpn_info->pip_ip_static.s_addr
5658 != INADDR_ANY) {
5394a276 5659 vty_out(vty, " advertise-pip ip %s",
1c97c9fd
CS
5660 inet_ntop(AF_INET,
5661 &bgp->evpn_info->pip_ip_static,
5662 buf2, INET_ADDRSTRLEN));
0137a3d8
CS
5663 if (!is_zero_mac(&(
5664 bgp->evpn_info->pip_rmac_static))) {
5665 char buf[ETHER_ADDR_STRLEN];
5666
5667 vty_out(vty, " mac %s",
5668 prefix_mac2str(
5669 &bgp->evpn_info
5670 ->pip_rmac,
5671 buf, sizeof(buf)));
5672 }
5673 vty_out(vty, "\n");
5394a276 5674 }
5394a276
CS
5675 }
5676 }
a75c2553 5677 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
9e97ff03 5678 vty_out(vty, " rd %s\n",
a75c2553
MK
5679 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
5680
db29a4a8
MK
5681 /* import route-target */
5682 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5683 char *ecom_str;
5684 struct listnode *node, *nnode;
5685 struct ecommunity *ecom;
5686
5687 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
5688 ecom)) {
5689 ecom_str = ecommunity_ecom2str(
5690 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
530e8a6e 5691 vty_out(vty, " route-target import %s\n", ecom_str);
db29a4a8
MK
5692 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5693 }
5694 }
5695
5696 /* export route-target */
5697 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5698 char *ecom_str;
5699 struct listnode *node, *nnode;
5700 struct ecommunity *ecom;
5701
5702 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
5703 ecom)) {
5704 ecom_str = ecommunity_ecom2str(
5705 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
530e8a6e 5706 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
5707 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5708 }
5709 }
90e60aa7 5710}
5711
4d0e6ece 5712void bgp_ethernetvpn_init(void)
784d3a42 5713{
d62a17ae 5714 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
5715 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
5716 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
5717 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
5718 install_element(VIEW_NODE,
dcc1615e 5719 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
d62a17ae 5720 install_element(VIEW_NODE,
5721 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
5722 install_element(
5723 VIEW_NODE,
dcc1615e 5724 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
d62a17ae 5725 install_element(
5726 VIEW_NODE,
5727 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
5728 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
5729 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
5730 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
5731 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
d62a17ae 5732 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
5733 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
bf1061d8
VB
5734 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
5735 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
1a98c087
MK
5736 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
5737 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
24864e44 5738 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
342dd0c6 5739 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
5740 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
5741 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
5742 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
0b9d9cd0
CS
5743 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
5744 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
5745 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
fd069644 5746 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5394a276 5747 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
d62a17ae 5748
50f74cf1 5749 /* test commands */
b5e140c8
AK
5750 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
5751 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
50f74cf1 5752
f2d62262 5753 /* "show bgp l2vpn evpn" commands. */
50f74cf1 5754 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
b5e140c8 5755 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
f2d62262 5756 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
5757 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
5758 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
5759 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
5760 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
50f74cf1 5761 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
f2d62262 5762 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
5763 install_element(VIEW_NODE,
5764 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
5765 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
5766 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
5767 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 5768 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 5769
5014d96f
DW
5770 /* "show bgp evpn" commands. */
5771 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
5772 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
5773 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
5774 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
5775 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
5776 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
5777 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
5778 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
5779 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
5780 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 5781 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7f433a5e 5782 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
5014d96f 5783
d62a17ae 5784 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
5785 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
5786 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
5787 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
5788 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
5789 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
5790 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
5791 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
5792 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
5793 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5794 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 5795 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
5796 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5797 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
24864e44 5798 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
1a98c087
MK
5799 install_element(BGP_EVPN_VNI_NODE,
5800 &bgp_evpn_advertise_default_gw_vni_cmd);
5801 install_element(BGP_EVPN_VNI_NODE,
5802 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
5803 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5804 install_element(BGP_EVPN_VNI_NODE,
5805 &no_bgp_evpn_advertise_vni_subnet_cmd);
784d3a42 5806}