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