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