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