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