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