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