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