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