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