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