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