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