]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
bgpd: Display table version for EVPN routes
[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
MK
609{
610 json_object *json_vni;
611 json_object *json_import_rtl;
612 json_object *json_export_rtl;
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}
8c197128 2516#endif /* HAVE_CUMULUS */
7724c0a1 2517
2b791107 2518static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
d62a17ae 2519{
06b9f471 2520 char buf1[RD_ADDRSTRLEN];
d62a17ae 2521 char *ecom_str;
2522 struct listnode *node, *nnode;
2523 struct ecommunity *ecom;
2524
2525 if (is_vni_configured(vpn)) {
d62a17ae 2526 vty_out(vty, " vni %d\n", vpn->vni);
2527 if (is_rd_configured(vpn))
2528 vty_out(vty, " rd %s\n",
06b9f471 2529 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
d62a17ae 2530
2531 if (is_import_rt_configured(vpn)) {
2532 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2533 ecom)) {
2534 ecom_str = ecommunity_ecom2str(
2535 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2536 vty_out(vty, " route-target import %s\n",
2537 ecom_str);
2538 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2539 }
2540 }
2541
2542 if (is_export_rt_configured(vpn)) {
2543 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2544 ecom)) {
2545 ecom_str = ecommunity_ecom2str(
2546 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 2547 vty_out(vty, " route-target export %s\n",
d62a17ae 2548 ecom_str);
2549 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2550 }
2551 }
2552
1a98c087
MK
2553 if (vpn->advertise_gw_macip)
2554 vty_out(vty, " advertise-default-gw\n");
2555
31310b25
MK
2556 if (vpn->advertise_subnet)
2557 vty_out(vty, " advertise-subnet\n");
2558
d62a17ae 2559 vty_out(vty, " exit-vni\n");
2560 }
2561}
2562
2563static void write_vni_config_for_entry(struct hash_backet *backet,
2b791107 2564 struct vty *vty)
d62a17ae 2565{
2566 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
2b791107 2567 write_vni_config(vty, vpn);
d62a17ae 2568}
2569
2570#if defined(HAVE_CUMULUS)
1a98c087
MK
2571DEFUN (bgp_evpn_advertise_default_gw_vni,
2572 bgp_evpn_advertise_default_gw_vni_cmd,
2573 "advertise-default-gw",
078af92e 2574 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
1a98c087
MK
2575{
2576 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2577 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2578
2579 if (!bgp)
2580 return CMD_WARNING;
2581
2582 if (!vpn)
2583 return CMD_WARNING;
2584
2585 evpn_set_advertise_default_gw(bgp, vpn);
2586
2587 return CMD_SUCCESS;
2588}
2589
2590DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2591 no_bgp_evpn_advertise_default_gw_vni_cmd,
2592 "no advertise-default-gw",
2593 NO_STR
2594 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2595{
2596 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2597 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2598
2599 if (!bgp)
2600 return CMD_WARNING;
2601
2602 if (!vpn)
2603 return CMD_WARNING;
2604
2605 evpn_unset_advertise_default_gw(bgp, vpn);
2606
2607 return CMD_SUCCESS;
2608}
2609
2610
2611DEFUN (bgp_evpn_advertise_default_gw,
2612 bgp_evpn_advertise_default_gw_cmd,
2613 "advertise-default-gw",
078af92e 2614 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
2615{
2616 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2617
2618 if (!bgp)
2619 return CMD_WARNING;
2620
2621 evpn_set_advertise_default_gw(bgp, NULL);
2622
2623 return CMD_SUCCESS;
2624}
2625
2626DEFUN (no_bgp_evpn_advertise_default_gw,
2627 no_bgp_evpn_advertise_default_gw_cmd,
2628 "no advertise-default-gw",
2629 NO_STR
2630 "Withdraw All default g/w mac-ip routes from EVPN\n")
2631{
2632 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2633
2634 if (!bgp)
2635 return CMD_WARNING;
2636
2637 evpn_unset_advertise_default_gw(bgp, NULL);
2638
2639 return CMD_SUCCESS;
2640}
2641
7724c0a1 2642DEFUN (bgp_evpn_advertise_all_vni,
2643 bgp_evpn_advertise_all_vni_cmd,
2644 "advertise-all-vni",
2645 "Advertise All local VNIs\n")
2646{
d62a17ae 2647 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2648
d62a17ae 2649 if (!bgp)
2650 return CMD_WARNING;
2651 evpn_set_advertise_all_vni(bgp);
2652 return CMD_SUCCESS;
7724c0a1 2653}
2654
2655DEFUN (no_bgp_evpn_advertise_all_vni,
2656 no_bgp_evpn_advertise_all_vni_cmd,
2657 "no advertise-all-vni",
2658 NO_STR
2659 "Advertise All local VNIs\n")
2660{
d62a17ae 2661 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2662
d62a17ae 2663 if (!bgp)
2664 return CMD_WARNING;
2665 evpn_unset_advertise_all_vni(bgp);
2666 return CMD_SUCCESS;
7724c0a1 2667}
2668
486456ca
MK
2669DEFUN (bgp_evpn_default_originate,
2670 bgp_evpn_default_originate_cmd,
2671 "default-originate <ipv4 | ipv6>",
2672 "originate a default route\n"
2673 "ipv4 address family\n"
2674 "ipv6 address family\n")
2675{
2676 afi_t afi = 0;
2677 int idx_afi = 0;
2678 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2679
2680 if (!bgp_vrf)
2681 return CMD_WARNING;
2682 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2683 evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
2684 return CMD_SUCCESS;
2685}
2686
2687DEFUN (no_bgp_evpn_default_originate,
2688 no_bgp_evpn_default_originate_cmd,
2689 "no default-originate <ipv4 | ipv6>",
2690 NO_STR
2691 "withdraw a default route\n"
2692 "ipv4 address family\n"
2693 "ipv6 address family\n")
2694{
2695 afi_t afi = 0;
2696 int idx_afi = 0;
2697 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2698
2699 if (!bgp_vrf)
2700 return CMD_WARNING;
2701 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2702 evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
2703 return CMD_SUCCESS;
2704}
2705
689b5101
MK
2706DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
2707 bgp_evpn_advertise_vni_subnet_cmd,
2708 "advertise-subnet",
2709 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
2710{
2711 struct bgp *bgp_vrf = NULL;
2712 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2713 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2714
2715 if (!bgp)
2716 return CMD_WARNING;
2717
2718 if (!vpn)
2719 return CMD_WARNING;
2720
2721 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
2722 if (!bgp_vrf)
2723 return CMD_WARNING;
2724
31310b25
MK
2725 evpn_set_advertise_subnet(bgp, vpn);
2726 return CMD_SUCCESS;
2727}
2728
689b5101
MK
2729DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
2730 no_bgp_evpn_advertise_vni_subnet_cmd,
2731 "no advertise-subnet",
2732 NO_STR
2733 "Advertise All local VNIs\n")
31310b25
MK
2734{
2735 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2736 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2737
2738 if (!bgp)
2739 return CMD_WARNING;
2740
2741 if (!vpn)
2742 return CMD_WARNING;
2743
2744 evpn_unset_advertise_subnet(bgp, vpn);
2745 return CMD_SUCCESS;
2746}
2747
342dd0c6 2748DEFUN (bgp_evpn_advertise_type5,
2749 bgp_evpn_advertise_type5_cmd,
53c84f78 2750 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 2751 "Advertise prefix routes\n"
053905d2 2752 BGP_AFI_HELP_STR
53c84f78
MK
2753 BGP_SAFI_HELP_STR
2754 "route-map for filtering specific routes\n"
2755 "Name of the route map\n")
342dd0c6 2756{
2757 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
2758 int idx_afi = 0;
2759 int idx_safi = 0;
53c84f78 2760 int idx_rmap = 0;
053905d2
MK
2761 afi_t afi = 0;
2762 safi_t safi = 0;
53c84f78
MK
2763 int ret = 0;
2764 int rmap_changed = 0;
053905d2
MK
2765
2766 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2767 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
53c84f78
MK
2768 ret = argv_find(argv, argc, "route-map", &idx_rmap);
2769 if (ret) {
2770 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
2771 rmap_changed = 1;
2772 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
2773 bgp_vrf->adv_cmd_rmap[afi][safi].name)
2774 != 0)
53c84f78
MK
2775 rmap_changed = 1;
2776 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
2777 rmap_changed = 1;
2778 }
053905d2 2779
e779dc76 2780 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
2781 vty_out(vty,
2782 "%%only ipv4 or ipv6 address families are supported");
342dd0c6 2783 return CMD_WARNING;
2784 }
2785
053905d2
MK
2786 if (safi != SAFI_UNICAST) {
2787 vty_out(vty,
2788 "%%only ipv4 unicast or ipv6 unicast are supported");
2789 return CMD_WARNING;
2790 }
2791
2792 if (afi == AFI_IP) {
342dd0c6 2793
2794 /* if we are already advertising ipv4 prefix as type-5
523cafc4 2795 * nothing to do
2796 */
154faa50
MK
2797 if (!rmap_changed &&
2798 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2799 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
53c84f78 2800 return CMD_WARNING;
154faa50
MK
2801 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2802 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 2803 } else {
2804
2805 /* if we are already advertising ipv6 prefix as type-5
523cafc4 2806 * nothing to do
2807 */
154faa50
MK
2808 if (!rmap_changed &&
2809 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2810 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
53c84f78 2811 return CMD_WARNING;
154faa50
MK
2812 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2813 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
53c84f78
MK
2814 }
2815
2816 if (rmap_changed) {
2817 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
2818 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
2819 XFREE(MTYPE_ROUTE_MAP_NAME,
2820 bgp_vrf->adv_cmd_rmap[afi][safi].name);
2821 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
2822 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
342dd0c6 2823 }
2824 }
53c84f78
MK
2825
2826 /* set the route-map for advertise command */
2827 if (ret && argv[idx_rmap + 1]->arg) {
2828 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 2829 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
2830 bgp_vrf->adv_cmd_rmap[afi][safi].map =
2831 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
2832 }
2833
2834 /* advertise type-5 routes */
2835 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 2836 return CMD_SUCCESS;
2837}
2838
2839DEFUN (no_bgp_evpn_advertise_type5,
2840 no_bgp_evpn_advertise_type5_cmd,
053905d2 2841 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
342dd0c6 2842 NO_STR
2843 "Advertise prefix routes\n"
053905d2
MK
2844 BGP_AFI_HELP_STR
2845 BGP_SAFI_HELP_STR)
342dd0c6 2846{
2847 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
2848 int idx_afi = 0;
2849 int idx_safi = 0;
2850 afi_t afi = 0;
2851 safi_t safi = 0;
2852
2853 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2854 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
2855
1ec31309 2856 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
2857 vty_out(vty,
2858 "%%only ipv4 or ipv6 address families are supported");
2859 return CMD_WARNING;
2860 }
2861
2862 if (safi != SAFI_UNICAST) {
2863 vty_out(vty,
2864 "%%only ipv4 unicast or ipv6 unicast are supported");
342dd0c6 2865 return CMD_WARNING;
2866 }
2867
053905d2 2868 if (afi == AFI_IP) {
342dd0c6 2869
fdf19f06 2870 /* if we are not advertising ipv4 prefix as type-5
523cafc4 2871 * nothing to do
2872 */
154faa50
MK
2873 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2874 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
053905d2 2875 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50
MK
2876 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2877 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 2878 }
2879 } else {
2880
fdf19f06 2881 /* if we are not advertising ipv6 prefix as type-5
523cafc4 2882 * nothing to do
2883 */
154faa50
MK
2884 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2885 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
053905d2 2886 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
342dd0c6 2887 UNSET_FLAG(bgp_vrf->vrf_flags,
154faa50 2888 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
342dd0c6 2889 }
2890 }
53c84f78
MK
2891
2892 /* clear the route-map information for advertise ipv4/ipv6 unicast */
2893 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
2894 XFREE(MTYPE_ROUTE_MAP_NAME,
2895 bgp_vrf->adv_cmd_rmap[afi][safi].name);
2896 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
2897 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
2898 }
2899
342dd0c6 2900 return CMD_SUCCESS;
2901}
2902
f2d62262 2903/*
2904 * Display VNI information - for all or a specific VNI
2905 */
9c92b5f7
MK
2906DEFUN(show_bgp_l2vpn_evpn_vni,
2907 show_bgp_l2vpn_evpn_vni_cmd,
2908 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2909 SHOW_STR
2910 BGP_STR
2911 L2VPN_HELP_STR
2912 EVPN_HELP_STR
2913 "Show VNI\n"
2914 "VNI number\n"
2915 JSON_STR)
520d5d76 2916{
4cce389e 2917 struct bgp *bgp_def;
f2d62262 2918 vni_t vni;
2919 int idx = 0;
d7c0a89a 2920 uint8_t uj = 0;
9c92b5f7 2921 json_object *json = NULL;
d7c0a89a
QY
2922 uint32_t num_l2vnis = 0;
2923 uint32_t num_l3vnis = 0;
d4454626 2924 uint32_t num_vnis = 0;
4cce389e
MK
2925 struct listnode *node = NULL;
2926 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
2927
2928 uj = use_json(argc, argv);
520d5d76 2929
4cce389e
MK
2930 bgp_def = bgp_get_default();
2931 if (!bgp_def)
d62a17ae 2932 return CMD_WARNING;
520d5d76 2933
f2d62262 2934 if (!argv_find(argv, argc, "evpn", &idx))
2935 return CMD_WARNING;
2936
9c92b5f7
MK
2937 if (uj)
2938 json = json_object_new_object();
1a98c087 2939
9c92b5f7 2940 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e
MK
2941
2942 num_l2vnis = hashcount(bgp_def->vnihash);
4cce389e
MK
2943
2944 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2945 if (bgp_temp->l3vni)
2946 num_l3vnis++;
2947 }
d4454626 2948 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
2949 if (uj) {
2950 json_object_string_add(json, "advertiseGatewayMacip",
4cce389e 2951 bgp_def->advertise_gw_macip
9c92b5f7
MK
2952 ? "Enabled"
2953 : "Disabled");
2954 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
2955 is_evpn_enabled() ? "Enabled"
2956 : "Disabled");
d4454626 2957 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
2958 json_object_int_add(json, "numL2Vnis", num_l2vnis);
2959 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
2960 } else {
2961 vty_out(vty, "Advertise Gateway Macip: %s\n",
4cce389e 2962 bgp_def->advertise_gw_macip ? "Enabled"
996c9314 2963 : "Disabled");
9c92b5f7 2964 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 2965 is_evpn_enabled() ? "Enabled" : "Disabled");
4cce389e
MK
2966 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
2967 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 2968 }
4cce389e 2969 evpn_show_all_vnis(vty, bgp_def, json);
f2d62262 2970 } else {
9c92b5f7
MK
2971 int vni_idx = 0;
2972
2973 if (!argv_find(argv, argc, "vni", &vni_idx))
2974 return CMD_WARNING;
2975
f2d62262 2976 /* Display specific VNI */
9c92b5f7 2977 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4cce389e 2978 evpn_show_vni(vty, bgp_def, vni, json);
9c92b5f7
MK
2979 }
2980
2981 if (uj) {
2982 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2983 json, JSON_C_TO_STRING_PRETTY));
2984 json_object_free(json);
f2d62262 2985 }
520d5d76 2986
d62a17ae 2987 return CMD_SUCCESS;
520d5d76 2988}
2989
f2d62262 2990/*
2991 * Display EVPN neighbor summary.
2992 */
9c92b5f7
MK
2993DEFUN(show_bgp_l2vpn_evpn_summary,
2994 show_bgp_l2vpn_evpn_summary_cmd,
ee851c8c 2995 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
9c92b5f7
MK
2996 SHOW_STR
2997 BGP_STR
ee851c8c
MK
2998 "bgp vrf\n"
2999 "vrf name\n"
9c92b5f7
MK
3000 L2VPN_HELP_STR
3001 EVPN_HELP_STR
3002 "Summary of BGP neighbor status\n"
3003 JSON_STR)
520d5d76 3004{
ee851c8c 3005 int idx_vrf = 0;
d7c0a89a 3006 uint8_t uj = use_json(argc, argv);
ee851c8c
MK
3007 char *vrf = NULL;
3008
3009 if (argv_find(argv, argc, "vrf", &idx_vrf))
3010 vrf = argv[++idx_vrf]->arg;
3011 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, uj);
520d5d76 3012}
3013
f2d62262 3014/*
3015 * Display global EVPN routing table.
3016 */
60466a63
QY
3017DEFUN(show_bgp_l2vpn_evpn_route,
3018 show_bgp_l2vpn_evpn_route_cmd,
47b71369 3019 "show bgp l2vpn evpn route [type <macip|multicast|prefix>] [json]",
9c92b5f7
MK
3020 SHOW_STR
3021 BGP_STR
3022 L2VPN_HELP_STR
3023 EVPN_HELP_STR
3024 "EVPN route information\n"
3025 "Specify Route type\n"
3026 "MAC-IP (Type-2) route\n"
3027 "Multicast (Type-3) route\n"
aa9db9e6 3028 "Prefix route\n"
9c92b5f7 3029 JSON_STR)
520d5d76 3030{
d62a17ae 3031 struct bgp *bgp;
8367c327 3032 int type_idx = 0;
d62a17ae 3033 int type = 0;
d7c0a89a 3034 uint8_t uj = 0;
9c92b5f7
MK
3035 json_object *json = NULL;
3036
3037 uj = use_json(argc, argv);
520d5d76 3038
d62a17ae 3039 bgp = bgp_get_default();
3040 if (!bgp)
3041 return CMD_WARNING;
520d5d76 3042
9c92b5f7
MK
3043 if (uj)
3044 json = json_object_new_object();
f2d62262 3045
9c92b5f7
MK
3046 /* get the type */
3047 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3048 /* Specific type is requested */
9c92b5f7 3049 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3050 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3051 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3052 type = BGP_EVPN_IMET_ROUTE;
47b71369
MK
3053 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3054 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3055 else
3056 return CMD_WARNING;
3057 }
520d5d76 3058
9c92b5f7
MK
3059 evpn_show_all_routes(vty, bgp, type, json);
3060
3061 if (uj) {
3062 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3063 json, JSON_C_TO_STRING_PRETTY));
3064 json_object_free(json);
3065 }
d62a17ae 3066 return CMD_SUCCESS;
520d5d76 3067}
3068
f2d62262 3069/*
3070 * Display global EVPN routing table for specific RD.
3071 */
60466a63
QY
3072DEFUN(show_bgp_l2vpn_evpn_route_rd,
3073 show_bgp_l2vpn_evpn_route_rd_cmd,
aa9db9e6 3074 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|prefix>] [json]",
9c92b5f7
MK
3075 SHOW_STR
3076 BGP_STR
3077 L2VPN_HELP_STR
3078 EVPN_HELP_STR
3079 "EVPN route information\n"
3080 "Route Distinguisher\n"
3081 "ASN:XX or A.B.C.D:XX\n"
3082 "Specify Route type\n"
3083 "MAC-IP (Type-2) route\n"
3084 "Multicast (Type-3) route\n"
aa9db9e6 3085 "Prefix route\n"
9c92b5f7 3086 JSON_STR)
520d5d76 3087{
d62a17ae 3088 struct bgp *bgp;
3089 int ret;
3090 struct prefix_rd prd;
3091 int type = 0;
9c92b5f7
MK
3092 int rd_idx = 0;
3093 int type_idx = 0;
3094 int uj = 0;
3095 json_object *json = NULL;
520d5d76 3096
d62a17ae 3097 bgp = bgp_get_default();
3098 if (!bgp)
3099 return CMD_WARNING;
520d5d76 3100
9c92b5f7
MK
3101 /* check if we need json output */
3102 uj = use_json(argc, argv);
3103 if (uj)
3104 json = json_object_new_object();
f2d62262 3105
9c92b5f7
MK
3106 /* get the RD */
3107 if (argv_find(argv, argc, "rd", &rd_idx)) {
3108 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3109
3110 if (!ret) {
3111 vty_out(vty, "%% Malformed Route Distinguisher\n");
3112 return CMD_WARNING;
3113 }
d62a17ae 3114 }
520d5d76 3115
9c92b5f7
MK
3116 /* get the type */
3117 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3118 /* Specific type is requested */
9c92b5f7 3119 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3120 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3121 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3122 type = BGP_EVPN_IMET_ROUTE;
aa9db9e6
MK
3123 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3124 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3125 else
3126 return CMD_WARNING;
3127 }
520d5d76 3128
9c92b5f7
MK
3129 evpn_show_route_rd(vty, bgp, &prd, type, json);
3130
3131 if (uj) {
3132 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3133 json, JSON_C_TO_STRING_PRETTY));
3134 json_object_free(json);
3135 }
3136
d62a17ae 3137 return CMD_SUCCESS;
520d5d76 3138}
3139
f2d62262 3140/*
3141 * Display global EVPN routing table for specific RD and MACIP.
3142 */
9c92b5f7
MK
3143DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3144 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
d114b977 3145 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
9c92b5f7
MK
3146 SHOW_STR
3147 BGP_STR
3148 L2VPN_HELP_STR
3149 EVPN_HELP_STR
3150 "EVPN route information\n"
3151 "Route Distinguisher\n"
3152 "ASN:XX or A.B.C.D:XX\n"
3153 "MAC\n"
3154 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3155 "IP\n"
3156 "IP address (IPv4 or IPv6)\n"
3157 JSON_STR)
3158{
0291c246
MK
3159 struct bgp *bgp;
3160 int ret;
3161 struct prefix_rd prd;
3162 struct ethaddr mac;
3163 struct ipaddr ip;
3164 int rd_idx = 0;
3165 int mac_idx = 0;
3166 int ip_idx = 0;
3167 int uj = 0;
3168 json_object *json = NULL;
9c92b5f7
MK
3169
3170 memset(&mac, 0, sizeof(struct ethaddr));
3171 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 3172
3173 bgp = bgp_get_default();
3174 if (!bgp)
3175 return CMD_WARNING;
3176
9c92b5f7
MK
3177 /* check if we need json output */
3178 uj = use_json(argc, argv);
3179 if (uj)
3180 json = json_object_new_object();
f2d62262 3181
9c92b5f7
MK
3182 /* get the prd */
3183 if (argv_find(argv, argc, "rd", &rd_idx)) {
3184 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3185 if (!ret) {
3186 vty_out(vty, "%% Malformed Route Distinguisher\n");
3187 return CMD_WARNING;
3188 }
d62a17ae 3189 }
9c92b5f7
MK
3190
3191 /* get the mac */
3192 if (argv_find(argv, argc, "mac", &mac_idx)) {
3193 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
3194 vty_out(vty, "%% Malformed MAC address\n");
3195 return CMD_WARNING;
3196 }
d62a17ae 3197 }
9c92b5f7
MK
3198
3199 /* get the ip if specified */
3200 if (argv_find(argv, argc, "ip", &ip_idx)) {
3201 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 3202 vty_out(vty, "%% Malformed IP address\n");
3203 return CMD_WARNING;
3204 }
3205 }
3206
9c92b5f7
MK
3207 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
3208
3209 if (uj) {
3210 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3211 json, JSON_C_TO_STRING_PRETTY));
3212 json_object_free(json);
3213 }
3214
d62a17ae 3215 return CMD_SUCCESS;
520d5d76 3216}
3217
f2d62262 3218/*
3219 * Display per-VNI EVPN routing table.
3220 */
9c92b5f7
MK
3221DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
3222 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3223 SHOW_STR
3224 BGP_STR
3225 L2VPN_HELP_STR
3226 EVPN_HELP_STR
3227 "EVPN route information\n"
3228 "VXLAN Network Identifier\n"
3229 "VNI number\n"
3230 "Specify Route type\n"
3231 "MAC-IP (Type-2) route\n"
3232 "Multicast (Type-3) route\n"
3233 "Remote VTEP\n"
3234 "Remote VTEP IP address\n"
3235 JSON_STR)
520d5d76 3236{
d62a17ae 3237 vni_t vni;
3238 struct bgp *bgp;
3239 struct in_addr vtep_ip;
3240 int type = 0;
f2d62262 3241 int idx = 0;
9c92b5f7
MK
3242 int uj = 0;
3243 json_object *json = NULL;
d62a17ae 3244
3245 bgp = bgp_get_default();
3246 if (!bgp)
3247 return CMD_WARNING;
3248
9c92b5f7
MK
3249 /* check if we need json output */
3250 uj = use_json(argc, argv);
3251 if (uj)
3252 json = json_object_new_object();
3253
f2d62262 3254 if (!argv_find(argv, argc, "evpn", &idx))
3255 return CMD_WARNING;
3256
d62a17ae 3257 vtep_ip.s_addr = 0;
3258
f2d62262 3259 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 3260
9c92b5f7
MK
3261 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
3262 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 3263 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
3264 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 3265 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 3266 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 3267 type = BGP_EVPN_IMET_ROUTE;
3268 else
3269 return CMD_WARNING;
f2d62262 3270 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
3271 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3272 vty_out(vty, "%% Malformed VTEP IP address\n");
3273 return CMD_WARNING;
3274 }
3275 } else
3276 return CMD_WARNING;
3277 }
3278
9c92b5f7
MK
3279 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
3280
3281 if (uj) {
3282 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3283 json, JSON_C_TO_STRING_PRETTY));
3284 json_object_free(json);
3285 }
3286
d62a17ae 3287 return CMD_SUCCESS;
520d5d76 3288}
3289
f2d62262 3290/*
3291 * Display per-VNI EVPN routing table for specific MACIP.
3292 */
9c92b5f7
MK
3293DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
3294 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
3295 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3296 SHOW_STR
3297 BGP_STR
3298 L2VPN_HELP_STR
3299 EVPN_HELP_STR
3300 "EVPN route information\n"
3301 "VXLAN Network Identifier\n"
3302 "VNI number\n"
3303 "MAC\n"
3304 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3305 "IP\n"
3306 "IP address (IPv4 or IPv6)\n"
3307 JSON_STR)
520d5d76 3308{
d62a17ae 3309 vni_t vni;
3310 struct bgp *bgp;
3311 struct ethaddr mac;
3312 struct ipaddr ip;
f2d62262 3313 int idx = 0;
9c92b5f7
MK
3314 int uj = 0;
3315 json_object *json = NULL;
d62a17ae 3316
3317 bgp = bgp_get_default();
3318 if (!bgp)
3319 return CMD_WARNING;
3320
9c92b5f7
MK
3321 /* check if we need json output */
3322 uj = use_json(argc, argv);
3323 if (uj)
3324 json = json_object_new_object();
3325
f2d62262 3326 if (!argv_find(argv, argc, "evpn", &idx))
3327 return CMD_WARNING;
3328
9c92b5f7 3329 /* get the VNI */
f2d62262 3330 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3331
3332 /* get the mac */
f2d62262 3333 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 3334 vty_out(vty, "%% Malformed MAC address\n");
3335 return CMD_WARNING;
3336 }
9c92b5f7
MK
3337
3338 /* get the ip */
d62a17ae 3339 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
3340 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
3341 || (uj
3342 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 3343 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 3344 vty_out(vty, "%% Malformed IP address\n");
3345 return CMD_WARNING;
3346 }
3347 }
3348
9c92b5f7
MK
3349 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
3350
3351 if (uj) {
3352 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3353 json, JSON_C_TO_STRING_PRETTY));
3354 json_object_free(json);
3355 }
3356
d62a17ae 3357 return CMD_SUCCESS;
520d5d76 3358}
3359
f2d62262 3360/*
3361 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3362 */
9c92b5f7
MK
3363DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3364 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3365 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3366 SHOW_STR
3367 BGP_STR
3368 L2VPN_HELP_STR
3369 EVPN_HELP_STR
3370 "EVPN route information\n"
3371 "VXLAN Network Identifier\n"
3372 "VNI number\n"
3373 "Multicast (Type-3) route\n"
3374 "Originating Router IP address\n"
3375 JSON_STR)
520d5d76 3376{
d62a17ae 3377 vni_t vni;
3378 struct bgp *bgp;
3379 int ret;
3380 struct in_addr orig_ip;
f2d62262 3381 int idx = 0;
9c92b5f7
MK
3382 int uj = 0;
3383 json_object *json = NULL;
520d5d76 3384
d62a17ae 3385 bgp = bgp_get_default();
3386 if (!bgp)
3387 return CMD_WARNING;
520d5d76 3388
9c92b5f7
MK
3389 /* check if we need json output */
3390 uj = use_json(argc, argv);
3391 if (uj)
3392 json = json_object_new_object();
3393
f2d62262 3394 if (!argv_find(argv, argc, "evpn", &idx))
3395 return CMD_WARNING;
3396
9c92b5f7 3397 /* get the VNI */
f2d62262 3398 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3399
3400 /* get the ip */
f2d62262 3401 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 3402 if (!ret) {
3403 vty_out(vty, "%% Malformed Originating Router IP address\n");
3404 return CMD_WARNING;
3405 }
520d5d76 3406
9c92b5f7
MK
3407 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3408
3409 if (uj) {
3410 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3411 json, JSON_C_TO_STRING_PRETTY));
3412 json_object_free(json);
3413 }
3414
d62a17ae 3415 return CMD_SUCCESS;
520d5d76 3416}
3417
f2d62262 3418/*
3419 * Display per-VNI EVPN routing table - for all VNIs.
3420 */
60466a63
QY
3421DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3422 show_bgp_l2vpn_evpn_route_vni_all_cmd,
9c92b5f7
MK
3423 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3424 SHOW_STR
3425 BGP_STR
3426 L2VPN_HELP_STR
3427 EVPN_HELP_STR
3428 "EVPN route information\n"
3429 "VXLAN Network Identifier\n"
3430 "All VNIs\n"
3431 "Remote VTEP\n"
3432 "Remote VTEP IP address\n"
3433 JSON_STR)
520d5d76 3434{
d62a17ae 3435 struct bgp *bgp;
3436 struct in_addr vtep_ip;
f2d62262 3437 int idx = 0;
9c92b5f7
MK
3438 int uj = 0;
3439 json_object *json = NULL;
520d5d76 3440
d62a17ae 3441 bgp = bgp_get_default();
3442 if (!bgp)
3443 return CMD_WARNING;
520d5d76 3444
9c92b5f7
MK
3445 /* check if we need json output */
3446 uj = use_json(argc, argv);
3447 if (uj)
3448 json = json_object_new_object();
3449
f2d62262 3450 if (!argv_find(argv, argc, "evpn", &idx))
3451 return CMD_WARNING;
3452
d62a17ae 3453 vtep_ip.s_addr = 0;
9c92b5f7
MK
3454 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3455 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
f2d62262 3456 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3457 vty_out(vty, "%% Malformed VTEP IP address\n");
3458 return CMD_WARNING;
3459 }
3460 }
520d5d76 3461
9c92b5f7
MK
3462 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3463
3464 if (uj) {
3465 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3466 json, JSON_C_TO_STRING_PRETTY));
3467 json_object_free(json);
3468 }
3469
d62a17ae 3470 return CMD_SUCCESS;
520d5d76 3471}
3472
10ebe1ab
MK
3473/*
3474 * Display EVPN import route-target hash table
3475 */
3476DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3477 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3478 "show bgp l2vpn evpn vrf-import-rt [json]",
3479 SHOW_STR
3480 BGP_STR
3481 L2VPN_HELP_STR
3482 EVPN_HELP_STR
3483 "Show vrf import route target\n"
3484 JSON_STR)
3485{
d7c0a89a 3486 uint8_t uj = 0;
181c08c6 3487 struct bgp *bgp_def = NULL;
10ebe1ab
MK
3488 json_object *json = NULL;
3489
3490 bgp_def = bgp_get_default();
3491 if (!bgp_def)
3492 return CMD_WARNING;
3493
3494 uj = use_json(argc, argv);
3495 if (uj)
3496 json = json_object_new_object();
3497
3498 evpn_show_vrf_import_rts(vty, bgp_def, json);
3499
3500 if (uj) {
3501 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3502 json, JSON_C_TO_STRING_PRETTY));
3503 json_object_free(json);
3504 }
3505
3506 return CMD_SUCCESS;
3507}
3508
f2d62262 3509/*
3510 * Display EVPN import route-target hash table
3511 */
60466a63
QY
3512DEFUN(show_bgp_l2vpn_evpn_import_rt,
3513 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
3514 "show bgp l2vpn evpn import-rt [json]",
3515 SHOW_STR
3516 BGP_STR
3517 L2VPN_HELP_STR
3518 EVPN_HELP_STR
3519 "Show import route target\n"
3520 JSON_STR)
520d5d76 3521{
d62a17ae 3522 struct bgp *bgp;
d7c0a89a 3523 uint8_t uj = 0;
9c92b5f7 3524 json_object *json = NULL;
520d5d76 3525
d62a17ae 3526 bgp = bgp_get_default();
3527 if (!bgp)
3528 return CMD_WARNING;
520d5d76 3529
9c92b5f7
MK
3530 uj = use_json(argc, argv);
3531 if (uj)
3532 json = json_object_new_object();
3533
3534 evpn_show_import_rts(vty, bgp, json);
3535
3536 if (uj) {
3537 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3538 json, JSON_C_TO_STRING_PRETTY));
3539 json_object_free(json);
3540 }
3541
d62a17ae 3542 return CMD_SUCCESS;
520d5d76 3543}
3544
5014d96f
DW
3545#if defined(HAVE_CUMULUS)
3546ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3547 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3548 "Show VNI\n"
3549 "VNI number\n")
3550
3551ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3552 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 3553 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
3554
3555ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3556 "show bgp evpn route [type <macip|multicast>]",
3557 SHOW_STR BGP_STR EVPN_HELP_STR
3558 "EVPN route information\n"
3559 "Specify Route type\n"
3560 "MAC-IP (Type-2) route\n"
3561 "Multicast (Type-3) route\n")
3562
3563ALIAS_HIDDEN(
3564 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
d114b977 3565 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
5014d96f
DW
3566 SHOW_STR BGP_STR EVPN_HELP_STR
3567 "EVPN route information\n"
3568 "Route Distinguisher\n"
3569 "ASN:XX or A.B.C.D:XX\n"
3570 "Specify Route type\n"
3571 "MAC-IP (Type-2) route\n"
3572 "Multicast (Type-3) route\n")
3573
3574ALIAS_HIDDEN(
3575 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 3576 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f
DW
3577 SHOW_STR BGP_STR EVPN_HELP_STR
3578 "EVPN route information\n"
3579 "Route Distinguisher\n"
3580 "ASN:XX or A.B.C.D:XX\n"
3581 "MAC\n"
3582 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3583 "IP\n"
3584 "IP address (IPv4 or IPv6)\n")
3585
3586ALIAS_HIDDEN(
3587 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
3588 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3589 SHOW_STR BGP_STR EVPN_HELP_STR
3590 "EVPN route information\n"
3591 "VXLAN Network Identifier\n"
3592 "VNI number\n"
3593 "Specify Route type\n"
3594 "MAC-IP (Type-2) route\n"
3595 "Multicast (Type-3) route\n"
3596 "Remote VTEP\n"
3597 "Remote VTEP IP address\n")
3598
3599ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
3600 show_bgp_evpn_route_vni_macip_cmd,
3601 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3602 SHOW_STR BGP_STR EVPN_HELP_STR
3603 "EVPN route information\n"
3604 "VXLAN Network Identifier\n"
3605 "VNI number\n"
3606 "MAC\n"
3607 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3608 "IP\n"
3609 "IP address (IPv4 or IPv6)\n")
3610
3611ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
3612 show_bgp_evpn_route_vni_multicast_cmd,
3613 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3614 SHOW_STR BGP_STR EVPN_HELP_STR
3615 "EVPN route information\n"
3616 "VXLAN Network Identifier\n"
3617 "VNI number\n"
3618 "Multicast (Type-3) route\n"
3619 "Originating Router IP address\n")
3620
3621ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
3622 "show bgp evpn route vni all [vtep A.B.C.D]",
3623 SHOW_STR BGP_STR EVPN_HELP_STR
3624 "EVPN route information\n"
3625 "VXLAN Network Identifier\n"
3626 "All VNIs\n"
3627 "Remote VTEP\n"
3628 "Remote VTEP IP address\n")
3629
3630ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
3631 "show bgp evpn import-rt",
3632 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
3633#endif
3634
90e60aa7 3635DEFUN_NOSH (bgp_evpn_vni,
3636 bgp_evpn_vni_cmd,
3637 "vni (1-16777215)",
3638 "VXLAN Network Identifier\n"
3639 "VNI number\n")
3640{
d62a17ae 3641 vni_t vni;
3642 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3643 struct bgpevpn *vpn;
90e60aa7 3644
d62a17ae 3645 if (!bgp)
3646 return CMD_WARNING;
90e60aa7 3647
d62a17ae 3648 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 3649
d62a17ae 3650 /* Create VNI, or mark as configured. */
3651 vpn = evpn_create_update_vni(bgp, vni);
3652 if (!vpn) {
3653 vty_out(vty, "%% Failed to create VNI \n");
3654 return CMD_WARNING;
3655 }
90e60aa7 3656
d62a17ae 3657 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
3658 return CMD_SUCCESS;
90e60aa7 3659}
3660
3661DEFUN (no_bgp_evpn_vni,
3662 no_bgp_evpn_vni_cmd,
3663 "no vni (1-16777215)",
3664 NO_STR
3665 "VXLAN Network Identifier\n"
3666 "VNI number\n")
3667{
d62a17ae 3668 vni_t vni;
3669 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3670 struct bgpevpn *vpn;
90e60aa7 3671
d62a17ae 3672 if (!bgp)
3673 return CMD_WARNING;
90e60aa7 3674
d62a17ae 3675 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 3676
d62a17ae 3677 /* Check if we should disallow. */
3678 vpn = bgp_evpn_lookup_vni(bgp, vni);
3679 if (!vpn) {
3680 vty_out(vty, "%% Specified VNI does not exist\n");
3681 return CMD_WARNING;
3682 }
3683 if (!is_vni_configured(vpn)) {
3684 vty_out(vty, "%% Specified VNI is not configured\n");
3685 return CMD_WARNING;
3686 }
90e60aa7 3687
d62a17ae 3688 evpn_delete_vni(bgp, vpn);
3689 return CMD_SUCCESS;
90e60aa7 3690}
3691
3692DEFUN_NOSH (exit_vni,
3693 exit_vni_cmd,
3694 "exit-vni",
3695 "Exit from VNI mode\n")
3696{
d62a17ae 3697 if (vty->node == BGP_EVPN_VNI_NODE)
3698 vty->node = BGP_EVPN_NODE;
3699 return CMD_SUCCESS;
90e60aa7 3700}
3701
676f83b9 3702DEFUN (bgp_evpn_vrf_rd,
3703 bgp_evpn_vrf_rd_cmd,
3704 "rd ASN:NN_OR_IP-ADDRESS:NN",
3705 "Route Distinguisher\n"
3706 "ASN:XX or A.B.C.D:XX\n")
3707{
3708 int ret;
3709 struct prefix_rd prd;
3710 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3711
3712 if (!bgp_vrf)
3713 return CMD_WARNING;
3714
3715 ret = str2prefix_rd(argv[1]->arg, &prd);
3716 if (!ret) {
3717 vty_out(vty, "%% Malformed Route Distinguisher\n");
3718 return CMD_WARNING;
3719 }
3720
3721 /* If same as existing value, there is nothing more to do. */
3722 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
3723 return CMD_SUCCESS;
3724
3725 /* Configure or update the RD. */
3726 evpn_configure_vrf_rd(bgp_vrf, &prd);
3727 return CMD_SUCCESS;
3728}
3729
3730DEFUN (no_bgp_evpn_vrf_rd,
3731 no_bgp_evpn_vrf_rd_cmd,
3732 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3733 NO_STR
3734 "Route Distinguisher\n"
3735 "ASN:XX or A.B.C.D:XX\n")
3736{
3737 int ret;
3738 struct prefix_rd prd;
3739 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3740
3741 if (!bgp_vrf)
3742 return CMD_WARNING;
3743
3744 ret = str2prefix_rd(argv[2]->arg, &prd);
3745 if (!ret) {
3746 vty_out(vty, "%% Malformed Route Distinguisher\n");
3747 return CMD_WARNING;
3748 }
3749
3750 /* Check if we should disallow. */
3751 if (!is_vrf_rd_configured(bgp_vrf)) {
3752 vty_out(vty, "%% RD is not configured for this VRF\n");
3753 return CMD_WARNING;
3754 }
3755
3756 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
3757 vty_out(vty,
3758 "%% RD specified does not match configuration for this VRF\n");
3759 return CMD_WARNING;
3760 }
3761
3762 evpn_unconfigure_vrf_rd(bgp_vrf);
3763 return CMD_SUCCESS;
3764}
3765
3766DEFUN (no_bgp_evpn_vrf_rd_without_val,
3767 no_bgp_evpn_vrf_rd_without_val_cmd,
3768 "no rd",
3769 NO_STR
3770 "Route Distinguisher\n")
3771{
3772 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3773
3774 if (!bgp_vrf)
3775 return CMD_WARNING;
3776
3777 /* Check if we should disallow. */
3778 if (!is_vrf_rd_configured(bgp_vrf)) {
3779 vty_out(vty, "%% RD is not configured for this VRF\n");
3780 return CMD_WARNING;
3781 }
3782
3783 evpn_unconfigure_vrf_rd(bgp_vrf);
3784 return CMD_SUCCESS;
3785}
3786
90e60aa7 3787DEFUN (bgp_evpn_vni_rd,
3788 bgp_evpn_vni_rd_cmd,
d114b977 3789 "rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 3790 "Route Distinguisher\n"
3791 "ASN:XX or A.B.C.D:XX\n")
3792{
d62a17ae 3793 struct prefix_rd prd;
3794 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3795 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3796 int ret;
90e60aa7 3797
d62a17ae 3798 if (!bgp || !vpn)
3799 return CMD_WARNING;
90e60aa7 3800
d62a17ae 3801 ret = str2prefix_rd(argv[1]->arg, &prd);
3802 if (!ret) {
3803 vty_out(vty, "%% Malformed Route Distinguisher\n");
3804 return CMD_WARNING;
3805 }
90e60aa7 3806
d62a17ae 3807 /* If same as existing value, there is nothing more to do. */
3808 if (bgp_evpn_rd_matches_existing(vpn, &prd))
3809 return CMD_SUCCESS;
90e60aa7 3810
d62a17ae 3811 /* Configure or update the RD. */
3812 evpn_configure_rd(bgp, vpn, &prd);
3813 return CMD_SUCCESS;
90e60aa7 3814}
3815
3816DEFUN (no_bgp_evpn_vni_rd,
3817 no_bgp_evpn_vni_rd_cmd,
d114b977 3818 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 3819 NO_STR
3820 "Route Distinguisher\n"
3821 "ASN:XX or A.B.C.D:XX\n")
3822{
d62a17ae 3823 struct prefix_rd prd;
3824 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3825 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3826 int ret;
90e60aa7 3827
d62a17ae 3828 if (!bgp || !vpn)
3829 return CMD_WARNING;
90e60aa7 3830
d62a17ae 3831 ret = str2prefix_rd(argv[2]->arg, &prd);
3832 if (!ret) {
3833 vty_out(vty, "%% Malformed Route Distinguisher\n");
3834 return CMD_WARNING;
3835 }
90e60aa7 3836
d62a17ae 3837 /* Check if we should disallow. */
3838 if (!is_rd_configured(vpn)) {
3839 vty_out(vty, "%% RD is not configured for this VNI\n");
3840 return CMD_WARNING;
3841 }
90e60aa7 3842
d62a17ae 3843 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
3844 vty_out(vty,
3845 "%% RD specified does not match configuration for this VNI\n");
3846 return CMD_WARNING;
3847 }
90e60aa7 3848
d62a17ae 3849 evpn_unconfigure_rd(bgp, vpn);
3850 return CMD_SUCCESS;
90e60aa7 3851}
3852
3853DEFUN (no_bgp_evpn_vni_rd_without_val,
3854 no_bgp_evpn_vni_rd_without_val_cmd,
3855 "no rd",
3856 NO_STR
3857 "Route Distinguisher\n")
3858{
d62a17ae 3859 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3860 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 3861
d62a17ae 3862 if (!bgp || !vpn)
3863 return CMD_WARNING;
90e60aa7 3864
d62a17ae 3865 /* Check if we should disallow. */
3866 if (!is_rd_configured(vpn)) {
3867 vty_out(vty, "%% RD is not configured for this VNI\n");
3868 return CMD_WARNING;
3869 }
90e60aa7 3870
d62a17ae 3871 evpn_unconfigure_rd(bgp, vpn);
3872 return CMD_SUCCESS;
90e60aa7 3873}
3874
3875/*
3876 * Loop over all extended-communities in the route-target list rtl and
3877 * return 1 if we find ecomtarget
3878 */
d62a17ae 3879static int bgp_evpn_rt_matches_existing(struct list *rtl,
3880 struct ecommunity *ecomtarget)
90e60aa7 3881{
d62a17ae 3882 struct listnode *node, *nnode;
3883 struct ecommunity *ecom;
90e60aa7 3884
d62a17ae 3885 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
3886 if (ecommunity_match(ecom, ecomtarget))
3887 return 1;
3888 }
90e60aa7 3889
d62a17ae 3890 return 0;
90e60aa7 3891}
3892
c581d8b0
MK
3893/* display L3VNI related info for a VRF instance */
3894DEFUN (show_bgp_vrf_l3vni_info,
3895 show_bgp_vrf_l3vni_info_cmd,
4cce389e 3896 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
3897 SHOW_STR
3898 BGP_STR
3899 "show bgp vrf\n"
3900 "VRF Name\n"
3901 "L3-VNI\n"
ceb9a921 3902 JSON_STR)
c581d8b0
MK
3903{
3904 char buf[ETHER_ADDR_STRLEN];
676f83b9 3905 char buf1[INET6_ADDRSTRLEN];
c581d8b0
MK
3906 int idx_vrf = 3;
3907 const char *name = NULL;
3908 struct bgp *bgp = NULL;
3909 struct listnode *node = NULL;
6a8657d0 3910 struct bgpevpn *vpn = NULL;
c581d8b0 3911 struct ecommunity *ecom = NULL;
ceb9a921
MK
3912 json_object *json = NULL;
3913 json_object *json_vnis = NULL;
3914 json_object *json_export_rts = NULL;
3915 json_object *json_import_rts = NULL;
d7c0a89a 3916 uint8_t uj = use_json(argc, argv);
ceb9a921
MK
3917
3918 if (uj) {
3919 json = json_object_new_object();
3920 json_vnis = json_object_new_array();
3921 json_export_rts = json_object_new_array();
3922 json_import_rts = json_object_new_array();
3923 }
c581d8b0
MK
3924
3925 name = argv[idx_vrf]->arg;
3926 bgp = bgp_lookup_by_name(name);
3927 if (!bgp) {
ceb9a921 3928 if (!uj)
996c9314 3929 vty_out(vty, "BGP instance for VRF %s not found", name);
ceb9a921
MK
3930 else {
3931 json_object_string_add(json, "warning",
3932 "BGP instance not found");
996c9314 3933 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
3934 json_object_free(json);
3935 }
c581d8b0
MK
3936 return CMD_WARNING;
3937 }
3938
ceb9a921
MK
3939 if (!json) {
3940 vty_out(vty, "BGP VRF: %s\n", name);
996c9314 3941 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
ceb9a921
MK
3942 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
3943 vty_out(vty, " Rmac: %s\n",
3944 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
3945 vty_out(vty, " VNI Filter: %s\n",
3946 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
3947 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
3948 ? "prefix-routes-only"
3949 : "none");
ceb9a921
MK
3950 vty_out(vty, " L2-VNI List:\n");
3951 vty_out(vty, " ");
3952 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3953 vty_out(vty, "%u ", vpn->vni);
3954 vty_out(vty, "\n");
3955 vty_out(vty, " Export-RTs:\n");
3956 vty_out(vty, " ");
3957 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3958 vty_out(vty, "%s ", ecommunity_str(ecom));
3959 vty_out(vty, "\n");
3960 vty_out(vty, " Import-RTs:\n");
3961 vty_out(vty, " ");
3962 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3963 vty_out(vty, "%s ", ecommunity_str(ecom));
3964 vty_out(vty, "\n");
676f83b9 3965 vty_out(vty, " RD: %s\n",
3966 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
3967 } else {
3968 json_object_string_add(json, "vrf", name);
b67a60d2 3969 json_object_string_add(json, "local-ip",
3970 inet_ntoa(bgp->originator_ip));
ceb9a921 3971 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
3972 json_object_string_add(
3973 json, "rmac",
3974 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
3975 json_object_string_add(
3976 json, "vniFilter",
3977 CHECK_FLAG(bgp->vrf_flags,
3978 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
3979 ? "prefix-routes-only"
3980 : "none");
ceb9a921
MK
3981 /* list of l2vnis */
3982 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3983 json_object_array_add(json_vnis,
3984 json_object_new_int(vpn->vni));
3985 json_object_object_add(json, "l2vnis", json_vnis);
3986
3987 /* export rts */
3988 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
996c9314
LB
3989 json_object_array_add(
3990 json_export_rts,
3991 json_object_new_string(ecommunity_str(ecom)));
ceb9a921
MK
3992 json_object_object_add(json, "export-rts", json_export_rts);
3993
3994 /* import rts */
3995 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
996c9314
LB
3996 json_object_array_add(
3997 json_import_rts,
3998 json_object_new_string(ecommunity_str(ecom)));
ceb9a921 3999 json_object_object_add(json, "import-rts", json_import_rts);
676f83b9 4000 json_object_string_add(
4001 json, "rd",
4002 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921 4003 }
c581d8b0 4004
ceb9a921
MK
4005 if (uj) {
4006 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4007 json, JSON_C_TO_STRING_PRETTY));
4008 json_object_free(json);
4009 }
c581d8b0
MK
4010 return CMD_SUCCESS;
4011}
4012
4013/* import/export rt for l3vni-vrf */
4014DEFUN (bgp_evpn_vrf_rt,
4015 bgp_evpn_vrf_rt_cmd,
4016 "route-target <both|import|export> RT",
4017 "Route Target\n"
4018 "import and export\n"
4019 "import\n"
4020 "export\n"
4021 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4022{
4023 int rt_type;
4024 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4025 struct ecommunity *ecomadd = NULL;
4026
4027 if (!bgp)
4028 return CMD_WARNING;
4029
4030 if (!strcmp(argv[1]->arg, "import"))
4031 rt_type = RT_TYPE_IMPORT;
4032 else if (!strcmp(argv[1]->arg, "export"))
4033 rt_type = RT_TYPE_EXPORT;
4034 else if (!strcmp(argv[1]->arg, "both"))
4035 rt_type = RT_TYPE_BOTH;
4036 else {
4037 vty_out(vty, "%% Invalid Route Target type\n");
4038 return CMD_WARNING;
4039 }
4040
4041 /* Add/update the import route-target */
4042 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4043 ecomadd = ecommunity_str2com(argv[2]->arg,
4044 ECOMMUNITY_ROUTE_TARGET, 0);
4045 if (!ecomadd) {
4046 vty_out(vty, "%% Malformed Route Target list\n");
4047 return CMD_WARNING;
4048 }
4049 ecommunity_str(ecomadd);
4050
4051 /* Do nothing if we already have this import route-target */
996c9314 4052 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
c581d8b0
MK
4053 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
4054 }
4055
4056 /* Add/update the export route-target */
4057 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4058 ecomadd = ecommunity_str2com(argv[2]->arg,
4059 ECOMMUNITY_ROUTE_TARGET, 0);
4060 if (!ecomadd) {
4061 vty_out(vty, "%% Malformed Route Target list\n");
4062 return CMD_WARNING;
4063 }
4064 ecommunity_str(ecomadd);
4065
4066 /* Do nothing if we already have this export route-target */
996c9314 4067 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
c581d8b0
MK
4068 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
4069 }
4070
4071 return CMD_SUCCESS;
4072}
4073
4074DEFUN (no_bgp_evpn_vrf_rt,
4075 no_bgp_evpn_vrf_rt_cmd,
4076 "no route-target <both|import|export> RT",
4077 NO_STR
4078 "Route Target\n"
4079 "import and export\n"
4080 "import\n"
4081 "export\n"
4082 "ASN:XX or A.B.C.D:XX\n")
4083{
4084 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4085 int rt_type, found_ecomdel;
4086 struct ecommunity *ecomdel = NULL;
4087
4088 if (!bgp)
4089 return CMD_WARNING;
4090
4091 if (!strcmp(argv[2]->arg, "import"))
4092 rt_type = RT_TYPE_IMPORT;
4093 else if (!strcmp(argv[2]->arg, "export"))
4094 rt_type = RT_TYPE_EXPORT;
4095 else if (!strcmp(argv[2]->arg, "both"))
4096 rt_type = RT_TYPE_BOTH;
4097 else {
4098 vty_out(vty, "%% Invalid Route Target type\n");
4099 return CMD_WARNING;
4100 }
4101
4102 if (rt_type == RT_TYPE_IMPORT) {
4103 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4104 vty_out(vty,
4105 "%% Import RT is not configured for this VRF\n");
4106 return CMD_WARNING;
4107 }
4108 } else if (rt_type == RT_TYPE_EXPORT) {
4109 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4110 vty_out(vty,
4111 "%% Export RT is not configured for this VRF\n");
4112 return CMD_WARNING;
4113 }
4114 } else if (rt_type == RT_TYPE_BOTH) {
4115 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
4116 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4117 vty_out(vty,
4118 "%% Import/Export RT is not configured for this VRF\n");
4119 return CMD_WARNING;
4120 }
4121 }
4122
4123 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
4124 if (!ecomdel) {
4125 vty_out(vty, "%% Malformed Route Target list\n");
4126 return CMD_WARNING;
4127 }
4128 ecommunity_str(ecomdel);
4129
4130 if (rt_type == RT_TYPE_IMPORT) {
4131 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4132 ecomdel)) {
4133 vty_out(vty,
4134 "%% RT specified does not match configuration for this VRF\n");
4135 return CMD_WARNING;
4136 }
4137 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4138 } else if (rt_type == RT_TYPE_EXPORT) {
4139 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4140 ecomdel)) {
4141 vty_out(vty,
4142 "%% RT specified does not match configuration for this VRF\n");
4143 return CMD_WARNING;
4144 }
4145 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4146 } else if (rt_type == RT_TYPE_BOTH) {
4147 found_ecomdel = 0;
4148
4149 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4150 ecomdel)) {
4151 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4152 found_ecomdel = 1;
4153 }
4154
4155 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4156 ecomdel)) {
4157 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4158 found_ecomdel = 1;
4159 }
4160
4161 if (!found_ecomdel) {
4162 vty_out(vty,
4163 "%% RT specified does not match configuration for this VRF\n");
4164 return CMD_WARNING;
4165 }
4166 }
4167
4168 return CMD_SUCCESS;
4169}
90e60aa7 4170
4171DEFUN (bgp_evpn_vni_rt,
4172 bgp_evpn_vni_rt_cmd,
4173 "route-target <both|import|export> RT",
4174 "Route Target\n"
4175 "import and export\n"
4176 "import\n"
4177 "export\n"
4178 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4179{
d62a17ae 4180 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4181 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4182 int rt_type;
4183 struct ecommunity *ecomadd = NULL;
4184
4185 if (!bgp || !vpn)
4186 return CMD_WARNING;
4187
8034beff 4188 if (!strcmp(argv[1]->text, "import"))
d62a17ae 4189 rt_type = RT_TYPE_IMPORT;
8034beff 4190 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 4191 rt_type = RT_TYPE_EXPORT;
8034beff 4192 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 4193 rt_type = RT_TYPE_BOTH;
4194 else {
4195 vty_out(vty, "%% Invalid Route Target type\n");
4196 return CMD_WARNING;
4197 }
4198
4199 /* Add/update the import route-target */
4200 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4201 ecomadd = ecommunity_str2com(argv[2]->arg,
4202 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4203 if (!ecomadd) {
4204 vty_out(vty, "%% Malformed Route Target list\n");
4205 return CMD_WARNING;
4206 }
5bc2ed52 4207 ecommunity_str(ecomadd);
d62a17ae 4208
4209 /* Do nothing if we already have this import route-target */
4210 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
4211 evpn_configure_import_rt(bgp, vpn, ecomadd);
4212 }
4213
4214 /* Add/update the export route-target */
4215 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4216 ecomadd = ecommunity_str2com(argv[2]->arg,
4217 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4218 if (!ecomadd) {
4219 vty_out(vty, "%% Malformed Route Target list\n");
4220 return CMD_WARNING;
4221 }
5bc2ed52 4222 ecommunity_str(ecomadd);
d62a17ae 4223
4224 /* Do nothing if we already have this export route-target */
4225 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
4226 evpn_configure_export_rt(bgp, vpn, ecomadd);
4227 }
4228
4229 return CMD_SUCCESS;
90e60aa7 4230}
4231
4232DEFUN (no_bgp_evpn_vni_rt,
4233 no_bgp_evpn_vni_rt_cmd,
4234 "no route-target <both|import|export> RT",
4235 NO_STR
4236 "Route Target\n"
4237 "import and export\n"
4238 "import\n"
4239 "export\n"
4240 "ASN:XX or A.B.C.D:XX\n")
4241{
d62a17ae 4242 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4243 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4244 int rt_type, found_ecomdel;
4245 struct ecommunity *ecomdel = NULL;
4246
4247 if (!bgp || !vpn)
4248 return CMD_WARNING;
4249
8034beff 4250 if (!strcmp(argv[2]->text, "import"))
d62a17ae 4251 rt_type = RT_TYPE_IMPORT;
8034beff 4252 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 4253 rt_type = RT_TYPE_EXPORT;
8034beff 4254 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 4255 rt_type = RT_TYPE_BOTH;
4256 else {
4257 vty_out(vty, "%% Invalid Route Target type\n");
4258 return CMD_WARNING;
4259 }
4260
4261 /* The user did "no route-target import", check to see if there are any
4262 * import route-targets configured. */
4263 if (rt_type == RT_TYPE_IMPORT) {
4264 if (!is_import_rt_configured(vpn)) {
4265 vty_out(vty,
4266 "%% Import RT is not configured for this VNI\n");
4267 return CMD_WARNING;
4268 }
4269 } else if (rt_type == RT_TYPE_EXPORT) {
4270 if (!is_export_rt_configured(vpn)) {
4271 vty_out(vty,
4272 "%% Export RT is not configured for this VNI\n");
4273 return CMD_WARNING;
4274 }
4275 } else if (rt_type == RT_TYPE_BOTH) {
4276 if (!is_import_rt_configured(vpn)
4277 && !is_export_rt_configured(vpn)) {
4278 vty_out(vty,
4279 "%% Import/Export RT is not configured for this VNI\n");
4280 return CMD_WARNING;
4281 }
4282 }
4283
4284 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4285 if (!ecomdel) {
4286 vty_out(vty, "%% Malformed Route Target list\n");
4287 return CMD_WARNING;
4288 }
5bc2ed52 4289 ecommunity_str(ecomdel);
d62a17ae 4290
4291 if (rt_type == RT_TYPE_IMPORT) {
4292 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4293 vty_out(vty,
4294 "%% RT specified does not match configuration for this VNI\n");
4295 return CMD_WARNING;
4296 }
4297 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4298 } else if (rt_type == RT_TYPE_EXPORT) {
4299 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4300 vty_out(vty,
4301 "%% RT specified does not match configuration for this VNI\n");
4302 return CMD_WARNING;
4303 }
4304 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4305 } else if (rt_type == RT_TYPE_BOTH) {
4306 found_ecomdel = 0;
4307
4308 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4309 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4310 found_ecomdel = 1;
4311 }
4312
4313 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4314 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4315 found_ecomdel = 1;
4316 }
4317
4318 if (!found_ecomdel) {
4319 vty_out(vty,
4320 "%% RT specified does not match configuration for this VNI\n");
4321 return CMD_WARNING;
4322 }
4323 }
4324
4325 return CMD_SUCCESS;
90e60aa7 4326}
4327
4328DEFUN (no_bgp_evpn_vni_rt_without_val,
4329 no_bgp_evpn_vni_rt_without_val_cmd,
4330 "no route-target <import|export>",
4331 NO_STR
4332 "Route Target\n"
4333 "import\n"
4334 "export\n")
4335{
d62a17ae 4336 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4337 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4338 int rt_type;
4339
4340 if (!bgp || !vpn)
4341 return CMD_WARNING;
4342
8034beff 4343 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 4344 rt_type = RT_TYPE_IMPORT;
8034beff 4345 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 4346 rt_type = RT_TYPE_EXPORT;
4347 } else {
4348 vty_out(vty, "%% Invalid Route Target type\n");
4349 return CMD_WARNING;
4350 }
4351
4352 /* Check if we should disallow. */
4353 if (rt_type == RT_TYPE_IMPORT) {
4354 if (!is_import_rt_configured(vpn)) {
4355 vty_out(vty,
4356 "%% Import RT is not configured for this VNI\n");
4357 return CMD_WARNING;
4358 }
4359 } else {
4360 if (!is_export_rt_configured(vpn)) {
4361 vty_out(vty,
4362 "%% Export RT is not configured for this VNI\n");
4363 return CMD_WARNING;
4364 }
4365 }
4366
4367 /* Unconfigure the RT. */
4368 if (rt_type == RT_TYPE_IMPORT)
4369 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4370 else
4371 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4372 return CMD_SUCCESS;
90e60aa7 4373}
8c197128 4374#endif
90e60aa7 4375/*
4376 * Output EVPN configuration information.
4377 */
d62a17ae 4378void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 4379 safi_t safi)
d62a17ae 4380{
a75c2553
MK
4381 char buf1[RD_ADDRSTRLEN];
4382
2b791107 4383 if (bgp->vnihash)
d62a17ae 4384 hash_iterate(bgp->vnihash,
4385 (void (*)(struct hash_backet *,
4386 void *))write_vni_config_for_entry,
2b791107 4387 vty);
90e60aa7 4388
2b791107 4389 if (bgp->advertise_all_vni)
d62a17ae 4390 vty_out(vty, " advertise-all-vni\n");
1a98c087 4391
2b791107 4392 if (bgp->advertise_gw_macip)
1a98c087 4393 vty_out(vty, " advertise-default-gw\n");
6ee86383 4394
154faa50
MK
4395 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4396 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
6ee86383
MK
4397 vty_out(vty, " advertise ipv4 unicast\n");
4398
154faa50
MK
4399 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4400 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
6ee86383 4401 vty_out(vty, " advertise ipv6 unicast\n");
486456ca
MK
4402
4403 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4404 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
4405 vty_out(vty, " default-originate ipv4\n");
4406
4407 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4408 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
4409 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 4410
a75c2553
MK
4411 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
4412 vty_out(vty, " rd %s\n",
4413 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
4414
db29a4a8
MK
4415 /* import route-target */
4416 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4417 char *ecom_str;
4418 struct listnode *node, *nnode;
4419 struct ecommunity *ecom;
4420
4421 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
4422 ecom)) {
4423 ecom_str = ecommunity_ecom2str(
4424 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4425 vty_out(vty, " route-target import %s\n", ecom_str);
db29a4a8
MK
4426 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4427 }
4428 }
4429
4430 /* export route-target */
4431 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4432 char *ecom_str;
4433 struct listnode *node, *nnode;
4434 struct ecommunity *ecom;
4435
4436 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
4437 ecom)) {
4438 ecom_str = ecommunity_ecom2str(
4439 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4440 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
4441 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4442 }
4443 }
90e60aa7 4444}
4445
4d0e6ece 4446void bgp_ethernetvpn_init(void)
784d3a42 4447{
d62a17ae 4448 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4449 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4450 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4451 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4452 install_element(VIEW_NODE,
4453 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4454 install_element(VIEW_NODE,
4455 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4456 install_element(
4457 VIEW_NODE,
4458 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4459 install_element(
4460 VIEW_NODE,
4461 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4462 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4463 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4464 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4465 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
8c197128 4466#if defined(HAVE_CUMULUS)
d62a17ae 4467 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4468 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
1a98c087
MK
4469 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4470 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
342dd0c6 4471 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4472 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
4473 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
4474 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
d62a17ae 4475
f2d62262 4476 /* "show bgp l2vpn evpn" commands. */
4477 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4478 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4479 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4480 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4481 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
4482 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
4483 install_element(VIEW_NODE,
4484 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4485 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4486 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4487 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 4488 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 4489
5014d96f
DW
4490 /* "show bgp evpn" commands. */
4491 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4492 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4493 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4494 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4495 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4496 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4497 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4498 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4499 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4500 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 4501 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5014d96f 4502
d62a17ae 4503 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4504 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
4505 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4506 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
4507 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
4508 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
4509 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
4510 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
4511 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
4512 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
4513 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 4514 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
4515 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
4516 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
1a98c087
MK
4517 install_element(BGP_EVPN_VNI_NODE,
4518 &bgp_evpn_advertise_default_gw_vni_cmd);
4519 install_element(BGP_EVPN_VNI_NODE,
4520 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
4521 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
4522 install_element(BGP_EVPN_VNI_NODE,
4523 &no_bgp_evpn_advertise_vni_subnet_cmd);
8c197128 4524#endif
784d3a42 4525}