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