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