]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
Merge pull request #2894 from donaldsharp/thread_stuff
[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) {
7df407ed
CS
1891 /* Check if this L2VNI is already configured as L3VNI */
1892 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
1893 flog_err(BGP_ERR_VNI,
1894 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1895 bgp->vrf_id, vni);
1896 return NULL;
1897 }
1898
29c53922 1899 /* tenant vrf will be updated when we get local_vni_add from
523cafc4 1900 * zebra
1901 */
29c53922 1902 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0);
d62a17ae 1903 if (!vpn) {
af4c2728 1904 flog_err(
14454c9f 1905 BGP_ERR_VNI,
d62a17ae 1906 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1907 bgp->vrf_id, vni);
1908 return NULL;
1909 }
1910 }
90e60aa7 1911
d62a17ae 1912 /* Mark as configured. */
1913 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1914 return vpn;
90e60aa7 1915}
1916
1917/*
1918 * Delete VNI. If VNI does not exist in the system (i.e., just
1919 * configuration), all that is needed is to free it. Otherwise,
1920 * any parameters configured for the VNI need to be reset (with
1921 * appropriate action) and the VNI marked as unconfigured; the
1922 * VNI will continue to exist, purely as a "learnt" entity.
1923 */
d62a17ae 1924static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1925{
d62a17ae 1926 assert(bgp->vnihash);
90e60aa7 1927
d62a17ae 1928 if (!is_vni_live(vpn)) {
1929 bgp_evpn_free(bgp, vpn);
1930 return 0;
1931 }
90e60aa7 1932
d62a17ae 1933 /* We need to take the unconfigure action for each parameter of this VNI
1934 * that is configured. Some optimization is possible, but not worth the
1935 * additional code for an operation that should be pretty rare.
1936 */
1937 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
90e60aa7 1938
d62a17ae 1939 /* First, deal with the export side - RD and export RT changes. */
1940 if (is_rd_configured(vpn))
1941 evpn_unconfigure_rd(bgp, vpn);
1942 if (is_export_rt_configured(vpn))
1943 evpn_unconfigure_export_rt(bgp, vpn, NULL);
90e60aa7 1944
d62a17ae 1945 /* Next, deal with the import side. */
1946 if (is_import_rt_configured(vpn))
1947 evpn_unconfigure_import_rt(bgp, vpn, NULL);
90e60aa7 1948
d62a17ae 1949 return 0;
90e60aa7 1950}
1951
10ebe1ab
MK
1952/*
1953 * Display import RT mapping to VRFs (vty handler)
1954 * bgp_def: default bgp instance
1955 */
996c9314 1956static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_def,
10ebe1ab
MK
1957 json_object *json)
1958{
1959 void *args[2];
1960
1961 args[0] = vty;
1962 args[1] = json;
1963
1964 hash_iterate(bgp_def->vrf_import_rt_hash,
996c9314
LB
1965 (void (*)(struct hash_backet *,
1966 void *))show_vrf_import_rt_entry,
10ebe1ab
MK
1967 args);
1968}
1969
520d5d76 1970/*
1971 * Display import RT mapping to VNIs (vty handler)
1972 */
9c92b5f7
MK
1973static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
1974 json_object *json)
520d5d76 1975{
9c92b5f7
MK
1976 void *args[2];
1977
1978 args[0] = vty;
1979 args[1] = json;
1980
d62a17ae 1981 hash_iterate(
1982 bgp->import_rt_hash,
1983 (void (*)(struct hash_backet *, void *))show_import_rt_entry,
9c92b5f7 1984 args);
520d5d76 1985}
1986
1987/*
1988 * Display EVPN routes for all VNIs - vty handler.
1989 */
d62a17ae 1990static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
60466a63 1991 struct in_addr vtep_ip, json_object *json)
520d5d76 1992{
d7c0a89a 1993 uint32_t num_vnis;
d62a17ae 1994 struct vni_walk_ctx wctx;
520d5d76 1995
d62a17ae 1996 num_vnis = hashcount(bgp->vnihash);
1997 if (!num_vnis)
1998 return;
1999 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2000 wctx.bgp = bgp;
2001 wctx.vty = vty;
2002 wctx.vtep_ip = vtep_ip;
9c92b5f7 2003 wctx.json = json;
9d303b37
DL
2004 hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
2005 void *))show_vni_routes_hash,
2006 &wctx);
520d5d76 2007}
2008
2009/*
2010 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2011 */
d62a17ae 2012static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2013 vni_t vni, struct in_addr orig_ip,
2014 json_object *json)
d62a17ae 2015{
2016 struct bgpevpn *vpn;
2017 struct prefix_evpn p;
2018 struct bgp_node *rn;
2019 struct bgp_info *ri;
d7c0a89a 2020 uint32_t path_cnt = 0;
d62a17ae 2021 afi_t afi;
2022 safi_t safi;
9c92b5f7 2023 json_object *json_paths = NULL;
d62a17ae 2024
2025 afi = AFI_L2VPN;
2026 safi = SAFI_EVPN;
2027
2028 /* Locate VNI. */
2029 vpn = bgp_evpn_lookup_vni(bgp, vni);
2030 if (!vpn) {
2031 vty_out(vty, "VNI not found\n");
2032 return;
2033 }
2034
2035 /* See if route exists. */
2036 build_evpn_type3_prefix(&p, orig_ip);
2037 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2038 if (!rn || !rn->info) {
9c92b5f7
MK
2039 if (!json)
2040 vty_out(vty, "%% Network not in table\n");
d62a17ae 2041 return;
2042 }
2043
9c92b5f7
MK
2044 if (json)
2045 json_paths = json_object_new_array();
2046
d62a17ae 2047 /* Prefix and num paths displayed once per prefix. */
9c92b5f7 2048 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
d62a17ae 2049
2050 /* Display each path for this prefix. */
2051 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
2052 json_object *json_path = NULL;
2053
2054 if (json)
2055 json_path = json_object_new_array();
2056
2057 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
2058 json_path);
2059
2060 if (json)
2061 json_object_array_add(json_paths, json_path);
2062
d62a17ae 2063 path_cnt++;
2064 }
2065
9c92b5f7
MK
2066 if (json) {
2067 if (path_cnt)
2068 json_object_object_add(json, "paths", json_paths);
2069
2070 json_object_int_add(json, "numPaths", path_cnt);
2071 } else {
2072 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2073 path_cnt);
2074 }
520d5d76 2075}
2076
2077/*
2078 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2079 * By definition, only matching type-2 route will be displayed.
2080 */
d62a17ae 2081static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2082 vni_t vni, struct ethaddr *mac,
9c92b5f7 2083 struct ipaddr *ip, json_object *json)
d62a17ae 2084{
2085 struct bgpevpn *vpn;
2086 struct prefix_evpn p;
2087 struct bgp_node *rn;
2088 struct bgp_info *ri;
d7c0a89a 2089 uint32_t path_cnt = 0;
d62a17ae 2090 afi_t afi;
2091 safi_t safi;
9c92b5f7 2092 json_object *json_paths = NULL;
d62a17ae 2093
2094 afi = AFI_L2VPN;
2095 safi = SAFI_EVPN;
2096
2097 /* Locate VNI. */
2098 vpn = bgp_evpn_lookup_vni(bgp, vni);
2099 if (!vpn) {
9c92b5f7
MK
2100 if (!json)
2101 vty_out(vty, "VNI not found\n");
d62a17ae 2102 return;
2103 }
2104
2105 /* See if route exists. Look for both non-sticky and sticky. */
2106 build_evpn_type2_prefix(&p, mac, ip);
2107 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2108 if (!rn || !rn->info) {
9c92b5f7
MK
2109 if (!json)
2110 vty_out(vty, "%% Network not in table\n");
d62a17ae 2111 return;
2112 }
2113
9c92b5f7
MK
2114 if (json)
2115 json_paths = json_object_new_array();
2116
d62a17ae 2117 /* Prefix and num paths displayed once per prefix. */
9c92b5f7 2118 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
d62a17ae 2119
2120 /* Display each path for this prefix. */
2121 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
2122 json_object *json_path = NULL;
2123
2124 if (json)
2125 json_path = json_object_new_array();
2126
2127 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
2128 json_path);
2129
2130 if (json)
2131 json_object_array_add(json_paths, json_path);
2132
d62a17ae 2133 path_cnt++;
2134 }
2135
9c92b5f7
MK
2136 if (json) {
2137 if (path_cnt)
2138 json_object_object_add(json, "paths", json_paths);
2139
2140 json_object_int_add(json, "numPaths", path_cnt);
2141 } else {
2142 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2143 path_cnt);
2144 }
520d5d76 2145}
2146
50f74cf1 2147/* Disaplay EVPN routes for a ESI - VTY handler */
2148static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2149 esi_t *esi, json_object *json)
2150{
2151 struct evpnes *es = NULL;
2152
2153 /* locate the ES */
2154 es = bgp_evpn_lookup_es(bgp, esi);
2155 if (!es) {
2156 if (!json)
2157 vty_out(vty, "ESI not found\n");
2158 return;
2159 }
2160
2161 show_esi_routes(bgp, es, vty, json);
2162}
2163
520d5d76 2164/*
2165 * Display EVPN routes for a VNI - vty handler.
2166 * If 'type' is non-zero, only routes matching that type are shown.
2167 * If the vtep_ip is non zero, only routes behind that vtep are shown
2168 */
d62a17ae 2169static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
9c92b5f7
MK
2170 int type, struct in_addr vtep_ip,
2171 json_object *json)
520d5d76 2172{
d62a17ae 2173 struct bgpevpn *vpn;
520d5d76 2174
d62a17ae 2175 /* Locate VNI. */
2176 vpn = bgp_evpn_lookup_vni(bgp, vni);
2177 if (!vpn) {
9c92b5f7
MK
2178 if (!json)
2179 vty_out(vty, "VNI not found\n");
d62a17ae 2180 return;
2181 }
520d5d76 2182
d62a17ae 2183 /* Walk this VNI's route table and display appropriate routes. */
9c92b5f7 2184 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
520d5d76 2185}
2186
2187/*
2188 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2189 * IP (vty handler). By definition, only matching type-2 route will be
2190 * displayed.
2191 */
d62a17ae 2192static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2193 struct prefix_rd *prd, struct ethaddr *mac,
9c92b5f7 2194 struct ipaddr *ip, json_object *json)
d62a17ae 2195{
2196 struct prefix_evpn p;
2197 struct bgp_node *rn;
2198 struct bgp_info *ri;
2199 afi_t afi;
2200 safi_t safi;
d7c0a89a 2201 uint32_t path_cnt = 0;
9c92b5f7
MK
2202 json_object *json_paths = NULL;
2203 char prefix_str[BUFSIZ];
d62a17ae 2204
2205 afi = AFI_L2VPN;
2206 safi = SAFI_EVPN;
2207
2208 /* See if route exists. Look for both non-sticky and sticky. */
2209 build_evpn_type2_prefix(&p, mac, ip);
2210 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2211 (struct prefix *)&p, prd);
2212 if (!rn || !rn->info) {
9c92b5f7
MK
2213 if (!json)
2214 vty_out(vty, "%% Network not in table\n");
d62a17ae 2215 return;
2216 }
2217
9c92b5f7
MK
2218 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
2219 sizeof(prefix_str));
2220
d62a17ae 2221 /* Prefix and num paths displayed once per prefix. */
9c92b5f7
MK
2222 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
2223
2224 if (json)
2225 json_paths = json_object_new_array();
d62a17ae 2226
2227 /* Display each path for this prefix. */
2228 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
2229 json_object *json_path = NULL;
2230
2231 if (json)
2232 json_path = json_object_new_array();
2233
2234 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
2235 json_path);
2236
2237 if (json)
2238 json_object_array_add(json_paths, json_path);
2239
d62a17ae 2240 path_cnt++;
2241 }
2242
9c92b5f7
MK
2243 if (json && path_cnt) {
2244 if (path_cnt)
2245 json_object_object_add(json, prefix_str, json_paths);
2246 json_object_int_add(json, "numPaths", path_cnt);
2247 } else {
2248 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2249 path_cnt);
2250 }
520d5d76 2251}
2252
2253/*
2254 * Display BGP EVPN routing table -- for specific RD (vty handler)
2255 * If 'type' is non-zero, only routes matching that type are shown.
2256 */
d62a17ae 2257static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2258 struct prefix_rd *prd, int type,
2259 json_object *json)
d62a17ae 2260{
2261 struct bgp_node *rd_rn;
2262 struct bgp_table *table;
2263 struct bgp_node *rn;
2264 struct bgp_info *ri;
2265 int rd_header = 1;
2266 afi_t afi;
2267 safi_t safi;
d7c0a89a 2268 uint32_t prefix_cnt, path_cnt;
9c92b5f7
MK
2269 char rd_str[RD_ADDRSTRLEN];
2270 json_object *json_rd = NULL;
2271 int add_rd_to_json = 0;
d62a17ae 2272
2273 afi = AFI_L2VPN;
2274 safi = SAFI_EVPN;
2275 prefix_cnt = path_cnt = 0;
2276
9c92b5f7
MK
2277 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
2278
d62a17ae 2279 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2280 if (!rd_rn)
2281 return;
9c92b5f7 2282
d62a17ae 2283 table = (struct bgp_table *)rd_rn->info;
2284 if (table == NULL)
2285 return;
2286
9c92b5f7
MK
2287 if (json) {
2288 json_rd = json_object_new_object();
2289 json_object_string_add(json_rd, "rd", rd_str);
2290 }
2291
d62a17ae 2292 /* Display all prefixes with this RD. */
2293 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2294 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
9c92b5f7
MK
2295 json_object *json_prefix = NULL;
2296 json_object *json_paths = NULL;
2297 char prefix_str[BUFSIZ];
2298 int add_prefix_to_json = 0;
2299
2300 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
2301 sizeof(prefix_str));
d62a17ae 2302
2303 if (type && evp->prefix.route_type != type)
2304 continue;
2305
9c92b5f7
MK
2306 if (json)
2307 json_prefix = json_object_new_object();
2308
d62a17ae 2309 if (rn->info) {
2310 /* RD header and legend - once overall. */
9c92b5f7 2311 if (rd_header && !json) {
d62a17ae 2312 vty_out(vty,
554cd77a 2313 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
d62a17ae 2314 vty_out(vty,
342dd0c6 2315 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2316 vty_out(vty,
554cd77a 2317 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
d62a17ae 2318 rd_header = 0;
2319 }
2320
2321 /* Prefix and num paths displayed once per prefix. */
2322 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
9c92b5f7 2323 safi, json_prefix);
d62a17ae 2324
2325 prefix_cnt++;
2326 }
2327
9c92b5f7
MK
2328 if (json)
2329 json_paths = json_object_new_array();
2330
d62a17ae 2331 /* Display each path for this prefix. */
2332 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
2333 json_object *json_path = NULL;
2334
2335 if (json)
2336 json_path = json_object_new_array();
2337
d62a17ae 2338 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
9c92b5f7
MK
2339 json_path);
2340
2341 if (json)
2342 json_object_array_add(json_paths, json_path);
2343
d62a17ae 2344 path_cnt++;
9c92b5f7
MK
2345 add_prefix_to_json = 1;
2346 add_rd_to_json = 1;
2347 }
2348
2349 if (json && add_prefix_to_json) {
2350 json_object_object_add(json_prefix, "paths",
2351 json_paths);
2352 json_object_object_add(json_rd, prefix_str,
2353 json_prefix);
d62a17ae 2354 }
2355 }
2356
9c92b5f7
MK
2357 if (json && add_rd_to_json)
2358 json_object_object_add(json, rd_str, json_rd);
2359
2360 if (json) {
2361 json_object_int_add(json, "numPrefix", prefix_cnt);
2362 json_object_int_add(json, "numPaths", path_cnt);
2363 } else {
2364 if (prefix_cnt == 0)
2365 vty_out(vty, "No prefixes exist with this RD%s\n",
2366 type ? " (of requested type)" : "");
2367 else
2368 vty_out(vty,
2369 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2370 prefix_cnt, path_cnt,
2371 type ? " (of requested type)" : "");
2372 }
520d5d76 2373}
2374
2375/*
2376 * Display BGP EVPN routing table - all routes (vty handler).
2377 * If 'type' is non-zero, only routes matching that type are shown.
2378 */
9c92b5f7
MK
2379static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2380 json_object *json)
d62a17ae 2381{
2382 struct bgp_node *rd_rn;
2383 struct bgp_table *table;
2384 struct bgp_node *rn;
2385 struct bgp_info *ri;
2386 int header = 1;
2387 int rd_header;
2388 afi_t afi;
2389 safi_t safi;
d7c0a89a 2390 uint32_t prefix_cnt, path_cnt;
d62a17ae 2391
2392 afi = AFI_L2VPN;
2393 safi = SAFI_EVPN;
2394 prefix_cnt = path_cnt = 0;
2395
2396 /* EVPN routing table is a 2-level table with the first level being
2397 * the RD.
2398 */
2399 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2400 rd_rn = bgp_route_next(rd_rn)) {
9c92b5f7
MK
2401 char rd_str[RD_ADDRSTRLEN];
2402 json_object *json_rd = NULL; /* contains routes for an RD */
2403 int add_rd_to_json = 0;
2dd32217 2404 uint64_t tbl_ver;
9c92b5f7 2405
d62a17ae 2406 table = (struct bgp_table *)rd_rn->info;
2407 if (table == NULL)
2408 continue;
2409
2dd32217 2410 tbl_ver = table->version;
9c92b5f7
MK
2411 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2412 sizeof(rd_str));
2413
2414 if (json) {
2415 json_rd = json_object_new_object();
2416 json_object_string_add(json_rd, "rd", rd_str);
2417 }
2418
d62a17ae 2419 rd_header = 1;
2420
2421 /* Display all prefixes for an RD */
2422 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
9c92b5f7
MK
2423 json_object *json_prefix =
2424 NULL; /* contains prefix under a RD */
2425 json_object *json_paths =
2426 NULL; /* array of paths under a prefix*/
d62a17ae 2427 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
9c92b5f7
MK
2428 char prefix_str[BUFSIZ];
2429 int add_prefix_to_json = 0;
2430
2431 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2432 prefix_str, sizeof(prefix_str));
d62a17ae 2433
2434 if (type && evp->prefix.route_type != type)
2435 continue;
2436
2437 if (rn->info) {
2438 /* Overall header/legend displayed once. */
2439 if (header) {
9c92b5f7 2440 bgp_evpn_show_route_header(vty, bgp,
2dd32217 2441 tbl_ver,
9c92b5f7 2442 json);
d62a17ae 2443 header = 0;
2444 }
2445
2446 /* RD header - per RD. */
2447 if (rd_header) {
9c92b5f7
MK
2448 bgp_evpn_show_route_rd_header(
2449 vty, rd_rn, json);
d62a17ae 2450 rd_header = 0;
2451 }
2452
2453 prefix_cnt++;
2454 }
2455
9c92b5f7
MK
2456 if (json) {
2457 json_prefix = json_object_new_object();
2458 json_paths = json_object_new_array();
2459 json_object_string_add(json_prefix, "prefix",
2460 prefix_str);
2461 json_object_int_add(json_prefix, "prefixLen",
2462 rn->p.prefixlen);
2463 }
2464
d62a17ae 2465 /* For EVPN, the prefix is displayed for each path (to
2466 * fit in
2467 * with code that already exists).
2468 */
2469 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7 2470 json_object *json_path = NULL;
d62a17ae 2471 path_cnt++;
9c92b5f7
MK
2472 add_prefix_to_json = 1;
2473 add_rd_to_json = 1;
2474
2475 if (json)
2476 json_path = json_object_new_array();
2477
d62a17ae 2478 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
9c92b5f7
MK
2479 json_path);
2480
2481 if (json)
2482 json_object_array_add(json_paths,
2483 json_path);
2484 }
2485
2486 if (json && add_prefix_to_json) {
2487 json_object_object_add(json_prefix, "paths",
2488 json_paths);
2489 json_object_object_add(json_rd, prefix_str,
2490 json_prefix);
d62a17ae 2491 }
2492 }
9c92b5f7
MK
2493
2494 if (json && add_rd_to_json)
2495 json_object_object_add(json, rd_str, json_rd);
d62a17ae 2496 }
2497
9c92b5f7
MK
2498 if (json) {
2499 json_object_int_add(json, "numPrefix", prefix_cnt);
2500 json_object_int_add(json, "numPaths", path_cnt);
2501 } else {
2502 if (prefix_cnt == 0) {
2503 vty_out(vty, "No EVPN prefixes %sexist\n",
2504 type ? "(of requested type) " : "");
2505 } else {
2506 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2507 prefix_cnt, path_cnt,
2508 type ? " (of requested type)" : "");
2509 }
2510 }
520d5d76 2511}
2512
50f74cf1 2513/* Display specific ES */
2514static void evpn_show_es(struct vty *vty, struct bgp *bgp, esi_t *esi,
2515 json_object *json)
2516{
2517 struct evpnes *es = NULL;
2518
2519 es = bgp_evpn_lookup_es(bgp, esi);
2520 if (es) {
2521 display_es(vty, es, json);
2522 } else {
2523 if (json) {
2524 vty_out(vty, "{}\n");
2525 } else {
2526 vty_out(vty, "ESI not found\n");
2527 return;
2528 }
2529 }
2530}
2531
2532/* Display all ESs */
2bb9eff4
DS
2533static void evpn_show_all_es(struct vty *vty, struct bgp *bgp,
2534 json_object *json)
50f74cf1 2535{
2536 void *args[2];
2537
2538 if (!json)
2539 vty_out(vty, "%-30s %-6s %-21s %-15s %-6s\n",
2540 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2541
2542 /* print all ESs */
2543 args[0] = vty;
2544 args[1] = json;
2545 hash_iterate(bgp->esihash,
2546 (void (*)(struct hash_backet *, void *))show_es_entry,
2547 args);
2548}
2549
520d5d76 2550/*
2551 * Display specified VNI (vty handler)
2552 */
9c92b5f7
MK
2553static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2554 json_object *json)
520d5d76 2555{
d7c0a89a 2556 uint8_t found = 0;
d62a17ae 2557 struct bgpevpn *vpn;
520d5d76 2558
d62a17ae 2559 vpn = bgp_evpn_lookup_vni(bgp, vni);
4cce389e
MK
2560 if (vpn) {
2561 found = 1;
2562 display_vni(vty, vpn, json);
2563 } else {
2564 struct bgp *bgp_temp;
2565 struct listnode *node = NULL;
2566
2567 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2568 if (bgp_temp->l3vni == vni) {
2569 found = 1;
2570 display_l3vni(vty, bgp_temp, json);
2571 }
2572 }
2573 }
2574
2575 if (!found) {
9c92b5f7
MK
2576 if (json) {
2577 vty_out(vty, "{}\n");
2578 } else {
2579 vty_out(vty, "VNI not found\n");
2580 return;
2581 }
d62a17ae 2582 }
520d5d76 2583}
2584
2585/*
2586 * Display a VNI (upon user query).
2587 */
9c92b5f7
MK
2588static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2589 json_object *json)
520d5d76 2590{
9c92b5f7 2591 void *args[2];
4cce389e
MK
2592 struct bgp *bgp_temp = NULL;
2593 struct listnode *node;
520d5d76 2594
9c92b5f7 2595
4cce389e 2596 if (!json) {
9c92b5f7 2597 vty_out(vty, "Flags: * - Kernel\n");
4cce389e 2598 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
996c9314 2599 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
9c92b5f7
MK
2600 }
2601
4cce389e 2602 /* print all L2 VNIS */
9c92b5f7
MK
2603 args[0] = vty;
2604 args[1] = json;
d62a17ae 2605 hash_iterate(bgp->vnihash,
2606 (void (*)(struct hash_backet *, void *))show_vni_entry,
9c92b5f7 2607 args);
4cce389e
MK
2608
2609 /* print all L3 VNIs */
2610 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
2611 show_l3vni_entry(vty, bgp_temp, json);
520d5d76 2612}
2613
1a98c087
MK
2614/*
2615 * evpn - enable advertisement of default g/w
2616 */
2617static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2618{
2619 if (!vpn) {
2620 if (bgp->advertise_gw_macip)
2621 return;
2622
2623 bgp->advertise_gw_macip = 1;
2624 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2625 } else {
2626 if (vpn->advertise_gw_macip)
2627 return;
2628
2629 vpn->advertise_gw_macip = 1;
2630 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2631 vpn->vni);
2632 }
2633 return;
2634}
2635
2636/*
2637 * evpn - disable advertisement of default g/w
2638 */
2639static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2640 struct bgpevpn *vpn)
2641{
2642 if (!vpn) {
2643 if (!bgp->advertise_gw_macip)
2644 return;
2645
2646 bgp->advertise_gw_macip = 0;
2647 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2648 } else {
2649 if (!vpn->advertise_gw_macip)
2650 return;
2651
2652 vpn->advertise_gw_macip = 0;
2653 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2654 vpn->vni);
2655 }
2656 return;
2657}
2658
486456ca
MK
2659/*
2660 * evpn - enable advertisement of default g/w
2661 */
2662static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
2663 afi_t afi, int add)
2664{
2665 struct prefix ip_prefix;
2666 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
2667
2668 /* form the default prefix 0.0.0.0/0 */
2669 memset(&ip_prefix, 0, sizeof(struct prefix));
2670 ip_prefix.family = afi2family(afi);
2671 ip_prefix.prefixlen = 0;
2672
2673 if (add) {
2674 /* bail if we are already advertising default route */
2675 if (evpn_default_originate_set(bgp_vrf, afi, safi))
2676 return;
2677
2678 if (afi == AFI_IP)
2679 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2680 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2681 else if (afi == AFI_IP6)
2682 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2683 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2684 bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
2685 NULL, afi, safi);
2686 } else {
2687 /* bail out if we havent advertised the default route */
2688 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
2689 return;
2690 if (afi == AFI_IP)
2691 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2692 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2693 else if (afi == AFI_IP6)
2694 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2695 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2696 bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
2697 afi, safi);
2698 }
2699}
2700
31310b25
MK
2701/*
2702 * evpn - enable advertisement of default g/w
2703 */
2704static void evpn_set_advertise_subnet(struct bgp *bgp,
2705 struct bgpevpn *vpn)
2706{
2707 if (vpn->advertise_subnet)
2708 return;
2709
2710 vpn->advertise_subnet = 1;
2711 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2712}
2713
2714/*
2715 * evpn - disable advertisement of default g/w
2716 */
996c9314 2717static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
31310b25
MK
2718{
2719 if (!vpn->advertise_subnet)
2720 return;
2721
2722 vpn->advertise_subnet = 0;
2723 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2724}
2725
7724c0a1 2726/*
2727 * EVPN (VNI advertisement) enabled. Register with zebra.
2728 */
d62a17ae 2729static void evpn_set_advertise_all_vni(struct bgp *bgp)
7724c0a1 2730{
d62a17ae 2731 bgp->advertise_all_vni = 1;
2732 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
7724c0a1 2733}
2734
2735/*
2736 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2737 * cache, EVPN routes (delete and withdraw from peers).
2738 */
d62a17ae 2739static void evpn_unset_advertise_all_vni(struct bgp *bgp)
7724c0a1 2740{
d62a17ae 2741 bgp->advertise_all_vni = 0;
2742 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2743 bgp_evpn_cleanup_on_disable(bgp);
7724c0a1 2744}
bf1061d8
VB
2745
2746/*
2747 * EVPN - use RFC8365 to auto-derive RT
2748 */
2749static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
2750{
2751 bgp->advertise_autort_rfc8365 = 1;
2752 bgp_evpn_handle_autort_change(bgp);
2753}
2754
2755/*
2756 * EVPN - don't use RFC8365 to auto-derive RT
2757 */
2758static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
2759{
2760 bgp->advertise_autort_rfc8365 = 0;
2761 bgp_evpn_handle_autort_change(bgp);
2762}
7724c0a1 2763
2b791107 2764static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
d62a17ae 2765{
06b9f471 2766 char buf1[RD_ADDRSTRLEN];
d62a17ae 2767 char *ecom_str;
2768 struct listnode *node, *nnode;
2769 struct ecommunity *ecom;
2770
2771 if (is_vni_configured(vpn)) {
d62a17ae 2772 vty_out(vty, " vni %d\n", vpn->vni);
2773 if (is_rd_configured(vpn))
2774 vty_out(vty, " rd %s\n",
06b9f471 2775 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
d62a17ae 2776
2777 if (is_import_rt_configured(vpn)) {
2778 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2779 ecom)) {
2780 ecom_str = ecommunity_ecom2str(
2781 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2782 vty_out(vty, " route-target import %s\n",
2783 ecom_str);
2784 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2785 }
2786 }
2787
2788 if (is_export_rt_configured(vpn)) {
2789 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2790 ecom)) {
2791 ecom_str = ecommunity_ecom2str(
2792 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 2793 vty_out(vty, " route-target export %s\n",
d62a17ae 2794 ecom_str);
2795 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2796 }
2797 }
2798
1a98c087
MK
2799 if (vpn->advertise_gw_macip)
2800 vty_out(vty, " advertise-default-gw\n");
2801
31310b25
MK
2802 if (vpn->advertise_subnet)
2803 vty_out(vty, " advertise-subnet\n");
2804
d62a17ae 2805 vty_out(vty, " exit-vni\n");
2806 }
2807}
2808
1a98c087
MK
2809DEFUN (bgp_evpn_advertise_default_gw_vni,
2810 bgp_evpn_advertise_default_gw_vni_cmd,
2811 "advertise-default-gw",
078af92e 2812 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
1a98c087
MK
2813{
2814 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2815 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2816
2817 if (!bgp)
2818 return CMD_WARNING;
2819
1a98c087
MK
2820 evpn_set_advertise_default_gw(bgp, vpn);
2821
2822 return CMD_SUCCESS;
2823}
2824
2825DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2826 no_bgp_evpn_advertise_default_gw_vni_cmd,
2827 "no advertise-default-gw",
2828 NO_STR
2829 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2830{
2831 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2832 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2833
2834 if (!bgp)
2835 return CMD_WARNING;
2836
1a98c087
MK
2837 evpn_unset_advertise_default_gw(bgp, vpn);
2838
2839 return CMD_SUCCESS;
2840}
2841
2842
2843DEFUN (bgp_evpn_advertise_default_gw,
2844 bgp_evpn_advertise_default_gw_cmd,
2845 "advertise-default-gw",
078af92e 2846 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
2847{
2848 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2849
2850 if (!bgp)
2851 return CMD_WARNING;
2852
2853 evpn_set_advertise_default_gw(bgp, NULL);
2854
2855 return CMD_SUCCESS;
2856}
2857
2858DEFUN (no_bgp_evpn_advertise_default_gw,
2859 no_bgp_evpn_advertise_default_gw_cmd,
2860 "no advertise-default-gw",
2861 NO_STR
2862 "Withdraw All default g/w mac-ip routes from EVPN\n")
2863{
2864 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2865
2866 if (!bgp)
2867 return CMD_WARNING;
2868
2869 evpn_unset_advertise_default_gw(bgp, NULL);
2870
2871 return CMD_SUCCESS;
2872}
2873
7724c0a1 2874DEFUN (bgp_evpn_advertise_all_vni,
2875 bgp_evpn_advertise_all_vni_cmd,
2876 "advertise-all-vni",
2877 "Advertise All local VNIs\n")
2878{
d62a17ae 2879 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2880
d62a17ae 2881 if (!bgp)
2882 return CMD_WARNING;
2883 evpn_set_advertise_all_vni(bgp);
2884 return CMD_SUCCESS;
7724c0a1 2885}
2886
2887DEFUN (no_bgp_evpn_advertise_all_vni,
2888 no_bgp_evpn_advertise_all_vni_cmd,
2889 "no advertise-all-vni",
2890 NO_STR
2891 "Advertise All local VNIs\n")
2892{
d62a17ae 2893 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2894
d62a17ae 2895 if (!bgp)
2896 return CMD_WARNING;
2897 evpn_unset_advertise_all_vni(bgp);
2898 return CMD_SUCCESS;
7724c0a1 2899}
2900
bf1061d8
VB
2901DEFUN (bgp_evpn_advertise_autort_rfc8365,
2902 bgp_evpn_advertise_autort_rfc8365_cmd,
2903 "autort rfc8365-compatible",
2904 "Auto-derivation of RT\n"
2905 "Auto-derivation of RT using RFC8365\n")
2906{
2907 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2908
2909 if (!bgp)
2910 return CMD_WARNING;
2911 evpn_set_advertise_autort_rfc8365(bgp);
2912 return CMD_SUCCESS;
2913}
2914
2915DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
2916 no_bgp_evpn_advertise_autort_rfc8365_cmd,
2917 "no autort rfc8365-compatible",
2918 NO_STR
2919 "Auto-derivation of RT\n"
2920 "Auto-derivation of RT using RFC8365\n")
2921{
2922 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2923
2924 if (!bgp)
2925 return CMD_WARNING;
2926 evpn_unset_advertise_autort_rfc8365(bgp);
2927 return CMD_SUCCESS;
2928}
2929
486456ca
MK
2930DEFUN (bgp_evpn_default_originate,
2931 bgp_evpn_default_originate_cmd,
2932 "default-originate <ipv4 | ipv6>",
2933 "originate a default route\n"
2934 "ipv4 address family\n"
2935 "ipv6 address family\n")
2936{
2937 afi_t afi = 0;
2938 int idx_afi = 0;
2939 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2940
2941 if (!bgp_vrf)
2942 return CMD_WARNING;
2943 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2944 evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
2945 return CMD_SUCCESS;
2946}
2947
2948DEFUN (no_bgp_evpn_default_originate,
2949 no_bgp_evpn_default_originate_cmd,
2950 "no default-originate <ipv4 | ipv6>",
2951 NO_STR
2952 "withdraw a default route\n"
2953 "ipv4 address family\n"
2954 "ipv6 address family\n")
2955{
2956 afi_t afi = 0;
2957 int idx_afi = 0;
2958 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
2959
2960 if (!bgp_vrf)
2961 return CMD_WARNING;
2962 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2963 evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
2964 return CMD_SUCCESS;
2965}
2966
689b5101
MK
2967DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
2968 bgp_evpn_advertise_vni_subnet_cmd,
2969 "advertise-subnet",
2970 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
2971{
2972 struct bgp *bgp_vrf = NULL;
2973 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2974 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2975
2976 if (!bgp)
2977 return CMD_WARNING;
2978
31310b25
MK
2979 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
2980 if (!bgp_vrf)
2981 return CMD_WARNING;
2982
31310b25
MK
2983 evpn_set_advertise_subnet(bgp, vpn);
2984 return CMD_SUCCESS;
2985}
2986
689b5101
MK
2987DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
2988 no_bgp_evpn_advertise_vni_subnet_cmd,
2989 "no advertise-subnet",
2990 NO_STR
2991 "Advertise All local VNIs\n")
31310b25
MK
2992{
2993 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2994 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2995
2996 if (!bgp)
2997 return CMD_WARNING;
2998
31310b25
MK
2999 evpn_unset_advertise_subnet(bgp, vpn);
3000 return CMD_SUCCESS;
3001}
3002
342dd0c6 3003DEFUN (bgp_evpn_advertise_type5,
3004 bgp_evpn_advertise_type5_cmd,
53c84f78 3005 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 3006 "Advertise prefix routes\n"
053905d2 3007 BGP_AFI_HELP_STR
53c84f78
MK
3008 BGP_SAFI_HELP_STR
3009 "route-map for filtering specific routes\n"
3010 "Name of the route map\n")
342dd0c6 3011{
3012 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3013 int idx_afi = 0;
3014 int idx_safi = 0;
53c84f78 3015 int idx_rmap = 0;
053905d2
MK
3016 afi_t afi = 0;
3017 safi_t safi = 0;
53c84f78
MK
3018 int ret = 0;
3019 int rmap_changed = 0;
053905d2
MK
3020
3021 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3022 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
53c84f78
MK
3023 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3024 if (ret) {
3025 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3026 rmap_changed = 1;
3027 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
3028 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3029 != 0)
53c84f78
MK
3030 rmap_changed = 1;
3031 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3032 rmap_changed = 1;
3033 }
053905d2 3034
e779dc76 3035 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3036 vty_out(vty,
3037 "%%only ipv4 or ipv6 address families are supported");
342dd0c6 3038 return CMD_WARNING;
3039 }
3040
053905d2
MK
3041 if (safi != SAFI_UNICAST) {
3042 vty_out(vty,
3043 "%%only ipv4 unicast or ipv6 unicast are supported");
3044 return CMD_WARNING;
3045 }
3046
3047 if (afi == AFI_IP) {
342dd0c6 3048
3049 /* if we are already advertising ipv4 prefix as type-5
523cafc4 3050 * nothing to do
3051 */
154faa50
MK
3052 if (!rmap_changed &&
3053 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3054 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
53c84f78 3055 return CMD_WARNING;
154faa50
MK
3056 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3057 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3058 } else {
3059
3060 /* if we are already advertising ipv6 prefix as type-5
523cafc4 3061 * nothing to do
3062 */
154faa50
MK
3063 if (!rmap_changed &&
3064 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3065 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
53c84f78 3066 return CMD_WARNING;
154faa50
MK
3067 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3068 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
53c84f78
MK
3069 }
3070
3071 if (rmap_changed) {
3072 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3073 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3074 XFREE(MTYPE_ROUTE_MAP_NAME,
3075 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3076 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3077 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
342dd0c6 3078 }
3079 }
53c84f78
MK
3080
3081 /* set the route-map for advertise command */
3082 if (ret && argv[idx_rmap + 1]->arg) {
3083 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 3084 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
3085 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3086 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3087 }
3088
3089 /* advertise type-5 routes */
3090 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 3091 return CMD_SUCCESS;
3092}
3093
3094DEFUN (no_bgp_evpn_advertise_type5,
3095 no_bgp_evpn_advertise_type5_cmd,
053905d2 3096 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
342dd0c6 3097 NO_STR
3098 "Advertise prefix routes\n"
053905d2
MK
3099 BGP_AFI_HELP_STR
3100 BGP_SAFI_HELP_STR)
342dd0c6 3101{
3102 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3103 int idx_afi = 0;
3104 int idx_safi = 0;
3105 afi_t afi = 0;
3106 safi_t safi = 0;
3107
3108 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3109 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3110
1ec31309 3111 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2
MK
3112 vty_out(vty,
3113 "%%only ipv4 or ipv6 address families are supported");
3114 return CMD_WARNING;
3115 }
3116
3117 if (safi != SAFI_UNICAST) {
3118 vty_out(vty,
3119 "%%only ipv4 unicast or ipv6 unicast are supported");
342dd0c6 3120 return CMD_WARNING;
3121 }
3122
053905d2 3123 if (afi == AFI_IP) {
342dd0c6 3124
fdf19f06 3125 /* if we are not advertising ipv4 prefix as type-5
523cafc4 3126 * nothing to do
3127 */
154faa50
MK
3128 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3129 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
053905d2 3130 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50
MK
3131 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3132 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
342dd0c6 3133 }
3134 } else {
3135
fdf19f06 3136 /* if we are not advertising ipv6 prefix as type-5
523cafc4 3137 * nothing to do
3138 */
154faa50
MK
3139 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3140 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
053905d2 3141 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4f7497e 3142 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
154faa50 3143 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
342dd0c6 3144 }
3145 }
53c84f78
MK
3146
3147 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3148 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3149 XFREE(MTYPE_ROUTE_MAP_NAME,
3150 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3151 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3152 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3153 }
3154
342dd0c6 3155 return CMD_SUCCESS;
3156}
3157
f2d62262 3158/*
3159 * Display VNI information - for all or a specific VNI
3160 */
9c92b5f7
MK
3161DEFUN(show_bgp_l2vpn_evpn_vni,
3162 show_bgp_l2vpn_evpn_vni_cmd,
3163 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
3164 SHOW_STR
3165 BGP_STR
3166 L2VPN_HELP_STR
3167 EVPN_HELP_STR
3168 "Show VNI\n"
3169 "VNI number\n"
3170 JSON_STR)
520d5d76 3171{
4cce389e 3172 struct bgp *bgp_def;
f2d62262 3173 vni_t vni;
3174 int idx = 0;
d7c0a89a 3175 uint8_t uj = 0;
9c92b5f7 3176 json_object *json = NULL;
d7c0a89a
QY
3177 uint32_t num_l2vnis = 0;
3178 uint32_t num_l3vnis = 0;
d4454626 3179 uint32_t num_vnis = 0;
4cce389e
MK
3180 struct listnode *node = NULL;
3181 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
3182
3183 uj = use_json(argc, argv);
520d5d76 3184
4cce389e
MK
3185 bgp_def = bgp_get_default();
3186 if (!bgp_def)
d62a17ae 3187 return CMD_WARNING;
520d5d76 3188
f2d62262 3189 if (!argv_find(argv, argc, "evpn", &idx))
3190 return CMD_WARNING;
3191
9c92b5f7
MK
3192 if (uj)
3193 json = json_object_new_object();
1a98c087 3194
9c92b5f7 3195 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e
MK
3196
3197 num_l2vnis = hashcount(bgp_def->vnihash);
4cce389e
MK
3198
3199 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3200 if (bgp_temp->l3vni)
3201 num_l3vnis++;
3202 }
d4454626 3203 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
3204 if (uj) {
3205 json_object_string_add(json, "advertiseGatewayMacip",
4cce389e 3206 bgp_def->advertise_gw_macip
9c92b5f7
MK
3207 ? "Enabled"
3208 : "Disabled");
3209 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
3210 is_evpn_enabled() ? "Enabled"
3211 : "Disabled");
d4454626 3212 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
3213 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3214 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
3215 } else {
3216 vty_out(vty, "Advertise Gateway Macip: %s\n",
4cce389e 3217 bgp_def->advertise_gw_macip ? "Enabled"
996c9314 3218 : "Disabled");
9c92b5f7 3219 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 3220 is_evpn_enabled() ? "Enabled" : "Disabled");
4cce389e
MK
3221 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3222 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 3223 }
4cce389e 3224 evpn_show_all_vnis(vty, bgp_def, json);
f2d62262 3225 } else {
9c92b5f7
MK
3226 int vni_idx = 0;
3227
3228 if (!argv_find(argv, argc, "vni", &vni_idx))
3229 return CMD_WARNING;
3230
f2d62262 3231 /* Display specific VNI */
9c92b5f7 3232 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4cce389e 3233 evpn_show_vni(vty, bgp_def, vni, json);
9c92b5f7
MK
3234 }
3235
3236 if (uj) {
3237 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3238 json, JSON_C_TO_STRING_PRETTY));
3239 json_object_free(json);
f2d62262 3240 }
520d5d76 3241
d62a17ae 3242 return CMD_SUCCESS;
520d5d76 3243}
3244
50f74cf1 3245/* Disaply ES */
3246DEFUN(show_bgp_l2vpn_evpn_es,
3247 show_bgp_l2vpn_evpn_es_cmd,
3248 "show bgp l2vpn evpn es [ESI] [json]",
3249 SHOW_STR
3250 BGP_STR
3251 L2VPN_HELP_STR
3252 EVPN_HELP_STR
3253 "ethernet-Segment\n"
b482a7fd
QY
3254 "Ethernet-Segment Identifier\n"
3255 JSON_STR)
50f74cf1 3256{
3257 int idx = 0;
3258 uint8_t uj = 0;
6a527b2f 3259 esi_t esi;
50f74cf1 3260 json_object *json = NULL;
3261 struct bgp *bgp = NULL;
3262
6a527b2f 3263 memset(&esi, 0, sizeof(esi));
50f74cf1 3264 uj = use_json(argc, argv);
3265
3266 bgp = bgp_get_default();
3267 if (!bgp)
3268 return CMD_WARNING;
3269
3270 if (!argv_find(argv, argc, "evpn", &idx))
3271 return CMD_WARNING;
3272
3273 if ((uj && argc == ((idx + 1) + 2)) ||
3274 (!uj && argc == (idx + 1) + 1)) {
3275
3276 /* show all ESs */
3277 evpn_show_all_es(vty, bgp, json);
3278 } else {
3279
3280 /* show a specific ES */
3281
3282 /* get the ESI - ESI-ID is at argv[5] */
3283 if (!str_to_esi(argv[idx + 2]->arg, &esi)) {
3284 vty_out(vty, "%% Malformed ESI\n");
3285 return CMD_WARNING;
3286 }
3287 evpn_show_es(vty, bgp, &esi, json);
3288 }
3289
3290 if (uj) {
3291 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3292 json, JSON_C_TO_STRING_PRETTY));
3293 json_object_free(json);
3294 }
3295
3296 return CMD_SUCCESS;
3297}
3298
f2d62262 3299/*
3300 * Display EVPN neighbor summary.
3301 */
9c92b5f7
MK
3302DEFUN(show_bgp_l2vpn_evpn_summary,
3303 show_bgp_l2vpn_evpn_summary_cmd,
ee851c8c 3304 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
9c92b5f7
MK
3305 SHOW_STR
3306 BGP_STR
ee851c8c
MK
3307 "bgp vrf\n"
3308 "vrf name\n"
9c92b5f7
MK
3309 L2VPN_HELP_STR
3310 EVPN_HELP_STR
3311 "Summary of BGP neighbor status\n"
3312 JSON_STR)
520d5d76 3313{
ee851c8c 3314 int idx_vrf = 0;
d7c0a89a 3315 uint8_t uj = use_json(argc, argv);
ee851c8c
MK
3316 char *vrf = NULL;
3317
3318 if (argv_find(argv, argc, "vrf", &idx_vrf))
3319 vrf = argv[++idx_vrf]->arg;
3320 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, uj);
520d5d76 3321}
3322
f2d62262 3323/*
3324 * Display global EVPN routing table.
3325 */
60466a63
QY
3326DEFUN(show_bgp_l2vpn_evpn_route,
3327 show_bgp_l2vpn_evpn_route_cmd,
50f74cf1 3328 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
9c92b5f7
MK
3329 SHOW_STR
3330 BGP_STR
3331 L2VPN_HELP_STR
3332 EVPN_HELP_STR
3333 "EVPN route information\n"
3334 "Specify Route type\n"
3335 "MAC-IP (Type-2) route\n"
3336 "Multicast (Type-3) route\n"
50f74cf1 3337 "Ethernet Segment (type-4) route \n"
3338 "Prefix (type-5 )route\n"
9c92b5f7 3339 JSON_STR)
520d5d76 3340{
d62a17ae 3341 struct bgp *bgp;
8367c327 3342 int type_idx = 0;
d62a17ae 3343 int type = 0;
d7c0a89a 3344 uint8_t uj = 0;
9c92b5f7
MK
3345 json_object *json = NULL;
3346
3347 uj = use_json(argc, argv);
520d5d76 3348
d62a17ae 3349 bgp = bgp_get_default();
3350 if (!bgp)
3351 return CMD_WARNING;
520d5d76 3352
9c92b5f7
MK
3353 if (uj)
3354 json = json_object_new_object();
f2d62262 3355
9c92b5f7
MK
3356 /* get the type */
3357 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3358 /* Specific type is requested */
9c92b5f7 3359 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3360 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3361 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3362 type = BGP_EVPN_IMET_ROUTE;
50f74cf1 3363 else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
3364 type = BGP_EVPN_ES_ROUTE;
47b71369
MK
3365 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3366 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3367 else
3368 return CMD_WARNING;
3369 }
520d5d76 3370
9c92b5f7
MK
3371 evpn_show_all_routes(vty, bgp, type, json);
3372
3373 if (uj) {
3374 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3375 json, JSON_C_TO_STRING_PRETTY));
3376 json_object_free(json);
3377 }
d62a17ae 3378 return CMD_SUCCESS;
520d5d76 3379}
3380
f2d62262 3381/*
3382 * Display global EVPN routing table for specific RD.
3383 */
60466a63
QY
3384DEFUN(show_bgp_l2vpn_evpn_route_rd,
3385 show_bgp_l2vpn_evpn_route_rd_cmd,
50f74cf1 3386 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
9c92b5f7
MK
3387 SHOW_STR
3388 BGP_STR
3389 L2VPN_HELP_STR
3390 EVPN_HELP_STR
3391 "EVPN route information\n"
3392 "Route Distinguisher\n"
3393 "ASN:XX or A.B.C.D:XX\n"
3394 "Specify Route type\n"
3395 "MAC-IP (Type-2) route\n"
3396 "Multicast (Type-3) route\n"
50f74cf1 3397 "Ethernet Segment route\n"
aa9db9e6 3398 "Prefix route\n"
9c92b5f7 3399 JSON_STR)
520d5d76 3400{
d62a17ae 3401 struct bgp *bgp;
3402 int ret;
3403 struct prefix_rd prd;
3404 int type = 0;
9c92b5f7
MK
3405 int rd_idx = 0;
3406 int type_idx = 0;
3407 int uj = 0;
3408 json_object *json = NULL;
520d5d76 3409
d62a17ae 3410 bgp = bgp_get_default();
3411 if (!bgp)
3412 return CMD_WARNING;
520d5d76 3413
9c92b5f7
MK
3414 /* check if we need json output */
3415 uj = use_json(argc, argv);
3416 if (uj)
3417 json = json_object_new_object();
f2d62262 3418
9c92b5f7
MK
3419 /* get the RD */
3420 if (argv_find(argv, argc, "rd", &rd_idx)) {
3421 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3422
3423 if (!ret) {
3424 vty_out(vty, "%% Malformed Route Distinguisher\n");
3425 return CMD_WARNING;
3426 }
d62a17ae 3427 }
520d5d76 3428
9c92b5f7
MK
3429 /* get the type */
3430 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 3431 /* Specific type is requested */
9c92b5f7 3432 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 3433 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 3434 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 3435 type = BGP_EVPN_IMET_ROUTE;
aa9db9e6
MK
3436 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3437 type = BGP_EVPN_IP_PREFIX_ROUTE;
d62a17ae 3438 else
3439 return CMD_WARNING;
3440 }
520d5d76 3441
9c92b5f7
MK
3442 evpn_show_route_rd(vty, bgp, &prd, type, json);
3443
3444 if (uj) {
3445 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3446 json, JSON_C_TO_STRING_PRETTY));
3447 json_object_free(json);
3448 }
3449
d62a17ae 3450 return CMD_SUCCESS;
520d5d76 3451}
3452
f2d62262 3453/*
3454 * Display global EVPN routing table for specific RD and MACIP.
3455 */
9c92b5f7
MK
3456DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3457 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
d114b977 3458 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
9c92b5f7
MK
3459 SHOW_STR
3460 BGP_STR
3461 L2VPN_HELP_STR
3462 EVPN_HELP_STR
3463 "EVPN route information\n"
3464 "Route Distinguisher\n"
3465 "ASN:XX or A.B.C.D:XX\n"
3466 "MAC\n"
3467 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3468 "IP\n"
3469 "IP address (IPv4 or IPv6)\n"
3470 JSON_STR)
3471{
0291c246
MK
3472 struct bgp *bgp;
3473 int ret;
3474 struct prefix_rd prd;
3475 struct ethaddr mac;
3476 struct ipaddr ip;
3477 int rd_idx = 0;
3478 int mac_idx = 0;
3479 int ip_idx = 0;
3480 int uj = 0;
3481 json_object *json = NULL;
9c92b5f7
MK
3482
3483 memset(&mac, 0, sizeof(struct ethaddr));
3484 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 3485
3486 bgp = bgp_get_default();
3487 if (!bgp)
3488 return CMD_WARNING;
3489
9c92b5f7
MK
3490 /* check if we need json output */
3491 uj = use_json(argc, argv);
3492 if (uj)
3493 json = json_object_new_object();
f2d62262 3494
9c92b5f7
MK
3495 /* get the prd */
3496 if (argv_find(argv, argc, "rd", &rd_idx)) {
3497 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3498 if (!ret) {
3499 vty_out(vty, "%% Malformed Route Distinguisher\n");
3500 return CMD_WARNING;
3501 }
d62a17ae 3502 }
9c92b5f7
MK
3503
3504 /* get the mac */
3505 if (argv_find(argv, argc, "mac", &mac_idx)) {
3506 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
3507 vty_out(vty, "%% Malformed MAC address\n");
3508 return CMD_WARNING;
3509 }
d62a17ae 3510 }
9c92b5f7
MK
3511
3512 /* get the ip if specified */
3513 if (argv_find(argv, argc, "ip", &ip_idx)) {
3514 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 3515 vty_out(vty, "%% Malformed IP address\n");
3516 return CMD_WARNING;
3517 }
3518 }
3519
9c92b5f7
MK
3520 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
3521
3522 if (uj) {
3523 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3524 json, JSON_C_TO_STRING_PRETTY));
3525 json_object_free(json);
3526 }
3527
d62a17ae 3528 return CMD_SUCCESS;
520d5d76 3529}
3530
50f74cf1 3531/* Display per ESI routing table */
3532DEFUN(show_bgp_l2vpn_evpn_route_esi,
3533 show_bgp_l2vpn_evpn_route_esi_cmd,
3534 "show bgp l2vpn evpn route esi ESI [json]",
3535 SHOW_STR
3536 BGP_STR
3537 L2VPN_HELP_STR
3538 EVPN_HELP_STR
3539 "EVPN route information\n"
3540 "Ethernet Segment Identifier\n"
3541 "ESI ID\n"
3542 JSON_STR)
3543{
3544 int uj = 0;
6a527b2f 3545 esi_t esi;
50f74cf1 3546 struct bgp *bgp = NULL;
3547 json_object *json = NULL;
3548
6a527b2f 3549 memset(&esi, 0, sizeof(esi));
50f74cf1 3550 bgp = bgp_get_default();
3551 if (!bgp)
3552 return CMD_WARNING;
3553
3554 uj = use_json(argc, argv);
3555 if (uj)
3556 json = json_object_new_object();
3557
3558 /* get the ESI - ESI-ID is at argv[6] */
3559 if (!str_to_esi(argv[6]->arg, &esi)) {
3560 vty_out(vty, "%% Malformed ESI\n");
3561 return CMD_WARNING;
3562 }
3563
3564 evpn_show_routes_esi(vty, bgp, &esi, json);
3565
3566 if (uj) {
3567 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3568 json, JSON_C_TO_STRING_PRETTY));
3569 json_object_free(json);
3570 }
3571
3572 return CMD_SUCCESS;
3573}
3574
3575
f2d62262 3576/*
3577 * Display per-VNI EVPN routing table.
3578 */
9c92b5f7
MK
3579DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
3580 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3581 SHOW_STR
3582 BGP_STR
3583 L2VPN_HELP_STR
3584 EVPN_HELP_STR
3585 "EVPN route information\n"
3586 "VXLAN Network Identifier\n"
3587 "VNI number\n"
3588 "Specify Route type\n"
3589 "MAC-IP (Type-2) route\n"
3590 "Multicast (Type-3) route\n"
3591 "Remote VTEP\n"
3592 "Remote VTEP IP address\n"
3593 JSON_STR)
520d5d76 3594{
d62a17ae 3595 vni_t vni;
3596 struct bgp *bgp;
3597 struct in_addr vtep_ip;
3598 int type = 0;
f2d62262 3599 int idx = 0;
9c92b5f7
MK
3600 int uj = 0;
3601 json_object *json = NULL;
d62a17ae 3602
3603 bgp = bgp_get_default();
3604 if (!bgp)
3605 return CMD_WARNING;
3606
9c92b5f7
MK
3607 /* check if we need json output */
3608 uj = use_json(argc, argv);
3609 if (uj)
3610 json = json_object_new_object();
3611
f2d62262 3612 if (!argv_find(argv, argc, "evpn", &idx))
3613 return CMD_WARNING;
3614
d62a17ae 3615 vtep_ip.s_addr = 0;
3616
f2d62262 3617 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 3618
9c92b5f7
MK
3619 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
3620 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 3621 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
3622 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 3623 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 3624 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 3625 type = BGP_EVPN_IMET_ROUTE;
3626 else
3627 return CMD_WARNING;
f2d62262 3628 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
3629 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3630 vty_out(vty, "%% Malformed VTEP IP address\n");
3631 return CMD_WARNING;
3632 }
3633 } else
3634 return CMD_WARNING;
3635 }
3636
9c92b5f7
MK
3637 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
3638
3639 if (uj) {
3640 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3641 json, JSON_C_TO_STRING_PRETTY));
3642 json_object_free(json);
3643 }
3644
d62a17ae 3645 return CMD_SUCCESS;
520d5d76 3646}
3647
f2d62262 3648/*
3649 * Display per-VNI EVPN routing table for specific MACIP.
3650 */
9c92b5f7
MK
3651DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
3652 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
3653 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3654 SHOW_STR
3655 BGP_STR
3656 L2VPN_HELP_STR
3657 EVPN_HELP_STR
3658 "EVPN route information\n"
3659 "VXLAN Network Identifier\n"
3660 "VNI number\n"
3661 "MAC\n"
3662 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3663 "IP\n"
3664 "IP address (IPv4 or IPv6)\n"
3665 JSON_STR)
520d5d76 3666{
d62a17ae 3667 vni_t vni;
3668 struct bgp *bgp;
3669 struct ethaddr mac;
3670 struct ipaddr ip;
f2d62262 3671 int idx = 0;
9c92b5f7
MK
3672 int uj = 0;
3673 json_object *json = NULL;
d62a17ae 3674
3675 bgp = bgp_get_default();
3676 if (!bgp)
3677 return CMD_WARNING;
3678
9c92b5f7
MK
3679 /* check if we need json output */
3680 uj = use_json(argc, argv);
3681 if (uj)
3682 json = json_object_new_object();
3683
f2d62262 3684 if (!argv_find(argv, argc, "evpn", &idx))
3685 return CMD_WARNING;
3686
9c92b5f7 3687 /* get the VNI */
f2d62262 3688 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3689
3690 /* get the mac */
f2d62262 3691 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 3692 vty_out(vty, "%% Malformed MAC address\n");
3693 return CMD_WARNING;
3694 }
9c92b5f7
MK
3695
3696 /* get the ip */
d62a17ae 3697 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
3698 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
3699 || (uj
3700 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 3701 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 3702 vty_out(vty, "%% Malformed IP address\n");
3703 return CMD_WARNING;
3704 }
3705 }
3706
9c92b5f7
MK
3707 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
3708
3709 if (uj) {
3710 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3711 json, JSON_C_TO_STRING_PRETTY));
3712 json_object_free(json);
3713 }
3714
d62a17ae 3715 return CMD_SUCCESS;
520d5d76 3716}
3717
f2d62262 3718/*
3719 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3720 */
9c92b5f7
MK
3721DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3722 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3723 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3724 SHOW_STR
3725 BGP_STR
3726 L2VPN_HELP_STR
3727 EVPN_HELP_STR
3728 "EVPN route information\n"
3729 "VXLAN Network Identifier\n"
3730 "VNI number\n"
3731 "Multicast (Type-3) route\n"
3732 "Originating Router IP address\n"
3733 JSON_STR)
520d5d76 3734{
d62a17ae 3735 vni_t vni;
3736 struct bgp *bgp;
3737 int ret;
3738 struct in_addr orig_ip;
f2d62262 3739 int idx = 0;
9c92b5f7
MK
3740 int uj = 0;
3741 json_object *json = NULL;
520d5d76 3742
d62a17ae 3743 bgp = bgp_get_default();
3744 if (!bgp)
3745 return CMD_WARNING;
520d5d76 3746
9c92b5f7
MK
3747 /* check if we need json output */
3748 uj = use_json(argc, argv);
3749 if (uj)
3750 json = json_object_new_object();
3751
f2d62262 3752 if (!argv_find(argv, argc, "evpn", &idx))
3753 return CMD_WARNING;
3754
9c92b5f7 3755 /* get the VNI */
f2d62262 3756 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
3757
3758 /* get the ip */
f2d62262 3759 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 3760 if (!ret) {
3761 vty_out(vty, "%% Malformed Originating Router IP address\n");
3762 return CMD_WARNING;
3763 }
520d5d76 3764
9c92b5f7
MK
3765 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3766
3767 if (uj) {
3768 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3769 json, JSON_C_TO_STRING_PRETTY));
3770 json_object_free(json);
3771 }
3772
d62a17ae 3773 return CMD_SUCCESS;
520d5d76 3774}
3775
f2d62262 3776/*
3777 * Display per-VNI EVPN routing table - for all VNIs.
3778 */
60466a63
QY
3779DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3780 show_bgp_l2vpn_evpn_route_vni_all_cmd,
9c92b5f7
MK
3781 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3782 SHOW_STR
3783 BGP_STR
3784 L2VPN_HELP_STR
3785 EVPN_HELP_STR
3786 "EVPN route information\n"
3787 "VXLAN Network Identifier\n"
3788 "All VNIs\n"
3789 "Remote VTEP\n"
3790 "Remote VTEP IP address\n"
3791 JSON_STR)
520d5d76 3792{
d62a17ae 3793 struct bgp *bgp;
3794 struct in_addr vtep_ip;
f2d62262 3795 int idx = 0;
9c92b5f7
MK
3796 int uj = 0;
3797 json_object *json = NULL;
520d5d76 3798
d62a17ae 3799 bgp = bgp_get_default();
3800 if (!bgp)
3801 return CMD_WARNING;
520d5d76 3802
9c92b5f7
MK
3803 /* check if we need json output */
3804 uj = use_json(argc, argv);
3805 if (uj)
3806 json = json_object_new_object();
3807
f2d62262 3808 if (!argv_find(argv, argc, "evpn", &idx))
3809 return CMD_WARNING;
3810
d62a17ae 3811 vtep_ip.s_addr = 0;
9c92b5f7
MK
3812 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3813 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
f2d62262 3814 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 3815 vty_out(vty, "%% Malformed VTEP IP address\n");
3816 return CMD_WARNING;
3817 }
3818 }
520d5d76 3819
9c92b5f7
MK
3820 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3821
3822 if (uj) {
3823 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3824 json, JSON_C_TO_STRING_PRETTY));
3825 json_object_free(json);
3826 }
3827
d62a17ae 3828 return CMD_SUCCESS;
520d5d76 3829}
3830
10ebe1ab
MK
3831/*
3832 * Display EVPN import route-target hash table
3833 */
3834DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3835 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3836 "show bgp l2vpn evpn vrf-import-rt [json]",
3837 SHOW_STR
3838 BGP_STR
3839 L2VPN_HELP_STR
3840 EVPN_HELP_STR
3841 "Show vrf import route target\n"
3842 JSON_STR)
3843{
d7c0a89a 3844 uint8_t uj = 0;
181c08c6 3845 struct bgp *bgp_def = NULL;
10ebe1ab
MK
3846 json_object *json = NULL;
3847
3848 bgp_def = bgp_get_default();
3849 if (!bgp_def)
3850 return CMD_WARNING;
3851
3852 uj = use_json(argc, argv);
3853 if (uj)
3854 json = json_object_new_object();
3855
3856 evpn_show_vrf_import_rts(vty, bgp_def, json);
3857
3858 if (uj) {
3859 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3860 json, JSON_C_TO_STRING_PRETTY));
3861 json_object_free(json);
3862 }
3863
3864 return CMD_SUCCESS;
3865}
3866
f2d62262 3867/*
3868 * Display EVPN import route-target hash table
3869 */
60466a63
QY
3870DEFUN(show_bgp_l2vpn_evpn_import_rt,
3871 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
3872 "show bgp l2vpn evpn import-rt [json]",
3873 SHOW_STR
3874 BGP_STR
3875 L2VPN_HELP_STR
3876 EVPN_HELP_STR
3877 "Show import route target\n"
3878 JSON_STR)
520d5d76 3879{
d62a17ae 3880 struct bgp *bgp;
d7c0a89a 3881 uint8_t uj = 0;
9c92b5f7 3882 json_object *json = NULL;
520d5d76 3883
d62a17ae 3884 bgp = bgp_get_default();
3885 if (!bgp)
3886 return CMD_WARNING;
520d5d76 3887
9c92b5f7
MK
3888 uj = use_json(argc, argv);
3889 if (uj)
3890 json = json_object_new_object();
3891
3892 evpn_show_import_rts(vty, bgp, json);
3893
3894 if (uj) {
3895 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3896 json, JSON_C_TO_STRING_PRETTY));
3897 json_object_free(json);
3898 }
3899
d62a17ae 3900 return CMD_SUCCESS;
520d5d76 3901}
3902
50f74cf1 3903DEFUN(test_adv_evpn_type4_route,
3904 test_adv_evpn_type4_route_cmd,
3905 "advertise es ESI",
3906 "Advertise EVPN ES route\n"
3907 "Ethernet-segment\n"
3908 "Ethernet-Segment Identifier\n")
3909{
3910 int ret = 0;
3911 esi_t esi;
3912 struct bgp *bgp;
3913 struct ipaddr vtep_ip;
3914
3915 bgp = bgp_get_default();
3916 if (!bgp) {
3917 vty_out(vty, "%%Default BGP instance not yet created\n");
3918 return CMD_WARNING;
3919 }
3920
2bb9eff4 3921 if (!str_to_esi(argv[2]->arg, &esi)) {
50f74cf1 3922 vty_out(vty, "%%Malformed ESI\n");
3923 return CMD_WARNING;
3924 }
3925
3926 vtep_ip.ipa_type = IPADDR_V4;
3927 vtep_ip.ipaddr_v4 = bgp->router_id;
3928
3929 ret = bgp_evpn_local_es_add(bgp, &esi, &vtep_ip);
3930 if (ret == -1) {
3931 vty_out(vty, "%%Failed to EVPN advertise type-4 route\n");
3932 return CMD_WARNING;
3933 }
3934 return CMD_SUCCESS;
3935}
3936
3937DEFUN(test_withdraw_evpn_type4_route,
3938 test_withdraw_evpn_type4_route_cmd,
3939 "withdraw es ESI",
3940 "Advertise EVPN ES route\n"
3941 "Ethernet-segment\n"
3942 "Ethernet-Segment Identifier\n")
3943{
3944 int ret = 0;
3945 esi_t esi;
3946 struct bgp *bgp;
3947 struct ipaddr vtep_ip;
3948
3949 bgp = bgp_get_default();
3950 if (!bgp) {
3951 vty_out(vty, "%%Default BGP instance not yet created\n");
3952 return CMD_WARNING;
3953 }
3954
3955 if (!bgp->peer_self) {
3956 vty_out(vty, "%%BGP instance doesnt have self peer\n");
3957 return CMD_WARNING;
3958 }
3959
2bb9eff4 3960 if (!str_to_esi(argv[2]->arg, &esi)) {
50f74cf1 3961 vty_out(vty, "%%Malformed ESI\n");
3962 return CMD_WARNING;
3963 }
3964
3965 vtep_ip.ipa_type = IPADDR_V4;
3966 vtep_ip.ipaddr_v4 = bgp->router_id;
3967 ret = bgp_evpn_local_es_del(bgp, &esi, &vtep_ip);
3968 if (ret == -1) {
3969 vty_out(vty, "%%Failed to withdraw EVPN type-4 route\n");
3970 return CMD_WARNING;
3971 }
3972 return CMD_SUCCESS;
3973}
3974
5014d96f
DW
3975ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3976 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3977 "Show VNI\n"
3978 "VNI number\n")
3979
3980ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3981 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 3982 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
3983
3984ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3985 "show bgp evpn route [type <macip|multicast>]",
3986 SHOW_STR BGP_STR EVPN_HELP_STR
3987 "EVPN route information\n"
3988 "Specify Route type\n"
3989 "MAC-IP (Type-2) route\n"
3990 "Multicast (Type-3) route\n")
3991
3992ALIAS_HIDDEN(
3993 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
d114b977 3994 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
5014d96f
DW
3995 SHOW_STR BGP_STR EVPN_HELP_STR
3996 "EVPN route information\n"
3997 "Route Distinguisher\n"
3998 "ASN:XX or A.B.C.D:XX\n"
3999 "Specify Route type\n"
4000 "MAC-IP (Type-2) route\n"
4001 "Multicast (Type-3) route\n")
4002
4003ALIAS_HIDDEN(
4004 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 4005 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f
DW
4006 SHOW_STR BGP_STR EVPN_HELP_STR
4007 "EVPN route information\n"
4008 "Route Distinguisher\n"
4009 "ASN:XX or A.B.C.D:XX\n"
4010 "MAC\n"
4011 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4012 "IP\n"
4013 "IP address (IPv4 or IPv6)\n")
4014
4015ALIAS_HIDDEN(
4016 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
4017 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
4018 SHOW_STR BGP_STR EVPN_HELP_STR
4019 "EVPN route information\n"
4020 "VXLAN Network Identifier\n"
4021 "VNI number\n"
4022 "Specify Route type\n"
4023 "MAC-IP (Type-2) route\n"
4024 "Multicast (Type-3) route\n"
4025 "Remote VTEP\n"
4026 "Remote VTEP IP address\n")
4027
4028ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4029 show_bgp_evpn_route_vni_macip_cmd,
4030 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
4031 SHOW_STR BGP_STR EVPN_HELP_STR
4032 "EVPN route information\n"
4033 "VXLAN Network Identifier\n"
4034 "VNI number\n"
4035 "MAC\n"
4036 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4037 "IP\n"
4038 "IP address (IPv4 or IPv6)\n")
4039
4040ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4041 show_bgp_evpn_route_vni_multicast_cmd,
4042 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
4043 SHOW_STR BGP_STR EVPN_HELP_STR
4044 "EVPN route information\n"
4045 "VXLAN Network Identifier\n"
4046 "VNI number\n"
4047 "Multicast (Type-3) route\n"
4048 "Originating Router IP address\n")
4049
4050ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
4051 "show bgp evpn route vni all [vtep A.B.C.D]",
4052 SHOW_STR BGP_STR EVPN_HELP_STR
4053 "EVPN route information\n"
4054 "VXLAN Network Identifier\n"
4055 "All VNIs\n"
4056 "Remote VTEP\n"
4057 "Remote VTEP IP address\n")
4058
4059ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4060 "show bgp evpn import-rt",
4061 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5014d96f 4062
90e60aa7 4063DEFUN_NOSH (bgp_evpn_vni,
4064 bgp_evpn_vni_cmd,
4065 "vni (1-16777215)",
4066 "VXLAN Network Identifier\n"
4067 "VNI number\n")
4068{
d62a17ae 4069 vni_t vni;
4070 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4071 struct bgpevpn *vpn;
90e60aa7 4072
d62a17ae 4073 if (!bgp)
4074 return CMD_WARNING;
90e60aa7 4075
d62a17ae 4076 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 4077
d62a17ae 4078 /* Create VNI, or mark as configured. */
4079 vpn = evpn_create_update_vni(bgp, vni);
4080 if (!vpn) {
4081 vty_out(vty, "%% Failed to create VNI \n");
4082 return CMD_WARNING;
4083 }
90e60aa7 4084
d62a17ae 4085 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4086 return CMD_SUCCESS;
90e60aa7 4087}
4088
4089DEFUN (no_bgp_evpn_vni,
4090 no_bgp_evpn_vni_cmd,
4091 "no vni (1-16777215)",
4092 NO_STR
4093 "VXLAN Network Identifier\n"
4094 "VNI number\n")
4095{
d62a17ae 4096 vni_t vni;
4097 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4098 struct bgpevpn *vpn;
90e60aa7 4099
d62a17ae 4100 if (!bgp)
4101 return CMD_WARNING;
90e60aa7 4102
d62a17ae 4103 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 4104
d62a17ae 4105 /* Check if we should disallow. */
4106 vpn = bgp_evpn_lookup_vni(bgp, vni);
4107 if (!vpn) {
4108 vty_out(vty, "%% Specified VNI does not exist\n");
4109 return CMD_WARNING;
4110 }
4111 if (!is_vni_configured(vpn)) {
4112 vty_out(vty, "%% Specified VNI is not configured\n");
4113 return CMD_WARNING;
4114 }
90e60aa7 4115
d62a17ae 4116 evpn_delete_vni(bgp, vpn);
4117 return CMD_SUCCESS;
90e60aa7 4118}
4119
4120DEFUN_NOSH (exit_vni,
4121 exit_vni_cmd,
4122 "exit-vni",
4123 "Exit from VNI mode\n")
4124{
d62a17ae 4125 if (vty->node == BGP_EVPN_VNI_NODE)
4126 vty->node = BGP_EVPN_NODE;
4127 return CMD_SUCCESS;
90e60aa7 4128}
4129
676f83b9 4130DEFUN (bgp_evpn_vrf_rd,
4131 bgp_evpn_vrf_rd_cmd,
4132 "rd ASN:NN_OR_IP-ADDRESS:NN",
4133 "Route Distinguisher\n"
4134 "ASN:XX or A.B.C.D:XX\n")
4135{
4136 int ret;
4137 struct prefix_rd prd;
4138 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4139
4140 if (!bgp_vrf)
4141 return CMD_WARNING;
4142
4143 ret = str2prefix_rd(argv[1]->arg, &prd);
4144 if (!ret) {
4145 vty_out(vty, "%% Malformed Route Distinguisher\n");
4146 return CMD_WARNING;
4147 }
4148
4149 /* If same as existing value, there is nothing more to do. */
4150 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4151 return CMD_SUCCESS;
4152
4153 /* Configure or update the RD. */
4154 evpn_configure_vrf_rd(bgp_vrf, &prd);
4155 return CMD_SUCCESS;
4156}
4157
4158DEFUN (no_bgp_evpn_vrf_rd,
4159 no_bgp_evpn_vrf_rd_cmd,
4160 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4161 NO_STR
4162 "Route Distinguisher\n"
4163 "ASN:XX or A.B.C.D:XX\n")
4164{
4165 int ret;
4166 struct prefix_rd prd;
4167 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4168
4169 if (!bgp_vrf)
4170 return CMD_WARNING;
4171
4172 ret = str2prefix_rd(argv[2]->arg, &prd);
4173 if (!ret) {
4174 vty_out(vty, "%% Malformed Route Distinguisher\n");
4175 return CMD_WARNING;
4176 }
4177
4178 /* Check if we should disallow. */
4179 if (!is_vrf_rd_configured(bgp_vrf)) {
4180 vty_out(vty, "%% RD is not configured for this VRF\n");
4181 return CMD_WARNING;
4182 }
4183
4184 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4185 vty_out(vty,
4186 "%% RD specified does not match configuration for this VRF\n");
4187 return CMD_WARNING;
4188 }
4189
4190 evpn_unconfigure_vrf_rd(bgp_vrf);
4191 return CMD_SUCCESS;
4192}
4193
4194DEFUN (no_bgp_evpn_vrf_rd_without_val,
4195 no_bgp_evpn_vrf_rd_without_val_cmd,
4196 "no rd",
4197 NO_STR
4198 "Route Distinguisher\n")
4199{
4200 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4201
4202 if (!bgp_vrf)
4203 return CMD_WARNING;
4204
4205 /* Check if we should disallow. */
4206 if (!is_vrf_rd_configured(bgp_vrf)) {
4207 vty_out(vty, "%% RD is not configured for this VRF\n");
4208 return CMD_WARNING;
4209 }
4210
4211 evpn_unconfigure_vrf_rd(bgp_vrf);
4212 return CMD_SUCCESS;
4213}
4214
90e60aa7 4215DEFUN (bgp_evpn_vni_rd,
4216 bgp_evpn_vni_rd_cmd,
d114b977 4217 "rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 4218 "Route Distinguisher\n"
4219 "ASN:XX or A.B.C.D:XX\n")
4220{
d62a17ae 4221 struct prefix_rd prd;
4222 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4223 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4224 int ret;
90e60aa7 4225
06fe25f4 4226 if (!bgp)
d62a17ae 4227 return CMD_WARNING;
90e60aa7 4228
a2a8153f
CS
4229 if (bgp->vrf_id != VRF_DEFAULT) {
4230 vty_out(vty,
4231 "This command is only supported under Default VRF\n");
4232 return CMD_WARNING;
4233 }
4234
d62a17ae 4235 ret = str2prefix_rd(argv[1]->arg, &prd);
4236 if (!ret) {
4237 vty_out(vty, "%% Malformed Route Distinguisher\n");
4238 return CMD_WARNING;
4239 }
90e60aa7 4240
d62a17ae 4241 /* If same as existing value, there is nothing more to do. */
4242 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4243 return CMD_SUCCESS;
90e60aa7 4244
d62a17ae 4245 /* Configure or update the RD. */
4246 evpn_configure_rd(bgp, vpn, &prd);
4247 return CMD_SUCCESS;
90e60aa7 4248}
4249
4250DEFUN (no_bgp_evpn_vni_rd,
4251 no_bgp_evpn_vni_rd_cmd,
d114b977 4252 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 4253 NO_STR
4254 "Route Distinguisher\n"
4255 "ASN:XX or A.B.C.D:XX\n")
4256{
d62a17ae 4257 struct prefix_rd prd;
4258 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4259 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4260 int ret;
90e60aa7 4261
06fe25f4 4262 if (!bgp)
d62a17ae 4263 return CMD_WARNING;
90e60aa7 4264
a2a8153f
CS
4265 if (bgp->vrf_id != VRF_DEFAULT) {
4266 vty_out(vty,
4267 "This command is only supported under Default VRF\n");
4268 return CMD_WARNING;
4269 }
4270
d62a17ae 4271 ret = str2prefix_rd(argv[2]->arg, &prd);
4272 if (!ret) {
4273 vty_out(vty, "%% Malformed Route Distinguisher\n");
4274 return CMD_WARNING;
4275 }
90e60aa7 4276
d62a17ae 4277 /* Check if we should disallow. */
4278 if (!is_rd_configured(vpn)) {
4279 vty_out(vty, "%% RD is not configured for this VNI\n");
4280 return CMD_WARNING;
4281 }
90e60aa7 4282
d62a17ae 4283 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
4284 vty_out(vty,
4285 "%% RD specified does not match configuration for this VNI\n");
4286 return CMD_WARNING;
4287 }
90e60aa7 4288
d62a17ae 4289 evpn_unconfigure_rd(bgp, vpn);
4290 return CMD_SUCCESS;
90e60aa7 4291}
4292
4293DEFUN (no_bgp_evpn_vni_rd_without_val,
4294 no_bgp_evpn_vni_rd_without_val_cmd,
4295 "no rd",
4296 NO_STR
4297 "Route Distinguisher\n")
4298{
d62a17ae 4299 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4300 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 4301
06fe25f4 4302 if (!bgp)
d62a17ae 4303 return CMD_WARNING;
90e60aa7 4304
a2a8153f
CS
4305 if (bgp->vrf_id != VRF_DEFAULT) {
4306 vty_out(vty,
4307 "This command is only supported under Default VRF\n");
4308 return CMD_WARNING;
4309 }
4310
d62a17ae 4311 /* Check if we should disallow. */
4312 if (!is_rd_configured(vpn)) {
4313 vty_out(vty, "%% RD is not configured for this VNI\n");
4314 return CMD_WARNING;
4315 }
90e60aa7 4316
d62a17ae 4317 evpn_unconfigure_rd(bgp, vpn);
4318 return CMD_SUCCESS;
90e60aa7 4319}
4320
4321/*
4322 * Loop over all extended-communities in the route-target list rtl and
4323 * return 1 if we find ecomtarget
4324 */
d62a17ae 4325static int bgp_evpn_rt_matches_existing(struct list *rtl,
4326 struct ecommunity *ecomtarget)
90e60aa7 4327{
d62a17ae 4328 struct listnode *node, *nnode;
4329 struct ecommunity *ecom;
90e60aa7 4330
d62a17ae 4331 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
4332 if (ecommunity_match(ecom, ecomtarget))
4333 return 1;
4334 }
90e60aa7 4335
d62a17ae 4336 return 0;
90e60aa7 4337}
4338
c581d8b0
MK
4339/* display L3VNI related info for a VRF instance */
4340DEFUN (show_bgp_vrf_l3vni_info,
4341 show_bgp_vrf_l3vni_info_cmd,
4cce389e 4342 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
4343 SHOW_STR
4344 BGP_STR
4345 "show bgp vrf\n"
4346 "VRF Name\n"
4347 "L3-VNI\n"
ceb9a921 4348 JSON_STR)
c581d8b0
MK
4349{
4350 char buf[ETHER_ADDR_STRLEN];
676f83b9 4351 char buf1[INET6_ADDRSTRLEN];
c581d8b0
MK
4352 int idx_vrf = 3;
4353 const char *name = NULL;
4354 struct bgp *bgp = NULL;
4355 struct listnode *node = NULL;
6a8657d0 4356 struct bgpevpn *vpn = NULL;
c581d8b0 4357 struct ecommunity *ecom = NULL;
ceb9a921
MK
4358 json_object *json = NULL;
4359 json_object *json_vnis = NULL;
4360 json_object *json_export_rts = NULL;
4361 json_object *json_import_rts = NULL;
d7c0a89a 4362 uint8_t uj = use_json(argc, argv);
ceb9a921
MK
4363
4364 if (uj) {
4365 json = json_object_new_object();
4366 json_vnis = json_object_new_array();
4367 json_export_rts = json_object_new_array();
4368 json_import_rts = json_object_new_array();
4369 }
c581d8b0
MK
4370
4371 name = argv[idx_vrf]->arg;
4372 bgp = bgp_lookup_by_name(name);
4373 if (!bgp) {
ceb9a921 4374 if (!uj)
996c9314 4375 vty_out(vty, "BGP instance for VRF %s not found", name);
ceb9a921
MK
4376 else {
4377 json_object_string_add(json, "warning",
4378 "BGP instance not found");
996c9314 4379 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
4380 json_object_free(json);
4381 }
c581d8b0
MK
4382 return CMD_WARNING;
4383 }
4384
ceb9a921
MK
4385 if (!json) {
4386 vty_out(vty, "BGP VRF: %s\n", name);
996c9314 4387 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
ceb9a921
MK
4388 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
4389 vty_out(vty, " Rmac: %s\n",
4390 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
4391 vty_out(vty, " VNI Filter: %s\n",
4392 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
4393 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4394 ? "prefix-routes-only"
4395 : "none");
ceb9a921
MK
4396 vty_out(vty, " L2-VNI List:\n");
4397 vty_out(vty, " ");
4398 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4399 vty_out(vty, "%u ", vpn->vni);
4400 vty_out(vty, "\n");
4401 vty_out(vty, " Export-RTs:\n");
4402 vty_out(vty, " ");
4403 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4404 vty_out(vty, "%s ", ecommunity_str(ecom));
4405 vty_out(vty, "\n");
4406 vty_out(vty, " Import-RTs:\n");
4407 vty_out(vty, " ");
4408 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4409 vty_out(vty, "%s ", ecommunity_str(ecom));
4410 vty_out(vty, "\n");
676f83b9 4411 vty_out(vty, " RD: %s\n",
4412 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921
MK
4413 } else {
4414 json_object_string_add(json, "vrf", name);
b67a60d2 4415 json_object_string_add(json, "local-ip",
4416 inet_ntoa(bgp->originator_ip));
ceb9a921 4417 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
4418 json_object_string_add(
4419 json, "rmac",
4420 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4421 json_object_string_add(
4422 json, "vniFilter",
4423 CHECK_FLAG(bgp->vrf_flags,
4424 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4425 ? "prefix-routes-only"
4426 : "none");
ceb9a921
MK
4427 /* list of l2vnis */
4428 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4429 json_object_array_add(json_vnis,
4430 json_object_new_int(vpn->vni));
4431 json_object_object_add(json, "l2vnis", json_vnis);
4432
4433 /* export rts */
4434 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
996c9314
LB
4435 json_object_array_add(
4436 json_export_rts,
4437 json_object_new_string(ecommunity_str(ecom)));
ceb9a921
MK
4438 json_object_object_add(json, "export-rts", json_export_rts);
4439
4440 /* import rts */
4441 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
996c9314
LB
4442 json_object_array_add(
4443 json_import_rts,
4444 json_object_new_string(ecommunity_str(ecom)));
ceb9a921 4445 json_object_object_add(json, "import-rts", json_import_rts);
676f83b9 4446 json_object_string_add(
4447 json, "rd",
4448 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
ceb9a921 4449 }
c581d8b0 4450
ceb9a921
MK
4451 if (uj) {
4452 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4453 json, JSON_C_TO_STRING_PRETTY));
4454 json_object_free(json);
4455 }
c581d8b0
MK
4456 return CMD_SUCCESS;
4457}
4458
4459/* import/export rt for l3vni-vrf */
4460DEFUN (bgp_evpn_vrf_rt,
4461 bgp_evpn_vrf_rt_cmd,
4462 "route-target <both|import|export> RT",
4463 "Route Target\n"
4464 "import and export\n"
4465 "import\n"
4466 "export\n"
4467 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4468{
4469 int rt_type;
4470 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4471 struct ecommunity *ecomadd = NULL;
4472
4473 if (!bgp)
4474 return CMD_WARNING;
4475
4476 if (!strcmp(argv[1]->arg, "import"))
4477 rt_type = RT_TYPE_IMPORT;
4478 else if (!strcmp(argv[1]->arg, "export"))
4479 rt_type = RT_TYPE_EXPORT;
4480 else if (!strcmp(argv[1]->arg, "both"))
4481 rt_type = RT_TYPE_BOTH;
4482 else {
4483 vty_out(vty, "%% Invalid Route Target type\n");
4484 return CMD_WARNING;
4485 }
4486
4487 /* Add/update the import route-target */
4488 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4489 ecomadd = ecommunity_str2com(argv[2]->arg,
4490 ECOMMUNITY_ROUTE_TARGET, 0);
4491 if (!ecomadd) {
4492 vty_out(vty, "%% Malformed Route Target list\n");
4493 return CMD_WARNING;
4494 }
4495 ecommunity_str(ecomadd);
4496
4497 /* Do nothing if we already have this import route-target */
996c9314 4498 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
c581d8b0
MK
4499 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
4500 }
4501
4502 /* Add/update the export route-target */
4503 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4504 ecomadd = ecommunity_str2com(argv[2]->arg,
4505 ECOMMUNITY_ROUTE_TARGET, 0);
4506 if (!ecomadd) {
4507 vty_out(vty, "%% Malformed Route Target list\n");
4508 return CMD_WARNING;
4509 }
4510 ecommunity_str(ecomadd);
4511
4512 /* Do nothing if we already have this export route-target */
996c9314 4513 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
c581d8b0
MK
4514 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
4515 }
4516
4517 return CMD_SUCCESS;
4518}
4519
4520DEFUN (no_bgp_evpn_vrf_rt,
4521 no_bgp_evpn_vrf_rt_cmd,
4522 "no route-target <both|import|export> RT",
4523 NO_STR
4524 "Route Target\n"
4525 "import and export\n"
4526 "import\n"
4527 "export\n"
4528 "ASN:XX or A.B.C.D:XX\n")
4529{
4530 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4531 int rt_type, found_ecomdel;
4532 struct ecommunity *ecomdel = NULL;
4533
4534 if (!bgp)
4535 return CMD_WARNING;
4536
4537 if (!strcmp(argv[2]->arg, "import"))
4538 rt_type = RT_TYPE_IMPORT;
4539 else if (!strcmp(argv[2]->arg, "export"))
4540 rt_type = RT_TYPE_EXPORT;
4541 else if (!strcmp(argv[2]->arg, "both"))
4542 rt_type = RT_TYPE_BOTH;
4543 else {
4544 vty_out(vty, "%% Invalid Route Target type\n");
4545 return CMD_WARNING;
4546 }
4547
4548 if (rt_type == RT_TYPE_IMPORT) {
4549 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4550 vty_out(vty,
4551 "%% Import RT is not configured for this VRF\n");
4552 return CMD_WARNING;
4553 }
4554 } else if (rt_type == RT_TYPE_EXPORT) {
4555 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4556 vty_out(vty,
4557 "%% Export RT is not configured for this VRF\n");
4558 return CMD_WARNING;
4559 }
4560 } else if (rt_type == RT_TYPE_BOTH) {
4561 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
4562 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4563 vty_out(vty,
4564 "%% Import/Export RT is not configured for this VRF\n");
4565 return CMD_WARNING;
4566 }
4567 }
4568
4569 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
4570 if (!ecomdel) {
4571 vty_out(vty, "%% Malformed Route Target list\n");
4572 return CMD_WARNING;
4573 }
4574 ecommunity_str(ecomdel);
4575
4576 if (rt_type == RT_TYPE_IMPORT) {
4577 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_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_import_rt_for_vrf(bgp, ecomdel);
4584 } else if (rt_type == RT_TYPE_EXPORT) {
4585 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4586 ecomdel)) {
4587 vty_out(vty,
4588 "%% RT specified does not match configuration for this VRF\n");
4589 return CMD_WARNING;
4590 }
4591 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4592 } else if (rt_type == RT_TYPE_BOTH) {
4593 found_ecomdel = 0;
4594
4595 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4596 ecomdel)) {
4597 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4598 found_ecomdel = 1;
4599 }
4600
4601 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4602 ecomdel)) {
4603 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4604 found_ecomdel = 1;
4605 }
4606
4607 if (!found_ecomdel) {
4608 vty_out(vty,
4609 "%% RT specified does not match configuration for this VRF\n");
4610 return CMD_WARNING;
4611 }
4612 }
4613
4614 return CMD_SUCCESS;
4615}
90e60aa7 4616
4617DEFUN (bgp_evpn_vni_rt,
4618 bgp_evpn_vni_rt_cmd,
4619 "route-target <both|import|export> RT",
4620 "Route Target\n"
4621 "import and export\n"
4622 "import\n"
4623 "export\n"
4624 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4625{
d62a17ae 4626 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4627 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4628 int rt_type;
4629 struct ecommunity *ecomadd = NULL;
4630
06fe25f4 4631 if (!bgp)
d62a17ae 4632 return CMD_WARNING;
4633
a2a8153f
CS
4634 if (bgp->vrf_id != VRF_DEFAULT) {
4635 vty_out(vty,
4636 "This command is only supported under Default VRF\n");
4637 return CMD_WARNING;
4638 }
4639
8034beff 4640 if (!strcmp(argv[1]->text, "import"))
d62a17ae 4641 rt_type = RT_TYPE_IMPORT;
8034beff 4642 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 4643 rt_type = RT_TYPE_EXPORT;
8034beff 4644 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 4645 rt_type = RT_TYPE_BOTH;
4646 else {
4647 vty_out(vty, "%% Invalid Route Target type\n");
4648 return CMD_WARNING;
4649 }
4650
4651 /* Add/update the import route-target */
4652 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4653 ecomadd = ecommunity_str2com(argv[2]->arg,
4654 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4655 if (!ecomadd) {
4656 vty_out(vty, "%% Malformed Route Target list\n");
4657 return CMD_WARNING;
4658 }
5bc2ed52 4659 ecommunity_str(ecomadd);
d62a17ae 4660
4661 /* Do nothing if we already have this import route-target */
4662 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
4663 evpn_configure_import_rt(bgp, vpn, ecomadd);
4664 }
4665
4666 /* Add/update the export route-target */
4667 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4668 ecomadd = ecommunity_str2com(argv[2]->arg,
4669 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4670 if (!ecomadd) {
4671 vty_out(vty, "%% Malformed Route Target list\n");
4672 return CMD_WARNING;
4673 }
5bc2ed52 4674 ecommunity_str(ecomadd);
d62a17ae 4675
4676 /* Do nothing if we already have this export route-target */
4677 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
4678 evpn_configure_export_rt(bgp, vpn, ecomadd);
4679 }
4680
4681 return CMD_SUCCESS;
90e60aa7 4682}
4683
4684DEFUN (no_bgp_evpn_vni_rt,
4685 no_bgp_evpn_vni_rt_cmd,
4686 "no route-target <both|import|export> RT",
4687 NO_STR
4688 "Route Target\n"
4689 "import and export\n"
4690 "import\n"
4691 "export\n"
4692 "ASN:XX or A.B.C.D:XX\n")
4693{
d62a17ae 4694 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4695 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4696 int rt_type, found_ecomdel;
4697 struct ecommunity *ecomdel = NULL;
4698
06fe25f4 4699 if (!bgp)
d62a17ae 4700 return CMD_WARNING;
4701
a2a8153f
CS
4702 if (bgp->vrf_id != VRF_DEFAULT) {
4703 vty_out(vty,
4704 "This command is only supported under Default VRF\n");
4705 return CMD_WARNING;
4706 }
4707
8034beff 4708 if (!strcmp(argv[2]->text, "import"))
d62a17ae 4709 rt_type = RT_TYPE_IMPORT;
8034beff 4710 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 4711 rt_type = RT_TYPE_EXPORT;
8034beff 4712 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 4713 rt_type = RT_TYPE_BOTH;
4714 else {
4715 vty_out(vty, "%% Invalid Route Target type\n");
4716 return CMD_WARNING;
4717 }
4718
4719 /* The user did "no route-target import", check to see if there are any
4720 * import route-targets configured. */
4721 if (rt_type == RT_TYPE_IMPORT) {
4722 if (!is_import_rt_configured(vpn)) {
4723 vty_out(vty,
4724 "%% Import RT is not configured for this VNI\n");
4725 return CMD_WARNING;
4726 }
4727 } else if (rt_type == RT_TYPE_EXPORT) {
4728 if (!is_export_rt_configured(vpn)) {
4729 vty_out(vty,
4730 "%% Export RT is not configured for this VNI\n");
4731 return CMD_WARNING;
4732 }
4733 } else if (rt_type == RT_TYPE_BOTH) {
4734 if (!is_import_rt_configured(vpn)
4735 && !is_export_rt_configured(vpn)) {
4736 vty_out(vty,
4737 "%% Import/Export RT is not configured for this VNI\n");
4738 return CMD_WARNING;
4739 }
4740 }
4741
4742 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 4743 if (!ecomdel) {
4744 vty_out(vty, "%% Malformed Route Target list\n");
4745 return CMD_WARNING;
4746 }
5bc2ed52 4747 ecommunity_str(ecomdel);
d62a17ae 4748
4749 if (rt_type == RT_TYPE_IMPORT) {
4750 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4751 vty_out(vty,
4752 "%% RT specified does not match configuration for this VNI\n");
4753 return CMD_WARNING;
4754 }
4755 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4756 } else if (rt_type == RT_TYPE_EXPORT) {
4757 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4758 vty_out(vty,
4759 "%% RT specified does not match configuration for this VNI\n");
4760 return CMD_WARNING;
4761 }
4762 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4763 } else if (rt_type == RT_TYPE_BOTH) {
4764 found_ecomdel = 0;
4765
4766 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
4767 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
4768 found_ecomdel = 1;
4769 }
4770
4771 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
4772 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
4773 found_ecomdel = 1;
4774 }
4775
4776 if (!found_ecomdel) {
4777 vty_out(vty,
4778 "%% RT specified does not match configuration for this VNI\n");
4779 return CMD_WARNING;
4780 }
4781 }
4782
4783 return CMD_SUCCESS;
90e60aa7 4784}
4785
4786DEFUN (no_bgp_evpn_vni_rt_without_val,
4787 no_bgp_evpn_vni_rt_without_val_cmd,
4788 "no route-target <import|export>",
4789 NO_STR
4790 "Route Target\n"
4791 "import\n"
4792 "export\n")
4793{
d62a17ae 4794 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4795 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4796 int rt_type;
4797
06fe25f4 4798 if (!bgp)
d62a17ae 4799 return CMD_WARNING;
4800
a2a8153f
CS
4801 if (bgp->vrf_id != VRF_DEFAULT) {
4802 vty_out(vty,
4803 "This command is only supported under Default VRF\n");
4804 return CMD_WARNING;
4805 }
4806
8034beff 4807 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 4808 rt_type = RT_TYPE_IMPORT;
8034beff 4809 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 4810 rt_type = RT_TYPE_EXPORT;
4811 } else {
4812 vty_out(vty, "%% Invalid Route Target type\n");
4813 return CMD_WARNING;
4814 }
4815
4816 /* Check if we should disallow. */
4817 if (rt_type == RT_TYPE_IMPORT) {
4818 if (!is_import_rt_configured(vpn)) {
4819 vty_out(vty,
4820 "%% Import RT is not configured for this VNI\n");
4821 return CMD_WARNING;
4822 }
4823 } else {
4824 if (!is_export_rt_configured(vpn)) {
4825 vty_out(vty,
4826 "%% Export RT is not configured for this VNI\n");
4827 return CMD_WARNING;
4828 }
4829 }
4830
4831 /* Unconfigure the RT. */
4832 if (rt_type == RT_TYPE_IMPORT)
4833 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4834 else
4835 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4836 return CMD_SUCCESS;
90e60aa7 4837}
568b6b44
QY
4838
4839static int vni_cmp(const void **a, const void **b)
4840{
4841 const struct bgpevpn *first = *a;
4842 const struct bgpevpn *secnd = *b;
4843
4844 return secnd->vni - first->vni;
4845}
4846
90e60aa7 4847/*
4848 * Output EVPN configuration information.
4849 */
d62a17ae 4850void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 4851 safi_t safi)
d62a17ae 4852{
a75c2553
MK
4853 char buf1[RD_ADDRSTRLEN];
4854
568b6b44
QY
4855 if (bgp->vnihash) {
4856 struct list *vnilist = hash_to_list(bgp->vnihash);
4857 struct listnode *ln;
4858 struct bgpevpn *data;
4859
4860 list_sort(vnilist, vni_cmp);
4861 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
4862 write_vni_config(vty, data);
4863
4864 list_delete_and_null(&vnilist);
4865 }
90e60aa7 4866
2b791107 4867 if (bgp->advertise_all_vni)
d62a17ae 4868 vty_out(vty, " advertise-all-vni\n");
1a98c087 4869
bf1061d8
VB
4870 if (bgp->advertise_autort_rfc8365)
4871 vty_out(vty, " autort rfc8365-compatible\n");
4872
2b791107 4873 if (bgp->advertise_gw_macip)
1a98c087 4874 vty_out(vty, " advertise-default-gw\n");
6ee86383 4875
154faa50 4876 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
4877 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
4878 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
4879 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
4880 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
4881 else
4882 vty_out(vty, " advertise ipv4 unicast\n");
4883 }
6ee86383 4884
154faa50 4885 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d2a0075a
MK
4886 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
4887 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
4888 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
4889 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
4890 else
4891 vty_out(vty, " advertise ipv6 unicast\n");
4892 }
486456ca
MK
4893
4894 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4895 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
4896 vty_out(vty, " default-originate ipv4\n");
4897
4898 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
4899 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
4900 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 4901
a75c2553
MK
4902 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
4903 vty_out(vty, " rd %s\n",
4904 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
4905
db29a4a8
MK
4906 /* import route-target */
4907 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4908 char *ecom_str;
4909 struct listnode *node, *nnode;
4910 struct ecommunity *ecom;
4911
4912 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
4913 ecom)) {
4914 ecom_str = ecommunity_ecom2str(
4915 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4916 vty_out(vty, " route-target import %s\n", ecom_str);
db29a4a8
MK
4917 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4918 }
4919 }
4920
4921 /* export route-target */
4922 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4923 char *ecom_str;
4924 struct listnode *node, *nnode;
4925 struct ecommunity *ecom;
4926
4927 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
4928 ecom)) {
4929 ecom_str = ecommunity_ecom2str(
4930 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
996c9314 4931 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
4932 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
4933 }
4934 }
90e60aa7 4935}
4936
4d0e6ece 4937void bgp_ethernetvpn_init(void)
784d3a42 4938{
d62a17ae 4939 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4940 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4941 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4942 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4943 install_element(VIEW_NODE,
4944 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4945 install_element(VIEW_NODE,
4946 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4947 install_element(
4948 VIEW_NODE,
4949 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4950 install_element(
4951 VIEW_NODE,
4952 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4953 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4954 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4955 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4956 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
d62a17ae 4957 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4958 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
bf1061d8
VB
4959 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
4960 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
1a98c087
MK
4961 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4962 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
342dd0c6 4963 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4964 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
4965 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
4966 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
d62a17ae 4967
50f74cf1 4968 /* test commands */
4969 install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
4970 install_element(BGP_EVPN_NODE, &test_withdraw_evpn_type4_route_cmd);
4971
f2d62262 4972 /* "show bgp l2vpn evpn" commands. */
50f74cf1 4973 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
f2d62262 4974 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4975 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4976 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4977 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4978 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
50f74cf1 4979 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
f2d62262 4980 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
4981 install_element(VIEW_NODE,
4982 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4983 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4984 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4985 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 4986 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 4987
5014d96f
DW
4988 /* "show bgp evpn" commands. */
4989 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4990 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4991 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4992 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4993 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4994 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4995 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4996 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4997 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4998 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 4999 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5014d96f 5000
d62a17ae 5001 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
5002 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
5003 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
5004 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
5005 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
5006 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
5007 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
5008 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
5009 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
5010 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5011 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 5012 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
5013 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5014 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
1a98c087
MK
5015 install_element(BGP_EVPN_VNI_NODE,
5016 &bgp_evpn_advertise_default_gw_vni_cmd);
5017 install_element(BGP_EVPN_VNI_NODE,
5018 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
5019 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5020 install_element(BGP_EVPN_VNI_NODE,
5021 &no_bgp_evpn_advertise_vni_subnet_cmd);
784d3a42 5022}