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