]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
Merge pull request #2758 from donaldsharp/pim_join
[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
1a98c087
MK
2810 evpn_set_advertise_default_gw(bgp, vpn);
2811
2812 return CMD_SUCCESS;
2813}
2814
2815DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2816 no_bgp_evpn_advertise_default_gw_vni_cmd,
2817 "no advertise-default-gw",
2818 NO_STR
2819 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2820{
2821 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2822 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2823
2824 if (!bgp)
2825 return CMD_WARNING;
2826
1a98c087
MK
2827 evpn_unset_advertise_default_gw(bgp, vpn);
2828
2829 return CMD_SUCCESS;
2830}
2831
2832
2833DEFUN (bgp_evpn_advertise_default_gw,
2834 bgp_evpn_advertise_default_gw_cmd,
2835 "advertise-default-gw",
078af92e 2836 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
2837{
2838 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2839
2840 if (!bgp)
2841 return CMD_WARNING;
2842
2843 evpn_set_advertise_default_gw(bgp, NULL);
2844
2845 return CMD_SUCCESS;
2846}
2847
2848DEFUN (no_bgp_evpn_advertise_default_gw,
2849 no_bgp_evpn_advertise_default_gw_cmd,
2850 "no advertise-default-gw",
2851 NO_STR
2852 "Withdraw All default g/w mac-ip routes from EVPN\n")
2853{
2854 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2855
2856 if (!bgp)
2857 return CMD_WARNING;
2858
2859 evpn_unset_advertise_default_gw(bgp, NULL);
2860
2861 return CMD_SUCCESS;
2862}
2863
7724c0a1 2864DEFUN (bgp_evpn_advertise_all_vni,
2865 bgp_evpn_advertise_all_vni_cmd,
2866 "advertise-all-vni",
2867 "Advertise All local VNIs\n")
2868{
d62a17ae 2869 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2870
d62a17ae 2871 if (!bgp)
2872 return CMD_WARNING;
2873 evpn_set_advertise_all_vni(bgp);
2874 return CMD_SUCCESS;
7724c0a1 2875}
2876
2877DEFUN (no_bgp_evpn_advertise_all_vni,
2878 no_bgp_evpn_advertise_all_vni_cmd,
2879 "no advertise-all-vni",
2880 NO_STR
2881 "Advertise All local VNIs\n")
2882{
d62a17ae 2883 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2884
d62a17ae 2885 if (!bgp)
2886 return CMD_WARNING;
2887 evpn_unset_advertise_all_vni(bgp);
2888 return CMD_SUCCESS;
7724c0a1 2889}
2890
bf1061d8
VB
2891DEFUN (bgp_evpn_advertise_autort_rfc8365,
2892 bgp_evpn_advertise_autort_rfc8365_cmd,
2893 "autort rfc8365-compatible",
2894 "Auto-derivation of RT\n"
2895 "Auto-derivation of RT using RFC8365\n")
2896{
2897 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2898
2899 if (!bgp)
2900 return CMD_WARNING;
2901 evpn_set_advertise_autort_rfc8365(bgp);
2902 return CMD_SUCCESS;
2903}
2904
2905DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
2906 no_bgp_evpn_advertise_autort_rfc8365_cmd,
2907 "no autort rfc8365-compatible",
2908 NO_STR
2909 "Auto-derivation of RT\n"
2910 "Auto-derivation of RT using RFC8365\n")
2911{
2912 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2913
2914 if (!bgp)
2915 return CMD_WARNING;
2916 evpn_unset_advertise_autort_rfc8365(bgp);
2917 return CMD_SUCCESS;
2918}
2919
486456ca
MK
2920DEFUN (bgp_evpn_default_originate,
2921 bgp_evpn_default_originate_cmd,
2922 "default-originate <ipv4 | ipv6>",
2923 "originate a default route\n"
2924 "ipv4 address family\n"
2925 "ipv6 address family\n")
2926{
2927 afi_t afi = 0;
2928 int idx_afi = 0;
2929 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2930
2931 if (!bgp_vrf)
2932 return CMD_WARNING;
2933 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2934 evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
2935 return CMD_SUCCESS;
2936}
2937
2938DEFUN (no_bgp_evpn_default_originate,
2939 no_bgp_evpn_default_originate_cmd,
2940 "no default-originate <ipv4 | ipv6>",
2941 NO_STR
2942 "withdraw a default route\n"
2943 "ipv4 address family\n"
2944 "ipv6 address family\n")
2945{
2946 afi_t afi = 0;
2947 int idx_afi = 0;
2948 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2949
2950 if (!bgp_vrf)
2951 return CMD_WARNING;
2952 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2953 evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
2954 return CMD_SUCCESS;
2955}
2956
689b5101
MK
2957DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
2958 bgp_evpn_advertise_vni_subnet_cmd,
2959 "advertise-subnet",
2960 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
2961{
2962 struct bgp *bgp_vrf = NULL;
2963 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2964 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2965
2966 if (!bgp)
2967 return CMD_WARNING;
2968
31310b25
MK
2969 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
2970 if (!bgp_vrf)
2971 return CMD_WARNING;
2972
31310b25
MK
2973 evpn_set_advertise_subnet(bgp, vpn);
2974 return CMD_SUCCESS;
2975}
2976
689b5101
MK
2977DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
2978 no_bgp_evpn_advertise_vni_subnet_cmd,
2979 "no advertise-subnet",
2980 NO_STR
2981 "Advertise All local VNIs\n")
31310b25
MK
2982{
2983 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2984 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2985
2986 if (!bgp)
2987 return CMD_WARNING;
2988
31310b25
MK
2989 evpn_unset_advertise_subnet(bgp, vpn);
2990 return CMD_SUCCESS;
2991}
2992
342dd0c6 2993DEFUN (bgp_evpn_advertise_type5,
2994 bgp_evpn_advertise_type5_cmd,
53c84f78 2995 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 2996 "Advertise prefix routes\n"
053905d2 2997 BGP_AFI_HELP_STR
53c84f78
MK
2998 BGP_SAFI_HELP_STR
2999 "route-map for filtering specific routes\n"
3000 "Name of the route map\n")
342dd0c6 3001{
3002 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3003 int idx_afi = 0;
3004 int idx_safi = 0;
53c84f78 3005 int idx_rmap = 0;
053905d2
MK
3006 afi_t afi = 0;
3007 safi_t safi = 0;
53c84f78
MK
3008 int ret = 0;
3009 int rmap_changed = 0;
053905d2
MK
3010
3011 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3012 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
53c84f78
MK
3013 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3014 if (ret) {
3015 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3016 rmap_changed = 1;
3017 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
3018 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3019 != 0)
53c84f78
MK
3020 rmap_changed = 1;
3021 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3022 rmap_changed = 1;
3023 }
053905d2 3024
e779dc76 3025 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3026 vty_out(vty,
3027 "%%only ipv4 or ipv6 address families are supported");
342dd0c6 3028 return CMD_WARNING;
3029 }
3030
053905d2
MK
3031 if (safi != SAFI_UNICAST) {
3032 vty_out(vty,
3033 "%%only ipv4 unicast or ipv6 unicast are supported");
3034 return CMD_WARNING;
3035 }
3036
3037 if (afi == AFI_IP) {
342dd0c6 3038
3039 /* if we are already advertising ipv4 prefix as type-5
523cafc4 3040 * nothing to do
3041 */
154faa50
MK
3042 if (!rmap_changed &&
3043 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3044 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
53c84f78 3045 return CMD_WARNING;
154faa50
MK
3046 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3047 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3048 } else {
3049
3050 /* if we are already advertising ipv6 prefix as type-5
523cafc4 3051 * nothing to do
3052 */
154faa50
MK
3053 if (!rmap_changed &&
3054 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3055 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
53c84f78 3056 return CMD_WARNING;
154faa50
MK
3057 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3058 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
53c84f78
MK
3059 }
3060
3061 if (rmap_changed) {
3062 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3063 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3064 XFREE(MTYPE_ROUTE_MAP_NAME,
3065 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3066 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3067 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
342dd0c6 3068 }
3069 }
53c84f78
MK
3070
3071 /* set the route-map for advertise command */
3072 if (ret && argv[idx_rmap + 1]->arg) {
3073 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 3074 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
3075 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3076 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3077 }
3078
3079 /* advertise type-5 routes */
3080 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 3081 return CMD_SUCCESS;
3082}
3083
3084DEFUN (no_bgp_evpn_advertise_type5,
3085 no_bgp_evpn_advertise_type5_cmd,
053905d2 3086 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
342dd0c6 3087 NO_STR
3088 "Advertise prefix routes\n"
053905d2
MK
3089 BGP_AFI_HELP_STR
3090 BGP_SAFI_HELP_STR)
342dd0c6 3091{
3092 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3093 int idx_afi = 0;
3094 int idx_safi = 0;
3095 afi_t afi = 0;
3096 safi_t safi = 0;
3097
3098 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3099 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3100
1ec31309 3101 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3102 vty_out(vty,
3103 "%%only ipv4 or ipv6 address families are supported");
3104 return CMD_WARNING;
3105 }
3106
3107 if (safi != SAFI_UNICAST) {
3108 vty_out(vty,
3109 "%%only ipv4 unicast or ipv6 unicast are supported");
342dd0c6 3110 return CMD_WARNING;
3111 }
3112
053905d2 3113 if (afi == AFI_IP) {
342dd0c6 3114
fdf19f06 3115 /* if we are not advertising ipv4 prefix as type-5
523cafc4 3116 * nothing to do
3117 */
154faa50
MK
3118 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3119 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
053905d2 3120 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50
MK
3121 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3122 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3123 }
3124 } else {
3125
fdf19f06 3126 /* if we are not advertising ipv6 prefix as type-5
523cafc4 3127 * nothing to do
3128 */
154faa50
MK
3129 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3130 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
053905d2 3131 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4f7497e 3132 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
154faa50 3133 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
342dd0c6 3134 }
3135 }
53c84f78
MK
3136
3137 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3138 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3139 XFREE(MTYPE_ROUTE_MAP_NAME,
3140 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3141 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3142 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3143 }
3144
342dd0c6 3145 return CMD_SUCCESS;
3146}
3147
f2d62262 3148/*
3149 * Display VNI information - for all or a specific VNI
3150 */
9c92b5f7
MK
3151DEFUN(show_bgp_l2vpn_evpn_vni,
3152 show_bgp_l2vpn_evpn_vni_cmd,
3153 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
3154 SHOW_STR
3155 BGP_STR
3156 L2VPN_HELP_STR
3157 EVPN_HELP_STR
3158 "Show VNI\n"
3159 "VNI number\n"
3160 JSON_STR)
520d5d76 3161{
4cce389e 3162 struct bgp *bgp_def;
f2d62262 3163 vni_t vni;
3164 int idx = 0;
d7c0a89a 3165 uint8_t uj = 0;
9c92b5f7 3166 json_object *json = NULL;
d7c0a89a
QY
3167 uint32_t num_l2vnis = 0;
3168 uint32_t num_l3vnis = 0;
d4454626 3169 uint32_t num_vnis = 0;
4cce389e
MK
3170 struct listnode *node = NULL;
3171 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
3172
3173 uj = use_json(argc, argv);
520d5d76 3174
4cce389e
MK
3175 bgp_def = bgp_get_default();
3176 if (!bgp_def)
d62a17ae 3177 return CMD_WARNING;
520d5d76 3178
f2d62262 3179 if (!argv_find(argv, argc, "evpn", &idx))
3180 return CMD_WARNING;
3181
9c92b5f7
MK
3182 if (uj)
3183 json = json_object_new_object();
1a98c087 3184
9c92b5f7 3185 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e
MK
3186
3187 num_l2vnis = hashcount(bgp_def->vnihash);
4cce389e
MK
3188
3189 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3190 if (bgp_temp->l3vni)
3191 num_l3vnis++;
3192 }
d4454626 3193 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
3194 if (uj) {
3195 json_object_string_add(json, "advertiseGatewayMacip",
4cce389e 3196 bgp_def->advertise_gw_macip
9c92b5f7
MK
3197 ? "Enabled"
3198 : "Disabled");
3199 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
3200 is_evpn_enabled() ? "Enabled"
3201 : "Disabled");
d4454626 3202 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
3203 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3204 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
3205 } else {
3206 vty_out(vty, "Advertise Gateway Macip: %s\n",
4cce389e 3207 bgp_def->advertise_gw_macip ? "Enabled"
996c9314 3208 : "Disabled");
9c92b5f7 3209 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 3210 is_evpn_enabled() ? "Enabled" : "Disabled");
4cce389e
MK
3211 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3212 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 3213 }
4cce389e 3214 evpn_show_all_vnis(vty, bgp_def, json);
f2d62262 3215 } else {
9c92b5f7
MK
3216 int vni_idx = 0;
3217
3218 if (!argv_find(argv, argc, "vni", &vni_idx))
3219 return CMD_WARNING;
3220
f2d62262 3221 /* Display specific VNI */
9c92b5f7 3222 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4cce389e 3223 evpn_show_vni(vty, bgp_def, vni, json);
9c92b5f7
MK
3224 }
3225
3226 if (uj) {
3227 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3228 json, JSON_C_TO_STRING_PRETTY));
3229 json_object_free(json);
f2d62262 3230 }
520d5d76 3231
d62a17ae 3232 return CMD_SUCCESS;
520d5d76 3233}
3234
50f74cf1 3235/* Disaply ES */
3236DEFUN(show_bgp_l2vpn_evpn_es,
3237 show_bgp_l2vpn_evpn_es_cmd,
3238 "show bgp l2vpn evpn es [ESI] [json]",
3239 SHOW_STR
3240 BGP_STR
3241 L2VPN_HELP_STR
3242 EVPN_HELP_STR
3243 "ethernet-Segment\n"
b482a7fd
QY
3244 "Ethernet-Segment Identifier\n"
3245 JSON_STR)
50f74cf1 3246{
3247 int idx = 0;
3248 uint8_t uj = 0;
6a527b2f 3249 esi_t esi;
50f74cf1 3250 json_object *json = NULL;
3251 struct bgp *bgp = NULL;
3252
6a527b2f 3253 memset(&esi, 0, sizeof(esi));
50f74cf1 3254 uj = use_json(argc, argv);
3255
3256 bgp = bgp_get_default();
3257 if (!bgp)
3258 return CMD_WARNING;
3259
3260 if (!argv_find(argv, argc, "evpn", &idx))
3261 return CMD_WARNING;
3262
3263 if ((uj && argc == ((idx + 1) + 2)) ||
3264 (!uj && argc == (idx + 1) + 1)) {
3265
3266 /* show all ESs */
3267 evpn_show_all_es(vty, bgp, json);
3268 } else {
3269
3270 /* show a specific ES */
3271
3272 /* get the ESI - ESI-ID is at argv[5] */
3273 if (!str_to_esi(argv[idx + 2]->arg, &esi)) {
3274 vty_out(vty, "%% Malformed ESI\n");
3275 return CMD_WARNING;
3276 }
3277 evpn_show_es(vty, bgp, &esi, json);
3278 }
3279
3280 if (uj) {
3281 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3282 json, JSON_C_TO_STRING_PRETTY));
3283 json_object_free(json);
3284 }
3285
3286 return CMD_SUCCESS;
3287}
3288
f2d62262 3289/*
3290 * Display EVPN neighbor summary.
3291 */
9c92b5f7
MK
3292DEFUN(show_bgp_l2vpn_evpn_summary,
3293 show_bgp_l2vpn_evpn_summary_cmd,
ee851c8c 3294 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
9c92b5f7
MK
3295 SHOW_STR
3296 BGP_STR
ee851c8c
MK
3297 "bgp vrf\n"
3298 "vrf name\n"
9c92b5f7
MK
3299 L2VPN_HELP_STR
3300 EVPN_HELP_STR
3301 "Summary of BGP neighbor status\n"
3302 JSON_STR)
520d5d76 3303{
ee851c8c 3304 int idx_vrf = 0;
d7c0a89a 3305 uint8_t uj = use_json(argc, argv);
ee851c8c
MK
3306 char *vrf = NULL;
3307
3308 if (argv_find(argv, argc, "vrf", &idx_vrf))
3309 vrf = argv[++idx_vrf]->arg;
3310 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, uj);
520d5d76 3311}
3312
f2d62262 3313/*
3314 * Display global EVPN routing table.
3315 */
60466a63
QY
3316DEFUN(show_bgp_l2vpn_evpn_route,
3317 show_bgp_l2vpn_evpn_route_cmd,
50f74cf1 3318 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
9c92b5f7
MK
3319 SHOW_STR
3320 BGP_STR
3321 L2VPN_HELP_STR
3322 EVPN_HELP_STR
3323 "EVPN route information\n"
3324 "Specify Route type\n"
3325 "MAC-IP (Type-2) route\n"
3326 "Multicast (Type-3) route\n"
50f74cf1 3327 "Ethernet Segment (type-4) route \n"
3328 "Prefix (type-5 )route\n"
9c92b5f7 3329 JSON_STR)
520d5d76 3330{
d62a17ae 3331 struct bgp *bgp;
8367c327 3332 int type_idx = 0;
d62a17ae 3333 int type = 0;
d7c0a89a 3334 uint8_t uj = 0;
9c92b5f7
MK
3335 json_object *json = NULL;
3336
3337 uj = use_json(argc, argv);
520d5d76 3338
d62a17ae 3339 bgp = bgp_get_default();
3340 if (!bgp)
3341 return CMD_WARNING;
520d5d76 3342
9c92b5f7
MK
3343 if (uj)
3344 json = json_object_new_object();
f2d62262 3345
9c92b5f7
MK
3346 /* get the type */
3347 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3348 /* Specific type is requested */
9c92b5f7 3349 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3350 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3351 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3352 type = BGP_EVPN_IMET_ROUTE;
50f74cf1 3353 else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
3354 type = BGP_EVPN_ES_ROUTE;
47b71369
MK
3355 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3356 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3357 else
3358 return CMD_WARNING;
3359 }
520d5d76 3360
9c92b5f7
MK
3361 evpn_show_all_routes(vty, bgp, type, json);
3362
3363 if (uj) {
3364 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3365 json, JSON_C_TO_STRING_PRETTY));
3366 json_object_free(json);
3367 }
d62a17ae 3368 return CMD_SUCCESS;
520d5d76 3369}
3370
f2d62262 3371/*
3372 * Display global EVPN routing table for specific RD.
3373 */
60466a63
QY
3374DEFUN(show_bgp_l2vpn_evpn_route_rd,
3375 show_bgp_l2vpn_evpn_route_rd_cmd,
50f74cf1 3376 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
9c92b5f7
MK
3377 SHOW_STR
3378 BGP_STR
3379 L2VPN_HELP_STR
3380 EVPN_HELP_STR
3381 "EVPN route information\n"
3382 "Route Distinguisher\n"
3383 "ASN:XX or A.B.C.D:XX\n"
3384 "Specify Route type\n"
3385 "MAC-IP (Type-2) route\n"
3386 "Multicast (Type-3) route\n"
50f74cf1 3387 "Ethernet Segment route\n"
aa9db9e6 3388 "Prefix route\n"
9c92b5f7 3389 JSON_STR)
520d5d76 3390{
d62a17ae 3391 struct bgp *bgp;
3392 int ret;
3393 struct prefix_rd prd;
3394 int type = 0;
9c92b5f7
MK
3395 int rd_idx = 0;
3396 int type_idx = 0;
3397 int uj = 0;
3398 json_object *json = NULL;
520d5d76 3399
d62a17ae 3400 bgp = bgp_get_default();
3401 if (!bgp)
3402 return CMD_WARNING;
520d5d76 3403
9c92b5f7
MK
3404 /* check if we need json output */
3405 uj = use_json(argc, argv);
3406 if (uj)
3407 json = json_object_new_object();
f2d62262 3408
9c92b5f7
MK
3409 /* get the RD */
3410 if (argv_find(argv, argc, "rd", &rd_idx)) {
3411 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3412
3413 if (!ret) {
3414 vty_out(vty, "%% Malformed Route Distinguisher\n");
3415 return CMD_WARNING;
3416 }
d62a17ae 3417 }
520d5d76 3418
9c92b5f7
MK
3419 /* get the type */
3420 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3421 /* Specific type is requested */
9c92b5f7 3422 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3423 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3424 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3425 type = BGP_EVPN_IMET_ROUTE;
aa9db9e6
MK
3426 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3427 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3428 else
3429 return CMD_WARNING;
3430 }
520d5d76 3431
9c92b5f7
MK
3432 evpn_show_route_rd(vty, bgp, &prd, type, json);
3433
3434 if (uj) {
3435 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3436 json, JSON_C_TO_STRING_PRETTY));
3437 json_object_free(json);
3438 }
3439
d62a17ae 3440 return CMD_SUCCESS;
520d5d76 3441}
3442
f2d62262 3443/*
3444 * Display global EVPN routing table for specific RD and MACIP.
3445 */
9c92b5f7
MK
3446DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3447 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
d114b977 3448 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
9c92b5f7
MK
3449 SHOW_STR
3450 BGP_STR
3451 L2VPN_HELP_STR
3452 EVPN_HELP_STR
3453 "EVPN route information\n"
3454 "Route Distinguisher\n"
3455 "ASN:XX or A.B.C.D:XX\n"
3456 "MAC\n"
3457 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3458 "IP\n"
3459 "IP address (IPv4 or IPv6)\n"
3460 JSON_STR)
3461{
0291c246
MK
3462 struct bgp *bgp;
3463 int ret;
3464 struct prefix_rd prd;
3465 struct ethaddr mac;
3466 struct ipaddr ip;
3467 int rd_idx = 0;
3468 int mac_idx = 0;
3469 int ip_idx = 0;
3470 int uj = 0;
3471 json_object *json = NULL;
9c92b5f7
MK
3472
3473 memset(&mac, 0, sizeof(struct ethaddr));
3474 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 3475
3476 bgp = bgp_get_default();
3477 if (!bgp)
3478 return CMD_WARNING;
3479
9c92b5f7
MK
3480 /* check if we need json output */
3481 uj = use_json(argc, argv);
3482 if (uj)
3483 json = json_object_new_object();
f2d62262 3484
9c92b5f7
MK
3485 /* get the prd */
3486 if (argv_find(argv, argc, "rd", &rd_idx)) {
3487 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3488 if (!ret) {
3489 vty_out(vty, "%% Malformed Route Distinguisher\n");
3490 return CMD_WARNING;
3491 }
d62a17ae 3492 }
9c92b5f7
MK
3493
3494 /* get the mac */
3495 if (argv_find(argv, argc, "mac", &mac_idx)) {
3496 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
3497 vty_out(vty, "%% Malformed MAC address\n");
3498 return CMD_WARNING;
3499 }
d62a17ae 3500 }
9c92b5f7
MK
3501
3502 /* get the ip if specified */
3503 if (argv_find(argv, argc, "ip", &ip_idx)) {
3504 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 3505 vty_out(vty, "%% Malformed IP address\n");
3506 return CMD_WARNING;
3507 }
3508 }
3509
9c92b5f7
MK
3510 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
3511
3512 if (uj) {
3513 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3514 json, JSON_C_TO_STRING_PRETTY));
3515 json_object_free(json);
3516 }
3517
d62a17ae 3518 return CMD_SUCCESS;
520d5d76 3519}
3520
50f74cf1 3521/* Display per ESI routing table */
3522DEFUN(show_bgp_l2vpn_evpn_route_esi,
3523 show_bgp_l2vpn_evpn_route_esi_cmd,
3524 "show bgp l2vpn evpn route esi ESI [json]",
3525 SHOW_STR
3526 BGP_STR
3527 L2VPN_HELP_STR
3528 EVPN_HELP_STR
3529 "EVPN route information\n"
3530 "Ethernet Segment Identifier\n"
3531 "ESI ID\n"
3532 JSON_STR)
3533{
3534 int uj = 0;
6a527b2f 3535 esi_t esi;
50f74cf1 3536 struct bgp *bgp = NULL;
3537 json_object *json = NULL;
3538
6a527b2f 3539 memset(&esi, 0, sizeof(esi));
50f74cf1 3540 bgp = bgp_get_default();
3541 if (!bgp)
3542 return CMD_WARNING;
3543
3544 uj = use_json(argc, argv);
3545 if (uj)
3546 json = json_object_new_object();
3547
3548 /* get the ESI - ESI-ID is at argv[6] */
3549 if (!str_to_esi(argv[6]->arg, &esi)) {
3550 vty_out(vty, "%% Malformed ESI\n");
3551 return CMD_WARNING;
3552 }
3553
3554 evpn_show_routes_esi(vty, bgp, &esi, json);
3555
3556 if (uj) {
3557 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3558 json, JSON_C_TO_STRING_PRETTY));
3559 json_object_free(json);
3560 }
3561
3562 return CMD_SUCCESS;
3563}
3564
3565
f2d62262 3566/*
3567 * Display per-VNI EVPN routing table.
3568 */
9c92b5f7
MK
3569DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
3570 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3571 SHOW_STR
3572 BGP_STR
3573 L2VPN_HELP_STR
3574 EVPN_HELP_STR
3575 "EVPN route information\n"
3576 "VXLAN Network Identifier\n"
3577 "VNI number\n"
3578 "Specify Route type\n"
3579 "MAC-IP (Type-2) route\n"
3580 "Multicast (Type-3) route\n"
3581 "Remote VTEP\n"
3582 "Remote VTEP IP address\n"
3583 JSON_STR)
520d5d76 3584{
d62a17ae 3585 vni_t vni;
3586 struct bgp *bgp;
3587 struct in_addr vtep_ip;
3588 int type = 0;
f2d62262 3589 int idx = 0;
9c92b5f7
MK
3590 int uj = 0;
3591 json_object *json = NULL;
d62a17ae 3592
3593 bgp = bgp_get_default();
3594 if (!bgp)
3595 return CMD_WARNING;
3596
9c92b5f7
MK
3597 /* check if we need json output */
3598 uj = use_json(argc, argv);
3599 if (uj)
3600 json = json_object_new_object();
3601
f2d62262 3602 if (!argv_find(argv, argc, "evpn", &idx))
3603 return CMD_WARNING;
3604
d62a17ae 3605 vtep_ip.s_addr = 0;
3606
f2d62262 3607 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 3608
9c92b5f7
MK
3609 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
3610 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 3611 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
3612 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 3613 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 3614 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 3615 type = BGP_EVPN_IMET_ROUTE;
3616 else
3617 return CMD_WARNING;
f2d62262 3618 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
3619 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3620 vty_out(vty, "%% Malformed VTEP IP address\n");
3621 return CMD_WARNING;
3622 }
3623 } else
3624 return CMD_WARNING;
3625 }
3626
9c92b5f7
MK
3627 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
3628
3629 if (uj) {
3630 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3631 json, JSON_C_TO_STRING_PRETTY));
3632 json_object_free(json);
3633 }
3634
d62a17ae 3635 return CMD_SUCCESS;
520d5d76 3636}
3637
f2d62262 3638/*
3639 * Display per-VNI EVPN routing table for specific MACIP.
3640 */
9c92b5f7
MK
3641DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
3642 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
3643 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3644 SHOW_STR
3645 BGP_STR
3646 L2VPN_HELP_STR
3647 EVPN_HELP_STR
3648 "EVPN route information\n"
3649 "VXLAN Network Identifier\n"
3650 "VNI number\n"
3651 "MAC\n"
3652 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3653 "IP\n"
3654 "IP address (IPv4 or IPv6)\n"
3655 JSON_STR)
520d5d76 3656{
d62a17ae 3657 vni_t vni;
3658 struct bgp *bgp;
3659 struct ethaddr mac;
3660 struct ipaddr ip;
f2d62262 3661 int idx = 0;
9c92b5f7
MK
3662 int uj = 0;
3663 json_object *json = NULL;
d62a17ae 3664
3665 bgp = bgp_get_default();
3666 if (!bgp)
3667 return CMD_WARNING;
3668
9c92b5f7
MK
3669 /* check if we need json output */
3670 uj = use_json(argc, argv);
3671 if (uj)
3672 json = json_object_new_object();
3673
f2d62262 3674 if (!argv_find(argv, argc, "evpn", &idx))
3675 return CMD_WARNING;
3676
9c92b5f7 3677 /* get the VNI */
f2d62262 3678 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3679
3680 /* get the mac */
f2d62262 3681 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 3682 vty_out(vty, "%% Malformed MAC address\n");
3683 return CMD_WARNING;
3684 }
9c92b5f7
MK
3685
3686 /* get the ip */
d62a17ae 3687 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
3688 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
3689 || (uj
3690 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 3691 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 3692 vty_out(vty, "%% Malformed IP address\n");
3693 return CMD_WARNING;
3694 }
3695 }
3696
9c92b5f7
MK
3697 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
3698
3699 if (uj) {
3700 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3701 json, JSON_C_TO_STRING_PRETTY));
3702 json_object_free(json);
3703 }
3704
d62a17ae 3705 return CMD_SUCCESS;
520d5d76 3706}
3707
f2d62262 3708/*
3709 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3710 */
9c92b5f7
MK
3711DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3712 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3713 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3714 SHOW_STR
3715 BGP_STR
3716 L2VPN_HELP_STR
3717 EVPN_HELP_STR
3718 "EVPN route information\n"
3719 "VXLAN Network Identifier\n"
3720 "VNI number\n"
3721 "Multicast (Type-3) route\n"
3722 "Originating Router IP address\n"
3723 JSON_STR)
520d5d76 3724{
d62a17ae 3725 vni_t vni;
3726 struct bgp *bgp;
3727 int ret;
3728 struct in_addr orig_ip;
f2d62262 3729 int idx = 0;
9c92b5f7
MK
3730 int uj = 0;
3731 json_object *json = NULL;
520d5d76 3732
d62a17ae 3733 bgp = bgp_get_default();
3734 if (!bgp)
3735 return CMD_WARNING;
520d5d76 3736
9c92b5f7
MK
3737 /* check if we need json output */
3738 uj = use_json(argc, argv);
3739 if (uj)
3740 json = json_object_new_object();
3741
f2d62262 3742 if (!argv_find(argv, argc, "evpn", &idx))
3743 return CMD_WARNING;
3744
9c92b5f7 3745 /* get the VNI */
f2d62262 3746 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3747
3748 /* get the ip */
f2d62262 3749 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 3750 if (!ret) {
3751 vty_out(vty, "%% Malformed Originating Router IP address\n");
3752 return CMD_WARNING;
3753 }
520d5d76 3754
9c92b5f7
MK
3755 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3756
3757 if (uj) {
3758 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3759 json, JSON_C_TO_STRING_PRETTY));
3760 json_object_free(json);
3761 }
3762
d62a17ae 3763 return CMD_SUCCESS;
520d5d76 3764}
3765
f2d62262 3766/*
3767 * Display per-VNI EVPN routing table - for all VNIs.
3768 */
60466a63
QY
3769DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3770 show_bgp_l2vpn_evpn_route_vni_all_cmd,
9c92b5f7
MK
3771 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3772 SHOW_STR
3773 BGP_STR
3774 L2VPN_HELP_STR
3775 EVPN_HELP_STR
3776 "EVPN route information\n"
3777 "VXLAN Network Identifier\n"
3778 "All VNIs\n"
3779 "Remote VTEP\n"
3780 "Remote VTEP IP address\n"
3781 JSON_STR)
520d5d76 3782{
d62a17ae 3783 struct bgp *bgp;
3784 struct in_addr vtep_ip;
f2d62262 3785 int idx = 0;
9c92b5f7
MK
3786 int uj = 0;
3787 json_object *json = NULL;
520d5d76 3788
d62a17ae 3789 bgp = bgp_get_default();
3790 if (!bgp)
3791 return CMD_WARNING;
520d5d76 3792
9c92b5f7
MK
3793 /* check if we need json output */
3794 uj = use_json(argc, argv);
3795 if (uj)
3796 json = json_object_new_object();
3797
f2d62262 3798 if (!argv_find(argv, argc, "evpn", &idx))
3799 return CMD_WARNING;
3800
d62a17ae 3801 vtep_ip.s_addr = 0;
9c92b5f7
MK
3802 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3803 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
f2d62262 3804 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3805 vty_out(vty, "%% Malformed VTEP IP address\n");
3806 return CMD_WARNING;
3807 }
3808 }
520d5d76 3809
9c92b5f7
MK
3810 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3811
3812 if (uj) {
3813 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3814 json, JSON_C_TO_STRING_PRETTY));
3815 json_object_free(json);
3816 }
3817
d62a17ae 3818 return CMD_SUCCESS;
520d5d76 3819}
3820
10ebe1ab
MK
3821/*
3822 * Display EVPN import route-target hash table
3823 */
3824DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3825 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3826 "show bgp l2vpn evpn vrf-import-rt [json]",
3827 SHOW_STR
3828 BGP_STR
3829 L2VPN_HELP_STR
3830 EVPN_HELP_STR
3831 "Show vrf import route target\n"
3832 JSON_STR)
3833{
d7c0a89a 3834 uint8_t uj = 0;
181c08c6 3835 struct bgp *bgp_def = NULL;
10ebe1ab
MK
3836 json_object *json = NULL;
3837
3838 bgp_def = bgp_get_default();
3839 if (!bgp_def)
3840 return CMD_WARNING;
3841
3842 uj = use_json(argc, argv);
3843 if (uj)
3844 json = json_object_new_object();
3845
3846 evpn_show_vrf_import_rts(vty, bgp_def, json);
3847
3848 if (uj) {
3849 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3850 json, JSON_C_TO_STRING_PRETTY));
3851 json_object_free(json);
3852 }
3853
3854 return CMD_SUCCESS;
3855}
3856
f2d62262 3857/*
3858 * Display EVPN import route-target hash table
3859 */
60466a63
QY
3860DEFUN(show_bgp_l2vpn_evpn_import_rt,
3861 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
3862 "show bgp l2vpn evpn import-rt [json]",
3863 SHOW_STR
3864 BGP_STR
3865 L2VPN_HELP_STR
3866 EVPN_HELP_STR
3867 "Show import route target\n"
3868 JSON_STR)
520d5d76 3869{
d62a17ae 3870 struct bgp *bgp;
d7c0a89a 3871 uint8_t uj = 0;
9c92b5f7 3872 json_object *json = NULL;
520d5d76 3873
d62a17ae 3874 bgp = bgp_get_default();
3875 if (!bgp)
3876 return CMD_WARNING;
520d5d76 3877
9c92b5f7
MK
3878 uj = use_json(argc, argv);
3879 if (uj)
3880 json = json_object_new_object();
3881
3882 evpn_show_import_rts(vty, bgp, json);
3883
3884 if (uj) {
3885 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3886 json, JSON_C_TO_STRING_PRETTY));
3887 json_object_free(json);
3888 }
3889
d62a17ae 3890 return CMD_SUCCESS;
520d5d76 3891}
3892
50f74cf1 3893DEFUN(test_adv_evpn_type4_route,
3894 test_adv_evpn_type4_route_cmd,
3895 "advertise es ESI",
3896 "Advertise EVPN ES route\n"
3897 "Ethernet-segment\n"
3898 "Ethernet-Segment Identifier\n")
3899{
3900 int ret = 0;
3901 esi_t esi;
3902 struct bgp *bgp;
3903 struct ipaddr vtep_ip;
3904
3905 bgp = bgp_get_default();
3906 if (!bgp) {
3907 vty_out(vty, "%%Default BGP instance not yet created\n");
3908 return CMD_WARNING;
3909 }
3910
2bb9eff4 3911 if (!str_to_esi(argv[2]->arg, &esi)) {
50f74cf1 3912 vty_out(vty, "%%Malformed ESI\n");
3913 return CMD_WARNING;
3914 }
3915
3916 vtep_ip.ipa_type = IPADDR_V4;
3917 vtep_ip.ipaddr_v4 = bgp->router_id;
3918
3919 ret = bgp_evpn_local_es_add(bgp, &esi, &vtep_ip);
3920 if (ret == -1) {
3921 vty_out(vty, "%%Failed to EVPN advertise type-4 route\n");
3922 return CMD_WARNING;
3923 }
3924 return CMD_SUCCESS;
3925}
3926
3927DEFUN(test_withdraw_evpn_type4_route,
3928 test_withdraw_evpn_type4_route_cmd,
3929 "withdraw es ESI",
3930 "Advertise EVPN ES route\n"
3931 "Ethernet-segment\n"
3932 "Ethernet-Segment Identifier\n")
3933{
3934 int ret = 0;
3935 esi_t esi;
3936 struct bgp *bgp;
3937 struct ipaddr vtep_ip;
3938
3939 bgp = bgp_get_default();
3940 if (!bgp) {
3941 vty_out(vty, "%%Default BGP instance not yet created\n");
3942 return CMD_WARNING;
3943 }
3944
3945 if (!bgp->peer_self) {
3946 vty_out(vty, "%%BGP instance doesnt have self peer\n");
3947 return CMD_WARNING;
3948 }
3949
2bb9eff4 3950 if (!str_to_esi(argv[2]->arg, &esi)) {
50f74cf1 3951 vty_out(vty, "%%Malformed ESI\n");
3952 return CMD_WARNING;
3953 }
3954
3955 vtep_ip.ipa_type = IPADDR_V4;
3956 vtep_ip.ipaddr_v4 = bgp->router_id;
3957 ret = bgp_evpn_local_es_del(bgp, &esi, &vtep_ip);
3958 if (ret == -1) {
3959 vty_out(vty, "%%Failed to withdraw EVPN type-4 route\n");
3960 return CMD_WARNING;
3961 }
3962 return CMD_SUCCESS;
3963}
3964
5014d96f
DW
3965ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3966 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3967 "Show VNI\n"
3968 "VNI number\n")
3969
3970ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3971 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 3972 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
3973
3974ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3975 "show bgp evpn route [type <macip|multicast>]",
3976 SHOW_STR BGP_STR EVPN_HELP_STR
3977 "EVPN route information\n"
3978 "Specify Route type\n"
3979 "MAC-IP (Type-2) route\n"
3980 "Multicast (Type-3) route\n")
3981
3982ALIAS_HIDDEN(
3983 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
d114b977 3984 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
5014d96f
DW
3985 SHOW_STR BGP_STR EVPN_HELP_STR
3986 "EVPN route information\n"
3987 "Route Distinguisher\n"
3988 "ASN:XX or A.B.C.D:XX\n"
3989 "Specify Route type\n"
3990 "MAC-IP (Type-2) route\n"
3991 "Multicast (Type-3) route\n")
3992
3993ALIAS_HIDDEN(
3994 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 3995 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f
DW
3996 SHOW_STR BGP_STR EVPN_HELP_STR
3997 "EVPN route information\n"
3998 "Route Distinguisher\n"
3999 "ASN:XX or A.B.C.D:XX\n"
4000 "MAC\n"
4001 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4002 "IP\n"
4003 "IP address (IPv4 or IPv6)\n")
4004
4005ALIAS_HIDDEN(
4006 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
4007 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
4008 SHOW_STR BGP_STR EVPN_HELP_STR
4009 "EVPN route information\n"
4010 "VXLAN Network Identifier\n"
4011 "VNI number\n"
4012 "Specify Route type\n"
4013 "MAC-IP (Type-2) route\n"
4014 "Multicast (Type-3) route\n"
4015 "Remote VTEP\n"
4016 "Remote VTEP IP address\n")
4017
4018ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4019 show_bgp_evpn_route_vni_macip_cmd,
4020 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
4021 SHOW_STR BGP_STR EVPN_HELP_STR
4022 "EVPN route information\n"
4023 "VXLAN Network Identifier\n"
4024 "VNI number\n"
4025 "MAC\n"
4026 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4027 "IP\n"
4028 "IP address (IPv4 or IPv6)\n")
4029
4030ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4031 show_bgp_evpn_route_vni_multicast_cmd,
4032 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
4033 SHOW_STR BGP_STR EVPN_HELP_STR
4034 "EVPN route information\n"
4035 "VXLAN Network Identifier\n"
4036 "VNI number\n"
4037 "Multicast (Type-3) route\n"
4038 "Originating Router IP address\n")
4039
4040ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
4041 "show bgp evpn route vni all [vtep A.B.C.D]",
4042 SHOW_STR BGP_STR EVPN_HELP_STR
4043 "EVPN route information\n"
4044 "VXLAN Network Identifier\n"
4045 "All VNIs\n"
4046 "Remote VTEP\n"
4047 "Remote VTEP IP address\n")
4048
4049ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4050 "show bgp evpn import-rt",
4051 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5014d96f 4052
90e60aa7 4053DEFUN_NOSH (bgp_evpn_vni,
4054 bgp_evpn_vni_cmd,
4055 "vni (1-16777215)",
4056 "VXLAN Network Identifier\n"
4057 "VNI number\n")
4058{
d62a17ae 4059 vni_t vni;
4060 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4061 struct bgpevpn *vpn;
90e60aa7 4062
d62a17ae 4063 if (!bgp)
4064 return CMD_WARNING;
90e60aa7 4065
d62a17ae 4066 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 4067
d62a17ae 4068 /* Create VNI, or mark as configured. */
4069 vpn = evpn_create_update_vni(bgp, vni);
4070 if (!vpn) {
4071 vty_out(vty, "%% Failed to create VNI \n");
4072 return CMD_WARNING;
4073 }
90e60aa7 4074
d62a17ae 4075 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4076 return CMD_SUCCESS;
90e60aa7 4077}
4078
4079DEFUN (no_bgp_evpn_vni,
4080 no_bgp_evpn_vni_cmd,
4081 "no vni (1-16777215)",
4082 NO_STR
4083 "VXLAN Network Identifier\n"
4084 "VNI number\n")
4085{
d62a17ae 4086 vni_t vni;
4087 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4088 struct bgpevpn *vpn;
90e60aa7 4089
d62a17ae 4090 if (!bgp)
4091 return CMD_WARNING;
90e60aa7 4092
d62a17ae 4093 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 4094
d62a17ae 4095 /* Check if we should disallow. */
4096 vpn = bgp_evpn_lookup_vni(bgp, vni);
4097 if (!vpn) {
4098 vty_out(vty, "%% Specified VNI does not exist\n");
4099 return CMD_WARNING;
4100 }
4101 if (!is_vni_configured(vpn)) {
4102 vty_out(vty, "%% Specified VNI is not configured\n");
4103 return CMD_WARNING;
4104 }
90e60aa7 4105
d62a17ae 4106 evpn_delete_vni(bgp, vpn);
4107 return CMD_SUCCESS;
90e60aa7 4108}
4109
4110DEFUN_NOSH (exit_vni,
4111 exit_vni_cmd,
4112 "exit-vni",
4113 "Exit from VNI mode\n")
4114{
d62a17ae 4115 if (vty->node == BGP_EVPN_VNI_NODE)
4116 vty->node = BGP_EVPN_NODE;
4117 return CMD_SUCCESS;
90e60aa7 4118}
4119
676f83b9 4120DEFUN (bgp_evpn_vrf_rd,
4121 bgp_evpn_vrf_rd_cmd,
4122 "rd ASN:NN_OR_IP-ADDRESS:NN",
4123 "Route Distinguisher\n"
4124 "ASN:XX or A.B.C.D:XX\n")
4125{
4126 int ret;
4127 struct prefix_rd prd;
4128 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4129
4130 if (!bgp_vrf)
4131 return CMD_WARNING;
4132
4133 ret = str2prefix_rd(argv[1]->arg, &prd);
4134 if (!ret) {
4135 vty_out(vty, "%% Malformed Route Distinguisher\n");
4136 return CMD_WARNING;
4137 }
4138
4139 /* If same as existing value, there is nothing more to do. */
4140 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4141 return CMD_SUCCESS;
4142
4143 /* Configure or update the RD. */
4144 evpn_configure_vrf_rd(bgp_vrf, &prd);
4145 return CMD_SUCCESS;
4146}
4147
4148DEFUN (no_bgp_evpn_vrf_rd,
4149 no_bgp_evpn_vrf_rd_cmd,
4150 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4151 NO_STR
4152 "Route Distinguisher\n"
4153 "ASN:XX or A.B.C.D:XX\n")
4154{
4155 int ret;
4156 struct prefix_rd prd;
4157 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4158
4159 if (!bgp_vrf)
4160 return CMD_WARNING;
4161
4162 ret = str2prefix_rd(argv[2]->arg, &prd);
4163 if (!ret) {
4164 vty_out(vty, "%% Malformed Route Distinguisher\n");
4165 return CMD_WARNING;
4166 }
4167
4168 /* Check if we should disallow. */
4169 if (!is_vrf_rd_configured(bgp_vrf)) {
4170 vty_out(vty, "%% RD is not configured for this VRF\n");
4171 return CMD_WARNING;
4172 }
4173
4174 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4175 vty_out(vty,
4176 "%% RD specified does not match configuration for this VRF\n");
4177 return CMD_WARNING;
4178 }
4179
4180 evpn_unconfigure_vrf_rd(bgp_vrf);
4181 return CMD_SUCCESS;
4182}
4183
4184DEFUN (no_bgp_evpn_vrf_rd_without_val,
4185 no_bgp_evpn_vrf_rd_without_val_cmd,
4186 "no rd",
4187 NO_STR
4188 "Route Distinguisher\n")
4189{
4190 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4191
4192 if (!bgp_vrf)
4193 return CMD_WARNING;
4194
4195 /* Check if we should disallow. */
4196 if (!is_vrf_rd_configured(bgp_vrf)) {
4197 vty_out(vty, "%% RD is not configured for this VRF\n");
4198 return CMD_WARNING;
4199 }
4200
4201 evpn_unconfigure_vrf_rd(bgp_vrf);
4202 return CMD_SUCCESS;
4203}
4204
90e60aa7 4205DEFUN (bgp_evpn_vni_rd,
4206 bgp_evpn_vni_rd_cmd,
d114b977 4207 "rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 4208 "Route Distinguisher\n"
4209 "ASN:XX or A.B.C.D:XX\n")
4210{
d62a17ae 4211 struct prefix_rd prd;
4212 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4213 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4214 int ret;
90e60aa7 4215
06fe25f4 4216 if (!bgp)
d62a17ae 4217 return CMD_WARNING;
90e60aa7 4218
a2a8153f
CS
4219 if (bgp->vrf_id != VRF_DEFAULT) {
4220 vty_out(vty,
4221 "This command is only supported under Default VRF\n");
4222 return CMD_WARNING;
4223 }
4224
d62a17ae 4225 ret = str2prefix_rd(argv[1]->arg, &prd);
4226 if (!ret) {
4227 vty_out(vty, "%% Malformed Route Distinguisher\n");
4228 return CMD_WARNING;
4229 }
90e60aa7 4230
d62a17ae 4231 /* If same as existing value, there is nothing more to do. */
4232 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4233 return CMD_SUCCESS;
90e60aa7 4234
d62a17ae 4235 /* Configure or update the RD. */
4236 evpn_configure_rd(bgp, vpn, &prd);
4237 return CMD_SUCCESS;
90e60aa7 4238}
4239
4240DEFUN (no_bgp_evpn_vni_rd,
4241 no_bgp_evpn_vni_rd_cmd,
d114b977 4242 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 4243 NO_STR
4244 "Route Distinguisher\n"
4245 "ASN:XX or A.B.C.D:XX\n")
4246{
d62a17ae 4247 struct prefix_rd prd;
4248 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4249 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4250 int ret;
90e60aa7 4251
06fe25f4 4252 if (!bgp)
d62a17ae 4253 return CMD_WARNING;
90e60aa7 4254
a2a8153f
CS
4255 if (bgp->vrf_id != VRF_DEFAULT) {
4256 vty_out(vty,
4257 "This command is only supported under Default VRF\n");
4258 return CMD_WARNING;
4259 }
4260
d62a17ae 4261 ret = str2prefix_rd(argv[2]->arg, &prd);
4262 if (!ret) {
4263 vty_out(vty, "%% Malformed Route Distinguisher\n");
4264 return CMD_WARNING;
4265 }
90e60aa7 4266
d62a17ae 4267 /* Check if we should disallow. */
4268 if (!is_rd_configured(vpn)) {
4269 vty_out(vty, "%% RD is not configured for this VNI\n");
4270 return CMD_WARNING;
4271 }
90e60aa7 4272
d62a17ae 4273 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
4274 vty_out(vty,
4275 "%% RD specified does not match configuration for this VNI\n");
4276 return CMD_WARNING;
4277 }
90e60aa7 4278
d62a17ae 4279 evpn_unconfigure_rd(bgp, vpn);
4280 return CMD_SUCCESS;
90e60aa7 4281}
4282
4283DEFUN (no_bgp_evpn_vni_rd_without_val,
4284 no_bgp_evpn_vni_rd_without_val_cmd,
4285 "no rd",
4286 NO_STR
4287 "Route Distinguisher\n")
4288{
d62a17ae 4289 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4290 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 4291
06fe25f4 4292 if (!bgp)
d62a17ae 4293 return CMD_WARNING;
90e60aa7 4294
a2a8153f
CS
4295 if (bgp->vrf_id != VRF_DEFAULT) {
4296 vty_out(vty,
4297 "This command is only supported under Default VRF\n");
4298 return CMD_WARNING;
4299 }
4300
d62a17ae 4301 /* Check if we should disallow. */
4302 if (!is_rd_configured(vpn)) {
4303 vty_out(vty, "%% RD is not configured for this VNI\n");
4304 return CMD_WARNING;
4305 }
90e60aa7 4306
d62a17ae 4307 evpn_unconfigure_rd(bgp, vpn);
4308 return CMD_SUCCESS;
90e60aa7 4309}
4310
4311/*
4312 * Loop over all extended-communities in the route-target list rtl and
4313 * return 1 if we find ecomtarget
4314 */
d62a17ae 4315static int bgp_evpn_rt_matches_existing(struct list *rtl,
4316 struct ecommunity *ecomtarget)
90e60aa7 4317{
d62a17ae 4318 struct listnode *node, *nnode;
4319 struct ecommunity *ecom;
90e60aa7 4320
d62a17ae 4321 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
4322 if (ecommunity_match(ecom, ecomtarget))
4323 return 1;
4324 }
90e60aa7 4325
d62a17ae 4326 return 0;
90e60aa7 4327}
4328
c581d8b0
MK
4329/* display L3VNI related info for a VRF instance */
4330DEFUN (show_bgp_vrf_l3vni_info,
4331 show_bgp_vrf_l3vni_info_cmd,
4cce389e 4332 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
4333 SHOW_STR
4334 BGP_STR
4335 "show bgp vrf\n"
4336 "VRF Name\n"
4337 "L3-VNI\n"
ceb9a921 4338 JSON_STR)
c581d8b0
MK
4339{
4340 char buf[ETHER_ADDR_STRLEN];
676f83b9 4341 char buf1[INET6_ADDRSTRLEN];
c581d8b0
MK
4342 int idx_vrf = 3;
4343 const char *name = NULL;
4344 struct bgp *bgp = NULL;
4345 struct listnode *node = NULL;
6a8657d0 4346 struct bgpevpn *vpn = NULL;
c581d8b0 4347 struct ecommunity *ecom = NULL;
ceb9a921
MK
4348 json_object *json = NULL;
4349 json_object *json_vnis = NULL;
4350 json_object *json_export_rts = NULL;
4351 json_object *json_import_rts = NULL;
d7c0a89a 4352 uint8_t uj = use_json(argc, argv);
ceb9a921
MK
4353
4354 if (uj) {
4355 json = json_object_new_object();
4356 json_vnis = json_object_new_array();
4357 json_export_rts = json_object_new_array();
4358 json_import_rts = json_object_new_array();
4359 }
c581d8b0
MK
4360
4361 name = argv[idx_vrf]->arg;
4362 bgp = bgp_lookup_by_name(name);
4363 if (!bgp) {
ceb9a921 4364 if (!uj)
996c9314 4365 vty_out(vty, "BGP instance for VRF %s not found", name);
ceb9a921
MK
4366 else {
4367 json_object_string_add(json, "warning",
4368 "BGP instance not found");
996c9314 4369 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
4370 json_object_free(json);
4371 }
c581d8b0
MK
4372 return CMD_WARNING;
4373 }
4374
ceb9a921
MK
4375 if (!json) {
4376 vty_out(vty, "BGP VRF: %s\n", name);
996c9314 4377 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
ceb9a921
MK
4378 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
4379 vty_out(vty, " Rmac: %s\n",
4380 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
4381 vty_out(vty, " VNI Filter: %s\n",
4382 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
4383 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4384 ? "prefix-routes-only"
4385 : "none");
ceb9a921
MK
4386 vty_out(vty, " L2-VNI List:\n");
4387 vty_out(vty, " ");
4388 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4389 vty_out(vty, "%u ", vpn->vni);
4390 vty_out(vty, "\n");
4391 vty_out(vty, " Export-RTs:\n");
4392 vty_out(vty, " ");
4393 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4394 vty_out(vty, "%s ", ecommunity_str(ecom));
4395 vty_out(vty, "\n");
4396 vty_out(vty, " Import-RTs:\n");
4397 vty_out(vty, " ");
4398 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4399 vty_out(vty, "%s ", ecommunity_str(ecom));
4400 vty_out(vty, "\n");
676f83b9 4401 vty_out(vty, " RD: %s\n",
4402 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
4403 } else {
4404 json_object_string_add(json, "vrf", name);
b67a60d2 4405 json_object_string_add(json, "local-ip",
4406 inet_ntoa(bgp->originator_ip));
ceb9a921 4407 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
4408 json_object_string_add(
4409 json, "rmac",
4410 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4411 json_object_string_add(
4412 json, "vniFilter",
4413 CHECK_FLAG(bgp->vrf_flags,
4414 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4415 ? "prefix-routes-only"
4416 : "none");
ceb9a921
MK
4417 /* list of l2vnis */
4418 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4419 json_object_array_add(json_vnis,
4420 json_object_new_int(vpn->vni));
4421 json_object_object_add(json, "l2vnis", json_vnis);
4422
4423 /* export rts */
4424 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
996c9314
LB
4425 json_object_array_add(
4426 json_export_rts,
4427 json_object_new_string(ecommunity_str(ecom)));
ceb9a921
MK
4428 json_object_object_add(json, "export-rts", json_export_rts);
4429
4430 /* import rts */
4431 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
996c9314
LB
4432 json_object_array_add(
4433 json_import_rts,
4434 json_object_new_string(ecommunity_str(ecom)));
ceb9a921 4435 json_object_object_add(json, "import-rts", json_import_rts);
676f83b9 4436 json_object_string_add(
4437 json, "rd",
4438 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921 4439 }
c581d8b0 4440
ceb9a921
MK
4441 if (uj) {
4442 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4443 json, JSON_C_TO_STRING_PRETTY));
4444 json_object_free(json);
4445 }
c581d8b0
MK
4446 return CMD_SUCCESS;
4447}
4448
4449/* import/export rt for l3vni-vrf */
4450DEFUN (bgp_evpn_vrf_rt,
4451 bgp_evpn_vrf_rt_cmd,
4452 "route-target <both|import|export> RT",
4453 "Route Target\n"
4454 "import and export\n"
4455 "import\n"
4456 "export\n"
4457 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4458{
4459 int rt_type;
4460 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4461 struct ecommunity *ecomadd = NULL;
4462
4463 if (!bgp)
4464 return CMD_WARNING;
4465
4466 if (!strcmp(argv[1]->arg, "import"))
4467 rt_type = RT_TYPE_IMPORT;
4468 else if (!strcmp(argv[1]->arg, "export"))
4469 rt_type = RT_TYPE_EXPORT;
4470 else if (!strcmp(argv[1]->arg, "both"))
4471 rt_type = RT_TYPE_BOTH;
4472 else {
4473 vty_out(vty, "%% Invalid Route Target type\n");
4474 return CMD_WARNING;
4475 }
4476
4477 /* Add/update the import route-target */
4478 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4479 ecomadd = ecommunity_str2com(argv[2]->arg,
4480 ECOMMUNITY_ROUTE_TARGET, 0);
4481 if (!ecomadd) {
4482 vty_out(vty, "%% Malformed Route Target list\n");
4483 return CMD_WARNING;
4484 }
4485 ecommunity_str(ecomadd);
4486
4487 /* Do nothing if we already have this import route-target */
996c9314 4488 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
c581d8b0
MK
4489 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
4490 }
4491
4492 /* Add/update the export route-target */
4493 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4494 ecomadd = ecommunity_str2com(argv[2]->arg,
4495 ECOMMUNITY_ROUTE_TARGET, 0);
4496 if (!ecomadd) {
4497 vty_out(vty, "%% Malformed Route Target list\n");
4498 return CMD_WARNING;
4499 }
4500 ecommunity_str(ecomadd);
4501
4502 /* Do nothing if we already have this export route-target */
996c9314 4503 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
c581d8b0
MK
4504 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
4505 }
4506
4507 return CMD_SUCCESS;
4508}
4509
4510DEFUN (no_bgp_evpn_vrf_rt,
4511 no_bgp_evpn_vrf_rt_cmd,
4512 "no route-target <both|import|export> RT",
4513 NO_STR
4514 "Route Target\n"
4515 "import and export\n"
4516 "import\n"
4517 "export\n"
4518 "ASN:XX or A.B.C.D:XX\n")
4519{
4520 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4521 int rt_type, found_ecomdel;
4522 struct ecommunity *ecomdel = NULL;
4523
4524 if (!bgp)
4525 return CMD_WARNING;
4526
4527 if (!strcmp(argv[2]->arg, "import"))
4528 rt_type = RT_TYPE_IMPORT;
4529 else if (!strcmp(argv[2]->arg, "export"))
4530 rt_type = RT_TYPE_EXPORT;
4531 else if (!strcmp(argv[2]->arg, "both"))
4532 rt_type = RT_TYPE_BOTH;
4533 else {
4534 vty_out(vty, "%% Invalid Route Target type\n");
4535 return CMD_WARNING;
4536 }
4537
4538 if (rt_type == RT_TYPE_IMPORT) {
4539 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4540 vty_out(vty,
4541 "%% Import RT is not configured for this VRF\n");
4542 return CMD_WARNING;
4543 }
4544 } else if (rt_type == RT_TYPE_EXPORT) {
4545 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4546 vty_out(vty,
4547 "%% Export RT is not configured for this VRF\n");
4548 return CMD_WARNING;
4549 }
4550 } else if (rt_type == RT_TYPE_BOTH) {
4551 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
4552 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4553 vty_out(vty,
4554 "%% Import/Export RT is not configured for this VRF\n");
4555 return CMD_WARNING;
4556 }
4557 }
4558
4559 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
4560 if (!ecomdel) {
4561 vty_out(vty, "%% Malformed Route Target list\n");
4562 return CMD_WARNING;
4563 }
4564 ecommunity_str(ecomdel);
4565
4566 if (rt_type == RT_TYPE_IMPORT) {
4567 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4568 ecomdel)) {
4569 vty_out(vty,
4570 "%% RT specified does not match configuration for this VRF\n");
4571 return CMD_WARNING;
4572 }
4573 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4574 } else if (rt_type == RT_TYPE_EXPORT) {
4575 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4576 ecomdel)) {
4577 vty_out(vty,
4578 "%% RT specified does not match configuration for this VRF\n");
4579 return CMD_WARNING;
4580 }
4581 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4582 } else if (rt_type == RT_TYPE_BOTH) {
4583 found_ecomdel = 0;
4584
4585 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4586 ecomdel)) {
4587 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4588 found_ecomdel = 1;
4589 }
4590
4591 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4592 ecomdel)) {
4593 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4594 found_ecomdel = 1;
4595 }
4596
4597 if (!found_ecomdel) {
4598 vty_out(vty,
4599 "%% RT specified does not match configuration for this VRF\n");
4600 return CMD_WARNING;
4601 }
4602 }
4603
4604 return CMD_SUCCESS;
4605}
90e60aa7 4606
4607DEFUN (bgp_evpn_vni_rt,
4608 bgp_evpn_vni_rt_cmd,
4609 "route-target <both|import|export> RT",
4610 "Route Target\n"
4611 "import and export\n"
4612 "import\n"
4613 "export\n"
4614 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4615{
d62a17ae 4616 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4617 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4618 int rt_type;
4619 struct ecommunity *ecomadd = NULL;
4620
06fe25f4 4621 if (!bgp)
d62a17ae 4622 return CMD_WARNING;
4623
a2a8153f
CS
4624 if (bgp->vrf_id != VRF_DEFAULT) {
4625 vty_out(vty,
4626 "This command is only supported under Default VRF\n");
4627 return CMD_WARNING;
4628 }
4629
8034beff 4630 if (!strcmp(argv[1]->text, "import"))
d62a17ae 4631 rt_type = RT_TYPE_IMPORT;
8034beff 4632 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 4633 rt_type = RT_TYPE_EXPORT;
8034beff 4634 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 4635 rt_type = RT_TYPE_BOTH;
4636 else {
4637 vty_out(vty, "%% Invalid Route Target type\n");
4638 return CMD_WARNING;
4639 }
4640
4641 /* Add/update the import route-target */
4642 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4643 ecomadd = ecommunity_str2com(argv[2]->arg,
4644 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4645 if (!ecomadd) {
4646 vty_out(vty, "%% Malformed Route Target list\n");
4647 return CMD_WARNING;
4648 }
5bc2ed52 4649 ecommunity_str(ecomadd);
d62a17ae 4650
4651 /* Do nothing if we already have this import route-target */
4652 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
4653 evpn_configure_import_rt(bgp, vpn, ecomadd);
4654 }
4655
4656 /* Add/update the export route-target */
4657 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4658 ecomadd = ecommunity_str2com(argv[2]->arg,
4659 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4660 if (!ecomadd) {
4661 vty_out(vty, "%% Malformed Route Target list\n");
4662 return CMD_WARNING;
4663 }
5bc2ed52 4664 ecommunity_str(ecomadd);
d62a17ae 4665
4666 /* Do nothing if we already have this export route-target */
4667 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
4668 evpn_configure_export_rt(bgp, vpn, ecomadd);
4669 }
4670
4671 return CMD_SUCCESS;
90e60aa7 4672}
4673
4674DEFUN (no_bgp_evpn_vni_rt,
4675 no_bgp_evpn_vni_rt_cmd,
4676 "no route-target <both|import|export> RT",
4677 NO_STR
4678 "Route Target\n"
4679 "import and export\n"
4680 "import\n"
4681 "export\n"
4682 "ASN:XX or A.B.C.D:XX\n")
4683{
d62a17ae 4684 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4685 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4686 int rt_type, found_ecomdel;
4687 struct ecommunity *ecomdel = NULL;
4688
06fe25f4 4689 if (!bgp)
d62a17ae 4690 return CMD_WARNING;
4691
a2a8153f
CS
4692 if (bgp->vrf_id != VRF_DEFAULT) {
4693 vty_out(vty,
4694 "This command is only supported under Default VRF\n");
4695 return CMD_WARNING;
4696 }
4697
8034beff 4698 if (!strcmp(argv[2]->text, "import"))
d62a17ae 4699 rt_type = RT_TYPE_IMPORT;
8034beff 4700 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 4701 rt_type = RT_TYPE_EXPORT;
8034beff 4702 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 4703 rt_type = RT_TYPE_BOTH;
4704 else {
4705 vty_out(vty, "%% Invalid Route Target type\n");
4706 return CMD_WARNING;
4707 }
4708
4709 /* The user did "no route-target import", check to see if there are any
4710 * import route-targets configured. */
4711 if (rt_type == RT_TYPE_IMPORT) {
4712 if (!is_import_rt_configured(vpn)) {
4713 vty_out(vty,
4714 "%% Import RT is not configured for this VNI\n");
4715 return CMD_WARNING;
4716 }
4717 } else if (rt_type == RT_TYPE_EXPORT) {
4718 if (!is_export_rt_configured(vpn)) {
4719 vty_out(vty,
4720 "%% Export RT is not configured for this VNI\n");
4721 return CMD_WARNING;
4722 }
4723 } else if (rt_type == RT_TYPE_BOTH) {
4724 if (!is_import_rt_configured(vpn)
4725 && !is_export_rt_configured(vpn)) {
4726 vty_out(vty,
4727 "%% Import/Export RT is not configured for this VNI\n");
4728 return CMD_WARNING;
4729 }
4730 }
4731
4732 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4733 if (!ecomdel) {
4734 vty_out(vty, "%% Malformed Route Target list\n");
4735 return CMD_WARNING;
4736 }
5bc2ed52 4737 ecommunity_str(ecomdel);
d62a17ae 4738
4739 if (rt_type == RT_TYPE_IMPORT) {
4740 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4741 vty_out(vty,
4742 "%% RT specified does not match configuration for this VNI\n");
4743 return CMD_WARNING;
4744 }
4745 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4746 } else if (rt_type == RT_TYPE_EXPORT) {
4747 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4748 vty_out(vty,
4749 "%% RT specified does not match configuration for this VNI\n");
4750 return CMD_WARNING;
4751 }
4752 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4753 } else if (rt_type == RT_TYPE_BOTH) {
4754 found_ecomdel = 0;
4755
4756 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4757 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4758 found_ecomdel = 1;
4759 }
4760
4761 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4762 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4763 found_ecomdel = 1;
4764 }
4765
4766 if (!found_ecomdel) {
4767 vty_out(vty,
4768 "%% RT specified does not match configuration for this VNI\n");
4769 return CMD_WARNING;
4770 }
4771 }
4772
4773 return CMD_SUCCESS;
90e60aa7 4774}
4775
4776DEFUN (no_bgp_evpn_vni_rt_without_val,
4777 no_bgp_evpn_vni_rt_without_val_cmd,
4778 "no route-target <import|export>",
4779 NO_STR
4780 "Route Target\n"
4781 "import\n"
4782 "export\n")
4783{
d62a17ae 4784 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4785 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4786 int rt_type;
4787
06fe25f4 4788 if (!bgp)
d62a17ae 4789 return CMD_WARNING;
4790
a2a8153f
CS
4791 if (bgp->vrf_id != VRF_DEFAULT) {
4792 vty_out(vty,
4793 "This command is only supported under Default VRF\n");
4794 return CMD_WARNING;
4795 }
4796
8034beff 4797 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 4798 rt_type = RT_TYPE_IMPORT;
8034beff 4799 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 4800 rt_type = RT_TYPE_EXPORT;
4801 } else {
4802 vty_out(vty, "%% Invalid Route Target type\n");
4803 return CMD_WARNING;
4804 }
4805
4806 /* Check if we should disallow. */
4807 if (rt_type == RT_TYPE_IMPORT) {
4808 if (!is_import_rt_configured(vpn)) {
4809 vty_out(vty,
4810 "%% Import RT is not configured for this VNI\n");
4811 return CMD_WARNING;
4812 }
4813 } else {
4814 if (!is_export_rt_configured(vpn)) {
4815 vty_out(vty,
4816 "%% Export RT is not configured for this VNI\n");
4817 return CMD_WARNING;
4818 }
4819 }
4820
4821 /* Unconfigure the RT. */
4822 if (rt_type == RT_TYPE_IMPORT)
4823 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4824 else
4825 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4826 return CMD_SUCCESS;
90e60aa7 4827}
568b6b44
QY
4828
4829static int vni_cmp(const void **a, const void **b)
4830{
4831 const struct bgpevpn *first = *a;
4832 const struct bgpevpn *secnd = *b;
4833
4834 return secnd->vni - first->vni;
4835}
4836
90e60aa7 4837/*
4838 * Output EVPN configuration information.
4839 */
d62a17ae 4840void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 4841 safi_t safi)
d62a17ae 4842{
a75c2553
MK
4843 char buf1[RD_ADDRSTRLEN];
4844
568b6b44
QY
4845 if (bgp->vnihash) {
4846 struct list *vnilist = hash_to_list(bgp->vnihash);
4847 struct listnode *ln;
4848 struct bgpevpn *data;
4849
4850 list_sort(vnilist, vni_cmp);
4851 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
4852 write_vni_config(vty, data);
4853
4854 list_delete_and_null(&vnilist);
4855 }
90e60aa7 4856
2b791107 4857 if (bgp->advertise_all_vni)
d62a17ae 4858 vty_out(vty, " advertise-all-vni\n");
1a98c087 4859
bf1061d8
VB
4860 if (bgp->advertise_autort_rfc8365)
4861 vty_out(vty, " autort rfc8365-compatible\n");
4862
2b791107 4863 if (bgp->advertise_gw_macip)
1a98c087 4864 vty_out(vty, " advertise-default-gw\n");
6ee86383 4865
154faa50 4866 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
4867 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
4868 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
4869 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
4870 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
4871 else
4872 vty_out(vty, " advertise ipv4 unicast\n");
4873 }
6ee86383 4874
154faa50 4875 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
4876 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
4877 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
4878 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
4879 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
4880 else
4881 vty_out(vty, " advertise ipv6 unicast\n");
4882 }
486456ca
MK
4883
4884 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4885 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
4886 vty_out(vty, " default-originate ipv4\n");
4887
4888 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4889 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
4890 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 4891
a75c2553
MK
4892 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
4893 vty_out(vty, " rd %s\n",
4894 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
4895
db29a4a8
MK
4896 /* import route-target */
4897 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4898 char *ecom_str;
4899 struct listnode *node, *nnode;
4900 struct ecommunity *ecom;
4901
4902 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
4903 ecom)) {
4904 ecom_str = ecommunity_ecom2str(
4905 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4906 vty_out(vty, " route-target import %s\n", ecom_str);
db29a4a8
MK
4907 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4908 }
4909 }
4910
4911 /* export route-target */
4912 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4913 char *ecom_str;
4914 struct listnode *node, *nnode;
4915 struct ecommunity *ecom;
4916
4917 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
4918 ecom)) {
4919 ecom_str = ecommunity_ecom2str(
4920 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4921 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
4922 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4923 }
4924 }
90e60aa7 4925}
4926
4d0e6ece 4927void bgp_ethernetvpn_init(void)
784d3a42 4928{
d62a17ae 4929 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4930 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4931 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4932 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4933 install_element(VIEW_NODE,
4934 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4935 install_element(VIEW_NODE,
4936 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4937 install_element(
4938 VIEW_NODE,
4939 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4940 install_element(
4941 VIEW_NODE,
4942 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4943 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4944 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4945 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4946 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
d62a17ae 4947 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4948 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
bf1061d8
VB
4949 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
4950 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
1a98c087
MK
4951 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4952 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
342dd0c6 4953 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4954 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
4955 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
4956 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
d62a17ae 4957
50f74cf1 4958 /* test commands */
4959 install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
4960 install_element(BGP_EVPN_NODE, &test_withdraw_evpn_type4_route_cmd);
4961
f2d62262 4962 /* "show bgp l2vpn evpn" commands. */
50f74cf1 4963 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
f2d62262 4964 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4965 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4966 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4967 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4968 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
50f74cf1 4969 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
f2d62262 4970 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
4971 install_element(VIEW_NODE,
4972 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4973 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4974 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4975 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 4976 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 4977
5014d96f
DW
4978 /* "show bgp evpn" commands. */
4979 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4980 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4981 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4982 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4983 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4984 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4985 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4986 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4987 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4988 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 4989 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5014d96f 4990
d62a17ae 4991 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4992 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
4993 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4994 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
4995 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
4996 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
4997 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
4998 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
4999 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
5000 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5001 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 5002 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
5003 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5004 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
1a98c087
MK
5005 install_element(BGP_EVPN_VNI_NODE,
5006 &bgp_evpn_advertise_default_gw_vni_cmd);
5007 install_element(BGP_EVPN_VNI_NODE,
5008 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
5009 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5010 install_element(BGP_EVPN_VNI_NODE,
5011 &no_bgp_evpn_advertise_vni_subnet_cmd);
784d3a42 5012}