]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
bgpd: provide filter for ip prefix route in bgp l2vpn evpn route cmd
[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,
47b71369 2935 "show bgp l2vpn evpn route [type <macip|multicast|prefix>] [json]",
9c92b5f7
MK
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"
47b71369 2944 "Prefix route"
9c92b5f7 2945 JSON_STR)
520d5d76 2946{
d62a17ae 2947 struct bgp *bgp;
8367c327 2948 int type_idx = 0;
d62a17ae 2949 int type = 0;
9c92b5f7
MK
2950 u_char uj = 0;
2951 json_object *json = NULL;
2952
2953 uj = use_json(argc, argv);
520d5d76 2954
d62a17ae 2955 bgp = bgp_get_default();
2956 if (!bgp)
2957 return CMD_WARNING;
520d5d76 2958
9c92b5f7
MK
2959 if (uj)
2960 json = json_object_new_object();
f2d62262 2961
9c92b5f7
MK
2962 /* get the type */
2963 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 2964 /* Specific type is requested */
9c92b5f7 2965 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 2966 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 2967 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 2968 type = BGP_EVPN_IMET_ROUTE;
47b71369
MK
2969 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
2970 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 2971 else
2972 return CMD_WARNING;
2973 }
520d5d76 2974
9c92b5f7
MK
2975 evpn_show_all_routes(vty, bgp, type, json);
2976
2977 if (uj) {
2978 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2979 json, JSON_C_TO_STRING_PRETTY));
2980 json_object_free(json);
2981 }
d62a17ae 2982 return CMD_SUCCESS;
520d5d76 2983}
2984
f2d62262 2985/*
2986 * Display global EVPN routing table for specific RD.
2987 */
60466a63
QY
2988DEFUN(show_bgp_l2vpn_evpn_route_rd,
2989 show_bgp_l2vpn_evpn_route_rd_cmd,
d114b977 2990 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]",
9c92b5f7
MK
2991 SHOW_STR
2992 BGP_STR
2993 L2VPN_HELP_STR
2994 EVPN_HELP_STR
2995 "EVPN route information\n"
2996 "Route Distinguisher\n"
2997 "ASN:XX or A.B.C.D:XX\n"
2998 "Specify Route type\n"
2999 "MAC-IP (Type-2) route\n"
3000 "Multicast (Type-3) route\n"
3001 JSON_STR)
520d5d76 3002{
d62a17ae 3003 struct bgp *bgp;
3004 int ret;
3005 struct prefix_rd prd;
3006 int type = 0;
9c92b5f7
MK
3007 int rd_idx = 0;
3008 int type_idx = 0;
3009 int uj = 0;
3010 json_object *json = NULL;
520d5d76 3011
d62a17ae 3012 bgp = bgp_get_default();
3013 if (!bgp)
3014 return CMD_WARNING;
520d5d76 3015
9c92b5f7
MK
3016 /* check if we need json output */
3017 uj = use_json(argc, argv);
3018 if (uj)
3019 json = json_object_new_object();
f2d62262 3020
9c92b5f7
MK
3021 /* get the RD */
3022 if (argv_find(argv, argc, "rd", &rd_idx)) {
3023 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3024
3025 if (!ret) {
3026 vty_out(vty, "%% Malformed Route Distinguisher\n");
3027 return CMD_WARNING;
3028 }
d62a17ae 3029 }
520d5d76 3030
9c92b5f7
MK
3031 /* get the type */
3032 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3033 /* Specific type is requested */
9c92b5f7 3034 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3035 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3036 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3037 type = BGP_EVPN_IMET_ROUTE;
3038 else
3039 return CMD_WARNING;
3040 }
520d5d76 3041
9c92b5f7
MK
3042 evpn_show_route_rd(vty, bgp, &prd, type, json);
3043
3044 if (uj) {
3045 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3046 json, JSON_C_TO_STRING_PRETTY));
3047 json_object_free(json);
3048 }
3049
d62a17ae 3050 return CMD_SUCCESS;
520d5d76 3051}
3052
f2d62262 3053/*
3054 * Display global EVPN routing table for specific RD and MACIP.
3055 */
9c92b5f7
MK
3056DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3057 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
d114b977 3058 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
9c92b5f7
MK
3059 SHOW_STR
3060 BGP_STR
3061 L2VPN_HELP_STR
3062 EVPN_HELP_STR
3063 "EVPN route information\n"
3064 "Route Distinguisher\n"
3065 "ASN:XX or A.B.C.D:XX\n"
3066 "MAC\n"
3067 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3068 "IP\n"
3069 "IP address (IPv4 or IPv6)\n"
3070 JSON_STR)
3071{
0291c246
MK
3072 struct bgp *bgp;
3073 int ret;
3074 struct prefix_rd prd;
3075 struct ethaddr mac;
3076 struct ipaddr ip;
3077 int rd_idx = 0;
3078 int mac_idx = 0;
3079 int ip_idx = 0;
3080 int uj = 0;
3081 json_object *json = NULL;
9c92b5f7
MK
3082
3083 memset(&mac, 0, sizeof(struct ethaddr));
3084 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 3085
3086 bgp = bgp_get_default();
3087 if (!bgp)
3088 return CMD_WARNING;
3089
9c92b5f7
MK
3090 /* check if we need json output */
3091 uj = use_json(argc, argv);
3092 if (uj)
3093 json = json_object_new_object();
f2d62262 3094
9c92b5f7
MK
3095 /* get the prd */
3096 if (argv_find(argv, argc, "rd", &rd_idx)) {
3097 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3098 if (!ret) {
3099 vty_out(vty, "%% Malformed Route Distinguisher\n");
3100 return CMD_WARNING;
3101 }
d62a17ae 3102 }
9c92b5f7
MK
3103
3104 /* get the mac */
3105 if (argv_find(argv, argc, "mac", &mac_idx)) {
3106 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
3107 vty_out(vty, "%% Malformed MAC address\n");
3108 return CMD_WARNING;
3109 }
d62a17ae 3110 }
9c92b5f7
MK
3111
3112 /* get the ip if specified */
3113 if (argv_find(argv, argc, "ip", &ip_idx)) {
3114 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 3115 vty_out(vty, "%% Malformed IP address\n");
3116 return CMD_WARNING;
3117 }
3118 }
3119
9c92b5f7
MK
3120 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
3121
3122 if (uj) {
3123 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3124 json, JSON_C_TO_STRING_PRETTY));
3125 json_object_free(json);
3126 }
3127
d62a17ae 3128 return CMD_SUCCESS;
520d5d76 3129}
3130
d3135ba3 3131/*
3132 * Display per-VRF EVPN routing table.
3133 */
3134DEFUN(show_bgp_l2vpn_evpn_route_vrf, show_bgp_l2vpn_evpn_route_vrf_cmd,
3135 "show bgp l2vpn evpn route vrf VRFNAME",
3136 SHOW_STR
3137 BGP_STR
3138 L2VPN_HELP_STR
3139 EVPN_HELP_STR
3140 "EVPN route information\n"
3141 "VRF\n"
3142 "VRF Name\n")
3143{
3144 int vrf_idx = 6;
3145 char *vrf_name = NULL;
3146 struct bgp *bgp_vrf = NULL;
3147
3148 vrf_name = argv[vrf_idx]->arg;
3149 bgp_vrf = bgp_lookup_by_name(vrf_name);
3150 if (!bgp_vrf)
3151 return CMD_WARNING;
3152
3153 evpn_show_vrf_routes(vty, bgp_vrf);
3154
3155 return CMD_SUCCESS;
3156}
3157
f2d62262 3158/*
3159 * Display per-VNI EVPN routing table.
3160 */
9c92b5f7
MK
3161DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
3162 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3163 SHOW_STR
3164 BGP_STR
3165 L2VPN_HELP_STR
3166 EVPN_HELP_STR
3167 "EVPN route information\n"
3168 "VXLAN Network Identifier\n"
3169 "VNI number\n"
3170 "Specify Route type\n"
3171 "MAC-IP (Type-2) route\n"
3172 "Multicast (Type-3) route\n"
3173 "Remote VTEP\n"
3174 "Remote VTEP IP address\n"
3175 JSON_STR)
520d5d76 3176{
d62a17ae 3177 vni_t vni;
3178 struct bgp *bgp;
3179 struct in_addr vtep_ip;
3180 int type = 0;
f2d62262 3181 int idx = 0;
9c92b5f7
MK
3182 int uj = 0;
3183 json_object *json = NULL;
d62a17ae 3184
3185 bgp = bgp_get_default();
3186 if (!bgp)
3187 return CMD_WARNING;
3188
9c92b5f7
MK
3189 /* check if we need json output */
3190 uj = use_json(argc, argv);
3191 if (uj)
3192 json = json_object_new_object();
3193
f2d62262 3194 if (!argv_find(argv, argc, "evpn", &idx))
3195 return CMD_WARNING;
3196
d62a17ae 3197 vtep_ip.s_addr = 0;
3198
f2d62262 3199 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 3200
9c92b5f7
MK
3201 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
3202 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 3203 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
3204 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 3205 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 3206 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 3207 type = BGP_EVPN_IMET_ROUTE;
3208 else
3209 return CMD_WARNING;
f2d62262 3210 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
3211 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3212 vty_out(vty, "%% Malformed VTEP IP address\n");
3213 return CMD_WARNING;
3214 }
3215 } else
3216 return CMD_WARNING;
3217 }
3218
9c92b5f7
MK
3219 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
3220
3221 if (uj) {
3222 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3223 json, JSON_C_TO_STRING_PRETTY));
3224 json_object_free(json);
3225 }
3226
d62a17ae 3227 return CMD_SUCCESS;
520d5d76 3228}
3229
f2d62262 3230/*
3231 * Display per-VNI EVPN routing table for specific MACIP.
3232 */
9c92b5f7
MK
3233DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
3234 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
3235 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3236 SHOW_STR
3237 BGP_STR
3238 L2VPN_HELP_STR
3239 EVPN_HELP_STR
3240 "EVPN route information\n"
3241 "VXLAN Network Identifier\n"
3242 "VNI number\n"
3243 "MAC\n"
3244 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3245 "IP\n"
3246 "IP address (IPv4 or IPv6)\n"
3247 JSON_STR)
520d5d76 3248{
d62a17ae 3249 vni_t vni;
3250 struct bgp *bgp;
3251 struct ethaddr mac;
3252 struct ipaddr ip;
f2d62262 3253 int idx = 0;
9c92b5f7
MK
3254 int uj = 0;
3255 json_object *json = NULL;
d62a17ae 3256
3257 bgp = bgp_get_default();
3258 if (!bgp)
3259 return CMD_WARNING;
3260
9c92b5f7
MK
3261 /* check if we need json output */
3262 uj = use_json(argc, argv);
3263 if (uj)
3264 json = json_object_new_object();
3265
f2d62262 3266 if (!argv_find(argv, argc, "evpn", &idx))
3267 return CMD_WARNING;
3268
9c92b5f7 3269 /* get the VNI */
f2d62262 3270 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3271
3272 /* get the mac */
f2d62262 3273 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 3274 vty_out(vty, "%% Malformed MAC address\n");
3275 return CMD_WARNING;
3276 }
9c92b5f7
MK
3277
3278 /* get the ip */
d62a17ae 3279 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
3280 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
3281 || (uj
3282 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 3283 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 3284 vty_out(vty, "%% Malformed IP address\n");
3285 return CMD_WARNING;
3286 }
3287 }
3288
9c92b5f7
MK
3289 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
3290
3291 if (uj) {
3292 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3293 json, JSON_C_TO_STRING_PRETTY));
3294 json_object_free(json);
3295 }
3296
d62a17ae 3297 return CMD_SUCCESS;
520d5d76 3298}
3299
f2d62262 3300/*
3301 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3302 */
9c92b5f7
MK
3303DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3304 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3305 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3306 SHOW_STR
3307 BGP_STR
3308 L2VPN_HELP_STR
3309 EVPN_HELP_STR
3310 "EVPN route information\n"
3311 "VXLAN Network Identifier\n"
3312 "VNI number\n"
3313 "Multicast (Type-3) route\n"
3314 "Originating Router IP address\n"
3315 JSON_STR)
520d5d76 3316{
d62a17ae 3317 vni_t vni;
3318 struct bgp *bgp;
3319 int ret;
3320 struct in_addr orig_ip;
f2d62262 3321 int idx = 0;
9c92b5f7
MK
3322 int uj = 0;
3323 json_object *json = NULL;
520d5d76 3324
d62a17ae 3325 bgp = bgp_get_default();
3326 if (!bgp)
3327 return CMD_WARNING;
520d5d76 3328
9c92b5f7
MK
3329 /* check if we need json output */
3330 uj = use_json(argc, argv);
3331 if (uj)
3332 json = json_object_new_object();
3333
f2d62262 3334 if (!argv_find(argv, argc, "evpn", &idx))
3335 return CMD_WARNING;
3336
9c92b5f7 3337 /* get the VNI */
f2d62262 3338 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3339
3340 /* get the ip */
f2d62262 3341 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 3342 if (!ret) {
3343 vty_out(vty, "%% Malformed Originating Router IP address\n");
3344 return CMD_WARNING;
3345 }
520d5d76 3346
9c92b5f7
MK
3347 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3348
3349 if (uj) {
3350 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3351 json, JSON_C_TO_STRING_PRETTY));
3352 json_object_free(json);
3353 }
3354
d62a17ae 3355 return CMD_SUCCESS;
520d5d76 3356}
3357
f2d62262 3358/*
3359 * Display per-VNI EVPN routing table - for all VNIs.
3360 */
60466a63
QY
3361DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3362 show_bgp_l2vpn_evpn_route_vni_all_cmd,
9c92b5f7
MK
3363 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3364 SHOW_STR
3365 BGP_STR
3366 L2VPN_HELP_STR
3367 EVPN_HELP_STR
3368 "EVPN route information\n"
3369 "VXLAN Network Identifier\n"
3370 "All VNIs\n"
3371 "Remote VTEP\n"
3372 "Remote VTEP IP address\n"
3373 JSON_STR)
520d5d76 3374{
d62a17ae 3375 struct bgp *bgp;
3376 struct in_addr vtep_ip;
f2d62262 3377 int idx = 0;
9c92b5f7
MK
3378 int uj = 0;
3379 json_object *json = NULL;
520d5d76 3380
d62a17ae 3381 bgp = bgp_get_default();
3382 if (!bgp)
3383 return CMD_WARNING;
520d5d76 3384
9c92b5f7
MK
3385 /* check if we need json output */
3386 uj = use_json(argc, argv);
3387 if (uj)
3388 json = json_object_new_object();
3389
f2d62262 3390 if (!argv_find(argv, argc, "evpn", &idx))
3391 return CMD_WARNING;
3392
d62a17ae 3393 vtep_ip.s_addr = 0;
9c92b5f7
MK
3394 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3395 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
f2d62262 3396 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3397 vty_out(vty, "%% Malformed VTEP IP address\n");
3398 return CMD_WARNING;
3399 }
3400 }
520d5d76 3401
9c92b5f7
MK
3402 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3403
3404 if (uj) {
3405 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3406 json, JSON_C_TO_STRING_PRETTY));
3407 json_object_free(json);
3408 }
3409
d62a17ae 3410 return CMD_SUCCESS;
520d5d76 3411}
3412
10ebe1ab
MK
3413/*
3414 * Display EVPN import route-target hash table
3415 */
3416DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3417 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3418 "show bgp l2vpn evpn vrf-import-rt [json]",
3419 SHOW_STR
3420 BGP_STR
3421 L2VPN_HELP_STR
3422 EVPN_HELP_STR
3423 "Show vrf import route target\n"
3424 JSON_STR)
3425{
3426 u_char uj = 0;
181c08c6 3427 struct bgp *bgp_def = NULL;
10ebe1ab
MK
3428 json_object *json = NULL;
3429
3430 bgp_def = bgp_get_default();
3431 if (!bgp_def)
3432 return CMD_WARNING;
3433
3434 uj = use_json(argc, argv);
3435 if (uj)
3436 json = json_object_new_object();
3437
3438 evpn_show_vrf_import_rts(vty, bgp_def, json);
3439
3440 if (uj) {
3441 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3442 json, JSON_C_TO_STRING_PRETTY));
3443 json_object_free(json);
3444 }
3445
3446 return CMD_SUCCESS;
3447}
3448
f2d62262 3449/*
3450 * Display EVPN import route-target hash table
3451 */
60466a63
QY
3452DEFUN(show_bgp_l2vpn_evpn_import_rt,
3453 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
3454 "show bgp l2vpn evpn import-rt [json]",
3455 SHOW_STR
3456 BGP_STR
3457 L2VPN_HELP_STR
3458 EVPN_HELP_STR
3459 "Show import route target\n"
3460 JSON_STR)
520d5d76 3461{
d62a17ae 3462 struct bgp *bgp;
9c92b5f7
MK
3463 u_char uj = 0;
3464 json_object *json = NULL;
520d5d76 3465
d62a17ae 3466 bgp = bgp_get_default();
3467 if (!bgp)
3468 return CMD_WARNING;
520d5d76 3469
9c92b5f7
MK
3470 uj = use_json(argc, argv);
3471 if (uj)
3472 json = json_object_new_object();
3473
3474 evpn_show_import_rts(vty, bgp, json);
3475
3476 if (uj) {
3477 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3478 json, JSON_C_TO_STRING_PRETTY));
3479 json_object_free(json);
3480 }
3481
d62a17ae 3482 return CMD_SUCCESS;
520d5d76 3483}
3484
5014d96f
DW
3485#if defined(HAVE_CUMULUS)
3486ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3487 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3488 "Show VNI\n"
3489 "VNI number\n")
3490
3491ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3492 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3493 "Summary of BGP neighbor status\n"
a85b24cc 3494 JSON_STR)
5014d96f
DW
3495
3496ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3497 "show bgp evpn route [type <macip|multicast>]",
3498 SHOW_STR BGP_STR EVPN_HELP_STR
3499 "EVPN route information\n"
3500 "Specify Route type\n"
3501 "MAC-IP (Type-2) route\n"
3502 "Multicast (Type-3) route\n")
3503
3504ALIAS_HIDDEN(
3505 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
d114b977 3506 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
5014d96f
DW
3507 SHOW_STR BGP_STR EVPN_HELP_STR
3508 "EVPN route information\n"
3509 "Route Distinguisher\n"
3510 "ASN:XX or A.B.C.D:XX\n"
3511 "Specify Route type\n"
3512 "MAC-IP (Type-2) route\n"
3513 "Multicast (Type-3) route\n")
3514
3515ALIAS_HIDDEN(
3516 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 3517 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f
DW
3518 SHOW_STR BGP_STR EVPN_HELP_STR
3519 "EVPN route information\n"
3520 "Route Distinguisher\n"
3521 "ASN:XX or A.B.C.D:XX\n"
3522 "MAC\n"
3523 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3524 "IP\n"
3525 "IP address (IPv4 or IPv6)\n")
3526
3527ALIAS_HIDDEN(
3528 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
3529 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3530 SHOW_STR BGP_STR EVPN_HELP_STR
3531 "EVPN route information\n"
3532 "VXLAN Network Identifier\n"
3533 "VNI number\n"
3534 "Specify Route type\n"
3535 "MAC-IP (Type-2) route\n"
3536 "Multicast (Type-3) route\n"
3537 "Remote VTEP\n"
3538 "Remote VTEP IP address\n")
3539
3540ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
3541 show_bgp_evpn_route_vni_macip_cmd,
3542 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3543 SHOW_STR BGP_STR EVPN_HELP_STR
3544 "EVPN route information\n"
3545 "VXLAN Network Identifier\n"
3546 "VNI number\n"
3547 "MAC\n"
3548 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3549 "IP\n"
3550 "IP address (IPv4 or IPv6)\n")
3551
3552ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
3553 show_bgp_evpn_route_vni_multicast_cmd,
3554 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3555 SHOW_STR BGP_STR EVPN_HELP_STR
3556 "EVPN route information\n"
3557 "VXLAN Network Identifier\n"
3558 "VNI number\n"
3559 "Multicast (Type-3) route\n"
3560 "Originating Router IP address\n")
3561
3562ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
3563 "show bgp evpn route vni all [vtep A.B.C.D]",
3564 SHOW_STR BGP_STR EVPN_HELP_STR
3565 "EVPN route information\n"
3566 "VXLAN Network Identifier\n"
3567 "All VNIs\n"
3568 "Remote VTEP\n"
3569 "Remote VTEP IP address\n")
3570
3571ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
3572 "show bgp evpn import-rt",
3573 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
3574#endif
3575
90e60aa7 3576DEFUN_NOSH (bgp_evpn_vni,
3577 bgp_evpn_vni_cmd,
3578 "vni (1-16777215)",
3579 "VXLAN Network Identifier\n"
3580 "VNI number\n")
3581{
d62a17ae 3582 vni_t vni;
3583 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3584 struct bgpevpn *vpn;
90e60aa7 3585
d62a17ae 3586 if (!bgp)
3587 return CMD_WARNING;
90e60aa7 3588
d62a17ae 3589 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 3590
d62a17ae 3591 /* Create VNI, or mark as configured. */
3592 vpn = evpn_create_update_vni(bgp, vni);
3593 if (!vpn) {
3594 vty_out(vty, "%% Failed to create VNI \n");
3595 return CMD_WARNING;
3596 }
90e60aa7 3597
d62a17ae 3598 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
3599 return CMD_SUCCESS;
90e60aa7 3600}
3601
3602DEFUN (no_bgp_evpn_vni,
3603 no_bgp_evpn_vni_cmd,
3604 "no vni (1-16777215)",
3605 NO_STR
3606 "VXLAN Network Identifier\n"
3607 "VNI number\n")
3608{
d62a17ae 3609 vni_t vni;
3610 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3611 struct bgpevpn *vpn;
90e60aa7 3612
d62a17ae 3613 if (!bgp)
3614 return CMD_WARNING;
90e60aa7 3615
d62a17ae 3616 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 3617
d62a17ae 3618 /* Check if we should disallow. */
3619 vpn = bgp_evpn_lookup_vni(bgp, vni);
3620 if (!vpn) {
3621 vty_out(vty, "%% Specified VNI does not exist\n");
3622 return CMD_WARNING;
3623 }
3624 if (!is_vni_configured(vpn)) {
3625 vty_out(vty, "%% Specified VNI is not configured\n");
3626 return CMD_WARNING;
3627 }
90e60aa7 3628
d62a17ae 3629 evpn_delete_vni(bgp, vpn);
3630 return CMD_SUCCESS;
90e60aa7 3631}
3632
3633DEFUN_NOSH (exit_vni,
3634 exit_vni_cmd,
3635 "exit-vni",
3636 "Exit from VNI mode\n")
3637{
d62a17ae 3638 if (vty->node == BGP_EVPN_VNI_NODE)
3639 vty->node = BGP_EVPN_NODE;
3640 return CMD_SUCCESS;
90e60aa7 3641}
3642
676f83b9 3643DEFUN (bgp_evpn_vrf_rd,
3644 bgp_evpn_vrf_rd_cmd,
3645 "rd ASN:NN_OR_IP-ADDRESS:NN",
3646 "Route Distinguisher\n"
3647 "ASN:XX or A.B.C.D:XX\n")
3648{
3649 int ret;
3650 struct prefix_rd prd;
3651 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3652
3653 if (!bgp_vrf)
3654 return CMD_WARNING;
3655
3656 ret = str2prefix_rd(argv[1]->arg, &prd);
3657 if (!ret) {
3658 vty_out(vty, "%% Malformed Route Distinguisher\n");
3659 return CMD_WARNING;
3660 }
3661
3662 /* If same as existing value, there is nothing more to do. */
3663 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
3664 return CMD_SUCCESS;
3665
3666 /* Configure or update the RD. */
3667 evpn_configure_vrf_rd(bgp_vrf, &prd);
3668 return CMD_SUCCESS;
3669}
3670
3671DEFUN (no_bgp_evpn_vrf_rd,
3672 no_bgp_evpn_vrf_rd_cmd,
3673 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3674 NO_STR
3675 "Route Distinguisher\n"
3676 "ASN:XX or A.B.C.D:XX\n")
3677{
3678 int ret;
3679 struct prefix_rd prd;
3680 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3681
3682 if (!bgp_vrf)
3683 return CMD_WARNING;
3684
3685 ret = str2prefix_rd(argv[2]->arg, &prd);
3686 if (!ret) {
3687 vty_out(vty, "%% Malformed Route Distinguisher\n");
3688 return CMD_WARNING;
3689 }
3690
3691 /* Check if we should disallow. */
3692 if (!is_vrf_rd_configured(bgp_vrf)) {
3693 vty_out(vty, "%% RD is not configured for this VRF\n");
3694 return CMD_WARNING;
3695 }
3696
3697 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
3698 vty_out(vty,
3699 "%% RD specified does not match configuration for this VRF\n");
3700 return CMD_WARNING;
3701 }
3702
3703 evpn_unconfigure_vrf_rd(bgp_vrf);
3704 return CMD_SUCCESS;
3705}
3706
3707DEFUN (no_bgp_evpn_vrf_rd_without_val,
3708 no_bgp_evpn_vrf_rd_without_val_cmd,
3709 "no rd",
3710 NO_STR
3711 "Route Distinguisher\n")
3712{
3713 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3714
3715 if (!bgp_vrf)
3716 return CMD_WARNING;
3717
3718 /* Check if we should disallow. */
3719 if (!is_vrf_rd_configured(bgp_vrf)) {
3720 vty_out(vty, "%% RD is not configured for this VRF\n");
3721 return CMD_WARNING;
3722 }
3723
3724 evpn_unconfigure_vrf_rd(bgp_vrf);
3725 return CMD_SUCCESS;
3726}
3727
90e60aa7 3728DEFUN (bgp_evpn_vni_rd,
3729 bgp_evpn_vni_rd_cmd,
d114b977 3730 "rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 3731 "Route Distinguisher\n"
3732 "ASN:XX or A.B.C.D:XX\n")
3733{
d62a17ae 3734 struct prefix_rd prd;
3735 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3736 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3737 int ret;
90e60aa7 3738
d62a17ae 3739 if (!bgp || !vpn)
3740 return CMD_WARNING;
90e60aa7 3741
d62a17ae 3742 ret = str2prefix_rd(argv[1]->arg, &prd);
3743 if (!ret) {
3744 vty_out(vty, "%% Malformed Route Distinguisher\n");
3745 return CMD_WARNING;
3746 }
90e60aa7 3747
d62a17ae 3748 /* If same as existing value, there is nothing more to do. */
3749 if (bgp_evpn_rd_matches_existing(vpn, &prd))
3750 return CMD_SUCCESS;
90e60aa7 3751
d62a17ae 3752 /* Configure or update the RD. */
3753 evpn_configure_rd(bgp, vpn, &prd);
3754 return CMD_SUCCESS;
90e60aa7 3755}
3756
3757DEFUN (no_bgp_evpn_vni_rd,
3758 no_bgp_evpn_vni_rd_cmd,
d114b977 3759 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 3760 NO_STR
3761 "Route Distinguisher\n"
3762 "ASN:XX or A.B.C.D:XX\n")
3763{
d62a17ae 3764 struct prefix_rd prd;
3765 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3766 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3767 int ret;
90e60aa7 3768
d62a17ae 3769 if (!bgp || !vpn)
3770 return CMD_WARNING;
90e60aa7 3771
d62a17ae 3772 ret = str2prefix_rd(argv[2]->arg, &prd);
3773 if (!ret) {
3774 vty_out(vty, "%% Malformed Route Distinguisher\n");
3775 return CMD_WARNING;
3776 }
90e60aa7 3777
d62a17ae 3778 /* Check if we should disallow. */
3779 if (!is_rd_configured(vpn)) {
3780 vty_out(vty, "%% RD is not configured for this VNI\n");
3781 return CMD_WARNING;
3782 }
90e60aa7 3783
d62a17ae 3784 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
3785 vty_out(vty,
3786 "%% RD specified does not match configuration for this VNI\n");
3787 return CMD_WARNING;
3788 }
90e60aa7 3789
d62a17ae 3790 evpn_unconfigure_rd(bgp, vpn);
3791 return CMD_SUCCESS;
90e60aa7 3792}
3793
3794DEFUN (no_bgp_evpn_vni_rd_without_val,
3795 no_bgp_evpn_vni_rd_without_val_cmd,
3796 "no rd",
3797 NO_STR
3798 "Route Distinguisher\n")
3799{
d62a17ae 3800 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3801 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 3802
d62a17ae 3803 if (!bgp || !vpn)
3804 return CMD_WARNING;
90e60aa7 3805
d62a17ae 3806 /* Check if we should disallow. */
3807 if (!is_rd_configured(vpn)) {
3808 vty_out(vty, "%% RD is not configured for this VNI\n");
3809 return CMD_WARNING;
3810 }
90e60aa7 3811
d62a17ae 3812 evpn_unconfigure_rd(bgp, vpn);
3813 return CMD_SUCCESS;
90e60aa7 3814}
3815
3816/*
3817 * Loop over all extended-communities in the route-target list rtl and
3818 * return 1 if we find ecomtarget
3819 */
d62a17ae 3820static int bgp_evpn_rt_matches_existing(struct list *rtl,
3821 struct ecommunity *ecomtarget)
90e60aa7 3822{
d62a17ae 3823 struct listnode *node, *nnode;
3824 struct ecommunity *ecom;
90e60aa7 3825
d62a17ae 3826 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
3827 if (ecommunity_match(ecom, ecomtarget))
3828 return 1;
3829 }
90e60aa7 3830
d62a17ae 3831 return 0;
90e60aa7 3832}
3833
c581d8b0
MK
3834/* display L3VNI related info for a VRF instance */
3835DEFUN (show_bgp_vrf_l3vni_info,
3836 show_bgp_vrf_l3vni_info_cmd,
4cce389e 3837 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
3838 SHOW_STR
3839 BGP_STR
3840 "show bgp vrf\n"
3841 "VRF Name\n"
3842 "L3-VNI\n"
ceb9a921 3843 JSON_STR)
c581d8b0
MK
3844{
3845 char buf[ETHER_ADDR_STRLEN];
676f83b9 3846 char buf1[INET6_ADDRSTRLEN];
c581d8b0
MK
3847 int idx_vrf = 3;
3848 const char *name = NULL;
3849 struct bgp *bgp = NULL;
3850 struct listnode *node = NULL;
6a8657d0 3851 struct bgpevpn *vpn = NULL;
c581d8b0 3852 struct ecommunity *ecom = NULL;
ceb9a921
MK
3853 json_object *json = NULL;
3854 json_object *json_vnis = NULL;
3855 json_object *json_export_rts = NULL;
3856 json_object *json_import_rts = NULL;
3857 u_char uj = use_json(argc, argv);
3858
3859 if (uj) {
3860 json = json_object_new_object();
3861 json_vnis = json_object_new_array();
3862 json_export_rts = json_object_new_array();
3863 json_import_rts = json_object_new_array();
3864 }
c581d8b0
MK
3865
3866 name = argv[idx_vrf]->arg;
3867 bgp = bgp_lookup_by_name(name);
3868 if (!bgp) {
ceb9a921
MK
3869 if (!uj)
3870 vty_out(vty, "BGP instance for VRF %s not found",
3871 name);
3872 else {
3873 json_object_string_add(json, "warning",
3874 "BGP instance not found");
3875 vty_out(vty, "%s\n",
3876 json_object_to_json_string(json));
3877 json_object_free(json);
3878 }
c581d8b0
MK
3879 return CMD_WARNING;
3880 }
3881
ceb9a921
MK
3882 if (!json) {
3883 vty_out(vty, "BGP VRF: %s\n", name);
b67a60d2 3884 vty_out(vty, " Local-Ip: %s\n",
3885 inet_ntoa(bgp->originator_ip));
ceb9a921
MK
3886 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
3887 vty_out(vty, " Rmac: %s\n",
3888 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
3889 vty_out(vty, " L2-VNI List:\n");
3890 vty_out(vty, " ");
3891 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3892 vty_out(vty, "%u ", vpn->vni);
3893 vty_out(vty, "\n");
3894 vty_out(vty, " Export-RTs:\n");
3895 vty_out(vty, " ");
3896 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3897 vty_out(vty, "%s ", ecommunity_str(ecom));
3898 vty_out(vty, "\n");
3899 vty_out(vty, " Import-RTs:\n");
3900 vty_out(vty, " ");
3901 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3902 vty_out(vty, "%s ", ecommunity_str(ecom));
3903 vty_out(vty, "\n");
676f83b9 3904 vty_out(vty, " RD: %s\n",
3905 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
3906 } else {
3907 json_object_string_add(json, "vrf", name);
b67a60d2 3908 json_object_string_add(json, "local-ip",
3909 inet_ntoa(bgp->originator_ip));
ceb9a921
MK
3910 json_object_int_add(json, "l3vni", bgp->l3vni);
3911 json_object_string_add(json, "rmac",
3912 prefix_mac2str(&bgp->rmac, buf,
3913 sizeof(buf)));
3914 /* list of l2vnis */
3915 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3916 json_object_array_add(json_vnis,
3917 json_object_new_int(vpn->vni));
3918 json_object_object_add(json, "l2vnis", json_vnis);
3919
3920 /* export rts */
3921 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3922 json_object_array_add(json_export_rts,
3923 json_object_new_string(
3924 ecommunity_str(ecom)));
3925 json_object_object_add(json, "export-rts", json_export_rts);
3926
3927 /* import rts */
3928 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3929 json_object_array_add(json_import_rts,
3930 json_object_new_string(
3931 ecommunity_str(ecom)));
3932 json_object_object_add(json, "import-rts", json_import_rts);
676f83b9 3933 json_object_string_add(
3934 json, "rd",
3935 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
3936
3937 }
c581d8b0 3938
ceb9a921
MK
3939 if (uj) {
3940 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3941 json, JSON_C_TO_STRING_PRETTY));
3942 json_object_free(json);
3943 }
c581d8b0
MK
3944 return CMD_SUCCESS;
3945}
3946
3947/* import/export rt for l3vni-vrf */
3948DEFUN (bgp_evpn_vrf_rt,
3949 bgp_evpn_vrf_rt_cmd,
3950 "route-target <both|import|export> RT",
3951 "Route Target\n"
3952 "import and export\n"
3953 "import\n"
3954 "export\n"
3955 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3956{
3957 int rt_type;
3958 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3959 struct ecommunity *ecomadd = NULL;
3960
3961 if (!bgp)
3962 return CMD_WARNING;
3963
3964 if (!strcmp(argv[1]->arg, "import"))
3965 rt_type = RT_TYPE_IMPORT;
3966 else if (!strcmp(argv[1]->arg, "export"))
3967 rt_type = RT_TYPE_EXPORT;
3968 else if (!strcmp(argv[1]->arg, "both"))
3969 rt_type = RT_TYPE_BOTH;
3970 else {
3971 vty_out(vty, "%% Invalid Route Target type\n");
3972 return CMD_WARNING;
3973 }
3974
3975 /* Add/update the import route-target */
3976 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3977 ecomadd = ecommunity_str2com(argv[2]->arg,
3978 ECOMMUNITY_ROUTE_TARGET, 0);
3979 if (!ecomadd) {
3980 vty_out(vty, "%% Malformed Route Target list\n");
3981 return CMD_WARNING;
3982 }
3983 ecommunity_str(ecomadd);
3984
3985 /* Do nothing if we already have this import route-target */
3986 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3987 ecomadd))
3988 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
3989 }
3990
3991 /* Add/update the export route-target */
3992 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3993 ecomadd = ecommunity_str2com(argv[2]->arg,
3994 ECOMMUNITY_ROUTE_TARGET, 0);
3995 if (!ecomadd) {
3996 vty_out(vty, "%% Malformed Route Target list\n");
3997 return CMD_WARNING;
3998 }
3999 ecommunity_str(ecomadd);
4000
4001 /* Do nothing if we already have this export route-target */
4002 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4003 ecomadd))
4004 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
4005 }
4006
4007 return CMD_SUCCESS;
4008}
4009
4010DEFUN (no_bgp_evpn_vrf_rt,
4011 no_bgp_evpn_vrf_rt_cmd,
4012 "no route-target <both|import|export> RT",
4013 NO_STR
4014 "Route Target\n"
4015 "import and export\n"
4016 "import\n"
4017 "export\n"
4018 "ASN:XX or A.B.C.D:XX\n")
4019{
4020 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4021 int rt_type, found_ecomdel;
4022 struct ecommunity *ecomdel = NULL;
4023
4024 if (!bgp)
4025 return CMD_WARNING;
4026
4027 if (!strcmp(argv[2]->arg, "import"))
4028 rt_type = RT_TYPE_IMPORT;
4029 else if (!strcmp(argv[2]->arg, "export"))
4030 rt_type = RT_TYPE_EXPORT;
4031 else if (!strcmp(argv[2]->arg, "both"))
4032 rt_type = RT_TYPE_BOTH;
4033 else {
4034 vty_out(vty, "%% Invalid Route Target type\n");
4035 return CMD_WARNING;
4036 }
4037
4038 if (rt_type == RT_TYPE_IMPORT) {
4039 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4040 vty_out(vty,
4041 "%% Import RT is not configured for this VRF\n");
4042 return CMD_WARNING;
4043 }
4044 } else if (rt_type == RT_TYPE_EXPORT) {
4045 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4046 vty_out(vty,
4047 "%% Export RT is not configured for this VRF\n");
4048 return CMD_WARNING;
4049 }
4050 } else if (rt_type == RT_TYPE_BOTH) {
4051 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
4052 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4053 vty_out(vty,
4054 "%% Import/Export RT is not configured for this VRF\n");
4055 return CMD_WARNING;
4056 }
4057 }
4058
4059 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
4060 if (!ecomdel) {
4061 vty_out(vty, "%% Malformed Route Target list\n");
4062 return CMD_WARNING;
4063 }
4064 ecommunity_str(ecomdel);
4065
4066 if (rt_type == RT_TYPE_IMPORT) {
4067 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4068 ecomdel)) {
4069 vty_out(vty,
4070 "%% RT specified does not match configuration for this VRF\n");
4071 return CMD_WARNING;
4072 }
4073 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4074 } else if (rt_type == RT_TYPE_EXPORT) {
4075 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4076 ecomdel)) {
4077 vty_out(vty,
4078 "%% RT specified does not match configuration for this VRF\n");
4079 return CMD_WARNING;
4080 }
4081 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4082 } else if (rt_type == RT_TYPE_BOTH) {
4083 found_ecomdel = 0;
4084
4085 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4086 ecomdel)) {
4087 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4088 found_ecomdel = 1;
4089 }
4090
4091 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4092 ecomdel)) {
4093 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4094 found_ecomdel = 1;
4095 }
4096
4097 if (!found_ecomdel) {
4098 vty_out(vty,
4099 "%% RT specified does not match configuration for this VRF\n");
4100 return CMD_WARNING;
4101 }
4102 }
4103
4104 return CMD_SUCCESS;
4105}
90e60aa7 4106
4107DEFUN (bgp_evpn_vni_rt,
4108 bgp_evpn_vni_rt_cmd,
4109 "route-target <both|import|export> RT",
4110 "Route Target\n"
4111 "import and export\n"
4112 "import\n"
4113 "export\n"
4114 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4115{
d62a17ae 4116 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4117 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4118 int rt_type;
4119 struct ecommunity *ecomadd = NULL;
4120
4121 if (!bgp || !vpn)
4122 return CMD_WARNING;
4123
8034beff 4124 if (!strcmp(argv[1]->text, "import"))
d62a17ae 4125 rt_type = RT_TYPE_IMPORT;
8034beff 4126 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 4127 rt_type = RT_TYPE_EXPORT;
8034beff 4128 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 4129 rt_type = RT_TYPE_BOTH;
4130 else {
4131 vty_out(vty, "%% Invalid Route Target type\n");
4132 return CMD_WARNING;
4133 }
4134
4135 /* Add/update the import route-target */
4136 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4137 ecomadd = ecommunity_str2com(argv[2]->arg,
4138 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4139 if (!ecomadd) {
4140 vty_out(vty, "%% Malformed Route Target list\n");
4141 return CMD_WARNING;
4142 }
5bc2ed52 4143 ecommunity_str(ecomadd);
d62a17ae 4144
4145 /* Do nothing if we already have this import route-target */
4146 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
4147 evpn_configure_import_rt(bgp, vpn, ecomadd);
4148 }
4149
4150 /* Add/update the export route-target */
4151 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4152 ecomadd = ecommunity_str2com(argv[2]->arg,
4153 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4154 if (!ecomadd) {
4155 vty_out(vty, "%% Malformed Route Target list\n");
4156 return CMD_WARNING;
4157 }
5bc2ed52 4158 ecommunity_str(ecomadd);
d62a17ae 4159
4160 /* Do nothing if we already have this export route-target */
4161 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
4162 evpn_configure_export_rt(bgp, vpn, ecomadd);
4163 }
4164
4165 return CMD_SUCCESS;
90e60aa7 4166}
4167
4168DEFUN (no_bgp_evpn_vni_rt,
4169 no_bgp_evpn_vni_rt_cmd,
4170 "no route-target <both|import|export> RT",
4171 NO_STR
4172 "Route Target\n"
4173 "import and export\n"
4174 "import\n"
4175 "export\n"
4176 "ASN:XX or A.B.C.D:XX\n")
4177{
d62a17ae 4178 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4179 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4180 int rt_type, found_ecomdel;
4181 struct ecommunity *ecomdel = NULL;
4182
4183 if (!bgp || !vpn)
4184 return CMD_WARNING;
4185
8034beff 4186 if (!strcmp(argv[2]->text, "import"))
d62a17ae 4187 rt_type = RT_TYPE_IMPORT;
8034beff 4188 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 4189 rt_type = RT_TYPE_EXPORT;
8034beff 4190 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 4191 rt_type = RT_TYPE_BOTH;
4192 else {
4193 vty_out(vty, "%% Invalid Route Target type\n");
4194 return CMD_WARNING;
4195 }
4196
4197 /* The user did "no route-target import", check to see if there are any
4198 * import route-targets configured. */
4199 if (rt_type == RT_TYPE_IMPORT) {
4200 if (!is_import_rt_configured(vpn)) {
4201 vty_out(vty,
4202 "%% Import RT is not configured for this VNI\n");
4203 return CMD_WARNING;
4204 }
4205 } else if (rt_type == RT_TYPE_EXPORT) {
4206 if (!is_export_rt_configured(vpn)) {
4207 vty_out(vty,
4208 "%% Export RT is not configured for this VNI\n");
4209 return CMD_WARNING;
4210 }
4211 } else if (rt_type == RT_TYPE_BOTH) {
4212 if (!is_import_rt_configured(vpn)
4213 && !is_export_rt_configured(vpn)) {
4214 vty_out(vty,
4215 "%% Import/Export RT is not configured for this VNI\n");
4216 return CMD_WARNING;
4217 }
4218 }
4219
4220 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4221 if (!ecomdel) {
4222 vty_out(vty, "%% Malformed Route Target list\n");
4223 return CMD_WARNING;
4224 }
5bc2ed52 4225 ecommunity_str(ecomdel);
d62a17ae 4226
4227 if (rt_type == RT_TYPE_IMPORT) {
4228 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4229 vty_out(vty,
4230 "%% RT specified does not match configuration for this VNI\n");
4231 return CMD_WARNING;
4232 }
4233 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4234 } else if (rt_type == RT_TYPE_EXPORT) {
4235 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4236 vty_out(vty,
4237 "%% RT specified does not match configuration for this VNI\n");
4238 return CMD_WARNING;
4239 }
4240 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4241 } else if (rt_type == RT_TYPE_BOTH) {
4242 found_ecomdel = 0;
4243
4244 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4245 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4246 found_ecomdel = 1;
4247 }
4248
4249 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4250 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4251 found_ecomdel = 1;
4252 }
4253
4254 if (!found_ecomdel) {
4255 vty_out(vty,
4256 "%% RT specified does not match configuration for this VNI\n");
4257 return CMD_WARNING;
4258 }
4259 }
4260
4261 return CMD_SUCCESS;
90e60aa7 4262}
4263
4264DEFUN (no_bgp_evpn_vni_rt_without_val,
4265 no_bgp_evpn_vni_rt_without_val_cmd,
4266 "no route-target <import|export>",
4267 NO_STR
4268 "Route Target\n"
4269 "import\n"
4270 "export\n")
4271{
d62a17ae 4272 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4273 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4274 int rt_type;
4275
4276 if (!bgp || !vpn)
4277 return CMD_WARNING;
4278
8034beff 4279 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 4280 rt_type = RT_TYPE_IMPORT;
8034beff 4281 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 4282 rt_type = RT_TYPE_EXPORT;
4283 } else {
4284 vty_out(vty, "%% Invalid Route Target type\n");
4285 return CMD_WARNING;
4286 }
4287
4288 /* Check if we should disallow. */
4289 if (rt_type == RT_TYPE_IMPORT) {
4290 if (!is_import_rt_configured(vpn)) {
4291 vty_out(vty,
4292 "%% Import RT is not configured for this VNI\n");
4293 return CMD_WARNING;
4294 }
4295 } else {
4296 if (!is_export_rt_configured(vpn)) {
4297 vty_out(vty,
4298 "%% Export RT is not configured for this VNI\n");
4299 return CMD_WARNING;
4300 }
4301 }
4302
4303 /* Unconfigure the RT. */
4304 if (rt_type == RT_TYPE_IMPORT)
4305 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4306 else
4307 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4308 return CMD_SUCCESS;
90e60aa7 4309}
8c197128 4310#endif
90e60aa7 4311/*
4312 * Output EVPN configuration information.
4313 */
d62a17ae 4314void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 4315 safi_t safi)
d62a17ae 4316{
2b791107 4317 if (bgp->vnihash)
d62a17ae 4318 hash_iterate(bgp->vnihash,
4319 (void (*)(struct hash_backet *,
4320 void *))write_vni_config_for_entry,
2b791107 4321 vty);
90e60aa7 4322
2b791107 4323 if (bgp->advertise_all_vni)
d62a17ae 4324 vty_out(vty, " advertise-all-vni\n");
1a98c087 4325
2b791107 4326 if (bgp->advertise_gw_macip)
1a98c087 4327 vty_out(vty, " advertise-default-gw\n");
6ee86383
MK
4328
4329 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
4330 vty_out(vty, " advertise ipv4 unicast\n");
4331
4332 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
4333 vty_out(vty, " advertise ipv6 unicast\n");
90e60aa7 4334}
4335
4d0e6ece 4336void bgp_ethernetvpn_init(void)
784d3a42 4337{
d62a17ae 4338 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4339 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4340 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4341 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4342 install_element(VIEW_NODE,
4343 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4344 install_element(VIEW_NODE,
4345 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4346 install_element(
4347 VIEW_NODE,
4348 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4349 install_element(
4350 VIEW_NODE,
4351 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4352 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4353 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4354 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4355 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
8c197128 4356#if defined(HAVE_CUMULUS)
d62a17ae 4357 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4358 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
1a98c087
MK
4359 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4360 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
342dd0c6 4361 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4362 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
d62a17ae 4363
f2d62262 4364 /* "show bgp l2vpn evpn" commands. */
4365 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4366 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4367 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4368 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4369 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
4370 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
d3135ba3 4371 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vrf_cmd);
f2d62262 4372 install_element(VIEW_NODE,
4373 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4374 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4375 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4376 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 4377 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 4378
5014d96f
DW
4379 /* "show bgp evpn" commands. */
4380 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4381 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4382 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4383 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4384 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4385 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4386 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4387 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4388 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4389 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 4390 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5014d96f 4391
d62a17ae 4392 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4393 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
4394 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4395 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
4396 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
4397 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
4398 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
4399 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
4400 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
4401 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
4402 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 4403 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
4404 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
4405 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
1a98c087
MK
4406 install_element(BGP_EVPN_VNI_NODE,
4407 &bgp_evpn_advertise_default_gw_vni_cmd);
4408 install_element(BGP_EVPN_VNI_NODE,
4409 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
4410 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
4411 install_element(BGP_EVPN_VNI_NODE,
4412 &no_bgp_evpn_advertise_vni_subnet_cmd);
8c197128 4413#endif
784d3a42 4414}