]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
bgpd: Using no pretty json output for l2vpn-Evpn routes
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
784d3a42 2/* Ethernet-VPN Packet and vty Processing File
896014f4
DL
3 * Copyright (C) 2017 6WIND
4 *
5 * This file is part of FRRouting
896014f4 6 */
784d3a42
PG
7
8#include <zebra.h>
9#include "command.h"
10#include "prefix.h"
11#include "lib/json.h"
23d0a753 12#include "lib/printfrr.h"
74e2bd89 13#include "lib/vxlan.h"
937652c6 14#include "stream.h"
784d3a42
PG
15
16#include "bgpd/bgpd.h"
17#include "bgpd/bgp_table.h"
18#include "bgpd/bgp_attr.h"
19#include "bgpd/bgp_route.h"
20#include "bgpd/bgp_mplsvpn.h"
21#include "bgpd/bgp_vpn.h"
22#include "bgpd/bgp_evpn_vty.h"
3da6fcd5 23#include "bgpd/bgp_evpn.h"
7724c0a1 24#include "bgpd/bgp_evpn_private.h"
185fb14a 25#include "bgpd/bgp_evpn_mh.h"
7724c0a1 26#include "bgpd/bgp_zebra.h"
520d5d76 27#include "bgpd/bgp_vty.h"
14454c9f 28#include "bgpd/bgp_errors.h"
5a0ccebf 29#include "bgpd/bgp_ecommunity.h"
7f433a5e
LK
30#include "bgpd/bgp_lcommunity.h"
31#include "bgpd/bgp_community.h"
784d3a42 32
784d3a42
PG
33#define SHOW_DISPLAY_STANDARD 0
34#define SHOW_DISPLAY_TAGS 1
35#define SHOW_DISPLAY_OVERLAY 2
60466a63 36#define VNI_STR_LEN 32
784d3a42 37
520d5d76 38/*
39 * Context for VNI hash walk - used by callbacks.
40 */
d62a17ae 41struct vni_walk_ctx {
42 struct bgp *bgp;
43 struct vty *vty;
44 struct in_addr vtep_ip;
9c92b5f7 45 json_object *json;
c7ef6cf2 46 int detail;
852d9f97
SW
47 int type;
48 bool mac_table;
520d5d76 49};
50
d4a88de3
AD
51int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx,
52 enum overlay_index_type *oly)
53{
54 *oly = OVERLAY_INDEX_TYPE_NONE;
a09811ff
IR
55 if (argv_find(argv, argc, "gateway-ip", oly_idx))
56 *oly = OVERLAY_INDEX_GATEWAY_IP;
d4a88de3
AD
57 return 1;
58}
59
996c9314 60static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
10ebe1ab
MK
61 json_object *json)
62{
1be1693e 63 const uint8_t *pnt;
d7c0a89a 64 uint8_t type, sub_type;
10ebe1ab
MK
65 struct ecommunity_as eas;
66 struct ecommunity_ip eip;
67 struct listnode *node, *nnode;
68 struct bgp *tmp_bgp_vrf = NULL;
69 json_object *json_rt = NULL;
70 json_object *json_vrfs = NULL;
71 char rt_buf[RT_ADDRSTRLEN];
72
73 if (json) {
74 json_rt = json_object_new_object();
75 json_vrfs = json_object_new_array();
76 }
77
d7c0a89a 78 pnt = (uint8_t *)&irt->rt.val;
10ebe1ab
MK
79 type = *pnt++;
80 sub_type = *pnt++;
81 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
82 return;
83
84 memset(&eas, 0, sizeof(eas));
85 switch (type) {
86 case ECOMMUNITY_ENCODE_AS:
87 eas.as = (*pnt++ << 8);
88 eas.as |= (*pnt++);
100cb793 89 ptr_get_be32(pnt, &eas.val);
10ebe1ab 90
772270f3 91 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
10ebe1ab
MK
92
93 if (json)
94 json_object_string_add(json_rt, "rt", rt_buf);
95 else
96 vty_out(vty, "Route-target: %s", rt_buf);
97
98 break;
99
100 case ECOMMUNITY_ENCODE_IP:
101 memcpy(&eip.ip, pnt, 4);
102 pnt += 4;
103 eip.val = (*pnt++ << 8);
104 eip.val |= (*pnt++);
105
23d0a753 106 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
10ebe1ab
MK
107
108 if (json)
109 json_object_string_add(json_rt, "rt", rt_buf);
110 else
111 vty_out(vty, "Route-target: %s", rt_buf);
112
113 break;
114
115 case ECOMMUNITY_ENCODE_AS4:
116 pnt = ptr_get_be32(pnt, &eas.val);
117 eas.val = (*pnt++ << 8);
118 eas.val |= (*pnt++);
119
772270f3 120 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
10ebe1ab
MK
121
122 if (json)
123 json_object_string_add(json_rt, "rt", rt_buf);
124 else
125 vty_out(vty, "Route-target: %s", rt_buf);
126
127 break;
128
129 default:
130 return;
131 }
132
133 if (!json) {
134 vty_out(vty,
135 "\nList of VRFs importing routes with this route-target:\n");
136 }
137
138 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
139 if (json)
140 json_object_array_add(
141 json_vrfs,
142 json_object_new_string(
996c9314 143 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
10ebe1ab
MK
144 else
145 vty_out(vty, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
147 }
148
149 if (json) {
150 json_object_object_add(json_rt, "vrfs", json_vrfs);
151 json_object_object_add(json, rt_buf, json_rt);
152 }
153}
154
e3b78da8 155static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
10ebe1ab
MK
156{
157 json_object *json = NULL;
158 struct vty *vty = NULL;
e3b78da8 159 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
10ebe1ab 160
181c08c6
MK
161 vty = (struct vty *)args[0];
162 json = (struct json_object *)args[1];
10ebe1ab
MK
163
164 display_vrf_import_rt(vty, irt, json);
165}
166
9c92b5f7
MK
167static void display_import_rt(struct vty *vty, struct irt_node *irt,
168 json_object *json)
d62a17ae 169{
1be1693e 170 const uint8_t *pnt;
d7c0a89a 171 uint8_t type, sub_type;
5a0ccebf
QY
172 struct ecommunity_as eas;
173 struct ecommunity_ip eip;
d62a17ae 174 struct listnode *node, *nnode;
175 struct bgpevpn *tmp_vpn;
9c92b5f7
MK
176 json_object *json_rt = NULL;
177 json_object *json_vnis = NULL;
178 char rt_buf[RT_ADDRSTRLEN];
d62a17ae 179
9c92b5f7 180 if (json) {
b682f6de 181 json_rt = json_object_new_object();
182 json_vnis = json_object_new_array();
9c92b5f7 183 }
d62a17ae 184
185 /* TODO: This needs to go into a function */
186
d7c0a89a 187 pnt = (uint8_t *)&irt->rt.val;
d62a17ae 188 type = *pnt++;
189 sub_type = *pnt++;
190 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191 return;
192
88a837f6 193 memset(&eas, 0, sizeof(eas));
d62a17ae 194 switch (type) {
195 case ECOMMUNITY_ENCODE_AS:
196 eas.as = (*pnt++ << 8);
197 eas.as |= (*pnt++);
100cb793 198 ptr_get_be32(pnt, &eas.val);
d62a17ae 199
772270f3 200 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
9c92b5f7
MK
201
202 if (json)
203 json_object_string_add(json_rt, "rt", rt_buf);
204 else
205 vty_out(vty, "Route-target: %s", rt_buf);
206
d62a17ae 207 break;
208
209 case ECOMMUNITY_ENCODE_IP:
210 memcpy(&eip.ip, pnt, 4);
211 pnt += 4;
212 eip.val = (*pnt++ << 8);
213 eip.val |= (*pnt++);
214
23d0a753 215 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
9c92b5f7
MK
216
217 if (json)
218 json_object_string_add(json_rt, "rt", rt_buf);
219 else
220 vty_out(vty, "Route-target: %s", rt_buf);
221
d62a17ae 222 break;
223
224 case ECOMMUNITY_ENCODE_AS4:
937652c6 225 pnt = ptr_get_be32(pnt, &eas.val);
d62a17ae 226 eas.val = (*pnt++ << 8);
227 eas.val |= (*pnt++);
228
772270f3 229 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
9c92b5f7
MK
230
231 if (json)
232 json_object_string_add(json_rt, "rt", rt_buf);
233 else
234 vty_out(vty, "Route-target: %s", rt_buf);
235
d62a17ae 236 break;
237
238 default:
239 return;
240 }
241
9c92b5f7
MK
242 if (!json) {
243 vty_out(vty,
244 "\nList of VNIs importing routes with this route-target:\n");
245 }
246
247 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
248 if (json)
249 json_object_array_add(
f00ba699 250 json_vnis, json_object_new_int(tmp_vpn->vni));
9c92b5f7
MK
251 else
252 vty_out(vty, " %u\n", tmp_vpn->vni);
253 }
254
255 if (json) {
256 json_object_object_add(json_rt, "vnis", json_vnis);
257 json_object_object_add(json, rt_buf, json_rt);
258 }
d62a17ae 259}
260
e3b78da8 261static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
520d5d76 262{
9c92b5f7
MK
263 json_object *json = NULL;
264 struct vty *vty = NULL;
e3b78da8 265 struct irt_node *irt = (struct irt_node *)bucket->data;
9c92b5f7
MK
266
267 vty = args[0];
268 json = args[1];
269
dff8f48d 270 display_import_rt(vty, irt, json);
9c92b5f7
MK
271
272 return;
d62a17ae 273}
520d5d76 274
d62a17ae 275static void bgp_evpn_show_route_rd_header(struct vty *vty,
9bcb3eef
DS
276 struct bgp_dest *rd_dest,
277 json_object *json, char *rd_str,
278 int len)
d62a17ae 279{
d7c0a89a 280 uint16_t type;
d62a17ae 281 struct rd_as rd_as;
282 struct rd_ip rd_ip;
b54892e0 283 const uint8_t *pnt;
9bcb3eef 284 const struct prefix *p = bgp_dest_get_prefix(rd_dest);
520d5d76 285
b54892e0 286 pnt = p->u.val;
520d5d76 287
d62a17ae 288 /* Decode RD type. */
289 type = decode_rd_type(pnt);
520d5d76 290
c69e79f1
LK
291 if (!json)
292 vty_out(vty, "Route Distinguisher: ");
520d5d76 293
d62a17ae 294 switch (type) {
295 case RD_TYPE_AS:
296 decode_rd_as(pnt + 2, &rd_as);
c69e79f1
LK
297 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
298 if (json)
299 json_object_string_add(json, "rd", rd_str);
300 else
527fd6de 301 vty_out(vty, "%s\n", rd_str);
c69e79f1
LK
302 break;
303
304 case RD_TYPE_AS4:
305 decode_rd_as4(pnt + 2, &rd_as);
306 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
307 if (json)
308 json_object_string_add(json, "rd", rd_str);
309 else
527fd6de 310 vty_out(vty, "%s\n", rd_str);
d62a17ae 311 break;
520d5d76 312
d62a17ae 313 case RD_TYPE_IP:
314 decode_rd_ip(pnt + 2, &rd_ip);
23d0a753 315 snprintfrr(rd_str, len, "%pI4:%d", &rd_ip.ip, rd_ip.val);
c69e79f1
LK
316 if (json)
317 json_object_string_add(json, "rd", rd_str);
318 else
527fd6de 319 vty_out(vty, "%s\n", rd_str);
d62a17ae 320 break;
520d5d76 321
d62a17ae 322 default:
c69e79f1
LK
323 if (json) {
324 snprintf(rd_str, len, "Unknown");
325 json_object_string_add(json, "rd", rd_str);
326 } else {
327 snprintf(rd_str, len, "Unknown RD type");
527fd6de 328 vty_out(vty, "%s\n", rd_str);
c69e79f1 329 }
d62a17ae 330 break;
331 }
d62a17ae 332}
333
9c92b5f7 334static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
2dd32217 335 uint64_t tbl_ver, json_object *json)
d62a17ae 336{
337 char ri_header[] =
338 " Network Next Hop Metric LocPrf Weight Path\n";
520d5d76 339
9c92b5f7
MK
340 if (json)
341 return;
342
23d0a753
DA
343 vty_out(vty,
344 "BGP table version is %" PRIu64 ", local router ID is %pI4\n",
345 tbl_ver, &bgp->router_id);
d62a17ae 346 vty_out(vty,
3efd0893 347 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
d62a17ae 348 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
b5e140c8 349 vty_out(vty,
7b0db0e4 350 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
d62a17ae 351 vty_out(vty,
554cd77a 352 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
b3628c70 353 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
50f74cf1 354 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
554cd77a 355 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
d62a17ae 356 vty_out(vty, "%s", ri_header);
357}
520d5d76 358
4cce389e
MK
359static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
360 json_object *json)
361{
4cce389e
MK
362 char *ecom_str;
363 struct listnode *node, *nnode;
ca337b46 364 struct vrf_route_target *l3rt;
4cce389e
MK
365 json_object *json_import_rtl = NULL;
366 json_object *json_export_rtl = NULL;
23c7421d 367 char buf2[ETHER_ADDR_STRLEN];
4cce389e
MK
368
369 json_import_rtl = json_export_rtl = 0;
370
371 if (json) {
372 json_import_rtl = json_object_new_array();
373 json_export_rtl = json_object_new_array();
374 json_object_int_add(json, "vni", bgp_vrf->l3vni);
375 json_object_string_add(json, "type", "L3");
37ae1adb 376 json_object_string_add(json, "inKernel", "True");
4a8cd6ad
PG
377 json_object_string_addf(json, "rd",
378 BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
379 &bgp_vrf->vrf_prd);
c949c771
DA
380 json_object_string_addf(json, "originatorIp", "%pI4",
381 &bgp_vrf->originator_ip);
4cce389e 382 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
0b509723 383 json_object_string_add(json, "advertiseSviMacIp", "n/a");
23c7421d
CS
384 json_object_string_add(json, "advertisePip",
385 bgp_vrf->evpn_info->advertise_pip ?
386 "Enabled" : "Disabled");
c949c771
DA
387 json_object_string_addf(json, "sysIP", "%pI4",
388 &bgp_vrf->evpn_info->pip_ip);
23c7421d
CS
389 json_object_string_add(json, "sysMac",
390 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
391 buf2, sizeof(buf2)));
392 json_object_string_add(json, "rmac",
393 prefix_mac2str(&bgp_vrf->rmac,
394 buf2, sizeof(buf2)));
4cce389e
MK
395 } else {
396 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
397 vty_out(vty, " (known to the kernel)");
398 vty_out(vty, "\n");
399
400 vty_out(vty, " Type: %s\n", "L3");
401 vty_out(vty, " Tenant VRF: %s\n",
402 vrf_id_to_name(bgp_vrf->vrf_id));
4a8cd6ad
PG
403 vty_out(vty, " RD: ");
404 vty_out(vty, BGP_RD_AS_FORMAT(bgp_vrf->asnotation),
405 &bgp_vrf->vrf_prd);
406 vty_out(vty, "\n");
23d0a753
DA
407 vty_out(vty, " Originator IP: %pI4\n",
408 &bgp_vrf->originator_ip);
4cce389e 409 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
cbdbb1ca 410 vty_out(vty, " Advertise-svi-macip : %s\n", "n/a");
23c7421d
CS
411 vty_out(vty, " Advertise-pip: %s\n",
412 bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
07380148
DA
413 vty_out(vty, " System-IP: %pI4\n",
414 &bgp_vrf->evpn_info->pip_ip);
23c7421d
CS
415 vty_out(vty, " System-MAC: %s\n",
416 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
417 buf2, sizeof(buf2)));
418 vty_out(vty, " Router-MAC: %s\n",
419 prefix_mac2str(&bgp_vrf->rmac,
420 buf2, sizeof(buf2)));
4cce389e
MK
421 }
422
423 if (!json)
424 vty_out(vty, " Import Route Target:\n");
425
ca337b46
SW
426 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt)) {
427 ecom_str = ecommunity_ecom2str(l3rt->ecom,
4cce389e
MK
428 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
429
430 if (json)
431 json_object_array_add(json_import_rtl,
432 json_object_new_string(ecom_str));
433 else
434 vty_out(vty, " %s\n", ecom_str);
435
436 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
437 }
438
439 if (json)
440 json_object_object_add(json, "importRts", json_import_rtl);
441 else
442 vty_out(vty, " Export Route Target:\n");
443
ca337b46
SW
444 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, l3rt)) {
445 ecom_str = ecommunity_ecom2str(l3rt->ecom,
4cce389e
MK
446 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
447
448 if (json)
449 json_object_array_add(json_export_rtl,
450 json_object_new_string(ecom_str));
451 else
452 vty_out(vty, " %s\n", ecom_str);
453
454 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
455 }
456
457 if (json)
458 json_object_object_add(json, "exportRts", json_export_rtl);
459}
460
9c92b5f7 461static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
d62a17ae 462{
d62a17ae 463 char *ecom_str;
464 struct listnode *node, *nnode;
465 struct ecommunity *ecom;
f57514e1
DS
466 json_object *json_import_rtl = NULL;
467 json_object *json_export_rtl = NULL;
2c4654a1 468 struct bgp *bgp_evpn;
4a8cd6ad 469 enum asnotation_mode asnotation;
2c4654a1
CS
470
471 bgp_evpn = bgp_get_evpn();
4a8cd6ad 472 asnotation = bgp_get_asnotation(bgp_evpn);
9c92b5f7
MK
473
474 if (json) {
475 json_import_rtl = json_object_new_array();
476 json_export_rtl = json_object_new_array();
477 json_object_int_add(json, "vni", vpn->vni);
4cce389e 478 json_object_string_add(json, "type", "L2");
37ae1adb
CS
479 json_object_string_add(json, "inKernel",
480 is_vni_live(vpn) ? "True" : "False");
4a8cd6ad
PG
481 json_object_string_addf(
482 json, "rd", BGP_RD_AS_FORMAT(asnotation), &vpn->prd);
c949c771
DA
483 json_object_string_addf(json, "originatorIp", "%pI4",
484 &vpn->originator_ip);
485 json_object_string_addf(json, "mcastGroup", "%pI4",
486 &vpn->mcast_grp);
2c4654a1
CS
487 /* per vni knob is enabled -- Enabled
488 * Global knob is enabled -- Active
489 * default -- Disabled
490 */
491 if (!vpn->advertise_gw_macip &&
492 bgp_evpn && bgp_evpn->advertise_gw_macip)
493 json_object_string_add(json, "advertiseGatewayMacip",
494 "Active");
495 else if (vpn->advertise_gw_macip)
496 json_object_string_add(json, "advertiseGatewayMacip",
497 "Enabled");
498 else
499 json_object_string_add(json, "advertiseGatewayMacip",
500 "Disabled");
501 if (!vpn->advertise_svi_macip && bgp_evpn &&
502 bgp_evpn->evpn_info->advertise_svi_macip)
0b509723 503 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1
CS
504 "Active");
505 else if (vpn->advertise_svi_macip)
0b509723 506 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1
CS
507 "Enabled");
508 else
0b509723 509 json_object_string_add(json, "advertiseSviMacIp",
2c4654a1 510 "Disabled");
9daa5d47
AD
511 json_object_string_add(
512 json, "sviInterface",
513 ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
9c92b5f7 514 } else {
339af96e 515 vty_out(vty, "VNI: %u", vpn->vni);
9c92b5f7
MK
516 if (is_vni_live(vpn))
517 vty_out(vty, " (known to the kernel)");
518 vty_out(vty, "\n");
519
4cce389e 520 vty_out(vty, " Type: %s\n", "L2");
29c53922
MK
521 vty_out(vty, " Tenant-Vrf: %s\n",
522 vrf_id_to_name(vpn->tenant_vrf_id));
4a8cd6ad
PG
523 vty_out(vty, " RD: ");
524 vty_out(vty, BGP_RD_AS_FORMAT(asnotation), &vpn->prd);
525 vty_out(vty, "\n");
23d0a753
DA
526 vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip);
527 vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp);
2c4654a1
CS
528 if (!vpn->advertise_gw_macip &&
529 bgp_evpn && bgp_evpn->advertise_gw_macip)
530 vty_out(vty, " Advertise-gw-macip : %s\n",
531 "Active");
532 else if (vpn->advertise_gw_macip)
533 vty_out(vty, " Advertise-gw-macip : %s\n",
534 "Enabled");
535 else
536 vty_out(vty, " Advertise-gw-macip : %s\n",
537 "Disabled");
538 if (!vpn->advertise_svi_macip && bgp_evpn &&
539 bgp_evpn->evpn_info->advertise_svi_macip)
540 vty_out(vty, " Advertise-svi-macip : %s\n",
541 "Active");
542 else if (vpn->advertise_svi_macip)
543 vty_out(vty, " Advertise-svi-macip : %s\n",
544 "Enabled");
545 else
546 vty_out(vty, " Advertise-svi-macip : %s\n",
547 "Disabled");
9daa5d47
AD
548 vty_out(vty, " SVI interface : %s\n",
549 ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
9c92b5f7 550 }
520d5d76 551
9c92b5f7
MK
552 if (!json)
553 vty_out(vty, " Import Route Target:\n");
520d5d76 554
d62a17ae 555 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
556 ecom_str = ecommunity_ecom2str(ecom,
557 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
558
559 if (json)
560 json_object_array_add(json_import_rtl,
561 json_object_new_string(ecom_str));
562 else
563 vty_out(vty, " %s\n", ecom_str);
564
d62a17ae 565 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
566 }
520d5d76 567
9c92b5f7
MK
568 if (json)
569 json_object_object_add(json, "importRts", json_import_rtl);
570 else
571 vty_out(vty, " Export Route Target:\n");
572
d62a17ae 573 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
574 ecom_str = ecommunity_ecom2str(ecom,
575 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
576
577 if (json)
578 json_object_array_add(json_export_rtl,
579 json_object_new_string(ecom_str));
580 else
581 vty_out(vty, " %s\n", ecom_str);
582
d62a17ae 583 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
584 }
9c92b5f7
MK
585
586 if (json)
587 json_object_object_add(json, "exportRts", json_export_rtl);
520d5d76 588}
d62a17ae 589
50f74cf1 590static void show_esi_routes(struct bgp *bgp,
b5e140c8 591 struct bgp_evpn_es *es,
50f74cf1 592 struct vty *vty,
593 json_object *json)
594{
595 int header = 1;
9bcb3eef 596 struct bgp_dest *dest;
40381db7 597 struct bgp_path_info *pi;
50f74cf1 598 uint32_t prefix_cnt, path_cnt;
599 uint64_t tbl_ver;
600
601 prefix_cnt = path_cnt = 0;
602
603 tbl_ver = es->route_table->version;
9bcb3eef
DS
604 for (dest = bgp_table_top(es->route_table); dest;
605 dest = bgp_route_next(dest)) {
50f74cf1 606 int add_prefix_to_json = 0;
50f74cf1 607 json_object *json_paths = NULL;
608 json_object *json_prefix = NULL;
9bcb3eef 609 const struct prefix *p = bgp_dest_get_prefix(dest);
50f74cf1 610
50f74cf1 611 if (json)
612 json_prefix = json_object_new_object();
613
9bcb3eef 614 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 615 if (pi) {
50f74cf1 616 /* Overall header/legend displayed once. */
617 if (header) {
618 bgp_evpn_show_route_header(vty, bgp,
619 tbl_ver, json);
620 header = 0;
621 }
622
623 prefix_cnt++;
624 }
625
626 if (json)
627 json_paths = json_object_new_array();
628
629 /* For EVPN, the prefix is displayed for each path (to fit in
630 * with code that already exists).
631 */
6f94b685 632 for (; pi; pi = pi->next) {
50f74cf1 633 json_object *json_path = NULL;
634
635 if (json)
636 json_path = json_object_new_array();
637
ae248832
MK
638 route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path,
639 false);
50f74cf1 640
641 if (json)
642 json_object_array_add(json_paths, json_path);
643
644 path_cnt++;
645 add_prefix_to_json = 1;
646 }
647
24882500
CS
648 if (json) {
649 if (add_prefix_to_json) {
511211bf
DA
650 json_object_string_addf(json_prefix, "prefix",
651 "%pFX", p);
24882500 652 json_object_int_add(json_prefix, "prefixLen",
b54892e0 653 p->prefixlen);
24882500
CS
654 json_object_object_add(json_prefix, "paths",
655 json_paths);
511211bf
DA
656 json_object_object_addf(json, json_prefix,
657 "%pFX", p);
24882500
CS
658 } else {
659 json_object_free(json_paths);
660 json_object_free(json_prefix);
661 json_paths = NULL;
662 json_prefix = NULL;
663 }
50f74cf1 664 }
665 }
666
667 if (json) {
668 json_object_int_add(json, "numPrefix", prefix_cnt);
669 json_object_int_add(json, "numPaths", path_cnt);
670 } else {
671 if (prefix_cnt == 0)
a2a8153f 672 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
50f74cf1 673 else
674 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
675 prefix_cnt, path_cnt);
676 }
677}
678
229587fb 679/* Display all MAC-IP VNI routes linked to an ES */
58bff4d1
AK
680static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,
681 json_object *json, int detail,
682 bool global_table)
229587fb
AK
683{
684 struct bgp_node *rn;
685 struct bgp_path_info *pi;
686 int header = detail ? 0 : 1;
687 uint32_t path_cnt;
688 struct listnode *node;
689 struct bgp_evpn_es *es;
690 struct bgp_path_es_info *es_info;
691 struct bgp *bgp = bgp_get_evpn();
692 json_object *json_paths = NULL;
693
694 if (!bgp)
695 return;
696
697 path_cnt = 0;
698
699 if (json)
700 json_paths = json_object_new_array();
701
702 RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
58bff4d1 703 struct list *es_list;
229587fb
AK
704
705 if (esi && memcmp(esi, &es->esi, sizeof(*esi)))
706 continue;
707
58bff4d1
AK
708 if (global_table)
709 es_list = es->macip_global_path_list;
710 else
711 es_list = es->macip_evi_path_list;
712
713 for (ALL_LIST_ELEMENTS_RO(es_list, node, es_info)) {
229587fb
AK
714 json_object *json_path = NULL;
715
716 pi = es_info->pi;
717 rn = pi->net;
718
719 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
720 continue;
721
722 /* Overall header/legend displayed once. */
723 if (header) {
724 bgp_evpn_show_route_header(vty, bgp, 0, json);
725 header = 0;
726 }
727
728 path_cnt++;
729
730 if (json)
731 json_path = json_object_new_array();
732
733 if (detail)
4933eaaf 734 route_vty_out_detail(
34c7f35f
SW
735 vty, bgp, rn, bgp_dest_get_prefix(rn),
736 pi, AFI_L2VPN, SAFI_EVPN,
4933eaaf 737 RPKI_NOT_BEING_USED, json_path);
229587fb
AK
738 else
739 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
740 json_path, false);
741
742 if (json)
743 json_object_array_add(json_paths, json_path);
744 }
745 }
746
747 if (json) {
748 json_object_object_add(json, "paths", json_paths);
749 json_object_int_add(json, "numPaths", path_cnt);
750 } else {
751 if (path_cnt == 0)
752 vty_out(vty, "There are no MAC-IP ES paths");
753 else
754 vty_out(vty, "\nDisplayed %u paths\n", path_cnt);
755 vty_out(vty, "\n");
756 }
757}
758
58bff4d1
AK
759static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi,
760 json_object *json, int detail)
761{
a454d9ab 762 bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, false);
58bff4d1
AK
763}
764
765static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi,
766 json_object *json, int detail)
767{
a454d9ab 768 bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true);
58bff4d1
AK
769}
770
852d9f97
SW
771static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn,
772 struct vty *vty, int type, bool mac_table,
773 struct in_addr vtep_ip, json_object *json,
774 int detail)
520d5d76 775{
9bcb3eef 776 struct bgp_dest *dest;
40381db7 777 struct bgp_path_info *pi;
2dd32217 778 struct bgp_table *table;
c7ef6cf2 779 int header = detail ? 0 : 1;
2dd32217 780 uint64_t tbl_ver;
d7c0a89a 781 uint32_t prefix_cnt, path_cnt;
d62a17ae 782
783 prefix_cnt = path_cnt = 0;
784
852d9f97
SW
785 if (mac_table)
786 table = vpn->mac_table;
787 else
788 table = vpn->ip_table;
789
2dd32217 790 tbl_ver = table->version;
9bcb3eef 791 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
b54892e0 792 const struct prefix_evpn *evp =
9bcb3eef 793 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
9c92b5f7 794 int add_prefix_to_json = 0;
9c92b5f7
MK
795 json_object *json_paths = NULL;
796 json_object *json_prefix = NULL;
9bcb3eef 797 const struct prefix *p = bgp_dest_get_prefix(dest);
9c92b5f7 798
d62a17ae 799 if (type && evp->prefix.route_type != type)
800 continue;
801
9c92b5f7
MK
802 if (json)
803 json_prefix = json_object_new_object();
804
9bcb3eef 805 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 806 if (pi) {
d62a17ae 807 /* Overall header/legend displayed once. */
808 if (header) {
2dd32217 809 bgp_evpn_show_route_header(vty, bgp,
810 tbl_ver, json);
d62a17ae 811 header = 0;
812 }
813
814 prefix_cnt++;
815 }
816
9c92b5f7
MK
817 if (json)
818 json_paths = json_object_new_array();
819
d62a17ae 820 /* For EVPN, the prefix is displayed for each path (to fit in
821 * with code that already exists).
822 */
6f94b685 823 for (; pi; pi = pi->next) {
34c7f35f 824 struct prefix tmp_p;
9c92b5f7
MK
825 json_object *json_path = NULL;
826
975a328e 827 if (vtep_ip.s_addr != INADDR_ANY
d62a17ae 828 && !IPV4_ADDR_SAME(&(vtep_ip),
40381db7 829 &(pi->attr->nexthop)))
d62a17ae 830 continue;
831
34c7f35f
SW
832 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
833 /*
852d9f97
SW
834 * VNI IP/MAC table prefixes don't have MAC/IP
835 * respectively so make sure it's set from path
836 * info here.
34c7f35f 837 */
852d9f97
SW
838 if (is_evpn_prefix_ipaddr_none(evp)) {
839 /* VNI MAC -> Global */
840 evpn_type2_prefix_global_copy(
841 (struct prefix_evpn *)&tmp_p,
842 evp, NULL /* mac */,
843 evpn_type2_path_info_get_ip(
844 pi));
845 } else {
846 /* VNI IP -> Global */
847 evpn_type2_prefix_global_copy(
848 (struct prefix_evpn *)&tmp_p,
849 evp,
850 evpn_type2_path_info_get_mac(
851 pi),
852 NULL /* ip */);
853 }
34c7f35f
SW
854 } else
855 memcpy(&tmp_p, p, sizeof(tmp_p));
856
857
9c92b5f7
MK
858 if (json)
859 json_path = json_object_new_array();
860
c7ef6cf2 861 if (detail)
34c7f35f 862 route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,
c7ef6cf2 863 AFI_L2VPN, SAFI_EVPN,
4933eaaf 864 RPKI_NOT_BEING_USED,
c7ef6cf2 865 json_path);
852d9f97 866
c7ef6cf2 867 else
34c7f35f 868 route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,
ae248832 869 json_path, false);
9c92b5f7
MK
870
871 if (json)
872 json_object_array_add(json_paths, json_path);
873
d62a17ae 874 path_cnt++;
9c92b5f7
MK
875 add_prefix_to_json = 1;
876 }
877
24882500
CS
878 if (json) {
879 if (add_prefix_to_json) {
511211bf
DA
880 json_object_string_addf(json_prefix, "prefix",
881 "%pFX", p);
24882500 882 json_object_int_add(json_prefix, "prefixLen",
b54892e0 883 p->prefixlen);
24882500
CS
884 json_object_object_add(json_prefix, "paths",
885 json_paths);
511211bf
DA
886 json_object_object_addf(json, json_prefix,
887 "%pFX", p);
24882500
CS
888 } else {
889 json_object_free(json_paths);
890 json_object_free(json_prefix);
891 json_paths = NULL;
892 json_prefix = NULL;
893 }
d62a17ae 894 }
895 }
896
9c92b5f7
MK
897 if (json) {
898 json_object_int_add(json, "numPrefix", prefix_cnt);
899 json_object_int_add(json, "numPaths", path_cnt);
900 } else {
901 if (prefix_cnt == 0)
902 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
903 type ? "(of requested type) " : "");
904 else
50f74cf1 905 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
9c92b5f7
MK
906 prefix_cnt, path_cnt,
907 type ? " (of requested type)" : "");
c7ef6cf2 908 vty_out(vty, "\n");
9c92b5f7 909 }
520d5d76 910}
911
e3b78da8 912static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
520d5d76 913{
e3b78da8 914 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
d62a17ae 915 struct vni_walk_ctx *wctx = arg;
916 struct vty *vty = wctx->vty;
9c92b5f7
MK
917 json_object *json = wctx->json;
918 json_object *json_vni = NULL;
919 char vni_str[VNI_STR_LEN];
920
339af96e 921 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
9c92b5f7
MK
922 if (json) {
923 json_vni = json_object_new_object();
924 json_object_int_add(json_vni, "vni", vpn->vni);
925 } else {
339af96e 926 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
9c92b5f7
MK
927 }
928
852d9f97
SW
929 show_vni_routes(wctx->bgp, vpn, wctx->vty, wctx->type, wctx->mac_table,
930 wctx->vtep_ip, json_vni, wctx->detail);
931
932 if (json)
933 json_object_object_add(json, vni_str, json_vni);
934}
935
936static void show_vni_routes_all_hash(struct hash_bucket *bucket, void *arg)
937{
938 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
939 struct vni_walk_ctx *wctx = arg;
940 struct vty *vty = wctx->vty;
941 json_object *json = wctx->json;
942 json_object *json_vni = NULL;
943 json_object *json_vni_mac = NULL;
944 char vni_str[VNI_STR_LEN];
945
339af96e 946 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
9c92b5f7
MK
947 if (json) {
948 json_vni = json_object_new_object();
949 json_object_int_add(json_vni, "vni", vpn->vni);
950 } else {
339af96e 951 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
9c92b5f7
MK
952 }
953
852d9f97
SW
954 show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, false, wctx->vtep_ip,
955 json_vni, wctx->detail);
520d5d76 956
9c92b5f7
MK
957 if (json)
958 json_object_object_add(json, vni_str, json_vni);
852d9f97
SW
959
960 if (json)
961 json_vni_mac = json_object_new_object();
962 else
339af96e 963 vty_out(vty, "\nVNI: %u MAC Table\n\n", vpn->vni);
852d9f97
SW
964
965 show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, true, wctx->vtep_ip,
966 json_vni_mac, wctx->detail);
967
968 if (json)
969 json_object_object_add(json_vni, "macTable", json_vni_mac);
520d5d76 970}
971
4cce389e 972static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
996c9314 973 json_object *json)
4cce389e 974{
dcfe4716
DS
975 json_object *json_vni = NULL;
976 json_object *json_import_rtl = NULL;
977 json_object *json_export_rtl = NULL;
4cce389e
MK
978 char buf1[10];
979 char buf2[INET6_ADDRSTRLEN];
980 char rt_buf[25];
981 char *ecom_str;
982 struct listnode *node, *nnode;
ca337b46 983 struct vrf_route_target *l3rt;
4cce389e
MK
984
985 if (!bgp->l3vni)
986 return;
987
988 if (json) {
989 json_vni = json_object_new_object();
990 json_import_rtl = json_object_new_array();
991 json_export_rtl = json_object_new_array();
992 }
993
994 /* if an l3vni is present in bgp it is live */
995 buf1[0] = '\0';
772270f3 996 snprintf(buf1, sizeof(buf1), "*");
4cce389e
MK
997
998 if (json) {
999 json_object_int_add(json_vni, "vni", bgp->l3vni);
1000 json_object_string_add(json_vni, "type", "L3");
1001 json_object_string_add(json_vni, "inKernel", "True");
c949c771
DA
1002 json_object_string_addf(json_vni, "originatorIp", "%pI4",
1003 &bgp->originator_ip);
4a8cd6ad
PG
1004 json_object_string_addf(json_vni, "rd",
1005 BGP_RD_AS_FORMAT(bgp->asnotation),
1006 &bgp->vrf_prd);
7c9cb387
CS
1007 json_object_string_add(json_vni, "advertiseGatewayMacip",
1008 "n/a");
0b509723 1009 json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
7c9cb387
CS
1010 json_object_string_add(
1011 json_vni, "advertisePip",
1012 bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
c949c771
DA
1013 json_object_string_addf(json_vni, "sysIP", "%pI4",
1014 &bgp->evpn_info->pip_ip);
7c9cb387
CS
1015 json_object_string_add(json_vni, "sysMAC",
1016 prefix_mac2str(&bgp->evpn_info->pip_rmac,
1017 buf2, sizeof(buf2)));
1018 json_object_string_add(
1019 json_vni, "rmac",
1020 prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
4cce389e 1021 } else {
4a8cd6ad
PG
1022 vty_out(vty, "%-1s %-10u %-4s ", buf1, bgp->l3vni, "L3");
1023 vty_out(vty, BGP_RD_AS_FORMAT_SPACE(bgp->asnotation),
c4f64ea9 1024 &bgp->vrf_prd);
4cce389e
MK
1025 }
1026
ca337b46
SW
1027 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, l3rt)) {
1028 ecom_str = ecommunity_ecom2str(l3rt->ecom,
4cce389e
MK
1029 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1030
1031 if (json) {
1032 json_object_array_add(json_import_rtl,
1033 json_object_new_string(ecom_str));
1034 } else {
1035 if (listcount(bgp->vrf_import_rtl) > 1)
772270f3
QY
1036 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1037 ecom_str);
4cce389e 1038 else
772270f3
QY
1039 snprintf(rt_buf, sizeof(rt_buf), "%s",
1040 ecom_str);
4cce389e
MK
1041 vty_out(vty, " %-25s", rt_buf);
1042 }
1043
1044 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1045
1046 /* If there are multiple import RTs we break here and show only
1047 * one */
1048 if (!json)
1049 break;
1050 }
1051
1052 if (json)
1053 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1054
ca337b46
SW
1055 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, l3rt)) {
1056 ecom_str = ecommunity_ecom2str(l3rt->ecom,
4cce389e
MK
1057 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1058
1059 if (json) {
1060 json_object_array_add(json_export_rtl,
1061 json_object_new_string(ecom_str));
1062 } else {
1063 if (listcount(bgp->vrf_export_rtl) > 1)
772270f3
QY
1064 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1065 ecom_str);
4cce389e 1066 else
772270f3
QY
1067 snprintf(rt_buf, sizeof(rt_buf), "%s",
1068 ecom_str);
4cce389e
MK
1069 vty_out(vty, " %-25s", rt_buf);
1070 }
1071
1072 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1073
1074 /* If there are multiple export RTs we break here and show only
1075 * one */
8248a4bc
DA
1076 if (!json) {
1077 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
4cce389e 1078 break;
8248a4bc 1079 }
4cce389e
MK
1080 }
1081
4cce389e
MK
1082 if (json) {
1083 char vni_str[VNI_STR_LEN];
1084
1085 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
772270f3 1086 snprintf(vni_str, sizeof(vni_str), "%u", bgp->l3vni);
4cce389e
MK
1087 json_object_object_add(json, vni_str, json_vni);
1088 } else {
1089 vty_out(vty, "\n");
1090 }
1091}
1092
e3b78da8 1093static void show_vni_entry(struct hash_bucket *bucket, void *args[])
520d5d76 1094{
9c92b5f7
MK
1095 struct vty *vty;
1096 json_object *json;
fb8f41e4
RB
1097 json_object *json_vni = NULL;
1098 json_object *json_import_rtl = NULL;
1099 json_object *json_export_rtl = NULL;
e3b78da8 1100 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
d62a17ae 1101 char buf1[10];
d62a17ae 1102 char rt_buf[25];
1103 char *ecom_str;
1104 struct listnode *node, *nnode;
1105 struct ecommunity *ecom;
7c9cb387 1106 struct bgp *bgp_evpn;
4a8cd6ad 1107 enum asnotation_mode asnotation;
520d5d76 1108
9c92b5f7
MK
1109 vty = args[0];
1110 json = args[1];
1111
7c9cb387 1112 bgp_evpn = bgp_get_evpn();
4a8cd6ad 1113 asnotation = bgp_get_asnotation(bgp_evpn);
7c9cb387 1114
9c92b5f7
MK
1115 if (json) {
1116 json_vni = json_object_new_object();
1117 json_import_rtl = json_object_new_array();
1118 json_export_rtl = json_object_new_array();
1119 }
1120
d62a17ae 1121 buf1[0] = '\0';
1122 if (is_vni_live(vpn))
772270f3 1123 snprintf(buf1, sizeof(buf1), "*");
520d5d76 1124
9c92b5f7
MK
1125 if (json) {
1126 json_object_int_add(json_vni, "vni", vpn->vni);
4cce389e 1127 json_object_string_add(json_vni, "type", "L2");
9c92b5f7
MK
1128 json_object_string_add(json_vni, "inKernel",
1129 is_vni_live(vpn) ? "True" : "False");
4a8cd6ad
PG
1130 json_object_string_addf(json_vni, "rd",
1131 BGP_RD_AS_FORMAT(asnotation),
1132 &vpn->prd);
c949c771
DA
1133 json_object_string_addf(json_vni, "originatorIp", "%pI4",
1134 &vpn->originator_ip);
1135 json_object_string_addf(json_vni, "mcastGroup", "%pI4",
1136 &vpn->mcast_grp);
7c9cb387
CS
1137 /* per vni knob is enabled -- Enabled
1138 * Global knob is enabled -- Active
1139 * default -- Disabled
1140 */
1141 if (!vpn->advertise_gw_macip && bgp_evpn
1142 && bgp_evpn->advertise_gw_macip)
1143 json_object_string_add(
1144 json_vni, "advertiseGatewayMacip", "Active");
1145 else if (vpn->advertise_gw_macip)
1146 json_object_string_add(
1147 json_vni, "advertiseGatewayMacip", "Enabled");
1148 else
1149 json_object_string_add(
1150 json_vni, "advertiseGatewayMacip", "Disabled");
1151 if (!vpn->advertise_svi_macip && bgp_evpn
1152 && bgp_evpn->evpn_info->advertise_svi_macip)
0b509723 1153 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387
CS
1154 "Active");
1155 else if (vpn->advertise_svi_macip)
0b509723 1156 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387
CS
1157 "Enabled");
1158 else
0b509723 1159 json_object_string_add(json_vni, "advertiseSviMacIp",
7c9cb387 1160 "Disabled");
9c92b5f7 1161 } else {
4a8cd6ad
PG
1162 vty_out(vty, "%-1s %-10u %-4s ", buf1, vpn->vni, "L2");
1163 vty_out(vty, BGP_RD_AS_FORMAT_SPACE(asnotation), &vpn->prd);
9c92b5f7 1164 }
520d5d76 1165
d62a17ae 1166 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1167 ecom_str = ecommunity_ecom2str(ecom,
1168 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
520d5d76 1169
9c92b5f7
MK
1170 if (json) {
1171 json_object_array_add(json_import_rtl,
1172 json_object_new_string(ecom_str));
1173 } else {
1174 if (listcount(vpn->import_rtl) > 1)
772270f3
QY
1175 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1176 ecom_str);
9c92b5f7 1177 else
772270f3
QY
1178 snprintf(rt_buf, sizeof(rt_buf), "%s",
1179 ecom_str);
9c92b5f7
MK
1180 vty_out(vty, " %-25s", rt_buf);
1181 }
520d5d76 1182
d62a17ae 1183 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
1184
1185 /* If there are multiple import RTs we break here and show only
1186 * one */
1187 if (!json)
1188 break;
d62a17ae 1189 }
1190
9c92b5f7
MK
1191 if (json)
1192 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1193
d62a17ae 1194 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1195 ecom_str = ecommunity_ecom2str(ecom,
1196 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1197
9c92b5f7
MK
1198 if (json) {
1199 json_object_array_add(json_export_rtl,
1200 json_object_new_string(ecom_str));
1201 } else {
1202 if (listcount(vpn->export_rtl) > 1)
772270f3
QY
1203 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1204 ecom_str);
9c92b5f7 1205 else
772270f3
QY
1206 snprintf(rt_buf, sizeof(rt_buf), "%s",
1207 ecom_str);
9c92b5f7
MK
1208 vty_out(vty, " %-25s", rt_buf);
1209 }
d62a17ae 1210
1211 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
1212
1213 /* If there are multiple export RTs we break here and show only
1214 * one */
8248a4bc
DA
1215 if (!json) {
1216 vty_out(vty, "%-37s",
1217 vrf_id_to_name(vpn->tenant_vrf_id));
9c92b5f7 1218 break;
8248a4bc 1219 }
9c92b5f7
MK
1220 }
1221
1222 if (json) {
1223 char vni_str[VNI_STR_LEN];
b682f6de 1224
9c92b5f7 1225 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
772270f3 1226 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
9c92b5f7
MK
1227 json_object_object_add(json, vni_str, json_vni);
1228 } else {
1229 vty_out(vty, "\n");
d62a17ae 1230 }
520d5d76 1231}
1232
d62a17ae 1233static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1234 enum bgp_show_type type, void *output_arg,
9f049418 1235 int option, bool use_json)
784d3a42 1236{
4d0e6ece
PG
1237 afi_t afi = AFI_L2VPN;
1238 struct bgp *bgp;
1239 struct bgp_table *table;
9bcb3eef
DS
1240 struct bgp_dest *dest;
1241 struct bgp_dest *rm;
40381db7 1242 struct bgp_path_info *pi;
4d0e6ece
PG
1243 int rd_header;
1244 int header = 1;
c69e79f1 1245 char rd_str[RD_ADDRSTRLEN];
0afbd728 1246 int no_display;
4d0e6ece
PG
1247
1248 unsigned long output_count = 0;
1249 unsigned long total_count = 0;
1250 json_object *json = NULL;
4d0e6ece 1251 json_object *json_array = NULL;
597f4b1a
LK
1252 json_object *json_prefix_info = NULL;
1253
c69e79f1 1254 memset(rd_str, 0, RD_ADDRSTRLEN);
4d0e6ece 1255
530db8dc 1256 bgp = bgp_get_evpn();
4d0e6ece
PG
1257 if (bgp == NULL) {
1258 if (!use_json)
d62a17ae 1259 vty_out(vty, "No BGP process is configured\n");
16307668
RW
1260 else
1261 vty_out(vty, "{}\n");
4d0e6ece
PG
1262 return CMD_WARNING;
1263 }
1264
597f4b1a 1265 if (use_json)
4d0e6ece 1266 json = json_object_new_object();
4d0e6ece 1267
9bcb3eef
DS
1268 for (dest = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); dest;
1269 dest = bgp_route_next(dest)) {
2dd32217 1270 uint64_t tbl_ver;
c69e79f1 1271 json_object *json_nroute = NULL;
9bcb3eef 1272 const struct prefix *p = bgp_dest_get_prefix(dest);
2dd32217 1273
b54892e0 1274 if (prd && memcmp(p->u.val, prd->val, 8) != 0)
4d0e6ece
PG
1275 continue;
1276
9bcb3eef 1277 table = bgp_dest_get_bgp_table_info(dest);
67009e22 1278 if (!table)
ea47320b 1279 continue;
4d0e6ece 1280
ea47320b 1281 rd_header = 1;
2dd32217 1282 tbl_ver = table->version;
4d0e6ece 1283
0ac811af 1284 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
9bcb3eef 1285 pi = bgp_dest_get_bgp_path_info(rm);
0afbd728
KA
1286 if (pi == NULL)
1287 continue;
1288
1289 no_display = 0;
0afbd728 1290 for (; pi; pi = pi->next) {
9a706b42
DA
1291 struct community *picomm = NULL;
1292
1293 picomm = bgp_attr_get_community(pi->attr);
1294
ea47320b
DL
1295 total_count++;
1296 if (type == bgp_show_type_neighbor) {
dcc1615e 1297 struct peer *peer = output_arg;
ea47320b 1298
dcc1615e 1299 if (peer_cmp(peer, pi->peer) != 0)
ea47320b
DL
1300 continue;
1301 }
7f433a5e
LK
1302 if (type == bgp_show_type_lcommunity_exact) {
1303 struct lcommunity *lcom = output_arg;
1304
1bcf3a96
DA
1305 if (!bgp_attr_get_lcommunity(
1306 pi->attr) ||
1307 !lcommunity_cmp(
1308 bgp_attr_get_lcommunity(
1309 pi->attr),
1310 lcom))
7f433a5e
LK
1311 continue;
1312 }
1313 if (type == bgp_show_type_lcommunity) {
1314 struct lcommunity *lcom = output_arg;
1315
1bcf3a96
DA
1316 if (!bgp_attr_get_lcommunity(
1317 pi->attr) ||
1318 !lcommunity_match(
1319 bgp_attr_get_lcommunity(
1320 pi->attr),
1321 lcom))
7f433a5e
LK
1322 continue;
1323 }
1324 if (type == bgp_show_type_community) {
1325 struct community *com = output_arg;
1326
9a706b42
DA
1327 if (!picomm ||
1328 !community_match(picomm, com))
7f433a5e
LK
1329 continue;
1330 }
1331 if (type == bgp_show_type_community_exact) {
1332 struct community *com = output_arg;
1333
9a706b42
DA
1334 if (!picomm ||
1335 !community_cmp(picomm, com))
7f433a5e
LK
1336 continue;
1337 }
597f4b1a 1338 if (header) {
ea47320b 1339 if (use_json) {
597f4b1a
LK
1340 json_object_int_add(
1341 json, "bgpTableVersion",
1342 tbl_ver);
c949c771 1343 json_object_string_addf(
597f4b1a
LK
1344 json,
1345 "bgpLocalRouterId",
c949c771
DA
1346 "%pI4",
1347 &bgp->router_id);
597f4b1a
LK
1348 json_object_int_add(
1349 json,
1350 "defaultLocPrf",
1351 bgp->default_local_pref);
e84c7c12
PG
1352 asn_asn2json(json, "localAS",
1353 bgp->as,
1354 bgp->asnotation);
ea47320b 1355 } else {
60466a63 1356 if (option == SHOW_DISPLAY_TAGS)
ea47320b
DL
1357 vty_out(vty,
1358 V4_HEADER_TAG);
1359 else if (
1360 option
1361 == SHOW_DISPLAY_OVERLAY)
1362 vty_out(vty,
1363 V4_HEADER_OVERLAY);
1364 else {
0afbd728 1365 bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
4d0e6ece 1366 }
4d0e6ece 1367 }
ea47320b 1368 header = 0;
4d0e6ece 1369 }
ea47320b 1370 if (rd_header) {
c69e79f1
LK
1371 if (use_json)
1372 json_nroute =
1373 json_object_new_object();
9bcb3eef
DS
1374 bgp_evpn_show_route_rd_header(
1375 vty, dest, json_nroute, rd_str,
c69e79f1 1376 RD_ADDRSTRLEN);
ea47320b
DL
1377 rd_header = 0;
1378 }
c69e79f1
LK
1379 if (use_json && !json_array)
1380 json_array = json_object_new_array();
0ac811af 1381
ea47320b 1382 if (option == SHOW_DISPLAY_TAGS)
b54892e0 1383 route_vty_out_tag(
9bcb3eef 1384 vty, bgp_dest_get_prefix(rm),
b54892e0
DS
1385 pi, no_display, SAFI_EVPN,
1386 json_array);
ea47320b 1387 else if (option == SHOW_DISPLAY_OVERLAY)
b54892e0 1388 route_vty_out_overlay(
9bcb3eef 1389 vty, bgp_dest_get_prefix(rm),
b54892e0 1390 pi, no_display, json_array);
ea47320b 1391 else
b54892e0 1392 route_vty_out(vty,
9bcb3eef 1393 bgp_dest_get_prefix(rm),
b54892e0 1394 pi, no_display, SAFI_EVPN,
ae248832 1395 json_array, false);
0afbd728 1396 no_display = 1;
ea47320b 1397 }
0afbd728
KA
1398
1399 if (no_display)
1400 output_count++;
1401
c69e79f1 1402 if (use_json && json_array) {
b54892e0 1403 const struct prefix *p =
9bcb3eef 1404 bgp_dest_get_prefix(rm);
b54892e0 1405
c69e79f1
LK
1406 json_prefix_info = json_object_new_object();
1407
511211bf
DA
1408 json_object_string_addf(json_prefix_info,
1409 "prefix", "%pFX", p);
c69e79f1
LK
1410
1411 json_object_int_add(json_prefix_info,
b54892e0 1412 "prefixLen", p->prefixlen);
c69e79f1 1413
0ac811af
LK
1414 json_object_object_add(json_prefix_info,
1415 "paths", json_array);
511211bf
DA
1416 json_object_object_addf(json_nroute,
1417 json_prefix_info,
1418 "%pFX", p);
c69e79f1 1419 json_array = NULL;
0ac811af
LK
1420 }
1421 }
597f4b1a 1422
c69e79f1 1423 if (use_json && json_nroute)
597f4b1a 1424 json_object_object_add(json, rd_str, json_nroute);
597f4b1a
LK
1425 }
1426
1427 if (use_json) {
1428 json_object_int_add(json, "numPrefix", output_count);
1429 json_object_int_add(json, "totalPrefix", total_count);
75eeda93 1430 vty_json(vty, json);
597f4b1a
LK
1431 } else {
1432 if (output_count == 0)
1433 vty_out(vty, "No prefixes displayed, %ld exist\n",
1434 total_count);
1435 else
1436 vty_out(vty,
1437 "\nDisplayed %ld out of %ld total prefixes\n",
1438 output_count, total_count);
4d0e6ece 1439 }
4d0e6ece 1440 return CMD_SUCCESS;
784d3a42
PG
1441}
1442
4d0e6ece
PG
1443DEFUN(show_ip_bgp_l2vpn_evpn,
1444 show_ip_bgp_l2vpn_evpn_cmd,
1445 "show [ip] bgp l2vpn evpn [json]",
1446 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
784d3a42 1447{
a111dd97
TA
1448 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1449 SHOW_DISPLAY_STANDARD,
4d0e6ece 1450 use_json(argc, argv));
784d3a42
PG
1451}
1452
4d0e6ece
PG
1453DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1454 show_ip_bgp_l2vpn_evpn_rd_cmd,
a111dd97 1455 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
4d0e6ece
PG
1456 SHOW_STR
1457 IP_STR
1458 BGP_STR
1459 L2VPN_HELP_STR
1460 EVPN_HELP_STR
1461 "Display information for a route distinguisher\n"
a111dd97
TA
1462 "VPN Route Distinguisher\n"
1463 "All VPN Route Distinguishers\n"
1464 JSON_STR)
784d3a42 1465{
313605cb 1466 int idx_ext_community = 0;
4d0e6ece
PG
1467 int ret;
1468 struct prefix_rd prd;
a111dd97 1469 int rd_all = 0;
313605cb 1470
9b01d289 1471 if (argv_find(argv, argc, "all", &rd_all))
a111dd97
TA
1472 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1473 NULL, SHOW_DISPLAY_STANDARD,
1474 use_json(argc, argv));
10794c49 1475
a111dd97 1476 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
4d0e6ece
PG
1477 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1478 if (!ret) {
d62a17ae 1479 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1480 return CMD_WARNING;
1481 }
a111dd97
TA
1482 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1483 SHOW_DISPLAY_STANDARD,
4d0e6ece 1484 use_json(argc, argv));
784d3a42
PG
1485}
1486
4d0e6ece
PG
1487DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1488 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1489 "show [ip] bgp l2vpn evpn all tags",
1490 SHOW_STR
1491 IP_STR
1492 BGP_STR
1493 L2VPN_HELP_STR
1494 EVPN_HELP_STR
1495 "Display information about all EVPN NLRIs\n"
1496 "Display BGP tags for prefixes\n")
784d3a42 1497{
a111dd97
TA
1498 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1499 SHOW_DISPLAY_TAGS, 0);
784d3a42
PG
1500}
1501
4d0e6ece
PG
1502DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1503 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
a111dd97 1504 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
4d0e6ece
PG
1505 SHOW_STR
1506 IP_STR
1507 BGP_STR
1508 L2VPN_HELP_STR
1509 EVPN_HELP_STR
1510 "Display information for a route distinguisher\n"
a111dd97
TA
1511 "VPN Route Distinguisher\n"
1512 "All VPN Route Distinguishers\n"
1513 "Display BGP tags for prefixes\n")
784d3a42 1514{
313605cb 1515 int idx_ext_community = 0;
4d0e6ece
PG
1516 int ret;
1517 struct prefix_rd prd;
a111dd97 1518 int rd_all = 0;
313605cb 1519
9b01d289 1520 if (argv_find(argv, argc, "all", &rd_all))
a111dd97
TA
1521 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1522 NULL, SHOW_DISPLAY_TAGS, 0);
10794c49 1523
a111dd97 1524 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
4d0e6ece
PG
1525 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1526 if (!ret) {
d62a17ae 1527 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1528 return CMD_WARNING;
1529 }
a111dd97
TA
1530 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1531 SHOW_DISPLAY_TAGS, 0);
784d3a42
PG
1532}
1533
dcc1615e
DD
1534DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1535 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1536 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
4d0e6ece
PG
1537 SHOW_STR
1538 IP_STR
1539 BGP_STR
1540 L2VPN_HELP_STR
1541 EVPN_HELP_STR
4d0e6ece 1542 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1543 "IPv4 Neighbor to display information about\n"
1544 "IPv6 Neighbor to display information about\n"
1545 "Neighbor on BGP configured interface\n"
4d0e6ece 1546 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 1547{
dcc1615e 1548 int idx = 0;
4d0e6ece 1549 struct peer *peer;
dcc1615e 1550 char *peerstr = NULL;
9f049418 1551 bool uj = use_json(argc, argv);
dcc1615e
DD
1552 afi_t afi = AFI_L2VPN;
1553 safi_t safi = SAFI_EVPN;
1554 struct bgp *bgp = NULL;
4d0e6ece 1555
dcc1615e
DD
1556 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1557 &bgp, uj);
1558 if (!idx) {
1559 vty_out(vty, "No index\n");
1560 return CMD_WARNING;
1561 }
1562
1563 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1564 argv_find(argv, argc, "neighbors", &idx);
1565 peerstr = argv[++idx]->arg;
313605cb 1566
dcc1615e
DD
1567 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1568 if (!peer) {
4d0e6ece
PG
1569 if (uj) {
1570 json_object *json_no = NULL;
1571 json_no = json_object_new_object();
1572 json_object_string_add(json_no, "warning",
1573 "Malformed address");
d62a17ae 1574 vty_out(vty, "%s\n",
96ade3ed 1575 json_object_to_json_string(json_no));
4d0e6ece
PG
1576 json_object_free(json_no);
1577 } else
d62a17ae 1578 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1579 argv[idx]->arg);
4d0e6ece
PG
1580 return CMD_WARNING;
1581 }
4d0e6ece
PG
1582 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1583 if (uj) {
1584 json_object *json_no = NULL;
1585 json_no = json_object_new_object();
d62a17ae 1586 json_object_string_add(
1587 json_no, "warning",
1588 "No such neighbor or address family");
1589 vty_out(vty, "%s\n",
96ade3ed 1590 json_object_to_json_string(json_no));
4d0e6ece
PG
1591 json_object_free(json_no);
1592 } else
d62a17ae 1593 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1594 return CMD_WARNING;
1595 }
1596
a111dd97
TA
1597 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer,
1598 SHOW_DISPLAY_STANDARD, uj);
784d3a42
PG
1599}
1600
4d0e6ece
PG
1601DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1602 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
a111dd97 1603 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
4d0e6ece
PG
1604 SHOW_STR
1605 IP_STR
1606 BGP_STR
1607 L2VPN_HELP_STR
1608 EVPN_HELP_STR
1609 "Display information for a route distinguisher\n"
1610 "VPN Route Distinguisher\n"
a111dd97 1611 "All VPN Route Distinguishers\n"
4d0e6ece 1612 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1613 "IPv4 Neighbor to display information about\n"
1614 "IPv6 Neighbor to display information about\n"
1615 "Neighbor on BGP configured interface\n"
4d0e6ece 1616 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 1617{
313605cb 1618 int idx_ext_community = 0;
dcc1615e 1619 int idx = 0;
4d0e6ece 1620 int ret;
4d0e6ece 1621 struct peer *peer;
dcc1615e 1622 char *peerstr = NULL;
3d2b35c4 1623 struct prefix_rd prd = {};
9f049418 1624 bool uj = use_json(argc, argv);
dcc1615e
DD
1625 afi_t afi = AFI_L2VPN;
1626 safi_t safi = SAFI_EVPN;
1627 struct bgp *bgp = NULL;
a111dd97 1628 int rd_all = 0;
4d0e6ece 1629
dcc1615e
DD
1630 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1631 &bgp, uj);
1632 if (!idx) {
1633 vty_out(vty, "No index\n");
1634 return CMD_WARNING;
1635 }
313605cb 1636
9b01d289 1637 if (argv_find(argv, argc, "all", &rd_all)) {
a111dd97
TA
1638 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1639 &idx_ext_community);
1640 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1641 if (!ret) {
1642 if (uj) {
1643 json_object *json_no = NULL;
1644 json_no = json_object_new_object();
1645 json_object_string_add(
1646 json_no, "warning",
1647 "Malformed Route Distinguisher");
1648 vty_out(vty, "%s\n",
1649 json_object_to_json_string(json_no));
1650 json_object_free(json_no);
1651 } else
1652 vty_out(vty,
1653 "%% Malformed Route Distinguisher\n");
1654 return CMD_WARNING;
1655 }
4d0e6ece
PG
1656 }
1657
dcc1615e
DD
1658 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1659 argv_find(argv, argc, "neighbors", &idx);
1660 peerstr = argv[++idx]->arg;
1661
1662 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1663 if (!peer) {
4d0e6ece
PG
1664 if (uj) {
1665 json_object *json_no = NULL;
1666 json_no = json_object_new_object();
1667 json_object_string_add(json_no, "warning",
1668 "Malformed address");
d62a17ae 1669 vty_out(vty, "%s\n",
96ade3ed 1670 json_object_to_json_string(json_no));
4d0e6ece
PG
1671 json_object_free(json_no);
1672 } else
d62a17ae 1673 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1674 argv[idx]->arg);
4d0e6ece
PG
1675 return CMD_WARNING;
1676 }
4d0e6ece
PG
1677 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1678 if (uj) {
1679 json_object *json_no = NULL;
1680 json_no = json_object_new_object();
d62a17ae 1681 json_object_string_add(
1682 json_no, "warning",
1683 "No such neighbor or address family");
1684 vty_out(vty, "%s\n",
96ade3ed 1685 json_object_to_json_string(json_no));
4d0e6ece
PG
1686 json_object_free(json_no);
1687 } else
d62a17ae 1688 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1689 return CMD_WARNING;
1690 }
1691
a111dd97
TA
1692
1693 if (rd_all)
1694 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor,
1695 peer, SHOW_DISPLAY_STANDARD, uj);
1696 else
1697 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor,
1698 peer, SHOW_DISPLAY_STANDARD, uj);
784d3a42
PG
1699}
1700
dcc1615e
DD
1701DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1702 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1703 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
4d0e6ece
PG
1704 SHOW_STR
1705 IP_STR
1706 BGP_STR
1707 L2VPN_HELP_STR
1708 EVPN_HELP_STR
4d0e6ece 1709 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1710 "IPv4 Neighbor to display information about\n"
1711 "IPv6 Neighbor to display information about\n"
1712 "Neighbor on BGP configured interface\n"
4d0e6ece 1713 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 1714{
dcc1615e 1715 int idx = 0;
4d0e6ece 1716 struct peer *peer;
9f049418 1717 bool uj = use_json(argc, argv);
dcc1615e
DD
1718 struct bgp *bgp = NULL;
1719 afi_t afi = AFI_L2VPN;
1720 safi_t safi = SAFI_EVPN;
1721 char *peerstr = NULL;
1722
1723 if (uj)
1724 argc--;
4d0e6ece 1725
dcc1615e
DD
1726 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1727 &bgp, uj);
1728 if (!idx) {
1729 vty_out(vty, "No index\n");
1730 return CMD_WARNING;
1731 }
1732
1733 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1734 argv_find(argv, argc, "neighbors", &idx);
1735 peerstr = argv[++idx]->arg;
313605cb 1736
dcc1615e
DD
1737 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1738 if (!peer) {
4d0e6ece
PG
1739 if (uj) {
1740 json_object *json_no = NULL;
1741 json_no = json_object_new_object();
1742 json_object_string_add(json_no, "warning",
1743 "Malformed address");
d62a17ae 1744 vty_out(vty, "%s\n",
96ade3ed 1745 json_object_to_json_string(json_no));
4d0e6ece
PG
1746 json_object_free(json_no);
1747 } else
d62a17ae 1748 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1749 argv[idx]->arg);
4d0e6ece
PG
1750 return CMD_WARNING;
1751 }
4d0e6ece
PG
1752 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1753 if (uj) {
1754 json_object *json_no = NULL;
1755 json_no = json_object_new_object();
d62a17ae 1756 json_object_string_add(
1757 json_no, "warning",
1758 "No such neighbor or address family");
1759 vty_out(vty, "%s\n",
96ade3ed 1760 json_object_to_json_string(json_no));
4d0e6ece
PG
1761 json_object_free(json_no);
1762 } else
d62a17ae 1763 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1764 return CMD_WARNING;
1765 }
1766
1767 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1768}
1769
4d0e6ece
PG
1770DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1771 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
a111dd97 1772 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
4d0e6ece
PG
1773 SHOW_STR
1774 IP_STR
1775 BGP_STR
1776 L2VPN_HELP_STR
1777 EVPN_HELP_STR
1778 "Display information for a route distinguisher\n"
1779 "VPN Route Distinguisher\n"
a111dd97 1780 "All VPN Route Distinguishers\n"
4d0e6ece 1781 "Detailed information on TCP and BGP neighbor connections\n"
dcc1615e
DD
1782 "IPv4 Neighbor to display information about\n"
1783 "IPv6 Neighbor to display information about\n"
1784 "Neighbor on BGP configured interface\n"
4d0e6ece 1785 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 1786{
313605cb 1787 int idx_ext_community = 0;
dcc1615e 1788 int idx = 0;
4d0e6ece
PG
1789 int ret;
1790 struct peer *peer;
1791 struct prefix_rd prd;
dcc1615e 1792 struct bgp *bgp = NULL;
9f049418 1793 bool uj = use_json(argc, argv);
dcc1615e
DD
1794 char *peerstr = NULL;
1795 afi_t afi = AFI_L2VPN;
1796 safi_t safi = SAFI_EVPN;
a111dd97 1797 int rd_all = 0;
dcc1615e
DD
1798
1799 if (uj)
1800 argc--;
1801
1802 if (uj)
1803 argc--;
1804
1805 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1806 &bgp, uj);
1807 if (!idx) {
1808 vty_out(vty, "No index\n");
1809 return CMD_WARNING;
1810 }
4d0e6ece 1811
dcc1615e
DD
1812 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1813 argv_find(argv, argc, "neighbors", &idx);
1814 peerstr = argv[++idx]->arg;
1815
1816 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1817 if (!peer) {
4d0e6ece
PG
1818 if (uj) {
1819 json_object *json_no = NULL;
1820 json_no = json_object_new_object();
1821 json_object_string_add(json_no, "warning",
1822 "Malformed address");
d62a17ae 1823 vty_out(vty, "%s\n",
96ade3ed 1824 json_object_to_json_string(json_no));
4d0e6ece
PG
1825 json_object_free(json_no);
1826 } else
d62a17ae 1827 vty_out(vty, "Malformed address: %s\n",
dcc1615e 1828 argv[idx]->arg);
4d0e6ece
PG
1829 return CMD_WARNING;
1830 }
4d0e6ece
PG
1831 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1832 if (uj) {
1833 json_object *json_no = NULL;
1834 json_no = json_object_new_object();
d62a17ae 1835 json_object_string_add(
1836 json_no, "warning",
1837 "No such neighbor or address family");
1838 vty_out(vty, "%s\n",
96ade3ed 1839 json_object_to_json_string(json_no));
4d0e6ece
PG
1840 json_object_free(json_no);
1841 } else
d62a17ae 1842 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1843 return CMD_WARNING;
1844 }
1845
9b01d289 1846 if (argv_find(argv, argc, "all", &rd_all))
a111dd97
TA
1847 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN,
1848 uj);
1849 else {
1850 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1851 &idx_ext_community);
1852 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1853 if (!ret) {
1854 if (uj) {
1855 json_object *json_no = NULL;
1856 json_no = json_object_new_object();
1857 json_object_string_add(
1858 json_no, "warning",
1859 "Malformed Route Distinguisher");
1860 vty_out(vty, "%s\n",
1861 json_object_to_json_string(json_no));
1862 json_object_free(json_no);
1863 } else
1864 vty_out(vty,
1865 "%% Malformed Route Distinguisher\n");
1866 return CMD_WARNING;
1867 }
4d0e6ece
PG
1868 }
1869
1870 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1871}
1872
4d0e6ece
PG
1873DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1874 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
14f51eba 1875 "show [ip] bgp l2vpn evpn all overlay [json]",
4d0e6ece
PG
1876 SHOW_STR
1877 IP_STR
1878 BGP_STR
1879 L2VPN_HELP_STR
1880 EVPN_HELP_STR
1881 "Display information about all EVPN NLRIs\n"
14f51eba
LK
1882 "Display BGP Overlay Information for prefixes\n"
1883 JSON_STR)
784d3a42 1884{
4d0e6ece 1885 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
d62a17ae 1886 SHOW_DISPLAY_OVERLAY,
1887 use_json(argc, argv));
784d3a42
PG
1888}
1889
4d0e6ece
PG
1890DEFUN(show_ip_bgp_evpn_rd_overlay,
1891 show_ip_bgp_evpn_rd_overlay_cmd,
a111dd97 1892 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
4d0e6ece
PG
1893 SHOW_STR
1894 IP_STR
1895 BGP_STR
1896 L2VPN_HELP_STR
1897 EVPN_HELP_STR
1898 "Display information for a route distinguisher\n"
1899 "VPN Route Distinguisher\n"
a111dd97 1900 "All VPN Route Distinguishers\n"
4d0e6ece 1901 "Display BGP Overlay Information for prefixes\n")
784d3a42 1902{
313605cb 1903 int idx_ext_community = 0;
4d0e6ece
PG
1904 int ret;
1905 struct prefix_rd prd;
a111dd97 1906 int rd_all = 0;
313605cb 1907
9b01d289 1908 if (argv_find(argv, argc, "all", &rd_all))
a111dd97
TA
1909 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1910 NULL, SHOW_DISPLAY_OVERLAY,
1911 use_json(argc, argv));
10794c49 1912
a111dd97 1913 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
4d0e6ece
PG
1914 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1915 if (!ret) {
d62a17ae 1916 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1917 return CMD_WARNING;
1918 }
1919 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
d62a17ae 1920 SHOW_DISPLAY_OVERLAY,
1921 use_json(argc, argv));
784d3a42
PG
1922}
1923
7f433a5e
LK
1924DEFUN(show_bgp_l2vpn_evpn_com,
1925 show_bgp_l2vpn_evpn_com_cmd,
1926 "show bgp l2vpn evpn \
1927 <community AA:NN|large-community AA:BB:CC> \
1928 [exact-match] [json]",
1929 SHOW_STR
1930 BGP_STR
1931 L2VPN_HELP_STR
1932 EVPN_HELP_STR
1933 "Display routes matching the community\n"
1934 "Community number where AA and NN are (0-65535)\n"
1935 "Display routes matching the large-community\n"
1936 "List of large-community numbers\n"
1937 "Exact match of the communities\n"
1938 JSON_STR)
1939{
1940 int idx = 0;
1941 int ret = 0;
1942 const char *clist_number_or_name;
1943 int show_type = bgp_show_type_normal;
1944 struct community *com;
1945 struct lcommunity *lcom;
1946
1947 if (argv_find(argv, argc, "large-community", &idx)) {
1948 clist_number_or_name = argv[++idx]->arg;
1949 show_type = bgp_show_type_lcommunity;
1950
1951 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1952 show_type = bgp_show_type_lcommunity_exact;
1953
1954 lcom = lcommunity_str2com(clist_number_or_name);
1955 if (!lcom) {
1956 vty_out(vty, "%% Large-community malformed\n");
1957 return CMD_WARNING;
1958 }
1959
1960 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1961 SHOW_DISPLAY_STANDARD,
1962 use_json(argc, argv));
1963
1964 lcommunity_free(&lcom);
1965 } else if (argv_find(argv, argc, "community", &idx)) {
1966 clist_number_or_name = argv[++idx]->arg;
1967 show_type = bgp_show_type_community;
1968
1969 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1970 show_type = bgp_show_type_community_exact;
1971
1972 com = community_str2com(clist_number_or_name);
1973
1974 if (!com) {
1975 vty_out(vty, "%% Community malformed: %s\n",
1976 clist_number_or_name);
1977 return CMD_WARNING;
1978 }
1979
1980 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1981 SHOW_DISPLAY_STANDARD,
1982 use_json(argc, argv));
1983 community_free(&com);
1984 }
1985
1986 return ret;
1987}
1988
dcc1615e 1989/* For testing purpose, static route of EVPN RT-5. */
4d0e6ece
PG
1990DEFUN(evpnrt5_network,
1991 evpnrt5_network_cmd,
70dd370f 1992 "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 RMAP_NAME]",
4d0e6ece
PG
1993 "Specify a network to announce via BGP\n"
1994 "IP prefix\n"
1995 "IPv6 prefix\n"
1996 "Specify Route Distinguisher\n"
1997 "VPN Route Distinguisher\n"
1998 "Ethernet Tag\n"
1999 "Ethernet Tag Value\n"
2000 "BGP label\n"
2001 "label value\n"
2002 "Ethernet Segment Identifier\n"
2003 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2004 "Gateway IP\n"
2005 "Gateway IP ( A.B.C.D )\n"
2006 "Gateway IPv6 ( X:X::X:X )\n"
2007 "Router Mac Ext Comm\n"
55daa605
DS
2008 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
2009 "Route-map to modify the attributes\n"
2010 "Name of the route map\n")
3da6fcd5 2011{
4d0e6ece 2012 int idx_ipv4_prefixlen = 1;
197cb530
PG
2013 int idx_route_distinguisher = 3;
2014 int idx_label = 7;
4d0e6ece
PG
2015 int idx_esi = 9;
2016 int idx_gwip = 11;
2017 int idx_ethtag = 5;
2018 int idx_routermac = 13;
197cb530 2019
d62a17ae 2020 return bgp_static_set_safi(
2021 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
996c9314 2022 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
d62a17ae 2023 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2024 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
2025 argv[idx_routermac]->arg);
3da6fcd5
PG
2026}
2027
dcc1615e 2028/* For testing purpose, static route of EVPN RT-5. */
4d0e6ece
PG
2029DEFUN(no_evpnrt5_network,
2030 no_evpnrt5_network_cmd,
d114b977 2031 "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
2032 NO_STR
2033 "Specify a network to announce via BGP\n"
2034 "IP prefix\n"
2035 "IPv6 prefix\n"
2036 "Specify Route Distinguisher\n"
2037 "VPN Route Distinguisher\n"
2038 "Ethernet Tag\n"
2039 "Ethernet Tag Value\n"
2040 "BGP label\n"
2041 "label value\n"
2042 "Ethernet Segment Identifier\n"
2043 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2044 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
3da6fcd5 2045{
4d0e6ece
PG
2046 int idx_ipv4_prefixlen = 2;
2047 int idx_ext_community = 4;
2048 int idx_label = 8;
2049 int idx_ethtag = 6;
2050 int idx_esi = 10;
2051 int idx_gwip = 12;
d62a17ae 2052 return bgp_static_unset_safi(
2053 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
2054 argv[idx_ext_community]->arg, argv[idx_label]->arg,
2055 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2056 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
3da6fcd5
PG
2057}
2058
d62a17ae 2059static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2060{
ca337b46 2061 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl, false);
90e60aa7 2062}
2063
d62a17ae 2064static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2065{
ca337b46 2066 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl, false);
90e60aa7 2067}
2068
2069/*
2070 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2071 * check that this is a change.
2072 */
d62a17ae 2073static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2074 struct ecommunity *ecomadd)
90e60aa7 2075{
d62a17ae 2076 /* If the VNI is "live", we need to uninstall routes using the current
2077 * import RT(s) first before we update the import RT, and subsequently
2078 * install routes.
2079 */
2080 if (is_vni_live(vpn))
2081 bgp_evpn_uninstall_routes(bgp, vpn);
90e60aa7 2082
d62a17ae 2083 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2084 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
90e60aa7 2085
d62a17ae 2086 /* If the auto route-target is in use we must remove it */
2087 evpn_import_rt_delete_auto(bgp, vpn);
90e60aa7 2088
d62a17ae 2089 /* Add new RT and rebuild the RT to VNI mapping */
2090 listnode_add_sort(vpn->import_rtl, ecomadd);
90e60aa7 2091
d62a17ae 2092 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2093 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
90e60aa7 2094
d62a17ae 2095 /* Install routes that match new import RT */
2096 if (is_vni_live(vpn))
2097 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 2098}
2099
2100/*
2101 * Unconfigure Import RT(s) for a VNI (vty handler).
2102 */
d62a17ae 2103static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2104 struct ecommunity *ecomdel)
2105{
2106 struct listnode *node, *nnode, *node_to_del;
2107 struct ecommunity *ecom;
2108
2109 /* Along the lines of "configure" except we have to reset to the
2110 * automatic value.
2111 */
2112 if (is_vni_live(vpn))
2113 bgp_evpn_uninstall_routes(bgp, vpn);
2114
2115 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2116 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
2117
2118 /* Delete all import RTs */
2119 if (ecomdel == NULL) {
1b7db1df 2120 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
d62a17ae 2121 ecommunity_free(&ecom);
1b7db1df
KA
2122 list_delete_node(vpn->import_rtl, node);
2123 }
d62a17ae 2124 }
2125
2126 /* Delete a specific import RT */
2127 else {
2128 node_to_del = NULL;
2129
2130 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
2131 if (ecommunity_match(ecom, ecomdel)) {
2132 ecommunity_free(&ecom);
2133 node_to_del = node;
2134 break;
2135 }
2136 }
2137
2138 if (node_to_del)
2139 list_delete_node(vpn->import_rtl, node_to_del);
2140 }
2141
b3a4db3d 2142 assert(vpn->import_rtl);
d62a17ae 2143 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2144 if (list_isempty(vpn->import_rtl)) {
2145 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2146 bgp_evpn_derive_auto_rt_import(bgp, vpn);
2147 }
2148 /* Rebuild the RT to VNI mapping */
2149 else
2150 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
2151
2152 /* Install routes that match new import RT */
2153 if (is_vni_live(vpn))
2154 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 2155}
2156
2157/*
2158 * Configure the Export RT for a VNI (vty handler). Caller expected to
2159 * check that this is a change. Note that only a single export RT is
2160 * allowed for a VNI and any change to configuration is implemented as
2161 * a "replace" (similar to other configuration).
2162 */
d62a17ae 2163static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2164 struct ecommunity *ecomadd)
90e60aa7 2165{
d62a17ae 2166 /* If the auto route-target is in use we must remove it */
2167 evpn_export_rt_delete_auto(bgp, vpn);
90e60aa7 2168
d62a17ae 2169 listnode_add_sort(vpn->export_rtl, ecomadd);
2170 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
90e60aa7 2171
d62a17ae 2172 if (is_vni_live(vpn))
2173 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 2174}
2175
2176/*
2177 * Unconfigure the Export RT for a VNI (vty handler)
2178 */
d62a17ae 2179static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2180 struct ecommunity *ecomdel)
2181{
2182 struct listnode *node, *nnode, *node_to_del;
2183 struct ecommunity *ecom;
2184
2185 /* Delete all export RTs */
2186 if (ecomdel == NULL) {
2187 /* Reset to default and process all routes. */
1b7db1df 2188 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
d62a17ae 2189 ecommunity_free(&ecom);
1b7db1df
KA
2190 list_delete_node(vpn->export_rtl, node);
2191 }
d62a17ae 2192 }
2193
2194 /* Delete a specific export RT */
2195 else {
2196 node_to_del = NULL;
2197
2198 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2199 if (ecommunity_match(ecom, ecomdel)) {
2200 ecommunity_free(&ecom);
2201 node_to_del = node;
2202 break;
2203 }
2204 }
2205
2206 if (node_to_del)
2207 list_delete_node(vpn->export_rtl, node_to_del);
2208 }
2209
b3a4db3d 2210 assert(vpn->export_rtl);
d62a17ae 2211 if (list_isempty(vpn->export_rtl)) {
2212 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2213 bgp_evpn_derive_auto_rt_export(bgp, vpn);
2214 }
2215
2216 if (is_vni_live(vpn))
2217 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 2218}
2219
676f83b9 2220/*
2221 * Configure RD for VRF
2222 */
fa566a94
PG
2223static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd,
2224 const char *rd_pretty)
676f83b9 2225{
2226 /* If we have already advertise type-5 routes with a diffrent RD, we
523cafc4 2227 * have to delete and withdraw them firs
2228 */
06d2e8f3 2229 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
676f83b9 2230
2231 /* update RD */
2232 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
fa566a94 2233 bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
676f83b9 2234 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2235
2236 /* We have a new RD for VRF.
523cafc4 2237 * Advertise all type-5 routes again with the new RD
2238 */
06d2e8f3 2239 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
676f83b9 2240}
2241
2242/*
2243 * Unconfigure RD for VRF
2244 */
2245static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2246{
2247 /* If we have already advertise type-5 routes with a diffrent RD, we
523cafc4 2248 * have to delete and withdraw them firs
2249 */
06d2e8f3 2250 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
676f83b9 2251
2252 /* fall back to default RD */
2253 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
99b4e972 2254 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
fa566a94
PG
2255 if (bgp_vrf->vrf_prd_pretty)
2256 XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);
676f83b9 2257 /* We have a new RD for VRF.
523cafc4 2258 * Advertise all type-5 routes again with the new RD
2259 */
06d2e8f3 2260 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
676f83b9 2261}
2262
90e60aa7 2263/*
2264 * Configure RD for a VNI (vty handler)
2265 */
d62a17ae 2266static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
fa566a94 2267 struct prefix_rd *rd, const char *rd_pretty)
90e60aa7 2268{
d62a17ae 2269 /* If the VNI is "live", we need to delete and withdraw this VNI's
2270 * local routes with the prior RD first. Then, after updating RD,
2271 * need to re-advertise.
2272 */
2273 if (is_vni_live(vpn))
2274 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 2275
d62a17ae 2276 /* update RD */
2277 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
fa566a94 2278 vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);
d62a17ae 2279 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
90e60aa7 2280
d62a17ae 2281 if (is_vni_live(vpn))
2282 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 2283}
2284
2285/*
2286 * Unconfigure RD for a VNI (vty handler)
2287 */
d62a17ae 2288static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2289{
d62a17ae 2290 /* If the VNI is "live", we need to delete and withdraw this VNI's
2291 * local routes with the prior RD first. Then, after resetting RD
2292 * to automatic value, need to re-advertise.
2293 */
2294 if (is_vni_live(vpn))
2295 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 2296
d62a17ae 2297 /* reset RD to default */
2298 bgp_evpn_derive_auto_rd(bgp, vpn);
90e60aa7 2299
d62a17ae 2300 if (is_vni_live(vpn))
2301 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 2302}
2303
2304/*
2305 * Create VNI, if not already present (VTY handler). Mark as configured.
2306 */
d62a17ae 2307static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
90e60aa7 2308{
d62a17ae 2309 struct bgpevpn *vpn;
76d07c7a 2310 struct in_addr mcast_grp = {INADDR_ANY};
90e60aa7 2311
d62a17ae 2312 vpn = bgp_evpn_lookup_vni(bgp, vni);
2313 if (!vpn) {
7df407ed
CS
2314 /* Check if this L2VNI is already configured as L3VNI */
2315 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
1c50c1c0
QY
2316 flog_err(
2317 EC_BGP_VNI,
2318 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2319 bgp->vrf_id, vni);
7df407ed
CS
2320 return NULL;
2321 }
2322
29c53922 2323 /* tenant vrf will be updated when we get local_vni_add from
523cafc4 2324 * zebra
2325 */
9daa5d47 2326 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp, 0);
d62a17ae 2327 }
90e60aa7 2328
d62a17ae 2329 /* Mark as configured. */
2330 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2331 return vpn;
90e60aa7 2332}
2333
2334/*
2335 * Delete VNI. If VNI does not exist in the system (i.e., just
2336 * configuration), all that is needed is to free it. Otherwise,
2337 * any parameters configured for the VNI need to be reset (with
2338 * appropriate action) and the VNI marked as unconfigured; the
2339 * VNI will continue to exist, purely as a "learnt" entity.
2340 */
3dc339cd 2341static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 2342{
d62a17ae 2343 if (!is_vni_live(vpn)) {
2344 bgp_evpn_free(bgp, vpn);
3dc339cd 2345 return;
d62a17ae 2346 }
90e60aa7 2347
d62a17ae 2348 /* We need to take the unconfigure action for each parameter of this VNI
2349 * that is configured. Some optimization is possible, but not worth the
2350 * additional code for an operation that should be pretty rare.
2351 */
2352 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
90e60aa7 2353
d62a17ae 2354 /* First, deal with the export side - RD and export RT changes. */
2355 if (is_rd_configured(vpn))
2356 evpn_unconfigure_rd(bgp, vpn);
2357 if (is_export_rt_configured(vpn))
2358 evpn_unconfigure_export_rt(bgp, vpn, NULL);
90e60aa7 2359
d62a17ae 2360 /* Next, deal with the import side. */
2361 if (is_import_rt_configured(vpn))
2362 evpn_unconfigure_import_rt(bgp, vpn, NULL);
90e60aa7 2363}
2364
10ebe1ab
MK
2365/*
2366 * Display import RT mapping to VRFs (vty handler)
5e53dce3 2367 * bgp_evpn: evpn bgp instance
10ebe1ab 2368 */
5e53dce3 2369static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
10ebe1ab
MK
2370 json_object *json)
2371{
2372 void *args[2];
2373
2374 args[0] = vty;
2375 args[1] = json;
2376
5e53dce3 2377 hash_iterate(bgp_evpn->vrf_import_rt_hash,
e3b78da8 2378 (void (*)(struct hash_bucket *,
996c9314 2379 void *))show_vrf_import_rt_entry,
10ebe1ab
MK
2380 args);
2381}
2382
520d5d76 2383/*
2384 * Display import RT mapping to VNIs (vty handler)
2385 */
9c92b5f7
MK
2386static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2387 json_object *json)
520d5d76 2388{
9c92b5f7
MK
2389 void *args[2];
2390
2391 args[0] = vty;
2392 args[1] = json;
2393
d62a17ae 2394 hash_iterate(
2395 bgp->import_rt_hash,
e3b78da8 2396 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
9c92b5f7 2397 args);
520d5d76 2398}
2399
2400/*
2401 * Display EVPN routes for all VNIs - vty handler.
2402 */
852d9f97
SW
2403static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, int type,
2404 bool mac_table, struct in_addr vtep_ip,
2405 json_object *json, int detail)
520d5d76 2406{
d7c0a89a 2407 uint32_t num_vnis;
d62a17ae 2408 struct vni_walk_ctx wctx;
520d5d76 2409
d62a17ae 2410 num_vnis = hashcount(bgp->vnihash);
2411 if (!num_vnis)
2412 return;
6006b807 2413 memset(&wctx, 0, sizeof(wctx));
d62a17ae 2414 wctx.bgp = bgp;
2415 wctx.vty = vty;
852d9f97
SW
2416 wctx.type = type;
2417 wctx.mac_table = mac_table;
d62a17ae 2418 wctx.vtep_ip = vtep_ip;
9c92b5f7 2419 wctx.json = json;
c7ef6cf2 2420 wctx.detail = detail;
e3b78da8 2421 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
9d303b37
DL
2422 void *))show_vni_routes_hash,
2423 &wctx);
520d5d76 2424}
2425
852d9f97
SW
2426/*
2427 * Display EVPN routes for all VNIs & all types - vty handler.
2428 */
2429static void evpn_show_routes_vni_all_type_all(struct vty *vty, struct bgp *bgp,
2430 struct in_addr vtep_ip,
2431 json_object *json, int detail)
2432{
2433 uint32_t num_vnis;
2434 struct vni_walk_ctx wctx;
2435
2436 num_vnis = hashcount(bgp->vnihash);
2437 if (!num_vnis)
2438 return;
2439
2440 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2441 wctx.bgp = bgp;
2442 wctx.vty = vty;
2443 wctx.vtep_ip = vtep_ip;
2444 wctx.json = json;
2445 wctx.detail = detail;
2446 hash_iterate(bgp->vnihash,
2447 (void (*)(struct hash_bucket *,
2448 void *))show_vni_routes_all_hash,
2449 &wctx);
2450}
2451
520d5d76 2452/*
2453 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2454 */
d62a17ae 2455static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2456 vni_t vni, struct in_addr orig_ip,
2457 json_object *json)
d62a17ae 2458{
2459 struct bgpevpn *vpn;
2460 struct prefix_evpn p;
9bcb3eef 2461 struct bgp_dest *dest;
40381db7 2462 struct bgp_path_info *pi;
d7c0a89a 2463 uint32_t path_cnt = 0;
d62a17ae 2464 afi_t afi;
2465 safi_t safi;
9c92b5f7 2466 json_object *json_paths = NULL;
d62a17ae 2467
2468 afi = AFI_L2VPN;
2469 safi = SAFI_EVPN;
2470
2471 /* Locate VNI. */
2472 vpn = bgp_evpn_lookup_vni(bgp, vni);
2473 if (!vpn) {
2474 vty_out(vty, "VNI not found\n");
2475 return;
2476 }
2477
2478 /* See if route exists. */
2479 build_evpn_type3_prefix(&p, orig_ip);
852d9f97 2480 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
9bcb3eef 2481 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2482 if (!json)
2483 vty_out(vty, "%% Network not in table\n");
e71ad4b6
DA
2484
2485 if (dest)
2486 bgp_dest_unlock_node(dest);
2487
d62a17ae 2488 return;
2489 }
2490
9c92b5f7
MK
2491 if (json)
2492 json_paths = json_object_new_array();
2493
d62a17ae 2494 /* Prefix and num paths displayed once per prefix. */
34c7f35f 2495 route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
f9f2d188 2496 NULL, afi, safi, json, false);
d62a17ae 2497
2498 /* Display each path for this prefix. */
9bcb3eef 2499 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2500 json_object *json_path = NULL;
2501
2502 if (json)
2503 json_path = json_object_new_array();
2504
34c7f35f
SW
2505 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2506 pi, afi, safi, RPKI_NOT_BEING_USED,
2507 json_path);
9c92b5f7
MK
2508
2509 if (json)
2510 json_object_array_add(json_paths, json_path);
2511
d62a17ae 2512 path_cnt++;
2513 }
2514
9c92b5f7
MK
2515 if (json) {
2516 if (path_cnt)
2517 json_object_object_add(json, "paths", json_paths);
2518
2519 json_object_int_add(json, "numPaths", path_cnt);
2520 } else {
2521 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2522 path_cnt);
2523 }
e71ad4b6
DA
2524
2525 bgp_dest_unlock_node(dest);
520d5d76 2526}
2527
2528/*
2529 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2530 * By definition, only matching type-2 route will be displayed.
2531 */
d62a17ae 2532static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2533 vni_t vni, struct ethaddr *mac,
9c92b5f7 2534 struct ipaddr *ip, json_object *json)
d62a17ae 2535{
2536 struct bgpevpn *vpn;
2537 struct prefix_evpn p;
34c7f35f 2538 struct prefix_evpn tmp_p;
9bcb3eef 2539 struct bgp_dest *dest;
40381db7 2540 struct bgp_path_info *pi;
d7c0a89a 2541 uint32_t path_cnt = 0;
d62a17ae 2542 afi_t afi;
2543 safi_t safi;
9c92b5f7 2544 json_object *json_paths = NULL;
852d9f97 2545 struct ethaddr empty_mac = {};
f3a88e72 2546 struct ipaddr empty_ip = {};
852d9f97 2547 const struct prefix_evpn *evp;
d62a17ae 2548
2549 afi = AFI_L2VPN;
2550 safi = SAFI_EVPN;
2551
2552 /* Locate VNI. */
2553 vpn = bgp_evpn_lookup_vni(bgp, vni);
2554 if (!vpn) {
9c92b5f7
MK
2555 if (!json)
2556 vty_out(vty, "VNI not found\n");
d62a17ae 2557 return;
2558 }
2559
f3a88e72 2560 build_evpn_type2_prefix(&p, mac ? mac : &empty_mac,
2561 ip ? ip : &empty_ip);
852d9f97 2562
d62a17ae 2563 /* See if route exists. Look for both non-sticky and sticky. */
852d9f97 2564 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
9bcb3eef 2565 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2566 if (!json)
2567 vty_out(vty, "%% Network not in table\n");
e71ad4b6
DA
2568
2569 if (dest)
2570 bgp_dest_unlock_node(dest);
2571
d62a17ae 2572 return;
2573 }
2574
34c7f35f
SW
2575 /*
2576 * MAC is per-path, we have to walk the path_info's and look for it
2577 * first here.
2578 */
852d9f97
SW
2579 if (ip && mac) {
2580 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2581 if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
2582 sizeof(*mac)) == 0)
2583 break;
2584 }
34c7f35f 2585
852d9f97
SW
2586 if (!pi) {
2587 if (!json)
2588 vty_out(vty, "%% Network not in table\n");
2589 return;
2590 }
34c7f35f
SW
2591 }
2592
9c92b5f7
MK
2593 if (json)
2594 json_paths = json_object_new_array();
2595
d62a17ae 2596 /* Prefix and num paths displayed once per prefix. */
34c7f35f 2597 route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
f9f2d188 2598 afi, safi, json, false);
d62a17ae 2599
852d9f97 2600 evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
d62a17ae 2601
2602 /* Display each path for this prefix. */
9bcb3eef 2603 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2604 json_object *json_path = NULL;
2605
34c7f35f 2606 /* skip non-matching MACs */
852d9f97
SW
2607 if (ip && mac &&
2608 memcmp(mac, evpn_type2_path_info_get_mac(pi),
34c7f35f
SW
2609 sizeof(*mac)) != 0)
2610 continue;
2611
9c92b5f7
MK
2612 if (json)
2613 json_path = json_object_new_array();
2614
34c7f35f
SW
2615 /*
2616 * VNI table MAC-IP prefixes don't have MAC so
2617 * make sure it's set from path info
2618 * here.
2619 */
852d9f97
SW
2620 if (is_evpn_prefix_ipaddr_none(evp)) {
2621 /* VNI MAC -> Global */
2622 evpn_type2_prefix_global_copy(
2623 (struct prefix_evpn *)&tmp_p, evp,
2624 NULL /* mac */,
2625 evpn_type2_path_info_get_ip(pi));
2626 } else {
2627 /* VNI IP -> Global */
2628 evpn_type2_prefix_global_copy(
2629 (struct prefix_evpn *)&tmp_p, evp,
2630 evpn_type2_path_info_get_mac(pi),
2631 NULL /* ip */);
2632 }
34c7f35f
SW
2633
2634 route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p,
2635 pi, afi, safi, RPKI_NOT_BEING_USED,
2636 json_path);
9c92b5f7
MK
2637
2638 if (json)
2639 json_object_array_add(json_paths, json_path);
2640
d62a17ae 2641 path_cnt++;
2642 }
2643
9c92b5f7
MK
2644 if (json) {
2645 if (path_cnt)
2646 json_object_object_add(json, "paths", json_paths);
2647
2648 json_object_int_add(json, "numPaths", path_cnt);
2649 } else {
2650 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2651 path_cnt);
2652 }
e71ad4b6
DA
2653
2654 bgp_dest_unlock_node(dest);
520d5d76 2655}
2656
50f74cf1 2657/* Disaplay EVPN routes for a ESI - VTY handler */
2658static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2659 esi_t *esi, json_object *json)
2660{
b5e140c8 2661 struct bgp_evpn_es *es = NULL;
50f74cf1 2662
2663 /* locate the ES */
b5e140c8 2664 es = bgp_evpn_es_find(esi);
50f74cf1 2665 if (!es) {
2666 if (!json)
2667 vty_out(vty, "ESI not found\n");
2668 return;
2669 }
2670
2671 show_esi_routes(bgp, es, vty, json);
2672}
2673
520d5d76 2674/*
2675 * Display EVPN routes for a VNI - vty handler.
2676 * If 'type' is non-zero, only routes matching that type are shown.
2677 * If the vtep_ip is non zero, only routes behind that vtep are shown
2678 */
d62a17ae 2679static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
852d9f97
SW
2680 int type, bool mac_table,
2681 struct in_addr vtep_ip, json_object *json)
520d5d76 2682{
d62a17ae 2683 struct bgpevpn *vpn;
520d5d76 2684
d62a17ae 2685 /* Locate VNI. */
2686 vpn = bgp_evpn_lookup_vni(bgp, vni);
2687 if (!vpn) {
9c92b5f7
MK
2688 if (!json)
2689 vty_out(vty, "VNI not found\n");
d62a17ae 2690 return;
2691 }
520d5d76 2692
d62a17ae 2693 /* Walk this VNI's route table and display appropriate routes. */
852d9f97 2694 show_vni_routes(bgp, vpn, vty, type, mac_table, vtep_ip, json, 0);
520d5d76 2695}
2696
2697/*
2698 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2699 * IP (vty handler). By definition, only matching type-2 route will be
2700 * displayed.
2701 */
d62a17ae 2702static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2703 struct prefix_rd *prd, struct ethaddr *mac,
9c92b5f7 2704 struct ipaddr *ip, json_object *json)
d62a17ae 2705{
2706 struct prefix_evpn p;
9bcb3eef 2707 struct bgp_dest *dest;
40381db7 2708 struct bgp_path_info *pi;
d62a17ae 2709 afi_t afi;
2710 safi_t safi;
d7c0a89a 2711 uint32_t path_cnt = 0;
9c92b5f7 2712 json_object *json_paths = NULL;
d62a17ae 2713
2714 afi = AFI_L2VPN;
2715 safi = SAFI_EVPN;
2716
2717 /* See if route exists. Look for both non-sticky and sticky. */
2718 build_evpn_type2_prefix(&p, mac, ip);
59d6b4d6
DA
2719 dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
2720 (struct prefix *)&p, prd);
9bcb3eef 2721 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
9c92b5f7
MK
2722 if (!json)
2723 vty_out(vty, "%% Network not in table\n");
e71ad4b6
DA
2724
2725 if (dest)
2726 bgp_dest_unlock_node(dest);
2727
d62a17ae 2728 return;
2729 }
2730
2731 /* Prefix and num paths displayed once per prefix. */
34c7f35f 2732 route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
f9f2d188 2733 prd, afi, safi, json, false);
9c92b5f7
MK
2734
2735 if (json)
2736 json_paths = json_object_new_array();
d62a17ae 2737
2738 /* Display each path for this prefix. */
9bcb3eef 2739 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c92b5f7
MK
2740 json_object *json_path = NULL;
2741
2742 if (json)
2743 json_path = json_object_new_array();
2744
34c7f35f
SW
2745 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2746 pi, afi, safi, RPKI_NOT_BEING_USED,
2747 json_path);
9c92b5f7
MK
2748
2749 if (json)
2750 json_object_array_add(json_paths, json_path);
2751
d62a17ae 2752 path_cnt++;
2753 }
2754
9c92b5f7
MK
2755 if (json && path_cnt) {
2756 if (path_cnt)
511211bf 2757 json_object_object_addf(json, json_paths, "%pFX", &p);
9c92b5f7
MK
2758 json_object_int_add(json, "numPaths", path_cnt);
2759 } else {
2760 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2761 path_cnt);
2762 }
e71ad4b6
DA
2763
2764 bgp_dest_unlock_node(dest);
520d5d76 2765}
2766
2767/*
2768 * Display BGP EVPN routing table -- for specific RD (vty handler)
2769 * If 'type' is non-zero, only routes matching that type are shown.
2770 */
d62a17ae 2771static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
2772 struct prefix_rd *prd, int type,
2773 json_object *json)
d62a17ae 2774{
9bcb3eef 2775 struct bgp_dest *rd_dest;
d62a17ae 2776 struct bgp_table *table;
9bcb3eef 2777 struct bgp_dest *dest;
40381db7 2778 struct bgp_path_info *pi;
d62a17ae 2779 int rd_header = 1;
2780 afi_t afi;
2781 safi_t safi;
d7c0a89a 2782 uint32_t prefix_cnt, path_cnt;
9c92b5f7
MK
2783 json_object *json_rd = NULL;
2784 int add_rd_to_json = 0;
d62a17ae 2785
2786 afi = AFI_L2VPN;
2787 safi = SAFI_EVPN;
2788 prefix_cnt = path_cnt = 0;
2789
9bcb3eef
DS
2790 rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2791 if (!rd_dest)
d62a17ae 2792 return;
9c92b5f7 2793
9bcb3eef 2794 table = bgp_dest_get_bgp_table_info(rd_dest);
e71ad4b6
DA
2795 if (table == NULL) {
2796 bgp_dest_unlock_node(rd_dest);
d62a17ae 2797 return;
e71ad4b6 2798 }
d62a17ae 2799
9c92b5f7
MK
2800 if (json) {
2801 json_rd = json_object_new_object();
4a8cd6ad
PG
2802 json_object_string_addf(json_rd, "rd",
2803 BGP_RD_AS_FORMAT(bgp->asnotation), prd);
9c92b5f7
MK
2804 }
2805
e71ad4b6
DA
2806 bgp_dest_unlock_node(rd_dest);
2807
d62a17ae 2808 /* Display all prefixes with this RD. */
9bcb3eef 2809 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
b54892e0 2810 const struct prefix_evpn *evp =
9bcb3eef 2811 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
9c92b5f7
MK
2812 json_object *json_prefix = NULL;
2813 json_object *json_paths = NULL;
9c92b5f7
MK
2814 int add_prefix_to_json = 0;
2815
d62a17ae 2816 if (type && evp->prefix.route_type != type)
2817 continue;
2818
9c92b5f7
MK
2819 if (json)
2820 json_prefix = json_object_new_object();
2821
9bcb3eef 2822 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2823 if (pi) {
d62a17ae 2824 /* RD header and legend - once overall. */
9c92b5f7 2825 if (rd_header && !json) {
6c111b51 2826 vty_out(vty,
7b0db0e4 2827 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
d62a17ae 2828 vty_out(vty,
554cd77a 2829 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
d62a17ae 2830 vty_out(vty,
342dd0c6 2831 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
6c111b51
AK
2832 vty_out(vty,
2833 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
342dd0c6 2834 vty_out(vty,
554cd77a 2835 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
d62a17ae 2836 rd_header = 0;
2837 }
2838
2839 /* Prefix and num paths displayed once per prefix. */
34c7f35f
SW
2840 route_vty_out_detail_header(
2841 vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
f9f2d188 2842 afi, safi, json_prefix, false);
d62a17ae 2843
2844 prefix_cnt++;
2845 }
2846
9c92b5f7
MK
2847 if (json)
2848 json_paths = json_object_new_array();
2849
d62a17ae 2850 /* Display each path for this prefix. */
6f94b685 2851 for (; pi; pi = pi->next) {
9c92b5f7
MK
2852 json_object *json_path = NULL;
2853
2854 if (json)
2855 json_path = json_object_new_array();
2856
34c7f35f
SW
2857 route_vty_out_detail(
2858 vty, bgp, dest, bgp_dest_get_prefix(dest), pi,
2859 afi, safi, RPKI_NOT_BEING_USED, json_path);
9c92b5f7
MK
2860
2861 if (json)
2862 json_object_array_add(json_paths, json_path);
2863
d62a17ae 2864 path_cnt++;
9c92b5f7
MK
2865 add_prefix_to_json = 1;
2866 add_rd_to_json = 1;
2867 }
2868
a1df2ac5
CS
2869 if (json) {
2870 if (add_prefix_to_json) {
2871 json_object_object_add(json_prefix, "paths",
2872 json_paths);
511211bf
DA
2873 json_object_object_addf(json_rd, json_prefix,
2874 "%pFX", evp);
a1df2ac5
CS
2875 } else {
2876 json_object_free(json_paths);
2877 json_object_free(json_prefix);
2878 json_paths = NULL;
2879 json_prefix = NULL;
2880 }
d62a17ae 2881 }
2882 }
2883
9c92b5f7 2884 if (json) {
a1df2ac5 2885 if (add_rd_to_json)
4a8cd6ad
PG
2886 json_object_object_addf(
2887 json, json_rd,
2888 BGP_RD_AS_FORMAT(bgp->asnotation), prd);
a1df2ac5
CS
2889 else {
2890 json_object_free(json_rd);
2891 json_rd = NULL;
2892 }
2893
9c92b5f7
MK
2894 json_object_int_add(json, "numPrefix", prefix_cnt);
2895 json_object_int_add(json, "numPaths", path_cnt);
2896 } else {
2897 if (prefix_cnt == 0)
2898 vty_out(vty, "No prefixes exist with this RD%s\n",
2899 type ? " (of requested type)" : "");
2900 else
2901 vty_out(vty,
2902 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2903 prefix_cnt, path_cnt,
2904 type ? " (of requested type)" : "");
2905 }
520d5d76 2906}
2907
a111dd97
TA
2908/*
2909 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2910 * (vty handler). Only matching type-2 routes will be displayed.
2911 */
2912static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
2913 struct ethaddr *mac, struct ipaddr *ip,
2914 json_object *json)
2915{
2916 struct bgp_dest *rd_dest;
2917 struct bgp_table *table;
2918 struct bgp_dest *dest;
2919 struct bgp_path_info *pi;
2920 afi_t afi = AFI_L2VPN;
2921 safi_t safi = SAFI_EVPN;
2922 uint32_t prefix_cnt, path_cnt;
2923 prefix_cnt = path_cnt = 0;
2924
2925 /* EVPN routing table is a 2-level table with the first level being
2926 * the RD. We need to look in every RD we know about.
2927 */
2928 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
2929 rd_dest = bgp_route_next(rd_dest)) {
2930 json_object *json_paths = NULL; /* paths array for prefix */
2931 json_object *json_prefix = NULL; /* prefix within an RD */
2932 json_object *json_rd = NULL; /* holds all prefixes for RD */
2933 char rd_str[RD_ADDRSTRLEN];
a111dd97
TA
2934 int add_rd_to_json = 0;
2935 struct prefix_evpn ep;
2936 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
2937
2938 table = bgp_dest_get_bgp_table_info(rd_dest);
2939 if (table == NULL)
2940 continue;
2941
2942 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
4a8cd6ad 2943 sizeof(rd_str), bgp->asnotation);
a111dd97
TA
2944
2945 /* Construct an RT-2 from the user-supplied mac(ip),
2946 * then search the l2vpn evpn table for it.
2947 */
2948 build_evpn_type2_prefix(&ep, mac, ip);
59d6b4d6
DA
2949 dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi,
2950 (struct prefix *)&ep,
2951 (struct prefix_rd *)rd_destp);
a111dd97
TA
2952 if (!dest)
2953 continue;
2954
2955 if (json)
2956 json_rd = json_object_new_object();
2957
2958 const struct prefix *p = bgp_dest_get_prefix(dest);
2959
a111dd97
TA
2960 pi = bgp_dest_get_bgp_path_info(dest);
2961 if (pi) {
2962 /* RD header - per RD. */
2963 bgp_evpn_show_route_rd_header(vty, rd_dest, json_rd,
2964 rd_str, RD_ADDRSTRLEN);
2965 prefix_cnt++;
2966 }
2967
2968 if (json) {
2969 json_prefix = json_object_new_object();
2970 json_paths = json_object_new_array();
511211bf
DA
2971 json_object_string_addf(json_prefix, "prefix", "%pFX",
2972 p);
a111dd97
TA
2973 json_object_int_add(json_prefix, "prefixLen",
2974 p->prefixlen);
2975 } else
2976 /* Prefix and num paths displayed once per prefix. */
2977 route_vty_out_detail_header(
34c7f35f 2978 vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
f9f2d188 2979 AFI_L2VPN, SAFI_EVPN, json_prefix, false);
a111dd97
TA
2980
2981 /* For EVPN, the prefix is displayed for each path (to
2982 * fit in with code that already exists).
2983 */
2984 for (; pi; pi = pi->next) {
2985 json_object *json_path = NULL;
2986
2987 add_rd_to_json = 1;
2988 path_cnt++;
2989
2990 if (json)
2991 json_path = json_object_new_array();
2992
34c7f35f 2993 route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,
a111dd97
TA
2994 SAFI_EVPN, RPKI_NOT_BEING_USED,
2995 json_path);
2996
2997 if (json)
2998 json_object_array_add(json_paths, json_path);
2999 else
3000 vty_out(vty, "\n");
3001 }
3002
3003 if (json) {
3004 json_object_object_add(json_prefix, "paths",
3005 json_paths);
511211bf
DA
3006 json_object_object_addf(json_rd, json_prefix, "%pFX",
3007 p);
a111dd97
TA
3008 if (add_rd_to_json)
3009 json_object_object_add(json, rd_str, json_rd);
3010 else {
3011 json_object_free(json_rd);
3012 json_rd = NULL;
3013 }
3014 }
e71ad4b6
DA
3015
3016 bgp_dest_unlock_node(dest);
a111dd97
TA
3017 }
3018
3019 if (json) {
3020 json_object_int_add(json, "numPrefix", prefix_cnt);
3021 json_object_int_add(json, "numPaths", path_cnt);
3022 } else {
3023 if (prefix_cnt == 0) {
3024 vty_out(vty, "No Matching EVPN prefixes exist\n");
3025 } else {
3026 vty_out(vty, "Displayed %u prefixes (%u paths)\n",
3027 prefix_cnt, path_cnt);
3028 }
3029 }
3030}
3031
520d5d76 3032/*
3033 * Display BGP EVPN routing table - all routes (vty handler).
3034 * If 'type' is non-zero, only routes matching that type are shown.
3035 */
9c92b5f7 3036static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
83856649 3037 json_object *json, int detail, bool self_orig)
d62a17ae 3038{
9bcb3eef 3039 struct bgp_dest *rd_dest;
d62a17ae 3040 struct bgp_table *table;
9bcb3eef 3041 struct bgp_dest *dest;
40381db7 3042 struct bgp_path_info *pi;
21f3551e 3043 int header = detail ? 0 : 1;
d62a17ae 3044 int rd_header;
3045 afi_t afi;
3046 safi_t safi;
d7c0a89a 3047 uint32_t prefix_cnt, path_cnt;
d62a17ae 3048
3049 afi = AFI_L2VPN;
3050 safi = SAFI_EVPN;
3051 prefix_cnt = path_cnt = 0;
3052
3053 /* EVPN routing table is a 2-level table with the first level being
3054 * the RD.
3055 */
9bcb3eef
DS
3056 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
3057 rd_dest = bgp_route_next(rd_dest)) {
9c92b5f7
MK
3058 char rd_str[RD_ADDRSTRLEN];
3059 json_object *json_rd = NULL; /* contains routes for an RD */
3060 int add_rd_to_json = 0;
2dd32217 3061 uint64_t tbl_ver;
9bcb3eef 3062 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
9c92b5f7 3063
9bcb3eef 3064 table = bgp_dest_get_bgp_table_info(rd_dest);
d62a17ae 3065 if (table == NULL)
3066 continue;
3067
2dd32217 3068 tbl_ver = table->version;
9bcb3eef 3069 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
4a8cd6ad 3070 sizeof(rd_str), bgp->asnotation);
9c92b5f7 3071
90c31d71 3072 if (json)
9c92b5f7 3073 json_rd = json_object_new_object();
9c92b5f7 3074
d62a17ae 3075 rd_header = 1;
3076
3077 /* Display all prefixes for an RD */
9bcb3eef
DS
3078 for (dest = bgp_table_top(table); dest;
3079 dest = bgp_route_next(dest)) {
9c92b5f7
MK
3080 json_object *json_prefix =
3081 NULL; /* contains prefix under a RD */
3082 json_object *json_paths =
3083 NULL; /* array of paths under a prefix*/
b54892e0 3084 const struct prefix_evpn *evp =
9bcb3eef
DS
3085 (const struct prefix_evpn *)bgp_dest_get_prefix(
3086 dest);
9c92b5f7 3087 int add_prefix_to_json = 0;
9bcb3eef 3088 const struct prefix *p = bgp_dest_get_prefix(dest);
9c92b5f7 3089
d62a17ae 3090 if (type && evp->prefix.route_type != type)
3091 continue;
3092
9bcb3eef 3093 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 3094 if (pi) {
83856649
KQ
3095 if (self_orig && (pi->peer != bgp->peer_self))
3096 continue;
3097
d62a17ae 3098 /* Overall header/legend displayed once. */
3099 if (header) {
9c92b5f7 3100 bgp_evpn_show_route_header(vty, bgp,
2dd32217 3101 tbl_ver,
9c92b5f7 3102 json);
c684d477
CS
3103 if (!json)
3104 vty_out(vty,
3105 "%19s Extended Community\n"
6f214dd3 3106 , " ");
d62a17ae 3107 header = 0;
3108 }
3109
3110 /* RD header - per RD. */
3111 if (rd_header) {
9c92b5f7 3112 bgp_evpn_show_route_rd_header(
9bcb3eef 3113 vty, rd_dest, json_rd, rd_str,
c69e79f1 3114 RD_ADDRSTRLEN);
d62a17ae 3115 rd_header = 0;
3116 }
3117
3118 prefix_cnt++;
3119 }
3120
9c92b5f7
MK
3121 if (json) {
3122 json_prefix = json_object_new_object();
3123 json_paths = json_object_new_array();
511211bf
DA
3124 json_object_string_addf(json_prefix, "prefix",
3125 "%pFX", p);
9c92b5f7 3126 json_object_int_add(json_prefix, "prefixLen",
b54892e0 3127 p->prefixlen);
9c92b5f7
MK
3128 }
3129
21f3551e
NS
3130 /* Prefix and num paths displayed once per prefix. */
3131 if (detail)
3132 route_vty_out_detail_header(
9bcb3eef 3133 vty, bgp, dest,
34c7f35f 3134 bgp_dest_get_prefix(dest),
9bcb3eef 3135 (struct prefix_rd *)rd_destp, AFI_L2VPN,
f9f2d188 3136 SAFI_EVPN, json_prefix, false);
21f3551e 3137
d62a17ae 3138 /* For EVPN, the prefix is displayed for each path (to
3139 * fit in
3140 * with code that already exists).
3141 */
6f94b685 3142 for (; pi; pi = pi->next) {
9c92b5f7 3143 json_object *json_path = NULL;
a111dd97 3144
d62a17ae 3145 path_cnt++;
9c92b5f7
MK
3146 add_prefix_to_json = 1;
3147 add_rd_to_json = 1;
3148
3149 if (json)
3150 json_path = json_object_new_array();
3151
21f3551e
NS
3152 if (detail) {
3153 route_vty_out_detail(
34c7f35f
SW
3154 vty, bgp, dest,
3155 bgp_dest_get_prefix(dest), pi,
3156 AFI_L2VPN, SAFI_EVPN,
3157 RPKI_NOT_BEING_USED, json_path);
21f3551e 3158 } else
b54892e0 3159 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
ae248832 3160 json_path, false);
9c92b5f7
MK
3161
3162 if (json)
3163 json_object_array_add(json_paths,
3164 json_path);
3165 }
3166
a1df2ac5
CS
3167 if (json) {
3168 if (add_prefix_to_json) {
3169 json_object_object_add(json_prefix,
3170 "paths",
3171 json_paths);
511211bf
DA
3172 json_object_object_addf(json_rd,
3173 json_prefix,
3174 "%pFX", p);
a1df2ac5
CS
3175 } else {
3176 json_object_free(json_prefix);
3177 json_object_free(json_paths);
3178 json_prefix = NULL;
3179 json_paths = NULL;
3180 }
d62a17ae 3181 }
3182 }
9c92b5f7 3183
a1df2ac5
CS
3184 if (json) {
3185 if (add_rd_to_json)
3186 json_object_object_add(json, rd_str, json_rd);
3187 else {
3188 json_object_free(json_rd);
3189 json_rd = NULL;
3190 }
3191 }
d62a17ae 3192 }
3193
9c92b5f7
MK
3194 if (json) {
3195 json_object_int_add(json, "numPrefix", prefix_cnt);
3196 json_object_int_add(json, "numPaths", path_cnt);
3197 } else {
3198 if (prefix_cnt == 0) {
3199 vty_out(vty, "No EVPN prefixes %sexist\n",
3200 type ? "(of requested type) " : "");
3201 } else {
3202 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
3203 prefix_cnt, path_cnt,
3204 type ? " (of requested type)" : "");
3205 }
3206 }
520d5d76 3207}
3208
0adc5bbb
LS
3209int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3210 bool use_json, int detail)
3211{
3212 json_object *json = NULL;
3213
3214 if (use_json)
3215 json = json_object_new_object();
3216
83856649 3217 evpn_show_all_routes(vty, bgp, type, json, detail, false);
0adc5bbb
LS
3218
3219 if (use_json)
82465ca7
RR
3220 /*
3221 * We are using no_pretty here because under extremely high
3222 * settings (lots of routes with many different paths) this can
3223 * save several minutes of output when FRR is run on older cpu's
3224 * or more underperforming routers out there. So for route
3225 * scale, we need to use no_pretty json.
3226 */
3227 vty_json_no_pretty(vty, json);
0adc5bbb
LS
3228 return CMD_SUCCESS;
3229}
3230
520d5d76 3231/*
3232 * Display specified VNI (vty handler)
3233 */
9c92b5f7
MK
3234static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
3235 json_object *json)
520d5d76 3236{
d7c0a89a 3237 uint8_t found = 0;
d62a17ae 3238 struct bgpevpn *vpn;
520d5d76 3239
d62a17ae 3240 vpn = bgp_evpn_lookup_vni(bgp, vni);
4cce389e
MK
3241 if (vpn) {
3242 found = 1;
3243 display_vni(vty, vpn, json);
3244 } else {
3245 struct bgp *bgp_temp;
3246 struct listnode *node = NULL;
3247
3248 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3249 if (bgp_temp->l3vni == vni) {
3250 found = 1;
3251 display_l3vni(vty, bgp_temp, json);
3252 }
3253 }
3254 }
3255
3256 if (!found) {
9c92b5f7
MK
3257 if (json) {
3258 vty_out(vty, "{}\n");
3259 } else {
3260 vty_out(vty, "VNI not found\n");
3261 return;
3262 }
d62a17ae 3263 }
520d5d76 3264}
3265
3266/*
3267 * Display a VNI (upon user query).
3268 */
9c92b5f7
MK
3269static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
3270 json_object *json)
520d5d76 3271{
9c92b5f7 3272 void *args[2];
4cce389e
MK
3273 struct bgp *bgp_temp = NULL;
3274 struct listnode *node;
520d5d76 3275
9c92b5f7 3276
4cce389e 3277 if (!json) {
9c92b5f7 3278 vty_out(vty, "Flags: * - Kernel\n");
4cce389e 3279 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
996c9314 3280 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
9c92b5f7
MK
3281 }
3282
4cce389e 3283 /* print all L2 VNIS */
9c92b5f7
MK
3284 args[0] = vty;
3285 args[1] = json;
d62a17ae 3286 hash_iterate(bgp->vnihash,
e3b78da8 3287 (void (*)(struct hash_bucket *, void *))show_vni_entry,
9c92b5f7 3288 args);
4cce389e
MK
3289
3290 /* print all L3 VNIs */
3291 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
3292 show_l3vni_entry(vty, bgp_temp, json);
520d5d76 3293}
3294
24864e44
CS
3295/*
3296 * evpn - enable advertisement of svi MAC-IP
3297 */
3298static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
3299 uint32_t set)
3300{
3301 if (!vpn) {
3302 if (set && bgp->evpn_info->advertise_svi_macip)
3303 return;
3304 else if (!set && !bgp->evpn_info->advertise_svi_macip)
3305 return;
3306
3307 bgp->evpn_info->advertise_svi_macip = set;
3308 bgp_zebra_advertise_svi_macip(bgp,
3309 bgp->evpn_info->advertise_svi_macip, 0);
3310 } else {
3311 if (set && vpn->advertise_svi_macip)
3312 return;
3313 else if (!set && !vpn->advertise_svi_macip)
3314 return;
3315
3316 vpn->advertise_svi_macip = set;
3317 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
3318 vpn->vni);
3319 }
3320}
3321
1a98c087
MK
3322/*
3323 * evpn - enable advertisement of default g/w
3324 */
3325static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
3326{
3327 if (!vpn) {
3328 if (bgp->advertise_gw_macip)
3329 return;
3330
3331 bgp->advertise_gw_macip = 1;
3332 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3333 } else {
3334 if (vpn->advertise_gw_macip)
3335 return;
3336
3337 vpn->advertise_gw_macip = 1;
3338 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3339 vpn->vni);
3340 }
3341 return;
3342}
3343
3344/*
3345 * evpn - disable advertisement of default g/w
3346 */
3347static void evpn_unset_advertise_default_gw(struct bgp *bgp,
3348 struct bgpevpn *vpn)
3349{
3350 if (!vpn) {
3351 if (!bgp->advertise_gw_macip)
3352 return;
3353
3354 bgp->advertise_gw_macip = 0;
3355 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3356 } else {
3357 if (!vpn->advertise_gw_macip)
3358 return;
3359
3360 vpn->advertise_gw_macip = 0;
3361 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3362 vpn->vni);
3363 }
3364 return;
3365}
3366
486456ca
MK
3367/*
3368 * evpn - enable advertisement of default g/w
3369 */
3370static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
5fd9c12b 3371 afi_t afi, bool add)
486456ca 3372{
486456ca
MK
3373 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
3374
486456ca
MK
3375 if (add) {
3376 /* bail if we are already advertising default route */
3377 if (evpn_default_originate_set(bgp_vrf, afi, safi))
3378 return;
3379
3380 if (afi == AFI_IP)
3381 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3382 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3383 else if (afi == AFI_IP6)
3384 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca
MK
3386 } else {
3387 /* bail out if we havent advertised the default route */
3388 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
3389 return;
3390 if (afi == AFI_IP)
3391 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3392 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3393 else if (afi == AFI_IP6)
3394 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3395 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca 3396 }
5fd9c12b
KA
3397
3398 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
486456ca
MK
3399}
3400
31310b25
MK
3401/*
3402 * evpn - enable advertisement of default g/w
3403 */
3404static void evpn_set_advertise_subnet(struct bgp *bgp,
3405 struct bgpevpn *vpn)
3406{
3407 if (vpn->advertise_subnet)
3408 return;
3409
3410 vpn->advertise_subnet = 1;
3411 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3412}
3413
3414/*
3415 * evpn - disable advertisement of default g/w
3416 */
996c9314 3417static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
31310b25
MK
3418{
3419 if (!vpn->advertise_subnet)
3420 return;
3421
3422 vpn->advertise_subnet = 0;
3423 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3424}
3425
7724c0a1 3426/*
3427 * EVPN (VNI advertisement) enabled. Register with zebra.
3428 */
d62a17ae 3429static void evpn_set_advertise_all_vni(struct bgp *bgp)
7724c0a1 3430{
d62a17ae 3431 bgp->advertise_all_vni = 1;
e2f3a930 3432 bgp_set_evpn(bgp);
d62a17ae 3433 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
7724c0a1 3434}
3435
3436/*
3437 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3438 * cache, EVPN routes (delete and withdraw from peers).
3439 */
d62a17ae 3440static void evpn_unset_advertise_all_vni(struct bgp *bgp)
7724c0a1 3441{
d62a17ae 3442 bgp->advertise_all_vni = 0;
e2f3a930 3443 bgp_set_evpn(bgp_get_default());
d62a17ae 3444 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3445 bgp_evpn_cleanup_on_disable(bgp);
7724c0a1 3446}
bf1061d8 3447
dc6cef73
AD
3448/* Set resolve overlay index flag */
3449static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
3450{
3451 if (set == bgp->resolve_overlay_index)
3452 return;
3453
3454 if (set) {
3455 bgp->resolve_overlay_index = true;
3456 hash_iterate(bgp->vnihash,
3457 (void (*)(struct hash_bucket *, void *))
3458 bgp_evpn_handle_resolve_overlay_index_set,
3459 NULL);
3460 } else {
3461 hash_iterate(
3462 bgp->vnihash,
3463 (void (*)(struct hash_bucket *, void *))
3464 bgp_evpn_handle_resolve_overlay_index_unset,
3465 NULL);
3466 bgp->resolve_overlay_index = false;
3467 }
3468}
3469
bf1061d8
VB
3470/*
3471 * EVPN - use RFC8365 to auto-derive RT
3472 */
3473static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3474{
3475 bgp->advertise_autort_rfc8365 = 1;
3476 bgp_evpn_handle_autort_change(bgp);
3477}
3478
3479/*
3480 * EVPN - don't use RFC8365 to auto-derive RT
3481 */
3482static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3483{
3484 bgp->advertise_autort_rfc8365 = 0;
3485 bgp_evpn_handle_autort_change(bgp);
3486}
7724c0a1 3487
2b791107 3488static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
d62a17ae 3489{
d62a17ae 3490 char *ecom_str;
3491 struct listnode *node, *nnode;
3492 struct ecommunity *ecom;
3493
3494 if (is_vni_configured(vpn)) {
339af96e 3495 vty_out(vty, " vni %u\n", vpn->vni);
d62a17ae 3496 if (is_rd_configured(vpn))
fa566a94 3497 vty_out(vty, " rd %s\n", vpn->prd_pretty);
d62a17ae 3498
3499 if (is_import_rt_configured(vpn)) {
3500 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3501 ecom)) {
3502 ecom_str = ecommunity_ecom2str(
3503 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3504 vty_out(vty, " route-target import %s\n",
3505 ecom_str);
3506 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3507 }
3508 }
3509
3510 if (is_export_rt_configured(vpn)) {
3511 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3512 ecom)) {
3513 ecom_str = ecommunity_ecom2str(
3514 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 3515 vty_out(vty, " route-target export %s\n",
d62a17ae 3516 ecom_str);
3517 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3518 }
3519 }
3520
1a98c087
MK
3521 if (vpn->advertise_gw_macip)
3522 vty_out(vty, " advertise-default-gw\n");
3523
24864e44
CS
3524 if (vpn->advertise_svi_macip)
3525 vty_out(vty, " advertise-svi-ip\n");
3526
31310b25
MK
3527 if (vpn->advertise_subnet)
3528 vty_out(vty, " advertise-subnet\n");
3529
d62a17ae 3530 vty_out(vty, " exit-vni\n");
3531 }
3532}
3533
fd069644 3534#include "bgpd/bgp_evpn_vty_clippy.c"
fd069644
DS
3535
3536DEFPY(bgp_evpn_flood_control,
3537 bgp_evpn_flood_control_cmd,
3538 "[no$no] flooding <disable$disable|head-end-replication$her>",
3539 NO_STR
3540 "Specify handling for BUM packets\n"
3541 "Do not flood any BUM packets\n"
3542 "Flood BUM packets using head-end replication\n")
3543{
3544 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3545 enum vxlan_flood_control flood_ctrl;
3546
3547 if (!bgp)
3548 return CMD_WARNING;
3549
3550 if (disable && !no)
3551 flood_ctrl = VXLAN_FLOOD_DISABLED;
3552 else if (her || no)
3553 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3554 else
3555 return CMD_WARNING;
3556
3557 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3558 return CMD_SUCCESS;
3559
3560 bgp->vxlan_flood_ctrl = flood_ctrl;
3561 bgp_evpn_flood_control_change(bgp);
3562
3563 return CMD_SUCCESS;
3564}
3565
1a98c087
MK
3566DEFUN (bgp_evpn_advertise_default_gw_vni,
3567 bgp_evpn_advertise_default_gw_vni_cmd,
3568 "advertise-default-gw",
078af92e 3569 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
1a98c087
MK
3570{
3571 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3572 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3573
3574 if (!bgp)
3575 return CMD_WARNING;
3576
1a98c087
MK
3577 evpn_set_advertise_default_gw(bgp, vpn);
3578
3579 return CMD_SUCCESS;
3580}
3581
3582DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3583 no_bgp_evpn_advertise_default_gw_vni_cmd,
3584 "no advertise-default-gw",
3585 NO_STR
3586 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3587{
3588 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3589 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3590
3591 if (!bgp)
3592 return CMD_WARNING;
3593
1a98c087
MK
3594 evpn_unset_advertise_default_gw(bgp, vpn);
3595
3596 return CMD_SUCCESS;
3597}
3598
3599
3600DEFUN (bgp_evpn_advertise_default_gw,
3601 bgp_evpn_advertise_default_gw_cmd,
3602 "advertise-default-gw",
078af92e 3603 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
3604{
3605 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3606
3607 if (!bgp)
3608 return CMD_WARNING;
3609
f920dd6d 3610 if (!EVPN_ENABLED(bgp)) {
7da47d66 3611 vty_out(vty,
530db8dc 3612 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3613 return CMD_WARNING;
3614 }
3615
1a98c087
MK
3616 evpn_set_advertise_default_gw(bgp, NULL);
3617
3618 return CMD_SUCCESS;
3619}
3620
3621DEFUN (no_bgp_evpn_advertise_default_gw,
3622 no_bgp_evpn_advertise_default_gw_cmd,
3623 "no advertise-default-gw",
3624 NO_STR
3625 "Withdraw All default g/w mac-ip routes from EVPN\n")
3626{
3627 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3628
3629 if (!bgp)
3630 return CMD_WARNING;
3631
3632 evpn_unset_advertise_default_gw(bgp, NULL);
3633
3634 return CMD_SUCCESS;
3635}
3636
7724c0a1 3637DEFUN (bgp_evpn_advertise_all_vni,
3638 bgp_evpn_advertise_all_vni_cmd,
3639 "advertise-all-vni",
3640 "Advertise All local VNIs\n")
3641{
d62a17ae 3642 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
e2f3a930 3643 struct bgp *bgp_evpn = NULL;
7724c0a1 3644
d62a17ae 3645 if (!bgp)
3646 return CMD_WARNING;
e2f3a930
T
3647
3648 bgp_evpn = bgp_get_evpn();
3649 if (bgp_evpn && bgp_evpn != bgp) {
2b94e4b6 3650 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3651 bgp_evpn->name_pretty);
e2f3a930
T
3652 return CMD_WARNING_CONFIG_FAILED;
3653 }
3654
d62a17ae 3655 evpn_set_advertise_all_vni(bgp);
3656 return CMD_SUCCESS;
7724c0a1 3657}
3658
3659DEFUN (no_bgp_evpn_advertise_all_vni,
3660 no_bgp_evpn_advertise_all_vni_cmd,
3661 "no advertise-all-vni",
3662 NO_STR
3663 "Advertise All local VNIs\n")
3664{
d62a17ae 3665 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 3666
d62a17ae 3667 if (!bgp)
3668 return CMD_WARNING;
3669 evpn_unset_advertise_all_vni(bgp);
3670 return CMD_SUCCESS;
7724c0a1 3671}
3672
bf1061d8
VB
3673DEFUN (bgp_evpn_advertise_autort_rfc8365,
3674 bgp_evpn_advertise_autort_rfc8365_cmd,
3675 "autort rfc8365-compatible",
3676 "Auto-derivation of RT\n"
3677 "Auto-derivation of RT using RFC8365\n")
3678{
3679 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3680
3681 if (!bgp)
3682 return CMD_WARNING;
3683 evpn_set_advertise_autort_rfc8365(bgp);
3684 return CMD_SUCCESS;
3685}
3686
3687DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3688 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3689 "no autort rfc8365-compatible",
3690 NO_STR
3691 "Auto-derivation of RT\n"
3692 "Auto-derivation of RT using RFC8365\n")
3693{
3694 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3695
3696 if (!bgp)
3697 return CMD_WARNING;
3698 evpn_unset_advertise_autort_rfc8365(bgp);
3699 return CMD_SUCCESS;
3700}
3701
486456ca
MK
3702DEFUN (bgp_evpn_default_originate,
3703 bgp_evpn_default_originate_cmd,
3704 "default-originate <ipv4 | ipv6>",
3705 "originate a default route\n"
3706 "ipv4 address family\n"
3707 "ipv6 address family\n")
3708{
3709 afi_t afi = 0;
3710 int idx_afi = 0;
3711 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3712
3713 if (!bgp_vrf)
3714 return CMD_WARNING;
3715 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3716 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
486456ca
MK
3717 return CMD_SUCCESS;
3718}
3719
3720DEFUN (no_bgp_evpn_default_originate,
3721 no_bgp_evpn_default_originate_cmd,
3722 "no default-originate <ipv4 | ipv6>",
3723 NO_STR
3724 "withdraw a default route\n"
3725 "ipv4 address family\n"
3726 "ipv6 address family\n")
3727{
3728 afi_t afi = 0;
3729 int idx_afi = 0;
3730 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3731
3732 if (!bgp_vrf)
3733 return CMD_WARNING;
3734 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3735 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
486456ca
MK
3736 return CMD_SUCCESS;
3737}
3738
0b9d9cd0
CS
3739DEFPY (dup_addr_detection,
3740 dup_addr_detection_cmd,
3741 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3742 "Duplicate address detection\n"
979777b2 3743 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3744 "Num of max allowed moves (2-1000) default 5\n"
3745 "Duplicate address detection time\n"
3746 "Time in seconds (2-1800) default 180\n")
3747{
3748 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3749
3750 if (!bgp_vrf)
3751 return CMD_WARNING;
3752
f920dd6d 3753 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3754 vty_out(vty,
530db8dc 3755 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3756 return CMD_WARNING;
3757 }
3758
0b9d9cd0
CS
3759 bgp_vrf->evpn_info->dup_addr_detect = true;
3760
3761 if (time_val)
3762 bgp_vrf->evpn_info->dad_time = time_val;
3763 if (max_moves_val)
3764 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3765
3766 bgp_zebra_dup_addr_detection(bgp_vrf);
3767
3768 return CMD_SUCCESS;
3769}
3770
3771DEFPY (dup_addr_detection_auto_recovery,
3772 dup_addr_detection_auto_recovery_cmd,
3773 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3774 "Duplicate address detection\n"
3775 "Duplicate address detection freeze\n"
3776 "Duplicate address detection permanent freeze\n"
3777 "Duplicate address detection freeze time (30-3600)\n")
3778{
3779 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3780 uint32_t freeze_time = freeze_time_val;
3781
3782 if (!bgp_vrf)
3783 return CMD_WARNING;
3784
f920dd6d 3785 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3786 vty_out(vty,
530db8dc 3787 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3788 return CMD_WARNING;
3789 }
3790
0b9d9cd0
CS
3791 bgp_vrf->evpn_info->dup_addr_detect = true;
3792 bgp_vrf->evpn_info->dad_freeze = true;
3793 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3794
3795 bgp_zebra_dup_addr_detection(bgp_vrf);
3796
3797 return CMD_SUCCESS;
3798}
3799
3800DEFPY (no_dup_addr_detection,
3801 no_dup_addr_detection_cmd,
3802 "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>]",
3803 NO_STR
3804 "Duplicate address detection\n"
979777b2 3805 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3806 "Num of max allowed moves (2-1000) default 5\n"
3807 "Duplicate address detection time\n"
3808 "Time in seconds (2-1800) default 180\n"
3809 "Duplicate address detection freeze\n"
3810 "Duplicate address detection permanent freeze\n"
3811 "Duplicate address detection freeze time (30-3600)\n")
3812{
3813 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3814 uint32_t max_moves = (uint32_t)max_moves_val;
3815 uint32_t freeze_time = (uint32_t)freeze_time_val;
3816
3817 if (!bgp_vrf)
3818 return CMD_WARNING;
3819
f920dd6d 3820 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3821 vty_out(vty,
530db8dc 3822 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3823 return CMD_WARNING;
3824 }
3825
0b9d9cd0
CS
3826 if (argc == 2) {
3827 if (!bgp_vrf->evpn_info->dup_addr_detect)
3828 return CMD_SUCCESS;
3829 /* Reset all parameters to default. */
3830 bgp_vrf->evpn_info->dup_addr_detect = false;
3831 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3832 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3833 bgp_vrf->evpn_info->dad_freeze = false;
3834 bgp_vrf->evpn_info->dad_freeze_time = 0;
3835 } else {
3836 if (max_moves) {
3837 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3838 vty_out(vty,
3839 "%% Value does not match with config\n");
3840 return CMD_SUCCESS;
3841 }
3842 bgp_vrf->evpn_info->dad_max_moves =
3843 EVPN_DAD_DEFAULT_MAX_MOVES;
3844 }
3845
3846 if (time_val) {
3847 if (bgp_vrf->evpn_info->dad_time != time_val) {
3848 vty_out(vty,
3849 "%% Value does not match with config\n");
3850 return CMD_SUCCESS;
3851 }
3852 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3853 }
3854
3855 if (freeze_time) {
3856 if (bgp_vrf->evpn_info->dad_freeze_time
3857 != freeze_time) {
3858 vty_out(vty,
3859 "%% Value does not match with config\n");
3860 return CMD_SUCCESS;
3861 }
3862 bgp_vrf->evpn_info->dad_freeze_time = 0;
3863 bgp_vrf->evpn_info->dad_freeze = false;
3864 }
3865
3866 if (permanent_val) {
3867 if (bgp_vrf->evpn_info->dad_freeze_time) {
3868 vty_out(vty,
3869 "%% Value does not match with config\n");
3870 return CMD_SUCCESS;
3871 }
3872 bgp_vrf->evpn_info->dad_freeze = false;
3873 }
3874 }
3875
3876 bgp_zebra_dup_addr_detection(bgp_vrf);
3877
3878 return CMD_SUCCESS;
3879}
3880
24864e44
CS
3881DEFPY(bgp_evpn_advertise_svi_ip,
3882 bgp_evpn_advertise_svi_ip_cmd,
3883 "[no$no] advertise-svi-ip",
3884 NO_STR
3885 "Advertise svi mac-ip routes in EVPN\n")
3886{
3887 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3888
3889 if (!bgp)
3890 return CMD_WARNING;
3891
24864e44
CS
3892 if (no)
3893 evpn_set_advertise_svi_macip(bgp, NULL, 0);
e5aee151
TA
3894 else {
3895 if (!EVPN_ENABLED(bgp)) {
3896 vty_out(vty,
3897 "This command is only supported under EVPN VRF\n");
3898 return CMD_WARNING;
3899 }
24864e44 3900 evpn_set_advertise_svi_macip(bgp, NULL, 1);
e5aee151 3901 }
24864e44
CS
3902
3903 return CMD_SUCCESS;
3904}
3905
3906DEFPY(bgp_evpn_advertise_svi_ip_vni,
3907 bgp_evpn_advertise_svi_ip_vni_cmd,
3908 "[no$no] advertise-svi-ip",
3909 NO_STR
3910 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3911{
3912 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3913 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3914
3915 if (!bgp)
3916 return CMD_WARNING;
3917
24864e44
CS
3918 if (no)
3919 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3920 else
3921 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3922
3923 return CMD_SUCCESS;
3924}
3925
689b5101
MK
3926DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3927 bgp_evpn_advertise_vni_subnet_cmd,
3928 "advertise-subnet",
3929 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
3930{
3931 struct bgp *bgp_vrf = NULL;
3932 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3933 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3934
3935 if (!bgp)
3936 return CMD_WARNING;
3937
31310b25
MK
3938 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3939 if (!bgp_vrf)
3940 return CMD_WARNING;
3941
31310b25
MK
3942 evpn_set_advertise_subnet(bgp, vpn);
3943 return CMD_SUCCESS;
3944}
3945
689b5101
MK
3946DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3947 no_bgp_evpn_advertise_vni_subnet_cmd,
3948 "no advertise-subnet",
3949 NO_STR
3950 "Advertise All local VNIs\n")
31310b25
MK
3951{
3952 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3953 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3954
3955 if (!bgp)
3956 return CMD_WARNING;
3957
31310b25
MK
3958 evpn_unset_advertise_subnet(bgp, vpn);
3959 return CMD_SUCCESS;
3960}
3961
342dd0c6 3962DEFUN (bgp_evpn_advertise_type5,
3963 bgp_evpn_advertise_type5_cmd,
70dd370f 3964 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
342dd0c6 3965 "Advertise prefix routes\n"
053905d2 3966 BGP_AFI_HELP_STR
53c84f78 3967 BGP_SAFI_HELP_STR
d4a88de3 3968 "advertise gateway IP overlay index\n"
53c84f78
MK
3969 "route-map for filtering specific routes\n"
3970 "Name of the route map\n")
342dd0c6 3971{
3972 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3973 int idx_afi = 0;
3974 int idx_safi = 0;
53c84f78 3975 int idx_rmap = 0;
053905d2
MK
3976 afi_t afi = 0;
3977 safi_t safi = 0;
53c84f78
MK
3978 int ret = 0;
3979 int rmap_changed = 0;
d4a88de3
AD
3980 enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3981 int idx_oly = 0;
3982 bool adv_flag_changed = false;
053905d2
MK
3983
3984 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3985 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
d4a88de3
AD
3986 argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3987
53c84f78
MK
3988 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3989 if (ret) {
3990 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3991 rmap_changed = 1;
3992 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
3993 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3994 != 0)
53c84f78
MK
3995 rmap_changed = 1;
3996 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3997 rmap_changed = 1;
3998 }
053905d2 3999
e779dc76 4000 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2 4001 vty_out(vty,
664b6f18 4002 "%% Only ipv4 or ipv6 address families are supported\n");
342dd0c6 4003 return CMD_WARNING;
4004 }
4005
053905d2
MK
4006 if (safi != SAFI_UNICAST) {
4007 vty_out(vty,
664b6f18 4008 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
053905d2
MK
4009 return CMD_WARNING;
4010 }
4011
d4a88de3
AD
4012 if ((oly != OVERLAY_INDEX_TYPE_NONE)
4013 && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
664b6f18 4014 vty_out(vty, "%% Unknown overlay-index type specified\n");
d4a88de3
AD
4015 return CMD_WARNING;
4016 }
4017
053905d2 4018 if (afi == AFI_IP) {
d4a88de3
AD
4019 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4020 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
4021 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4022 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4023
4024 /*
4025 * this is the case for first time ever configuration
4026 * adv ipv4 unicast is enabled for the first time.
4027 * So no need to reset any flag
4028 */
4029 if (oly == OVERLAY_INDEX_TYPE_NONE)
4030 SET_FLAG(
4031 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4032 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4033 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4034 SET_FLAG(
4035 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4036 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4037 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4038 && (!CHECK_FLAG(
4039 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4040 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
4041
4042 /*
4043 * This is modify case from gateway-ip
4044 * to no overlay index
4045 */
4046 adv_flag_changed = true;
4047 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4048 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4049 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4050 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4051 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4052 && (!CHECK_FLAG(
4053 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4054 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4055
4056 /*
4057 * This is modify case from no overlay index
4058 * to gateway-ip
4059 */
4060 adv_flag_changed = true;
4061 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4062 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4063 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4064 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4065 } else {
342dd0c6 4066
d4a88de3
AD
4067 /*
4068 * Command is issued with the same option
4069 * (no overlay index or gateway-ip) which was
4070 * already configured. So nothing to do.
4071 * However, route-map may have been modified.
4072 * check if route-map has been modified.
4073 * If not, return an error
4074 */
4075 if (!rmap_changed)
4076 return CMD_WARNING;
4077 }
342dd0c6 4078 } else {
d4a88de3
AD
4079 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4080 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
4081 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4083
4084 /*
4085 * this is the case for first time ever configuration
4086 * adv ipv6 unicast is enabled for the first time.
4087 * So no need to reset any flag
4088 */
4089 if (oly == OVERLAY_INDEX_TYPE_NONE)
4090 SET_FLAG(
4091 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4092 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4093 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4094 SET_FLAG(
4095 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4096 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4097 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4098 && (!CHECK_FLAG(
4099 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4100 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
4101
4102 /*
4103 * This is modify case from gateway-ip
4104 * to no overlay index
4105 */
4106 adv_flag_changed = true;
4107 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4108 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4109 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4110 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4111 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4112 && (!CHECK_FLAG(
4113 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4114 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4115
4116 /*
4117 * This is modify case from no overlay index
4118 * to gateway-ip
4119 */
4120 adv_flag_changed = true;
4121 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4122 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4123 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4124 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4125 } else {
342dd0c6 4126
d4a88de3
AD
4127 /*
4128 * Command is issued with the same option
4129 * (no overlay index or gateway-ip) which was
4130 * already configured. So nothing to do.
4131 * However, route-map may have been modified.
4132 * check if route-map has been modified.
4133 * If not, return an error
4134 */
4135 if (!rmap_changed)
4136 return CMD_WARNING;
4137 }
53c84f78
MK
4138 }
4139
d4a88de3
AD
4140 if ((rmap_changed) || (adv_flag_changed)) {
4141
4142 /* If either of these are changed, then FRR needs to
4143 * withdraw already advertised type5 routes.
4144 */
53c84f78 4145 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4a88de3
AD
4146 if (rmap_changed) {
4147 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4148 XFREE(MTYPE_ROUTE_MAP_NAME,
4149 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4150 route_map_counter_decrement(
b4897fa5 4151 bgp_vrf->adv_cmd_rmap[afi][safi].map);
d4a88de3
AD
4152 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4153 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4154 }
342dd0c6 4155 }
4156 }
53c84f78
MK
4157
4158 /* set the route-map for advertise command */
4159 if (ret && argv[idx_rmap + 1]->arg) {
4160 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 4161 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
4162 bgp_vrf->adv_cmd_rmap[afi][safi].map =
4163 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
b4897fa5 4164 route_map_counter_increment(
4165 bgp_vrf->adv_cmd_rmap[afi][safi].map);
53c84f78
MK
4166 }
4167
4168 /* advertise type-5 routes */
456a4697
AK
4169 if (advertise_type5_routes(bgp_vrf, afi))
4170 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 4171 return CMD_SUCCESS;
4172}
4173
4174DEFUN (no_bgp_evpn_advertise_type5,
4175 no_bgp_evpn_advertise_type5_cmd,
24df3379 4176 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 4177 NO_STR
4178 "Advertise prefix routes\n"
053905d2 4179 BGP_AFI_HELP_STR
24df3379
SW
4180 BGP_SAFI_HELP_STR
4181 "route-map for filtering specific routes\n"
4182 "Name of the route map\n")
342dd0c6 4183{
4184 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
4185 int idx_afi = 0;
4186 int idx_safi = 0;
4187 afi_t afi = 0;
4188 safi_t safi = 0;
4189
3e140309
DS
4190 if (!bgp_vrf)
4191 return CMD_WARNING;
4192
053905d2
MK
4193 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4194 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4195
1ec31309 4196 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2 4197 vty_out(vty,
664b6f18 4198 "%% Only ipv4 or ipv6 address families are supported\n");
053905d2
MK
4199 return CMD_WARNING;
4200 }
4201
4202 if (safi != SAFI_UNICAST) {
4203 vty_out(vty,
664b6f18 4204 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
342dd0c6 4205 return CMD_WARNING;
4206 }
4207
053905d2 4208 if (afi == AFI_IP) {
342dd0c6 4209
fdf19f06 4210 /* if we are not advertising ipv4 prefix as type-5
523cafc4 4211 * nothing to do
4212 */
d4a88de3
AD
4213 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4214 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4215 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4216 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
053905d2 4217 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50 4218 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3
AD
4219 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4220 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4221 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
342dd0c6 4222 }
4223 } else {
4224
fdf19f06 4225 /* if we are not advertising ipv6 prefix as type-5
523cafc4 4226 * nothing to do
4227 */
d4a88de3
AD
4228 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4229 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4230 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4231 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
053905d2 4232 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4f7497e 4233 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3
AD
4234 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4235 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4236 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
342dd0c6 4237 }
4238 }
53c84f78
MK
4239
4240 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4241 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4242 XFREE(MTYPE_ROUTE_MAP_NAME,
4243 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4244 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4245 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4246 }
4247
342dd0c6 4248 return CMD_SUCCESS;
4249}
4250
2867823e
AK
4251DEFPY (bgp_evpn_use_es_l3nhg,
4252 bgp_evpn_use_es_l3nhg_cmd,
4253 "[no$no] use-es-l3nhg",
4254 NO_STR
4255 "use L3 nexthop group for host routes with ES destination\n")
4256{
4257 bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4258 return CMD_SUCCESS;
4259}
4260
fe8293c3
AK
4261DEFPY (bgp_evpn_ead_evi_rx_disable,
4262 bgp_evpn_ead_evi_rx_disable_cmd,
4263 "[no$no] disable-ead-evi-rx",
4264 NO_STR
4265 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4266{
acd1d9bc
AD
4267 bool ead_evi_rx = no? true :false;
4268
4269 if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4270 bgp_mh_info->ead_evi_rx = ead_evi_rx;
4271 bgp_evpn_switch_ead_evi_rx();
4272 }
fe8293c3
AK
4273 return CMD_SUCCESS;
4274}
4275
4276DEFPY (bgp_evpn_ead_evi_tx_disable,
4277 bgp_evpn_ead_evi_tx_disable_cmd,
4278 "[no$no] disable-ead-evi-tx",
4279 NO_STR
4280 "Don't advertise EAD-EVI for local ESs\n")
4281{
4282 bgp_mh_info->ead_evi_tx = no? true :false;
4283 return CMD_SUCCESS;
4284}
4285
dc6cef73
AD
4286DEFPY (bgp_evpn_enable_resolve_overlay_index,
4287 bgp_evpn_enable_resolve_overlay_index_cmd,
4288 "[no$no] enable-resolve-overlay-index",
4289 NO_STR
4290 "Enable Recursive Resolution of type-5 route overlay index\n")
4291{
4292 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4293
4294 if (bgp != bgp_get_evpn()) {
4295 vty_out(vty, "This command is only supported under EVPN VRF\n");
4296 return CMD_WARNING;
4297 }
4298
4299 bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4300 return CMD_SUCCESS;
4301}
4302
5394a276
CS
4303DEFPY (bgp_evpn_advertise_pip_ip_mac,
4304 bgp_evpn_advertise_pip_ip_mac_cmd,
4305 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4306 NO_STR
4307 "evpn system primary IP\n"
4308 IP_STR
4309 "ip address\n"
4310 MAC_STR MAC_STR MAC_STR)
4311{
4312 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4313 struct bgp *bgp_evpn = NULL;
4314
332133d1 4315 if (!bgp_vrf || EVPN_ENABLED(bgp_vrf)) {
5394a276
CS
4316 vty_out(vty,
4317 "This command is supported under L3VNI BGP EVPN VRF\n");
a6e7677e 4318 return CMD_WARNING_CONFIG_FAILED;
5394a276
CS
4319 }
4320 bgp_evpn = bgp_get_evpn();
4321
4322 if (!no) {
4323 /* pip is already enabled */
4324 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4325 return CMD_SUCCESS;
4326
4327 bgp_vrf->evpn_info->advertise_pip = true;
4328 if (ip.s_addr != INADDR_ANY) {
4329 /* Already configured with same IP */
4330 if (IPV4_ADDR_SAME(&ip,
4331 &bgp_vrf->evpn_info->pip_ip_static))
4332 return CMD_SUCCESS;
4333
4334 bgp_vrf->evpn_info->pip_ip_static = ip;
4335 bgp_vrf->evpn_info->pip_ip = ip;
4336 } else {
4337 bgp_vrf->evpn_info->pip_ip_static.s_addr
4338 = INADDR_ANY;
4339 /* default instance router-id assignemt */
4340 if (bgp_evpn)
4341 bgp_vrf->evpn_info->pip_ip =
4342 bgp_evpn->router_id;
4343 }
4344 /* parse sys mac */
4345 if (!is_zero_mac(&mac->eth_addr)) {
4346 /* Already configured with same MAC */
4347 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4348 &mac->eth_addr, ETH_ALEN) == 0)
4349 return CMD_SUCCESS;
4350
4351 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4352 &mac->eth_addr, ETH_ALEN);
4353 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4354 &bgp_vrf->evpn_info->pip_rmac_static,
4355 ETH_ALEN);
4356 } else {
4357 /* Copy zebra sys mac */
4358 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4359 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4360 &bgp_vrf->evpn_info->pip_rmac_zebra,
4361 ETH_ALEN);
4362 }
4363 } else {
4364 if (argc == 2) {
4365 if (!bgp_vrf->evpn_info->advertise_pip)
4366 return CMD_SUCCESS;
4367 /* Disable PIP feature */
4368 bgp_vrf->evpn_info->advertise_pip = false;
4369 /* copy anycast mac */
4370 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4371 &bgp_vrf->rmac, ETH_ALEN);
4372 } else {
4373 /* remove MAC-IP option retain PIP knob. */
4374 if ((ip.s_addr != INADDR_ANY) &&
4375 !IPV4_ADDR_SAME(&ip,
4376 &bgp_vrf->evpn_info->pip_ip_static)) {
4377 vty_out(vty,
4378 "%% BGP EVPN PIP IP does not match\n");
4379 return CMD_WARNING_CONFIG_FAILED;
4380 }
4381
4382 if (!is_zero_mac(&mac->eth_addr) &&
4383 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4384 &mac->eth_addr, ETH_ALEN) != 0) {
4385 vty_out(vty,
4386 "%% BGP EVPN PIP MAC does not match\n");
4387 return CMD_WARNING_CONFIG_FAILED;
4388 }
4389 /* pip_rmac can carry vrr_rmac reset only if it matches
4390 * with static value.
4391 */
4392 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4393 &bgp_vrf->evpn_info->pip_rmac_static,
4394 ETH_ALEN) == 0) {
4395 /* Copy zebra sys mac */
4396 if (!is_zero_mac(
4397 &bgp_vrf->evpn_info->pip_rmac_zebra))
4398 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4399 &bgp_vrf->evpn_info->pip_rmac_zebra,
4400 ETH_ALEN);
4401 else {
4402 /* copy anycast mac */
4403 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4404 &bgp_vrf->rmac, ETH_ALEN);
4405 }
4406 }
4407 }
4408 /* reset user configured sys MAC */
4409 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4410 /* reset user configured sys IP */
4411 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4412 /* Assign default PIP IP (bgp instance router-id) */
4413 if (bgp_evpn)
4414 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4415 else
4416 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4417 }
4418
4419 if (is_evpn_enabled()) {
0ca10580
CS
4420 struct listnode *node = NULL;
4421 struct bgpevpn *vpn = NULL;
4422
5f140efe
DS
4423 /*
4424 * At this point if bgp_evpn is NULL and evpn is enabled
4425 * something stupid has gone wrong
4426 */
4427 assert(bgp_evpn);
4428
5394a276 4429 update_advertise_vrf_routes(bgp_vrf);
0ca10580
CS
4430
4431 /* Update (svi) type-2 routes */
4432 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4433 if (!bgp_evpn_is_svi_macip_enabled(vpn))
4434 continue;
4435 update_routes_for_vni(bgp_evpn, vpn);
4436 }
5394a276
CS
4437 }
4438
4439 return CMD_SUCCESS;
4440}
4441
f2d62262 4442/*
4443 * Display VNI information - for all or a specific VNI
4444 */
9c92b5f7
MK
4445DEFUN(show_bgp_l2vpn_evpn_vni,
4446 show_bgp_l2vpn_evpn_vni_cmd,
093e3f23 4447 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
9c92b5f7
MK
4448 SHOW_STR
4449 BGP_STR
4450 L2VPN_HELP_STR
4451 EVPN_HELP_STR
4452 "Show VNI\n"
4453 "VNI number\n"
4454 JSON_STR)
520d5d76 4455{
5e53dce3 4456 struct bgp *bgp_evpn;
f2d62262 4457 vni_t vni;
4458 int idx = 0;
9f049418 4459 bool uj = false;
9c92b5f7 4460 json_object *json = NULL;
d7c0a89a
QY
4461 uint32_t num_l2vnis = 0;
4462 uint32_t num_l3vnis = 0;
d4454626 4463 uint32_t num_vnis = 0;
4cce389e
MK
4464 struct listnode *node = NULL;
4465 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
4466
4467 uj = use_json(argc, argv);
520d5d76 4468
5e53dce3
T
4469 bgp_evpn = bgp_get_evpn();
4470 if (!bgp_evpn)
d62a17ae 4471 return CMD_WARNING;
520d5d76 4472
f2d62262 4473 if (!argv_find(argv, argc, "evpn", &idx))
4474 return CMD_WARNING;
4475
9c92b5f7
MK
4476 if (uj)
4477 json = json_object_new_object();
1a98c087 4478
9c92b5f7 4479 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e 4480
5e53dce3 4481 num_l2vnis = hashcount(bgp_evpn->vnihash);
4cce389e
MK
4482
4483 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4484 if (bgp_temp->l3vni)
4485 num_l3vnis++;
4486 }
d4454626 4487 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
4488 if (uj) {
4489 json_object_string_add(json, "advertiseGatewayMacip",
5e53dce3 4490 bgp_evpn->advertise_gw_macip
9c92b5f7
MK
4491 ? "Enabled"
4492 : "Disabled");
0b509723 4493 json_object_string_add(json, "advertiseSviMacIp",
cbdbb1ca
CS
4494 bgp_evpn->evpn_info->advertise_svi_macip
4495 ? "Enabled" : "Disabled");
9c92b5f7 4496 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
4497 is_evpn_enabled() ? "Enabled"
4498 : "Disabled");
fd069644
DS
4499 json_object_string_add(
4500 json, "flooding",
02dd2dd6
P
4501 bgp_evpn->vxlan_flood_ctrl ==
4502 VXLAN_FLOOD_HEAD_END_REPL
fd069644
DS
4503 ? "Head-end replication"
4504 : "Disabled");
02dd2dd6
P
4505 json_object_string_add(
4506 json, "vxlanFlooding",
6f086a7f
P
4507 bgp_evpn->vxlan_flood_ctrl ==
4508 VXLAN_FLOOD_HEAD_END_REPL
4509 ? "Enabled"
fd069644 4510 : "Disabled");
d4454626 4511 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
4512 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4513 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
4514 } else {
4515 vty_out(vty, "Advertise Gateway Macip: %s\n",
5e53dce3 4516 bgp_evpn->advertise_gw_macip ? "Enabled"
996c9314 4517 : "Disabled");
24864e44 4518 vty_out(vty, "Advertise SVI Macip: %s\n",
5e53dce3 4519 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
24864e44 4520 : "Disabled");
9c92b5f7 4521 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 4522 is_evpn_enabled() ? "Enabled" : "Disabled");
fd069644 4523 vty_out(vty, "BUM flooding: %s\n",
02dd2dd6
P
4524 bgp_evpn->vxlan_flood_ctrl ==
4525 VXLAN_FLOOD_HEAD_END_REPL
fd069644
DS
4526 ? "Head-end replication"
4527 : "Disabled");
02dd2dd6 4528 vty_out(vty, "VXLAN flooding: %s\n",
6f086a7f
P
4529 bgp_evpn->vxlan_flood_ctrl ==
4530 VXLAN_FLOOD_HEAD_END_REPL
4531 ? "Enabled"
fd069644 4532 : "Disabled");
4cce389e
MK
4533 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4534 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 4535 }
5e53dce3 4536 evpn_show_all_vnis(vty, bgp_evpn, json);
f2d62262 4537 } else {
9c92b5f7
MK
4538 int vni_idx = 0;
4539
4540 if (!argv_find(argv, argc, "vni", &vni_idx))
4541 return CMD_WARNING;
4542
f2d62262 4543 /* Display specific VNI */
9c92b5f7 4544 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
5e53dce3 4545 evpn_show_vni(vty, bgp_evpn, vni, json);
9c92b5f7
MK
4546 }
4547
c48349e3 4548 if (uj)
75eeda93 4549 vty_json(vty, json);
520d5d76 4550
d62a17ae 4551 return CMD_SUCCESS;
520d5d76 4552}
4553
021b6596
AD
4554DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4555 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4556 "show bgp l2vpn evpn vni remote-ip-hash",
4557 SHOW_STR
4558 BGP_STR
4559 L2VPN_HELP_STR
4560 EVPN_HELP_STR
4561 "Show VNI\n"
4562 "Remote IP hash\n")
4563{
4564 struct bgp *bgp_evpn;
4565 int idx = 0;
4566
4567 bgp_evpn = bgp_get_evpn();
4568 if (!bgp_evpn)
4569 return CMD_WARNING;
4570
4571 if (!argv_find(argv, argc, "evpn", &idx))
4572 return CMD_WARNING;
4573
4574 hash_iterate(bgp_evpn->vnihash,
4575 (void (*)(struct hash_bucket *,
4576 void *))bgp_evpn_show_remote_ip_hash,
4577 vty);
4578
4579 return CMD_SUCCESS;
4580}
4581
4582DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4583 show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4584 "show bgp l2vpn evpn vni-svi-hash",
4585 SHOW_STR
4586 BGP_STR
4587 L2VPN_HELP_STR
4588 EVPN_HELP_STR
4589 "Show vni-svi-hash\n")
4590{
4591 struct bgp *bgp_evpn;
4592 int idx = 0;
4593
4594 bgp_evpn = bgp_get_evpn();
4595 if (!bgp_evpn)
4596 return CMD_WARNING;
4597
4598 if (!argv_find(argv, argc, "evpn", &idx))
4599 return CMD_WARNING;
4600
4601 hash_iterate(bgp_evpn->vni_svi_hash,
4602 (void (*)(struct hash_bucket *,
4603 void *))bgp_evpn_show_vni_svi_hash,
4604 vty);
4605
4606 return CMD_SUCCESS;
4607}
4608
b5e140c8
AK
4609DEFPY(show_bgp_l2vpn_evpn_es_evi,
4610 show_bgp_l2vpn_evpn_es_evi_cmd,
4611 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4612 SHOW_STR
4613 BGP_STR
4614 L2VPN_HELP_STR
4615 EVPN_HELP_STR
4616 "ES per EVI\n"
4617 "VxLAN Network Identifier\n"
4618 "VNI\n"
4619 JSON_STR
4620 "Detailed information\n")
4621{
4622 if (vni)
4623 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4624 else
4625 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4626
4627 return CMD_SUCCESS;
4628}
4629
4630DEFPY(show_bgp_l2vpn_evpn_es,
50f74cf1 4631 show_bgp_l2vpn_evpn_es_cmd,
b5e140c8 4632 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
50f74cf1 4633 SHOW_STR
4634 BGP_STR
4635 L2VPN_HELP_STR
4636 EVPN_HELP_STR
b5e140c8
AK
4637 "Ethernet Segment\n"
4638 "ES ID\n"
4639 "Detailed information\n"
b482a7fd 4640 JSON_STR)
50f74cf1 4641{
6a527b2f 4642 esi_t esi;
50f74cf1 4643
b5e140c8
AK
4644 if (esi_str) {
4645 if (!str_to_esi(esi_str, &esi)) {
664b6f18 4646 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 4647 return CMD_WARNING;
4648 }
b5e140c8
AK
4649 bgp_evpn_es_show_esi(vty, &esi, uj);
4650 } else {
50f74cf1 4651
b5e140c8 4652 bgp_evpn_es_show(vty, uj, !!detail);
50f74cf1 4653 }
4654
4655 return CMD_SUCCESS;
4656}
4657
229587fb
AK
4658DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4659 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4660 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4661 "Ethernet Segment\n"
4662 "ES ID\n" JSON_STR)
4663{
4664 esi_t esi;
4665
4666 if (esi_str) {
4667 if (!str_to_esi(esi_str, &esi)) {
664b6f18 4668 vty_out(vty, "%% Malformed ESI\n");
229587fb
AK
4669 return CMD_WARNING;
4670 }
4671 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4672 } else {
4673
4674 bgp_evpn_es_vrf_show(vty, uj, NULL);
4675 }
4676
4677 return CMD_SUCCESS;
4678}
4679
090efa2f
AK
4680DEFPY(show_bgp_l2vpn_evpn_nh,
4681 show_bgp_l2vpn_evpn_nh_cmd,
4682 "show bgp l2vpn evpn next-hops [json$uj]",
4683 SHOW_STR
4684 BGP_STR
4685 L2VPN_HELP_STR
4686 EVPN_HELP_STR
4687 "Nexthops\n"
4688 JSON_STR)
4689{
4690 bgp_evpn_nh_show(vty, uj);
4691
4692 return CMD_SUCCESS;
4693}
4694
f2d62262 4695/*
4696 * Display EVPN neighbor summary.
4697 */
8c1d4cd5 4698DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
96c81f66 4699 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
8c1d4cd5 4700 SHOW_STR BGP_STR
ee851c8c 4701 "bgp vrf\n"
8c1d4cd5 4702 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
9c92b5f7 4703 "Summary of BGP neighbor status\n"
10b49f14 4704 "Show only sessions in Established state\n"
3577f1c5 4705 "Show only sessions not in Established state\n"
8c1d4cd5
LS
4706 "Show only the specified neighbor session\n"
4707 "Neighbor to display information about\n"
4708 "Neighbor to display information about\n"
4709 "Neighbor on BGP configured interface\n"
4710 "Show only the specified remote AS sessions\n"
4711 "AS number\n"
4712 "Internal (iBGP) AS sessions\n"
4713 "External (eBGP) AS sessions\n"
96c81f66 4714 "Shorten the information on BGP instances\n"
8c1d4cd5 4715 "Increase table width for longer output\n" JSON_STR)
520d5d76 4716{
ee851c8c 4717 int idx_vrf = 0;
85eeb029 4718 int idx = 0;
ee851c8c 4719 char *vrf = NULL;
8c1d4cd5
LS
4720 char *neighbor = NULL;
4721 as_t as = 0; /* 0 means AS filter not set */
4722 int as_type = AS_UNSPECIFIED;
96c81f66 4723 uint16_t show_flags = 0;
ee851c8c
MK
4724
4725 if (argv_find(argv, argc, "vrf", &idx_vrf))
4726 vrf = argv[++idx_vrf]->arg;
10b49f14 4727
85eeb029
DA
4728 if (argv_find(argv, argc, "failed", &idx))
4729 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4730
4731 if (argv_find(argv, argc, "established", &idx))
4732 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4733
8c1d4cd5
LS
4734
4735 if (argv_find(argv, argc, "neighbor", &idx))
4736 neighbor = argv[idx + 1]->arg;
4737
4738 if (argv_find(argv, argc, "remote-as", &idx)) {
4739 if (argv[idx + 1]->arg[0] == 'i')
4740 as_type = AS_INTERNAL;
4741 else if (argv[idx + 1]->arg[0] == 'e')
4742 as_type = AS_EXTERNAL;
4743 else
4744 as = (as_t)atoi(argv[idx + 1]->arg);
4745 }
4746
96c81f66
LS
4747 if (argv_find(argv, argc, "terse", &idx))
4748 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4749
85eeb029
DA
4750 if (argv_find(argv, argc, "wide", &idx))
4751 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4752
4753 if (use_json(argc, argv))
4754 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4755
8c1d4cd5
LS
4756 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4757 as_type, as, show_flags);
520d5d76 4758}
4759
852d9f97
SW
4760static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
4761{
4762 if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
4763 *type = BGP_EVPN_MAC_IP_ROUTE;
4764 else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
4765 *type = BGP_EVPN_IMET_ROUTE;
4766 else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
4767 *type = BGP_EVPN_ES_ROUTE;
4768 else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
4769 *type = BGP_EVPN_AD_ROUTE;
4770 else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
4771 *type = BGP_EVPN_IP_PREFIX_ROUTE;
4772 else
4773 return -1;
4774
4775 return 0;
4776}
4777
15dc08a6 4778int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
2b1364e1
SW
4779{
4780 int type_idx = 0;
4781
4782 if (argv_find(argv, argc, "type", &type_idx)) {
4783 /* Specific type is requested */
852d9f97
SW
4784 if (bgp_evpn_cli_parse_type_cmp(type,
4785 argv[type_idx + 1]->arg) != 0)
2b1364e1
SW
4786 return -1;
4787 }
4788
4789 return 0;
4790}
4791
f2d62262 4792/*
4793 * Display global EVPN routing table.
4794 */
60466a63
QY
4795DEFUN(show_bgp_l2vpn_evpn_route,
4796 show_bgp_l2vpn_evpn_route_cmd,
83856649 4797 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] ["BGP_SELF_ORIG_CMD_STR"] [json]",
9c92b5f7
MK
4798 SHOW_STR
4799 BGP_STR
4800 L2VPN_HELP_STR
4801 EVPN_HELP_STR
f5dc0b1a 4802 EVPN_RT_HELP_STR
21f3551e 4803 "Display Detailed Information\n"
f5dc0b1a 4804 EVPN_TYPE_HELP_STR
2b1364e1 4805 EVPN_TYPE_ALL_LIST_HELP_STR
83856649 4806 BGP_SELF_ORIG_HELP_STR
9c92b5f7 4807 JSON_STR)
520d5d76 4808{
d62a17ae 4809 struct bgp *bgp;
21f3551e 4810 int detail = 0;
d62a17ae 4811 int type = 0;
9f049418 4812 bool uj = false;
83856649
KQ
4813 int arg_idx = 0;
4814 bool self_orig = false;
9c92b5f7
MK
4815 json_object *json = NULL;
4816
4817 uj = use_json(argc, argv);
520d5d76 4818
530db8dc 4819 bgp = bgp_get_evpn();
d62a17ae 4820 if (!bgp)
4821 return CMD_WARNING;
520d5d76 4822
9c92b5f7
MK
4823 if (uj)
4824 json = json_object_new_object();
f2d62262 4825
15dc08a6 4826 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1 4827 return CMD_WARNING;
520d5d76 4828
21f3551e
NS
4829 if (argv_find(argv, argc, "detail", &detail))
4830 detail = 1;
4831
83856649
KQ
4832 if (argv_find(argv, argc, BGP_SELF_ORIG_CMD_STR, &arg_idx))
4833 self_orig = true;
4834
4835 evpn_show_all_routes(vty, bgp, type, json, detail, self_orig);
9c92b5f7 4836
2d4460de
DS
4837 /*
4838 * This is an extremely expensive operation at scale
4839 * and as such we need to save as much time as is
4840 * possible.
4841 */
4842 if (uj)
4843 vty_json_no_pretty(vty, json);
3cdb03fb 4844
d62a17ae 4845 return CMD_SUCCESS;
520d5d76 4846}
4847
f2d62262 4848/*
4849 * Display global EVPN routing table for specific RD.
4850 */
60466a63
QY
4851DEFUN(show_bgp_l2vpn_evpn_route_rd,
4852 show_bgp_l2vpn_evpn_route_rd_cmd,
a111dd97 4853 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
9c92b5f7
MK
4854 SHOW_STR
4855 BGP_STR
4856 L2VPN_HELP_STR
4857 EVPN_HELP_STR
f5dc0b1a
SW
4858 EVPN_RT_HELP_STR
4859 EVPN_RT_DIST_HELP_STR
10794c49 4860 EVPN_ASN_IP_HELP_STR
a111dd97 4861 "All VPN Route Distinguishers\n"
f5dc0b1a 4862 EVPN_TYPE_HELP_STR
2b1364e1 4863 EVPN_TYPE_ALL_LIST_HELP_STR
9c92b5f7 4864 JSON_STR)
520d5d76 4865{
d62a17ae 4866 struct bgp *bgp;
9b01d289 4867 int ret = 0;
d62a17ae 4868 struct prefix_rd prd;
4869 int type = 0;
9f049418 4870 bool uj = false;
9c92b5f7 4871 json_object *json = NULL;
a111dd97
TA
4872 int idx_ext_community = 0;
4873 int rd_all = 0;
520d5d76 4874
530db8dc 4875 bgp = bgp_get_evpn();
d62a17ae 4876 if (!bgp)
4877 return CMD_WARNING;
520d5d76 4878
9c92b5f7
MK
4879 /* check if we need json output */
4880 uj = use_json(argc, argv);
4881 if (uj)
4882 json = json_object_new_object();
f2d62262 4883
8923315d 4884 if (!argv_find(argv, argc, "all", &rd_all)) {
a111dd97 4885 /* get the RD */
9b01d289
DA
4886 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4887 &idx_ext_community)) {
4888 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4889 if (!ret) {
4890 vty_out(vty,
4891 "%% Malformed Route Distinguisher\n");
4892 return CMD_WARNING;
4893 }
9c92b5f7 4894 }
d62a17ae 4895 }
520d5d76 4896
15dc08a6 4897 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1 4898 return CMD_WARNING;
520d5d76 4899
a111dd97 4900 if (rd_all)
83856649 4901 evpn_show_all_routes(vty, bgp, type, json, 1, false);
a111dd97
TA
4902 else
4903 evpn_show_route_rd(vty, bgp, &prd, type, json);
9c92b5f7 4904
c48349e3 4905 if (uj)
75eeda93 4906 vty_json(vty, json);
9c92b5f7 4907
d62a17ae 4908 return CMD_SUCCESS;
520d5d76 4909}
4910
f2d62262 4911/*
4912 * Display global EVPN routing table for specific RD and MACIP.
4913 */
9c92b5f7
MK
4914DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4915 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
a111dd97 4916 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
9c92b5f7
MK
4917 SHOW_STR
4918 BGP_STR
4919 L2VPN_HELP_STR
4920 EVPN_HELP_STR
f5dc0b1a
SW
4921 EVPN_RT_HELP_STR
4922 EVPN_RT_DIST_HELP_STR
10794c49 4923 EVPN_ASN_IP_HELP_STR
a111dd97 4924 "All VPN Route Distinguishers\n"
9c92b5f7
MK
4925 "MAC\n"
4926 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4927 "IP\n"
4928 "IP address (IPv4 or IPv6)\n"
4929 JSON_STR)
4930{
0291c246 4931 struct bgp *bgp;
9b01d289 4932 int ret = 0;
0291c246
MK
4933 struct prefix_rd prd;
4934 struct ethaddr mac;
4935 struct ipaddr ip;
a111dd97 4936 int idx_ext_community = 0;
0291c246
MK
4937 int mac_idx = 0;
4938 int ip_idx = 0;
9f049418 4939 bool uj = false;
0291c246 4940 json_object *json = NULL;
a111dd97 4941 int rd_all = 0;
9c92b5f7
MK
4942
4943 memset(&mac, 0, sizeof(struct ethaddr));
4944 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 4945
530db8dc 4946 bgp = bgp_get_evpn();
d62a17ae 4947 if (!bgp)
4948 return CMD_WARNING;
4949
9c92b5f7
MK
4950 /* check if we need json output */
4951 uj = use_json(argc, argv);
4952 if (uj)
4953 json = json_object_new_object();
f2d62262 4954
9c92b5f7 4955 /* get the prd */
8923315d 4956 if (!argv_find(argv, argc, "all", &rd_all)) {
9b01d289
DA
4957 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4958 &idx_ext_community)) {
4959 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4960 if (!ret) {
4961 vty_out(vty,
4962 "%% Malformed Route Distinguisher\n");
4963 return CMD_WARNING;
4964 }
9c92b5f7 4965 }
d62a17ae 4966 }
9c92b5f7
MK
4967
4968 /* get the mac */
4969 if (argv_find(argv, argc, "mac", &mac_idx)) {
4970 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4971 vty_out(vty, "%% Malformed MAC address\n");
4972 return CMD_WARNING;
4973 }
d62a17ae 4974 }
9c92b5f7
MK
4975
4976 /* get the ip if specified */
4977 if (argv_find(argv, argc, "ip", &ip_idx)) {
4978 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 4979 vty_out(vty, "%% Malformed IP address\n");
4980 return CMD_WARNING;
4981 }
4982 }
4983
a111dd97
TA
4984 if (rd_all)
4985 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4986 else
4987 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
9c92b5f7 4988
c48349e3 4989 if (uj)
75eeda93 4990 vty_json(vty, json);
9c92b5f7 4991
d62a17ae 4992 return CMD_SUCCESS;
520d5d76 4993}
4994
50f74cf1 4995/* Display per ESI routing table */
4996DEFUN(show_bgp_l2vpn_evpn_route_esi,
4997 show_bgp_l2vpn_evpn_route_esi_cmd,
4998 "show bgp l2vpn evpn route esi ESI [json]",
4999 SHOW_STR
5000 BGP_STR
5001 L2VPN_HELP_STR
5002 EVPN_HELP_STR
f5dc0b1a 5003 EVPN_RT_HELP_STR
50f74cf1 5004 "Ethernet Segment Identifier\n"
5005 "ESI ID\n"
5006 JSON_STR)
5007{
9f049418 5008 bool uj = false;
6a527b2f 5009 esi_t esi;
50f74cf1 5010 struct bgp *bgp = NULL;
5011 json_object *json = NULL;
5012
6a527b2f 5013 memset(&esi, 0, sizeof(esi));
530db8dc 5014 bgp = bgp_get_evpn();
50f74cf1 5015 if (!bgp)
5016 return CMD_WARNING;
5017
5018 uj = use_json(argc, argv);
5019 if (uj)
5020 json = json_object_new_object();
5021
5022 /* get the ESI - ESI-ID is at argv[6] */
5023 if (!str_to_esi(argv[6]->arg, &esi)) {
5024 vty_out(vty, "%% Malformed ESI\n");
5025 return CMD_WARNING;
5026 }
5027
5028 evpn_show_routes_esi(vty, bgp, &esi, json);
5029
c48349e3 5030 if (uj)
75eeda93 5031 vty_json(vty, json);
50f74cf1 5032
5033 return CMD_SUCCESS;
5034}
5035
5036
f2d62262 5037/*
5038 * Display per-VNI EVPN routing table.
5039 */
9c92b5f7 5040DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
2b1364e1 5041 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
9c92b5f7
MK
5042 SHOW_STR
5043 BGP_STR
5044 L2VPN_HELP_STR
5045 EVPN_HELP_STR
f5dc0b1a 5046 EVPN_RT_HELP_STR
9c92b5f7
MK
5047 "VXLAN Network Identifier\n"
5048 "VNI number\n"
f5dc0b1a
SW
5049 EVPN_TYPE_HELP_STR
5050 EVPN_TYPE_1_HELP_STR
2b1364e1 5051 EVPN_TYPE_1_HELP_STR
f5dc0b1a 5052 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5053 EVPN_TYPE_2_HELP_STR
5054 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5055 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
5056 "Remote VTEP\n"
5057 "Remote VTEP IP address\n"
5058 JSON_STR)
520d5d76 5059{
d62a17ae 5060 vni_t vni;
5061 struct bgp *bgp;
5062 struct in_addr vtep_ip;
5063 int type = 0;
f2d62262 5064 int idx = 0;
2b1364e1 5065 int vtep_idx = 0;
9f049418 5066 bool uj = false;
9c92b5f7 5067 json_object *json = NULL;
d62a17ae 5068
530db8dc 5069 bgp = bgp_get_evpn();
d62a17ae 5070 if (!bgp)
5071 return CMD_WARNING;
5072
9c92b5f7
MK
5073 /* check if we need json output */
5074 uj = use_json(argc, argv);
5075 if (uj)
5076 json = json_object_new_object();
5077
f2d62262 5078 if (!argv_find(argv, argc, "evpn", &idx))
5079 return CMD_WARNING;
5080
d62a17ae 5081 vtep_ip.s_addr = 0;
5082
f2d62262 5083 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 5084
15dc08a6 5085 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1
SW
5086 return CMD_WARNING;
5087
5088 if (argv_find(argv, argc, "vtep", &vtep_idx)) {
5089 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
5090 vty_out(vty, "%% Malformed VTEP IP address\n");
d62a17ae 5091 return CMD_WARNING;
2b1364e1 5092 }
d62a17ae 5093 }
5094
852d9f97 5095 evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
9c92b5f7 5096
c48349e3 5097 if (uj)
75eeda93 5098 vty_json(vty, json);
9c92b5f7 5099
d62a17ae 5100 return CMD_SUCCESS;
520d5d76 5101}
5102
f2d62262 5103/*
5104 * Display per-VNI EVPN routing table for specific MACIP.
5105 */
9c92b5f7
MK
5106DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
5107 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
093e3f23 5108 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
9c92b5f7
MK
5109 SHOW_STR
5110 BGP_STR
5111 L2VPN_HELP_STR
5112 EVPN_HELP_STR
f5dc0b1a 5113 EVPN_RT_HELP_STR
9c92b5f7
MK
5114 "VXLAN Network Identifier\n"
5115 "VNI number\n"
5116 "MAC\n"
5117 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5118 "IP\n"
5119 "IP address (IPv4 or IPv6)\n"
5120 JSON_STR)
520d5d76 5121{
d62a17ae 5122 vni_t vni;
5123 struct bgp *bgp;
5124 struct ethaddr mac;
5125 struct ipaddr ip;
f2d62262 5126 int idx = 0;
9f049418 5127 bool uj = false;
9c92b5f7 5128 json_object *json = NULL;
d62a17ae 5129
530db8dc 5130 bgp = bgp_get_evpn();
d62a17ae 5131 if (!bgp)
5132 return CMD_WARNING;
5133
9c92b5f7
MK
5134 /* check if we need json output */
5135 uj = use_json(argc, argv);
5136 if (uj)
5137 json = json_object_new_object();
5138
f2d62262 5139 if (!argv_find(argv, argc, "evpn", &idx))
5140 return CMD_WARNING;
5141
9c92b5f7 5142 /* get the VNI */
f2d62262 5143 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
5144
5145 /* get the mac */
f2d62262 5146 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 5147 vty_out(vty, "%% Malformed MAC address\n");
5148 return CMD_WARNING;
5149 }
9c92b5f7
MK
5150
5151 /* get the ip */
d62a17ae 5152 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
5153 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
5154 || (uj
5155 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 5156 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 5157 vty_out(vty, "%% Malformed IP address\n");
5158 return CMD_WARNING;
5159 }
5160 }
5161
9c92b5f7
MK
5162 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
5163
c48349e3 5164 if (uj)
75eeda93 5165 vty_json(vty, json);
9c92b5f7 5166
d62a17ae 5167 return CMD_SUCCESS;
520d5d76 5168}
5169
f2d62262 5170/*
5171 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5172 */
9c92b5f7
MK
5173DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
5174 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
093e3f23 5175 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
9c92b5f7
MK
5176 SHOW_STR
5177 BGP_STR
5178 L2VPN_HELP_STR
5179 EVPN_HELP_STR
f5dc0b1a 5180 EVPN_RT_HELP_STR
9c92b5f7
MK
5181 "VXLAN Network Identifier\n"
5182 "VNI number\n"
f5dc0b1a 5183 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
5184 "Originating Router IP address\n"
5185 JSON_STR)
520d5d76 5186{
d62a17ae 5187 vni_t vni;
5188 struct bgp *bgp;
5189 int ret;
5190 struct in_addr orig_ip;
f2d62262 5191 int idx = 0;
9f049418 5192 bool uj = false;
9c92b5f7 5193 json_object *json = NULL;
520d5d76 5194
530db8dc 5195 bgp = bgp_get_evpn();
d62a17ae 5196 if (!bgp)
5197 return CMD_WARNING;
520d5d76 5198
9c92b5f7
MK
5199 /* check if we need json output */
5200 uj = use_json(argc, argv);
5201 if (uj)
5202 json = json_object_new_object();
5203
f2d62262 5204 if (!argv_find(argv, argc, "evpn", &idx))
5205 return CMD_WARNING;
5206
9c92b5f7 5207 /* get the VNI */
f2d62262 5208 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
5209
5210 /* get the ip */
f2d62262 5211 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 5212 if (!ret) {
5213 vty_out(vty, "%% Malformed Originating Router IP address\n");
5214 return CMD_WARNING;
5215 }
520d5d76 5216
9c92b5f7
MK
5217 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5218
c48349e3 5219 if (uj)
75eeda93 5220 vty_json(vty, json);
9c92b5f7 5221
d62a17ae 5222 return CMD_SUCCESS;
520d5d76 5223}
5224
f2d62262 5225/*
5226 * Display per-VNI EVPN routing table - for all VNIs.
5227 */
60466a63
QY
5228DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5229 show_bgp_l2vpn_evpn_route_vni_all_cmd,
c7ef6cf2 5230 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
9c92b5f7
MK
5231 SHOW_STR
5232 BGP_STR
5233 L2VPN_HELP_STR
5234 EVPN_HELP_STR
f5dc0b1a 5235 EVPN_RT_HELP_STR
9c92b5f7
MK
5236 "VXLAN Network Identifier\n"
5237 "All VNIs\n"
c7ef6cf2 5238 "Print Detailed Output\n"
9c92b5f7
MK
5239 "Remote VTEP\n"
5240 "Remote VTEP IP address\n"
5241 JSON_STR)
520d5d76 5242{
d62a17ae 5243 struct bgp *bgp;
5244 struct in_addr vtep_ip;
f2d62262 5245 int idx = 0;
9f049418 5246 bool uj = false;
9c92b5f7 5247 json_object *json = NULL;
c7ef6cf2
NS
5248 /* Detail Adjust. Adjust indexes according to detail option */
5249 int da = 0;
520d5d76 5250
530db8dc 5251 bgp = bgp_get_evpn();
d62a17ae 5252 if (!bgp)
5253 return CMD_WARNING;
520d5d76 5254
9c92b5f7
MK
5255 /* check if we need json output */
5256 uj = use_json(argc, argv);
5257 if (uj)
5258 json = json_object_new_object();
5259
f2d62262 5260 if (!argv_find(argv, argc, "evpn", &idx))
5261 return CMD_WARNING;
5262
c7ef6cf2
NS
5263 if (argv_find(argv, argc, "detail", &da))
5264 da = 1;
5265
5266 /* vtep-ip position depends on detail option */
d62a17ae 5267 vtep_ip.s_addr = 0;
c7ef6cf2
NS
5268 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5269 || (uj
5270 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5271 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
d62a17ae 5272 vty_out(vty, "%% Malformed VTEP IP address\n");
5273 return CMD_WARNING;
5274 }
5275 }
520d5d76 5276
852d9f97 5277 evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
9c92b5f7 5278
852d9f97 5279 if (uj) {
75eeda93 5280 vty_json(vty, json);
852d9f97
SW
5281 json_object_free(json);
5282 }
5283
5284 return CMD_SUCCESS;
5285}
5286
5287/*
5288 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5289 */
5290DEFPY(show_bgp_vni_all,
5291 show_bgp_vni_all_cmd,
15919b89 5292 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
852d9f97
SW
5293 SHOW_STR
5294 BGP_STR
5295 VNI_HELP_STR
5296 VNI_ALL_HELP_STR
5297 VTEP_HELP_STR
5298 VTEP_IP_HELP_STR
15919b89
SW
5299 DETAIL_HELP_STR
5300 JSON_STR)
852d9f97
SW
5301{
5302 struct bgp *bgp;
5303 json_object *json = NULL;
5304
5305 bgp = bgp_get_evpn();
5306 if (!bgp)
5307 return CMD_WARNING;
5308
5309 /* check if we need json output */
852d9f97
SW
5310 if (uj)
5311 json = json_object_new_object();
852d9f97
SW
5312
5313 evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
5314
d950d224
SW
5315 if (uj)
5316 vty_json(vty, json);
852d9f97
SW
5317
5318 return CMD_SUCCESS;
5319}
5320
5321/*
5322 * Display per-VNI EVPN EAD routing table - for all VNIs.
5323 */
5324DEFPY(show_bgp_vni_all_ead,
5325 show_bgp_vni_all_ead_cmd,
5326 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5327 SHOW_STR
5328 BGP_STR
5329 VNI_HELP_STR
5330 VNI_ALL_HELP_STR
5331 EVPN_TYPE_HELP_STR
5332 EVPN_TYPE_1_HELP_STR
5333 EVPN_TYPE_1_HELP_STR
5334 VTEP_HELP_STR
5335 VTEP_IP_HELP_STR
5336 DETAIL_HELP_STR
5337 JSON_STR)
5338{
5339 struct bgp *bgp;
5340 json_object *json = NULL;
5341
5342 bgp = bgp_get_evpn();
5343 if (!bgp)
5344 return CMD_WARNING;
5345
5346 /* check if we need json output */
5347 if (uj)
5348 json = json_object_new_object();
5349
5350 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
5351 !!detail);
5352
d950d224
SW
5353 if (uj)
5354 vty_json(vty, json);
852d9f97
SW
5355
5356 return CMD_SUCCESS;
5357}
5358
5359/*
5360 * Display per-VNI EVPN MAC routing table - for all VNIs.
5361 */
5362DEFPY(show_bgp_vni_all_macip_mac,
5363 show_bgp_vni_all_macip_mac_cmd,
5364 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5365 SHOW_STR
5366 BGP_STR
5367 VNI_HELP_STR
5368 VNI_ALL_HELP_STR
5369 EVPN_TYPE_HELP_STR
5370 EVPN_TYPE_2_HELP_STR
5371 EVPN_TYPE_2_HELP_STR
5372 "MAC Table\n"
5373 VTEP_HELP_STR
5374 VTEP_IP_HELP_STR
5375 DETAIL_HELP_STR
5376 JSON_STR)
5377{
5378 struct bgp *bgp;
5379 json_object *json = NULL;
5380
5381 bgp = bgp_get_evpn();
5382 if (!bgp)
5383 return CMD_WARNING;
5384
5385 /* check if we need json output */
5386 if (uj)
5387 json = json_object_new_object();
5388
5389 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5390 json, !!detail);
5391
d950d224
SW
5392 if (uj)
5393 vty_json(vty, json);
852d9f97
SW
5394
5395 return CMD_SUCCESS;
5396}
5397
5398/*
5399 * Display per-VNI EVPN IP routing table - for all VNIs.
5400 */
5401DEFPY(show_bgp_vni_all_macip_ip,
5402 show_bgp_vni_all_macip_ip_cmd,
5403 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5404 SHOW_STR
5405 BGP_STR
5406 VNI_HELP_STR
5407 VNI_ALL_HELP_STR
5408 EVPN_TYPE_HELP_STR
5409 EVPN_TYPE_2_HELP_STR
5410 EVPN_TYPE_2_HELP_STR
5411 "IP Table\n"
5412 VTEP_HELP_STR
5413 VTEP_IP_HELP_STR
5414 DETAIL_HELP_STR
5415 JSON_STR)
5416{
5417 struct bgp *bgp;
5418 json_object *json = NULL;
5419
5420 bgp = bgp_get_evpn();
5421 if (!bgp)
5422 return CMD_WARNING;
5423
5424 /* check if we need json output */
5425 if (uj)
5426 json = json_object_new_object();
5427
5428 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5429 json, !!detail);
5430
d950d224
SW
5431 if (uj)
5432 vty_json(vty, json);
852d9f97
SW
5433
5434 return CMD_SUCCESS;
5435}
5436
5437/*
5438 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5439 */
5440DEFPY(show_bgp_vni_all_imet,
5441 show_bgp_vni_all_imet_cmd,
5442 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5443 SHOW_STR
5444 BGP_STR
5445 VNI_HELP_STR
5446 VNI_ALL_HELP_STR
5447 EVPN_TYPE_HELP_STR
5448 EVPN_TYPE_3_HELP_STR
5449 EVPN_TYPE_3_HELP_STR
5450 VTEP_HELP_STR
5451 VTEP_IP_HELP_STR
5452 DETAIL_HELP_STR
5453 JSON_STR)
5454{
5455 struct bgp *bgp;
5456 json_object *json = NULL;
5457
5458 bgp = bgp_get_evpn();
5459 if (!bgp)
5460 return CMD_WARNING;
5461
5462 /* check if we need json output */
5463 if (uj)
5464 json = json_object_new_object();
5465
5466 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
5467 json, !!detail);
5468
d950d224
SW
5469 if (uj)
5470 vty_json(vty, json);
852d9f97
SW
5471
5472 return CMD_SUCCESS;
5473}
5474
5475/*
5476 * Display per-VNI EVPN ALL routing tables - for select VNI
5477 */
5478DEFPY(show_bgp_vni,
5479 show_bgp_vni_cmd,
15919b89 5480 "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
852d9f97
SW
5481 SHOW_STR
5482 BGP_STR
5483 VNI_HELP_STR
5484 VNI_NUM_HELP_STR
5485 VTEP_HELP_STR
15919b89
SW
5486 VTEP_IP_HELP_STR
5487 JSON_STR)
852d9f97
SW
5488{
5489 struct bgp *bgp;
15919b89
SW
5490 json_object *json = NULL;
5491 json_object *json_mac = NULL;
852d9f97
SW
5492
5493 bgp = bgp_get_evpn();
5494 if (!bgp)
5495 return CMD_WARNING;
5496
15919b89
SW
5497 /* check if we need json output */
5498 if (uj) {
5499 json = json_object_new_object();
5500 json_mac = json_object_new_object();
5501 }
5502
5503 evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
5504
5505 if (!uj)
5506 vty_out(vty, "\n\nMAC Table:\n\n");
5507
5508 evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
5509
5510 if (uj) {
5511 json_object_object_add(json, "macTable", json_mac);
d950d224 5512 vty_json(vty, json);
15919b89 5513 }
852d9f97
SW
5514
5515 return CMD_SUCCESS;
5516}
5517
5518/*
5519 * Display per-VNI EVPN EAD routing table - for select VNI
5520 */
5521DEFPY(show_bgp_vni_ead,
5522 show_bgp_vni_ead_cmd,
5523 "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5524 SHOW_STR
5525 BGP_STR
5526 VNI_HELP_STR
5527 VNI_NUM_HELP_STR
5528 EVPN_TYPE_HELP_STR
5529 EVPN_TYPE_1_HELP_STR
5530 EVPN_TYPE_1_HELP_STR
5531 VTEP_HELP_STR
5532 VTEP_IP_HELP_STR
5533 JSON_STR)
5534{
5535 struct bgp *bgp;
5536 json_object *json = NULL;
5537
5538 bgp = bgp_get_evpn();
5539 if (!bgp)
5540 return CMD_WARNING;
5541
5542 /* check if we need json output */
5543 if (uj)
5544 json = json_object_new_object();
5545
5546 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
5547 json);
5548
d950d224
SW
5549 if (uj)
5550 vty_json(vty, json);
852d9f97
SW
5551
5552 return CMD_SUCCESS;
5553}
5554
5555/*
5556 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5557 */
5558DEFPY(show_bgp_vni_macip_mac,
5559 show_bgp_vni_macip_mac_cmd,
5560 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5561 SHOW_STR
5562 BGP_STR
5563 VNI_HELP_STR
5564 VNI_NUM_HELP_STR
5565 EVPN_TYPE_HELP_STR
5566 EVPN_TYPE_2_HELP_STR
5567 EVPN_TYPE_2_HELP_STR
5568 "MAC Table\n"
5569 VTEP_HELP_STR
5570 VTEP_IP_HELP_STR
5571 JSON_STR)
5572{
5573 struct bgp *bgp;
5574 json_object *json = NULL;
5575
5576 bgp = bgp_get_evpn();
5577 if (!bgp)
5578 return CMD_WARNING;
5579
5580 /* check if we need json output */
5581 if (uj)
5582 json = json_object_new_object();
5583
5584 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5585 json);
5586
d950d224
SW
5587 if (uj)
5588 vty_json(vty, json);
852d9f97
SW
5589
5590 return CMD_SUCCESS;
5591}
5592
5593/*
5594 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5595 */
5596DEFPY(show_bgp_vni_macip_ip,
5597 show_bgp_vni_macip_ip_cmd,
5598 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5599 SHOW_STR
5600 BGP_STR
5601 VNI_HELP_STR
5602 VNI_NUM_HELP_STR
5603 EVPN_TYPE_HELP_STR
5604 EVPN_TYPE_2_HELP_STR
5605 EVPN_TYPE_2_HELP_STR
5606 "IP Table\n"
5607 VTEP_HELP_STR
5608 VTEP_IP_HELP_STR
5609 JSON_STR)
5610{
5611 struct bgp *bgp;
5612 json_object *json = NULL;
5613
5614 bgp = bgp_get_evpn();
5615 if (!bgp)
5616 return CMD_WARNING;
5617
5618 /* check if we need json output */
5619 if (uj)
5620 json = json_object_new_object();
5621
5622 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5623 json);
5624
d950d224
SW
5625 if (uj)
5626 vty_json(vty, json);
852d9f97
SW
5627
5628 return CMD_SUCCESS;
5629}
5630
5631/*
5632 * Display per-VNI EVPN Multicast routing table - for select VNI
5633 */
5634DEFPY(show_bgp_vni_imet,
5635 show_bgp_vni_imet_cmd,
5636 "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5637 SHOW_STR
5638 BGP_STR
5639 VNI_HELP_STR
5640 VNI_NUM_HELP_STR
5641 EVPN_TYPE_HELP_STR
5642 EVPN_TYPE_3_HELP_STR
5643 EVPN_TYPE_3_HELP_STR
5644 VTEP_HELP_STR
5645 VTEP_IP_HELP_STR
5646 JSON_STR)
5647{
5648 struct bgp *bgp;
5649 json_object *json = NULL;
5650
5651 bgp = bgp_get_evpn();
5652 if (!bgp)
5653 return CMD_WARNING;
5654
5655 /* check if we need json output */
5656 if (uj)
5657 json = json_object_new_object();
5658
5659 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
5660 json);
5661
d950d224
SW
5662 if (uj)
5663 vty_json(vty, json);
852d9f97
SW
5664
5665 return CMD_SUCCESS;
5666}
5667
5668/*
5669 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5670 */
5671DEFPY(show_bgp_vni_macip_mac_addr,
5672 show_bgp_vni_macip_mac_addr_cmd,
5673 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5674 SHOW_STR
5675 BGP_STR
5676 VNI_HELP_STR
5677 VNI_NUM_HELP_STR
5678 EVPN_TYPE_HELP_STR
5679 EVPN_TYPE_2_HELP_STR
5680 EVPN_TYPE_2_HELP_STR
5681 "MAC Table\n"
5682 MAC_STR
5683 JSON_STR)
5684{
5685 struct bgp *bgp;
5686 json_object *json = NULL;
5687
5688 bgp = bgp_get_evpn();
5689 if (!bgp)
5690 return CMD_WARNING;
5691
5692 /* check if we need json output */
5693 if (uj)
5694 json = json_object_new_object();
5695
5696 evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
5697
d950d224
SW
5698 if (uj)
5699 vty_json(vty, json);
852d9f97
SW
5700
5701 return CMD_SUCCESS;
5702}
5703
5704/*
5705 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5706 */
5707DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
5708 "show bgp vni " CMD_VNI_RANGE
5709 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5710 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5711 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5712 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
5713{
5714 struct bgp *bgp;
5715 json_object *json = NULL;
5716 struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
5717
5718 bgp = bgp_get_evpn();
5719 if (!bgp)
5720 return CMD_WARNING;
5721
5722 /* check if we need json output */
5723 if (uj)
5724 json = json_object_new_object();
5725
5726 if (sockunion_family(ip) == AF_INET) {
5727 ip_addr.ipa_type = IPADDR_V4;
5728 ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
5729 } else {
5730 ip_addr.ipa_type = IPADDR_V6;
5731 memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
5732 sizeof(struct in6_addr));
5733 }
5734 evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
9c92b5f7 5735
c48349e3 5736 if (uj)
75eeda93 5737 vty_json(vty, json);
9c92b5f7 5738
d62a17ae 5739 return CMD_SUCCESS;
520d5d76 5740}
5741
229587fb 5742DEFPY_HIDDEN(
d656e0ae
AK
5743 show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5744 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5745 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
229587fb
AK
5746 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5747 "EVPN route information\n"
d656e0ae 5748 "MAC IP routes in the EVI tables linked to the ES\n"
229587fb
AK
5749 "ES ID\n"
5750 "Detailed information\n" JSON_STR)
5751{
5752 esi_t esi;
5753 esi_t *esi_p;
5754 json_object *json = NULL;
5755
5756 if (esi_str) {
5757 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5758 vty_out(vty, "%% Malformed ESI\n");
229587fb
AK
5759 return CMD_WARNING;
5760 }
5761 esi_p = &esi;
5762 } else {
5763 esi_p = NULL;
5764 }
5765
5766 if (uj)
5767 json = json_object_new_object();
d656e0ae 5768 bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
c48349e3 5769 if (uj)
75eeda93 5770 vty_json(vty, json);
229587fb
AK
5771
5772 return CMD_SUCCESS;
5773}
5774
58bff4d1
AK
5775DEFPY_HIDDEN(
5776 show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5777 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5778 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5779 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5780 "EVPN route information\n"
5781 "MAC IP routes in the global table linked to the ES\n"
5782 "ES ID\n"
5783 "Detailed information\n" JSON_STR)
5784{
5785 esi_t esi;
5786 esi_t *esi_p;
5787 json_object *json = NULL;
5788
5789 if (esi_str) {
5790 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5791 vty_out(vty, "%% Malformed ESI\n");
58bff4d1
AK
5792 return CMD_WARNING;
5793 }
5794 esi_p = &esi;
5795 } else {
5796 esi_p = NULL;
5797 }
5798
5799 if (uj)
5800 json = json_object_new_object();
5801 bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
c48349e3 5802 if (uj)
75eeda93 5803 vty_json(vty, json);
58bff4d1
AK
5804
5805 return CMD_SUCCESS;
5806}
5807
10ebe1ab
MK
5808/*
5809 * Display EVPN import route-target hash table
5810 */
5811DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5812 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5813 "show bgp l2vpn evpn vrf-import-rt [json]",
5814 SHOW_STR
5815 BGP_STR
5816 L2VPN_HELP_STR
5817 EVPN_HELP_STR
5818 "Show vrf import route target\n"
5819 JSON_STR)
5820{
9f049418 5821 bool uj = false;
5e53dce3 5822 struct bgp *bgp_evpn = NULL;
10ebe1ab
MK
5823 json_object *json = NULL;
5824
5e53dce3
T
5825 bgp_evpn = bgp_get_evpn();
5826 if (!bgp_evpn)
10ebe1ab
MK
5827 return CMD_WARNING;
5828
5829 uj = use_json(argc, argv);
5830 if (uj)
5831 json = json_object_new_object();
5832
5e53dce3 5833 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
10ebe1ab 5834
c48349e3 5835 if (uj)
75eeda93 5836 vty_json(vty, json);
10ebe1ab
MK
5837
5838 return CMD_SUCCESS;
5839}
5840
f2d62262 5841/*
5842 * Display EVPN import route-target hash table
5843 */
60466a63
QY
5844DEFUN(show_bgp_l2vpn_evpn_import_rt,
5845 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
5846 "show bgp l2vpn evpn import-rt [json]",
5847 SHOW_STR
5848 BGP_STR
5849 L2VPN_HELP_STR
5850 EVPN_HELP_STR
5851 "Show import route target\n"
5852 JSON_STR)
520d5d76 5853{
d62a17ae 5854 struct bgp *bgp;
9f049418 5855 bool uj = false;
9c92b5f7 5856 json_object *json = NULL;
520d5d76 5857
530db8dc 5858 bgp = bgp_get_evpn();
d62a17ae 5859 if (!bgp)
5860 return CMD_WARNING;
520d5d76 5861
9c92b5f7
MK
5862 uj = use_json(argc, argv);
5863 if (uj)
5864 json = json_object_new_object();
5865
5866 evpn_show_import_rts(vty, bgp, json);
5867
c48349e3 5868 if (uj)
75eeda93 5869 vty_json(vty, json);
9c92b5f7 5870
d62a17ae 5871 return CMD_SUCCESS;
520d5d76 5872}
5873
1673a90d 5874DEFPY_HIDDEN(test_es_add,
b5e140c8
AK
5875 test_es_add_cmd,
5876 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5877 NO_STR
5878 "Test\n"
50f74cf1 5879 "Ethernet-segment\n"
b5e140c8
AK
5880 "Ethernet-Segment Identifier\n"
5881 "ES link state\n"
5882 "up|down\n"
5883)
50f74cf1 5884{
5885 int ret = 0;
5886 esi_t esi;
5887 struct bgp *bgp;
b5e140c8
AK
5888 struct in_addr vtep_ip;
5889 bool oper_up;
50f74cf1 5890
530db8dc 5891 bgp = bgp_get_evpn();
50f74cf1 5892 if (!bgp) {
664b6f18 5893 vty_out(vty, "%% EVPN BGP instance not yet created\n");
50f74cf1 5894 return CMD_WARNING;
5895 }
5896
b5e140c8 5897 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5898 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 5899 return CMD_WARNING;
5900 }
5901
b5e140c8
AK
5902 if (no) {
5903 ret = bgp_evpn_local_es_del(bgp, &esi);
5904 if (ret == -1) {
664b6f18 5905 vty_out(vty, "%% Failed to delete ES\n");
b5e140c8
AK
5906 return CMD_WARNING;
5907 }
5908 } else {
5909 if (state_str && !strcmp(state_str, "up"))
5910 oper_up = true;
5911 else
5912 oper_up = false;
5913 vtep_ip = bgp->router_id;
50f74cf1 5914
74e2bd89 5915 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
74be8313 5916 EVPN_MH_DF_PREF_MIN, false);
b5e140c8 5917 if (ret == -1) {
664b6f18 5918 vty_out(vty, "%% Failed to add ES\n");
b5e140c8
AK
5919 return CMD_WARNING;
5920 }
50f74cf1 5921 }
5922 return CMD_SUCCESS;
5923}
5924
1673a90d 5925DEFPY_HIDDEN(test_es_vni_add,
b5e140c8
AK
5926 test_es_vni_add_cmd,
5927 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5928 NO_STR
5929 "Test\n"
50f74cf1 5930 "Ethernet-segment\n"
b5e140c8
AK
5931 "Ethernet-Segment Identifier\n"
5932 "VNI\n"
5933 "1-16777215\n"
5934)
50f74cf1 5935{
5936 int ret = 0;
5937 esi_t esi;
5938 struct bgp *bgp;
50f74cf1 5939
530db8dc 5940 bgp = bgp_get_evpn();
50f74cf1 5941 if (!bgp) {
664b6f18 5942 vty_out(vty, "%% EVPN BGP instance not yet created\n");
50f74cf1 5943 return CMD_WARNING;
5944 }
5945
b5e140c8 5946 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5947 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 5948 return CMD_WARNING;
5949 }
5950
b5e140c8
AK
5951 if (no) {
5952 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5953 if (ret == -1) {
664b6f18 5954 vty_out(vty, "%% Failed to deref ES VNI\n");
b5e140c8
AK
5955 return CMD_WARNING;
5956 }
5957 } else {
5958 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5959 if (ret == -1) {
664b6f18 5960 vty_out(vty, "%% Failed to ref ES VNI\n");
b5e140c8
AK
5961 return CMD_WARNING;
5962 }
50f74cf1 5963 }
5964 return CMD_SUCCESS;
5965}
5966
5014d96f 5967ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
093e3f23 5968 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5014d96f
DW
5969 "Show VNI\n"
5970 "VNI number\n")
5971
5972ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5973 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 5974 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
5975
5976ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
2b1364e1 5977 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5014d96f 5978 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 5979 EVPN_RT_HELP_STR
21f3551e 5980 "Display Detailed Information\n"
f5dc0b1a
SW
5981 EVPN_TYPE_HELP_STR
5982 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5983 EVPN_TYPE_2_HELP_STR
5984 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5985 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
5986
5987ALIAS_HIDDEN(
5988 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
2b1364e1 5989 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5014d96f 5990 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
5991 EVPN_RT_HELP_STR
5992 EVPN_RT_DIST_HELP_STR
5993 EVPN_ASN_IP_HELP_STR
5994 EVPN_TYPE_HELP_STR
5995 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5996 EVPN_TYPE_2_HELP_STR
5997 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5998 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
5999
6000ALIAS_HIDDEN(
6001 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 6002 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f 6003 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
6004 EVPN_RT_HELP_STR
6005 EVPN_RT_DIST_HELP_STR
6006 EVPN_ASN_IP_HELP_STR
5014d96f
DW
6007 "MAC\n"
6008 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6009 "IP\n"
6010 "IP address (IPv4 or IPv6)\n")
6011
6012ALIAS_HIDDEN(
6013 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
2b1364e1 6014 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5014d96f 6015 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6016 EVPN_RT_HELP_STR
5014d96f
DW
6017 "VXLAN Network Identifier\n"
6018 "VNI number\n"
f5dc0b1a
SW
6019 EVPN_TYPE_HELP_STR
6020 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
6021 EVPN_TYPE_2_HELP_STR
6022 EVPN_TYPE_3_HELP_STR
f5dc0b1a 6023 EVPN_TYPE_3_HELP_STR
5014d96f
DW
6024 "Remote VTEP\n"
6025 "Remote VTEP IP address\n")
6026
6027ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
6028 show_bgp_evpn_route_vni_macip_cmd,
093e3f23 6029 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
5014d96f 6030 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6031 EVPN_RT_HELP_STR
5014d96f
DW
6032 "VXLAN Network Identifier\n"
6033 "VNI number\n"
6034 "MAC\n"
6035 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6036 "IP\n"
6037 "IP address (IPv4 or IPv6)\n")
6038
6039ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
6040 show_bgp_evpn_route_vni_multicast_cmd,
093e3f23 6041 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
5014d96f 6042 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6043 EVPN_RT_HELP_STR
5014d96f
DW
6044 "VXLAN Network Identifier\n"
6045 "VNI number\n"
f5dc0b1a 6046 EVPN_TYPE_3_HELP_STR
5014d96f
DW
6047 "Originating Router IP address\n")
6048
6049ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
c7ef6cf2 6050 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5014d96f 6051 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6052 EVPN_RT_HELP_STR
5014d96f
DW
6053 "VXLAN Network Identifier\n"
6054 "All VNIs\n"
c7ef6cf2 6055 "Print Detailed Output\n"
5014d96f
DW
6056 "Remote VTEP\n"
6057 "Remote VTEP IP address\n")
6058
6059ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
6060 "show bgp evpn import-rt",
6061 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5014d96f 6062
90e60aa7 6063DEFUN_NOSH (bgp_evpn_vni,
6064 bgp_evpn_vni_cmd,
093e3f23 6065 "vni " CMD_VNI_RANGE,
90e60aa7 6066 "VXLAN Network Identifier\n"
6067 "VNI number\n")
6068{
d62a17ae 6069 vni_t vni;
6070 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6071 struct bgpevpn *vpn;
90e60aa7 6072
d62a17ae 6073 if (!bgp)
6074 return CMD_WARNING;
90e60aa7 6075
d62a17ae 6076 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 6077
d62a17ae 6078 /* Create VNI, or mark as configured. */
6079 vpn = evpn_create_update_vni(bgp, vni);
6080 if (!vpn) {
6081 vty_out(vty, "%% Failed to create VNI \n");
6082 return CMD_WARNING;
6083 }
90e60aa7 6084
d62a17ae 6085 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
6086 return CMD_SUCCESS;
90e60aa7 6087}
6088
6089DEFUN (no_bgp_evpn_vni,
6090 no_bgp_evpn_vni_cmd,
093e3f23 6091 "no vni " CMD_VNI_RANGE,
90e60aa7 6092 NO_STR
6093 "VXLAN Network Identifier\n"
6094 "VNI number\n")
6095{
d62a17ae 6096 vni_t vni;
6097 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6098 struct bgpevpn *vpn;
90e60aa7 6099
d62a17ae 6100 if (!bgp)
6101 return CMD_WARNING;
90e60aa7 6102
d62a17ae 6103 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 6104
d62a17ae 6105 /* Check if we should disallow. */
6106 vpn = bgp_evpn_lookup_vni(bgp, vni);
6107 if (!vpn) {
6108 vty_out(vty, "%% Specified VNI does not exist\n");
6109 return CMD_WARNING;
6110 }
6111 if (!is_vni_configured(vpn)) {
6112 vty_out(vty, "%% Specified VNI is not configured\n");
6113 return CMD_WARNING;
6114 }
90e60aa7 6115
d62a17ae 6116 evpn_delete_vni(bgp, vpn);
6117 return CMD_SUCCESS;
90e60aa7 6118}
6119
6120DEFUN_NOSH (exit_vni,
6121 exit_vni_cmd,
6122 "exit-vni",
6123 "Exit from VNI mode\n")
6124{
d62a17ae 6125 if (vty->node == BGP_EVPN_VNI_NODE)
6126 vty->node = BGP_EVPN_NODE;
6127 return CMD_SUCCESS;
90e60aa7 6128}
6129
676f83b9 6130DEFUN (bgp_evpn_vrf_rd,
6131 bgp_evpn_vrf_rd_cmd,
6132 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
6133 EVPN_RT_DIST_HELP_STR
6134 EVPN_ASN_IP_HELP_STR)
676f83b9 6135{
6136 int ret;
6137 struct prefix_rd prd;
6138 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6139
6140 if (!bgp_vrf)
6141 return CMD_WARNING;
6142
6143 ret = str2prefix_rd(argv[1]->arg, &prd);
6144 if (!ret) {
6145 vty_out(vty, "%% Malformed Route Distinguisher\n");
6146 return CMD_WARNING;
6147 }
6148
6149 /* If same as existing value, there is nothing more to do. */
6150 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
6151 return CMD_SUCCESS;
6152
6153 /* Configure or update the RD. */
fa566a94 6154 evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);
676f83b9 6155 return CMD_SUCCESS;
6156}
6157
6158DEFUN (no_bgp_evpn_vrf_rd,
6159 no_bgp_evpn_vrf_rd_cmd,
6160 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6161 NO_STR
f5dc0b1a
SW
6162 EVPN_RT_DIST_HELP_STR
6163 EVPN_ASN_IP_HELP_STR)
676f83b9 6164{
6165 int ret;
6166 struct prefix_rd prd;
6167 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6168
6169 if (!bgp_vrf)
6170 return CMD_WARNING;
6171
6172 ret = str2prefix_rd(argv[2]->arg, &prd);
6173 if (!ret) {
6174 vty_out(vty, "%% Malformed Route Distinguisher\n");
6175 return CMD_WARNING;
6176 }
6177
6178 /* Check if we should disallow. */
6179 if (!is_vrf_rd_configured(bgp_vrf)) {
6180 vty_out(vty, "%% RD is not configured for this VRF\n");
6181 return CMD_WARNING;
6182 }
6183
6184 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
6185 vty_out(vty,
6186 "%% RD specified does not match configuration for this VRF\n");
6187 return CMD_WARNING;
6188 }
6189
6190 evpn_unconfigure_vrf_rd(bgp_vrf);
6191 return CMD_SUCCESS;
6192}
6193
6194DEFUN (no_bgp_evpn_vrf_rd_without_val,
6195 no_bgp_evpn_vrf_rd_without_val_cmd,
6196 "no rd",
6197 NO_STR
f5dc0b1a 6198 EVPN_RT_DIST_HELP_STR)
676f83b9 6199{
6200 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6201
6202 if (!bgp_vrf)
6203 return CMD_WARNING;
6204
6205 /* Check if we should disallow. */
6206 if (!is_vrf_rd_configured(bgp_vrf)) {
6207 vty_out(vty, "%% RD is not configured for this VRF\n");
6208 return CMD_WARNING;
6209 }
6210
6211 evpn_unconfigure_vrf_rd(bgp_vrf);
6212 return CMD_SUCCESS;
6213}
6214
90e60aa7 6215DEFUN (bgp_evpn_vni_rd,
6216 bgp_evpn_vni_rd_cmd,
d114b977 6217 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
6218 EVPN_RT_DIST_HELP_STR
6219 EVPN_ASN_IP_HELP_STR)
90e60aa7 6220{
d62a17ae 6221 struct prefix_rd prd;
6222 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6223 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6224 int ret;
90e60aa7 6225
06fe25f4 6226 if (!bgp)
d62a17ae 6227 return CMD_WARNING;
90e60aa7 6228
f920dd6d 6229 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6230 vty_out(vty,
530db8dc 6231 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6232 return CMD_WARNING;
6233 }
6234
d62a17ae 6235 ret = str2prefix_rd(argv[1]->arg, &prd);
6236 if (!ret) {
6237 vty_out(vty, "%% Malformed Route Distinguisher\n");
6238 return CMD_WARNING;
6239 }
90e60aa7 6240
d62a17ae 6241 /* If same as existing value, there is nothing more to do. */
6242 if (bgp_evpn_rd_matches_existing(vpn, &prd))
6243 return CMD_SUCCESS;
90e60aa7 6244
d62a17ae 6245 /* Configure or update the RD. */
fa566a94 6246 evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);
d62a17ae 6247 return CMD_SUCCESS;
90e60aa7 6248}
6249
6250DEFUN (no_bgp_evpn_vni_rd,
6251 no_bgp_evpn_vni_rd_cmd,
d114b977 6252 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 6253 NO_STR
f5dc0b1a
SW
6254 EVPN_RT_DIST_HELP_STR
6255 EVPN_ASN_IP_HELP_STR)
90e60aa7 6256{
d62a17ae 6257 struct prefix_rd prd;
6258 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6259 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6260 int ret;
90e60aa7 6261
06fe25f4 6262 if (!bgp)
d62a17ae 6263 return CMD_WARNING;
90e60aa7 6264
f920dd6d 6265 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6266 vty_out(vty,
530db8dc 6267 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6268 return CMD_WARNING;
6269 }
6270
d62a17ae 6271 ret = str2prefix_rd(argv[2]->arg, &prd);
6272 if (!ret) {
6273 vty_out(vty, "%% Malformed Route Distinguisher\n");
6274 return CMD_WARNING;
6275 }
90e60aa7 6276
d62a17ae 6277 /* Check if we should disallow. */
6278 if (!is_rd_configured(vpn)) {
6279 vty_out(vty, "%% RD is not configured for this VNI\n");
6280 return CMD_WARNING;
6281 }
90e60aa7 6282
d62a17ae 6283 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
6284 vty_out(vty,
6285 "%% RD specified does not match configuration for this VNI\n");
6286 return CMD_WARNING;
6287 }
90e60aa7 6288
d62a17ae 6289 evpn_unconfigure_rd(bgp, vpn);
6290 return CMD_SUCCESS;
90e60aa7 6291}
6292
6293DEFUN (no_bgp_evpn_vni_rd_without_val,
6294 no_bgp_evpn_vni_rd_without_val_cmd,
6295 "no rd",
6296 NO_STR
f5dc0b1a 6297 EVPN_RT_DIST_HELP_STR)
90e60aa7 6298{
d62a17ae 6299 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6300 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 6301
06fe25f4 6302 if (!bgp)
d62a17ae 6303 return CMD_WARNING;
90e60aa7 6304
f920dd6d 6305 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6306 vty_out(vty,
530db8dc 6307 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6308 return CMD_WARNING;
6309 }
6310
d62a17ae 6311 /* Check if we should disallow. */
6312 if (!is_rd_configured(vpn)) {
6313 vty_out(vty, "%% RD is not configured for this VNI\n");
6314 return CMD_WARNING;
6315 }
90e60aa7 6316
d62a17ae 6317 evpn_unconfigure_rd(bgp, vpn);
6318 return CMD_SUCCESS;
90e60aa7 6319}
6320
6321/*
6322 * Loop over all extended-communities in the route-target list rtl and
6323 * return 1 if we find ecomtarget
6324 */
ca337b46
SW
6325static bool bgp_evpn_rt_matches_existing(struct list *rtl,
6326 struct ecommunity *ecomtarget)
90e60aa7 6327{
ca337b46 6328 struct listnode *node;
d62a17ae 6329 struct ecommunity *ecom;
90e60aa7 6330
ca337b46 6331 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
d62a17ae 6332 if (ecommunity_match(ecom, ecomtarget))
ca337b46 6333 return true;
d62a17ae 6334 }
90e60aa7 6335
ca337b46
SW
6336 return false;
6337}
6338
6339/*
6340 * L3 RT version of above.
6341 */
6342static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
6343 struct ecommunity *ecomtarget)
6344{
6345 struct listnode *node;
6346 struct vrf_route_target *l3rt;
6347
6348 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
6349 if (ecommunity_match(l3rt->ecom, ecomtarget))
6350 return true;
6351 }
6352
6353 return false;
90e60aa7 6354}
6355
c581d8b0
MK
6356/* display L3VNI related info for a VRF instance */
6357DEFUN (show_bgp_vrf_l3vni_info,
6358 show_bgp_vrf_l3vni_info_cmd,
4cce389e 6359 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
6360 SHOW_STR
6361 BGP_STR
6362 "show bgp vrf\n"
6363 "VRF Name\n"
6364 "L3-VNI\n"
ceb9a921 6365 JSON_STR)
c581d8b0
MK
6366{
6367 char buf[ETHER_ADDR_STRLEN];
6368 int idx_vrf = 3;
6369 const char *name = NULL;
6370 struct bgp *bgp = NULL;
6371 struct listnode *node = NULL;
6a8657d0 6372 struct bgpevpn *vpn = NULL;
ca337b46 6373 struct vrf_route_target *l3rt;
ceb9a921
MK
6374 json_object *json = NULL;
6375 json_object *json_vnis = NULL;
6376 json_object *json_export_rts = NULL;
6377 json_object *json_import_rts = NULL;
9f049418 6378 bool uj = use_json(argc, argv);
ceb9a921
MK
6379
6380 if (uj) {
6381 json = json_object_new_object();
6382 json_vnis = json_object_new_array();
6383 json_export_rts = json_object_new_array();
6384 json_import_rts = json_object_new_array();
6385 }
c581d8b0
MK
6386
6387 name = argv[idx_vrf]->arg;
6388 bgp = bgp_lookup_by_name(name);
4a5271a5 6389 if (strmatch(name, VRF_DEFAULT_NAME))
6390 bgp = bgp_get_default();
6391
c581d8b0 6392 if (!bgp) {
ceb9a921 6393 if (!uj)
4a5271a5 6394 vty_out(vty, "BGP instance for VRF %s not found\n",
6395 name);
ceb9a921
MK
6396 else {
6397 json_object_string_add(json, "warning",
6398 "BGP instance not found");
996c9314 6399 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
6400 json_object_free(json);
6401 }
c581d8b0
MK
6402 return CMD_WARNING;
6403 }
6404
ceb9a921
MK
6405 if (!json) {
6406 vty_out(vty, "BGP VRF: %s\n", name);
23d0a753 6407 vty_out(vty, " Local-Ip: %pI4\n", &bgp->originator_ip);
ceb9a921
MK
6408 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
6409 vty_out(vty, " Rmac: %s\n",
6410 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
6411 vty_out(vty, " VNI Filter: %s\n",
6412 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
6413 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6414 ? "prefix-routes-only"
6415 : "none");
ceb9a921
MK
6416 vty_out(vty, " L2-VNI List:\n");
6417 vty_out(vty, " ");
6418 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6419 vty_out(vty, "%u ", vpn->vni);
6420 vty_out(vty, "\n");
6421 vty_out(vty, " Export-RTs:\n");
6422 vty_out(vty, " ");
ca337b46
SW
6423 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6424 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
ceb9a921
MK
6425 vty_out(vty, "\n");
6426 vty_out(vty, " Import-RTs:\n");
6427 vty_out(vty, " ");
ca337b46
SW
6428 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6429 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
ceb9a921 6430 vty_out(vty, "\n");
4a8cd6ad
PG
6431 vty_out(vty, " RD: ");
6432 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd);
6433 vty_out(vty, "\n");
ceb9a921
MK
6434 } else {
6435 json_object_string_add(json, "vrf", name);
c949c771
DA
6436 json_object_string_addf(json, "local-ip", "%pI4",
6437 &bgp->originator_ip);
ceb9a921 6438 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
6439 json_object_string_add(
6440 json, "rmac",
6441 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6442 json_object_string_add(
6443 json, "vniFilter",
6444 CHECK_FLAG(bgp->vrf_flags,
6445 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6446 ? "prefix-routes-only"
6447 : "none");
ceb9a921
MK
6448 /* list of l2vnis */
6449 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6450 json_object_array_add(json_vnis,
6451 json_object_new_int(vpn->vni));
6452 json_object_object_add(json, "l2vnis", json_vnis);
6453
6454 /* export rts */
ca337b46 6455 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
996c9314
LB
6456 json_object_array_add(
6457 json_export_rts,
ca337b46
SW
6458 json_object_new_string(
6459 ecommunity_str(l3rt->ecom)));
ceb9a921
MK
6460 json_object_object_add(json, "export-rts", json_export_rts);
6461
6462 /* import rts */
ca337b46 6463 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
996c9314
LB
6464 json_object_array_add(
6465 json_import_rts,
ca337b46
SW
6466 json_object_new_string(
6467 ecommunity_str(l3rt->ecom)));
ceb9a921 6468 json_object_object_add(json, "import-rts", json_import_rts);
4a8cd6ad
PG
6469 json_object_string_addf(json, "rd",
6470 BGP_RD_AS_FORMAT(bgp->asnotation),
6471 &bgp->vrf_prd);
ceb9a921 6472 }
c581d8b0 6473
c48349e3 6474 if (uj)
75eeda93 6475 vty_json(vty, json);
c581d8b0
MK
6476 return CMD_SUCCESS;
6477}
6478
58d8948c
SW
6479static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
6480 bool is_wildcard)
7022da35
SW
6481{
6482 /* Do nothing if we already have this route-target */
6483 if (is_import) {
ca337b46
SW
6484 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6485 ecom))
58d8948c
SW
6486 bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
6487 is_wildcard);
7022da35
SW
6488 else
6489 return -1;
6490 } else {
ca337b46
SW
6491 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6492 ecom))
7022da35
SW
6493 bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
6494 else
6495 return -1;
6496 }
6497
6498 return 0;
6499}
6500
6501static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
6502{
6503 /* Verify we already have this route-target */
6504 if (is_import) {
ca337b46
SW
6505 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6506 ecom))
7022da35
SW
6507 return -1;
6508
6509 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
6510 } else {
ca337b46
SW
6511 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6512 ecom))
7022da35
SW
6513 return -1;
6514
6515 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
6516 }
6517
6518 return 0;
6519}
6520
6521static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
6522 struct cmd_token **argv, int rt_idx, bool is_add,
6523 bool is_import)
6524{
6525 int ret = CMD_SUCCESS;
58d8948c 6526 bool is_wildcard = false;
7022da35
SW
6527 struct ecommunity *ecom = NULL;
6528
6529 for (int i = rt_idx; i < argc; i++) {
58d8948c
SW
6530 is_wildcard = false;
6531
6532 /*
6533 * Special handling for wildcard '*' here.
6534 *
6535 * Let's just convert it to 0 here so we dont have to modify
6536 * the ecommunity parser.
6537 */
6538 if ((argv[i]->arg)[0] == '*') {
58d8948c
SW
6539 (argv[i]->arg)[0] = '0';
6540 is_wildcard = true;
6541 }
6542
7022da35
SW
6543 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
6544 0);
6545
58d8948c
SW
6546 /* Put it back as was */
6547 if (is_wildcard)
6548 (argv[i]->arg)[0] = '*';
6549
7022da35
SW
6550 if (!ecom) {
6551 vty_out(vty, "%% Malformed Route Target list\n");
6552 ret = CMD_WARNING;
6553 continue;
6554 }
6555
6556 ecommunity_str(ecom);
6557
6558 if (is_add) {
58d8948c 6559 if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
7022da35
SW
6560 vty_out(vty,
6561 "%% RT specified already configured for this VRF: %s\n",
6562 argv[i]->arg);
6563 ecommunity_free(&ecom);
6564 ret = CMD_WARNING;
6565 }
6566
6567 } else {
6568 if (del_rt(bgp, ecom, is_import) != 0) {
6569 vty_out(vty,
6570 "%% RT specified does not match configuration for this VRF: %s\n",
6571 argv[i]->arg);
6572 ret = CMD_WARNING;
6573 }
6574
6575 ecommunity_free(&ecom);
6576 }
6577 }
6578
6579 return ret;
6580}
6581
c581d8b0
MK
6582/* import/export rt for l3vni-vrf */
6583DEFUN (bgp_evpn_vrf_rt,
6584 bgp_evpn_vrf_rt_cmd,
7022da35 6585 "route-target <both|import|export> RTLIST...",
c581d8b0
MK
6586 "Route Target\n"
6587 "import and export\n"
6588 "import\n"
6589 "export\n"
58d8948c 6590 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
c581d8b0 6591{
7022da35
SW
6592 int ret = CMD_SUCCESS;
6593 int tmp_ret = CMD_SUCCESS;
c581d8b0
MK
6594 int rt_type;
6595 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
c581d8b0
MK
6596
6597 if (!bgp)
7022da35 6598 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6599
6600 if (!strcmp(argv[1]->arg, "import"))
6601 rt_type = RT_TYPE_IMPORT;
6602 else if (!strcmp(argv[1]->arg, "export"))
6603 rt_type = RT_TYPE_EXPORT;
6604 else if (!strcmp(argv[1]->arg, "both"))
6605 rt_type = RT_TYPE_BOTH;
6606 else {
6607 vty_out(vty, "%% Invalid Route Target type\n");
7022da35 6608 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6609 }
6610
58d8948c
SW
6611 if (strmatch(argv[2]->arg, "auto")) {
6612 vty_out(vty, "%% `auto` cannot be configured via list\n");
6613 return CMD_WARNING_CONFIG_FAILED;
3b7e8d0f 6614 }
3b7e8d0f 6615
7231b9ab 6616 if (rt_type != RT_TYPE_IMPORT) {
6617 for (int i = 2; i < argc; i++) {
6618 if ((argv[i]->arg)[0] == '*') {
6619 vty_out(vty,
6620 "%% Wildcard '*' only applicable for import\n");
6621 return CMD_WARNING_CONFIG_FAILED;
6622 }
6623 }
6624 }
6625
c581d8b0 6626 /* Add/update the import route-target */
7022da35
SW
6627 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6628 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
c581d8b0 6629
7022da35
SW
6630 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6631 ret = tmp_ret;
c581d8b0 6632
7022da35
SW
6633 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6634 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
6635
6636 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6637 ret = tmp_ret;
6638
6639 return ret;
6640}
6641
a5d7012c 6642DEFPY (bgp_evpn_vrf_rt_auto,
7022da35 6643 bgp_evpn_vrf_rt_auto_cmd,
a5d7012c 6644 "route-target <both|import|export>$type auto",
7022da35
SW
6645 "Route Target\n"
6646 "import and export\n"
6647 "import\n"
6648 "export\n"
6649 "Automatically derive route target\n")
6650{
58d8948c
SW
6651 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6652 int rt_type;
6653
6654 if (!bgp)
6655 return CMD_WARNING_CONFIG_FAILED;
6656
a5d7012c 6657 if (strmatch(type, "import"))
58d8948c 6658 rt_type = RT_TYPE_IMPORT;
a5d7012c 6659 else if (strmatch(type, "export"))
58d8948c 6660 rt_type = RT_TYPE_EXPORT;
a5d7012c 6661 else if (strmatch(type, "both"))
58d8948c
SW
6662 rt_type = RT_TYPE_BOTH;
6663 else {
6664 vty_out(vty, "%% Invalid Route Target type\n");
6665 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6666 }
6667
58d8948c
SW
6668 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6669 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6670
6671 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6672 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6673
c581d8b0
MK
6674 return CMD_SUCCESS;
6675}
6676
6677DEFUN (no_bgp_evpn_vrf_rt,
6678 no_bgp_evpn_vrf_rt_cmd,
7022da35 6679 "no route-target <both|import|export> RTLIST...",
c581d8b0
MK
6680 NO_STR
6681 "Route Target\n"
6682 "import and export\n"
6683 "import\n"
6684 "export\n"
7022da35 6685 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
c581d8b0
MK
6686{
6687 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7022da35
SW
6688 int ret = CMD_SUCCESS;
6689 int tmp_ret = CMD_SUCCESS;
6690 int rt_type;
c581d8b0
MK
6691
6692 if (!bgp)
58d8948c 6693 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6694
6695 if (!strcmp(argv[2]->arg, "import"))
6696 rt_type = RT_TYPE_IMPORT;
6697 else if (!strcmp(argv[2]->arg, "export"))
6698 rt_type = RT_TYPE_EXPORT;
6699 else if (!strcmp(argv[2]->arg, "both"))
6700 rt_type = RT_TYPE_BOTH;
6701 else {
6702 vty_out(vty, "%% Invalid Route Target type\n");
7022da35 6703 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6704 }
6705
58d8948c
SW
6706 if (!strcmp(argv[3]->arg, "auto")) {
6707 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6708 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6709 }
6710
6711 if (rt_type == RT_TYPE_IMPORT) {
6712 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6713 vty_out(vty,
6714 "%% Import RT is not configured for this VRF\n");
58d8948c 6715 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6716 }
6717 } else if (rt_type == RT_TYPE_EXPORT) {
6718 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6719 vty_out(vty,
6720 "%% Export RT is not configured for this VRF\n");
58d8948c 6721 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6722 }
6723 } else if (rt_type == RT_TYPE_BOTH) {
6724 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6725 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6726 vty_out(vty,
6727 "%% Import/Export RT is not configured for this VRF\n");
58d8948c 6728 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6729 }
6730 }
6731
7231b9ab 6732 if (rt_type != RT_TYPE_IMPORT) {
6733 for (int i = 3; i < argc; i++) {
6734 if ((argv[i]->arg)[0] == '*') {
6735 vty_out(vty,
6736 "%% Wildcard '*' only applicable for import\n");
6737 return CMD_WARNING_CONFIG_FAILED;
6738 }
6739 }
6740 }
6741
7022da35
SW
6742 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6743 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
c581d8b0 6744
7022da35
SW
6745 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6746 ret = tmp_ret;
c581d8b0 6747
7022da35
SW
6748 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6749 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
c581d8b0 6750
7022da35
SW
6751 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6752 ret = tmp_ret;
c581d8b0 6753
7022da35
SW
6754 return ret;
6755}
c581d8b0 6756
a5d7012c 6757DEFPY (no_bgp_evpn_vrf_rt_auto,
7022da35 6758 no_bgp_evpn_vrf_rt_auto_cmd,
a5d7012c 6759 "no route-target <both|import|export>$type auto",
7022da35
SW
6760 NO_STR
6761 "Route Target\n"
6762 "import and export\n"
6763 "import\n"
6764 "export\n"
6765 "Automatically derive route target\n")
6766{
58d8948c
SW
6767 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6768 int rt_type;
6769
6770 if (!bgp)
6771 return CMD_WARNING_CONFIG_FAILED;
6772
a5d7012c 6773 if (strmatch(type, "import"))
58d8948c 6774 rt_type = RT_TYPE_IMPORT;
a5d7012c 6775 else if (strmatch(type, "export"))
58d8948c 6776 rt_type = RT_TYPE_EXPORT;
a5d7012c 6777 else if (strmatch(type, "both"))
58d8948c
SW
6778 rt_type = RT_TYPE_BOTH;
6779 else {
6780 vty_out(vty, "%% Invalid Route Target type\n");
6781 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6782 }
c581d8b0
MK
6783
6784 if (rt_type == RT_TYPE_IMPORT) {
58d8948c 6785 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
c581d8b0 6786 vty_out(vty,
58d8948c
SW
6787 "%% Import AUTO RT is not configured for this VRF\n");
6788 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6789 }
c581d8b0 6790 } else if (rt_type == RT_TYPE_EXPORT) {
58d8948c 6791 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
c581d8b0 6792 vty_out(vty,
58d8948c
SW
6793 "%% Export AUTO RT is not configured for this VRF\n");
6794 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6795 }
c581d8b0 6796 } else if (rt_type == RT_TYPE_BOTH) {
58d8948c
SW
6797 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6798 !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
c581d8b0 6799 vty_out(vty,
58d8948c
SW
6800 "%% Import/Export AUTO RT is not configured for this VRF\n");
6801 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6802 }
6803 }
6804
58d8948c
SW
6805 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6806 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6807
6808 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6809 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6810
c581d8b0
MK
6811 return CMD_SUCCESS;
6812}
90e60aa7 6813
bb37eabe
AK
6814DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6815 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6816 NO_STR
6817 "EAD ES fragment config\n"
6818 "EVIs per-fragment\n"
6819 "limit\n")
6820{
6821 bgp_mh_info->evi_per_es_frag =
6822 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6823
6824 return CMD_SUCCESS;
6825}
6826
f4a5218d
AK
6827DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6828 "ead-es-route-target export RT",
6829 "EAD ES Route Target\n"
6830 "export\n"
6831 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6832{
6833 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6834 struct ecommunity *ecomadd = NULL;
6835
6836 if (!bgp)
6837 return CMD_WARNING;
6838
6839 if (!EVPN_ENABLED(bgp)) {
6840 vty_out(vty, "This command is only supported under EVPN VRF\n");
6841 return CMD_WARNING;
6842 }
6843
6844 /* Add/update the export route-target */
6845 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6846 if (!ecomadd) {
6847 vty_out(vty, "%% Malformed Route Target list\n");
6848 return CMD_WARNING;
6849 }
6850 ecommunity_str(ecomadd);
6851
6852 /* Do nothing if we already have this export route-target */
6853 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6854 ecomadd))
6855 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6856
6857 return CMD_SUCCESS;
6858}
6859
6860DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6861 "no ead-es-route-target export RT",
6862 NO_STR
6863 "EAD ES Route Target\n"
6864 "export\n" EVPN_ASN_IP_HELP_STR)
6865{
6866 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6867 struct ecommunity *ecomdel = NULL;
6868
6869 if (!bgp)
6870 return CMD_WARNING;
6871
6872 if (!EVPN_ENABLED(bgp)) {
6873 vty_out(vty, "This command is only supported under EVPN VRF\n");
6874 return CMD_WARNING;
6875 }
6876
6877 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6878 if (!ecomdel) {
6879 vty_out(vty, "%% Malformed Route Target list\n");
6880 return CMD_WARNING;
6881 }
6882 ecommunity_str(ecomdel);
6883
6884 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6885 ecomdel)) {
df6a97a6 6886 ecommunity_free(&ecomdel);
f4a5218d
AK
6887 vty_out(vty,
6888 "%% RT specified does not match EAD-ES RT configuration\n");
6889 return CMD_WARNING;
6890 }
6891 bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6892
6893 return CMD_SUCCESS;
6894}
6895
90e60aa7 6896DEFUN (bgp_evpn_vni_rt,
6897 bgp_evpn_vni_rt_cmd,
6898 "route-target <both|import|export> RT",
6899 "Route Target\n"
6900 "import and export\n"
6901 "import\n"
6902 "export\n"
6903 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6904{
d62a17ae 6905 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6906 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6907 int rt_type;
6908 struct ecommunity *ecomadd = NULL;
6909
06fe25f4 6910 if (!bgp)
d62a17ae 6911 return CMD_WARNING;
6912
f920dd6d 6913 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6914 vty_out(vty,
530db8dc 6915 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6916 return CMD_WARNING;
6917 }
6918
8034beff 6919 if (!strcmp(argv[1]->text, "import"))
d62a17ae 6920 rt_type = RT_TYPE_IMPORT;
8034beff 6921 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 6922 rt_type = RT_TYPE_EXPORT;
8034beff 6923 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 6924 rt_type = RT_TYPE_BOTH;
6925 else {
6926 vty_out(vty, "%% Invalid Route Target type\n");
6927 return CMD_WARNING;
6928 }
6929
6930 /* Add/update the import route-target */
6931 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
432ff4b0 6932 /* Note that first of the two RTs is created for "both" type */
6933 ecomadd = ecommunity_str2com(argv[2]->arg,
6934 ECOMMUNITY_ROUTE_TARGET, 0);
6935 if (!ecomadd) {
6936 vty_out(vty, "%% Malformed Route Target list\n");
6937 return CMD_WARNING;
6938 }
6939 ecommunity_str(ecomadd);
6940
d62a17ae 6941 /* Do nothing if we already have this import route-target */
6942 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6943 evpn_configure_import_rt(bgp, vpn, ecomadd);
6944 }
6945
6946 /* Add/update the export route-target */
6947 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
432ff4b0 6948 /* Note that second of the two RTs is created for "both" type */
6949 ecomadd = ecommunity_str2com(argv[2]->arg,
6950 ECOMMUNITY_ROUTE_TARGET, 0);
6951 if (!ecomadd) {
6952 vty_out(vty, "%% Malformed Route Target list\n");
6953 return CMD_WARNING;
6954 }
6955 ecommunity_str(ecomadd);
6956
d62a17ae 6957 /* Do nothing if we already have this export route-target */
6958 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6959 evpn_configure_export_rt(bgp, vpn, ecomadd);
6960 }
6961
6962 return CMD_SUCCESS;
90e60aa7 6963}
6964
6965DEFUN (no_bgp_evpn_vni_rt,
6966 no_bgp_evpn_vni_rt_cmd,
6967 "no route-target <both|import|export> RT",
6968 NO_STR
6969 "Route Target\n"
6970 "import and export\n"
6971 "import\n"
6972 "export\n"
f5dc0b1a 6973 EVPN_ASN_IP_HELP_STR)
90e60aa7 6974{
d62a17ae 6975 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6976 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6977 int rt_type, found_ecomdel;
6978 struct ecommunity *ecomdel = NULL;
6979
06fe25f4 6980 if (!bgp)
d62a17ae 6981 return CMD_WARNING;
6982
f920dd6d 6983 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6984 vty_out(vty,
530db8dc 6985 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6986 return CMD_WARNING;
6987 }
6988
8034beff 6989 if (!strcmp(argv[2]->text, "import"))
d62a17ae 6990 rt_type = RT_TYPE_IMPORT;
8034beff 6991 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 6992 rt_type = RT_TYPE_EXPORT;
8034beff 6993 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 6994 rt_type = RT_TYPE_BOTH;
6995 else {
6996 vty_out(vty, "%% Invalid Route Target type\n");
6997 return CMD_WARNING;
6998 }
6999
7000 /* The user did "no route-target import", check to see if there are any
7001 * import route-targets configured. */
7002 if (rt_type == RT_TYPE_IMPORT) {
7003 if (!is_import_rt_configured(vpn)) {
7004 vty_out(vty,
7005 "%% Import RT is not configured for this VNI\n");
7006 return CMD_WARNING;
7007 }
7008 } else if (rt_type == RT_TYPE_EXPORT) {
7009 if (!is_export_rt_configured(vpn)) {
7010 vty_out(vty,
7011 "%% Export RT is not configured for this VNI\n");
7012 return CMD_WARNING;
7013 }
7014 } else if (rt_type == RT_TYPE_BOTH) {
7015 if (!is_import_rt_configured(vpn)
7016 && !is_export_rt_configured(vpn)) {
7017 vty_out(vty,
7018 "%% Import/Export RT is not configured for this VNI\n");
7019 return CMD_WARNING;
7020 }
7021 }
7022
7023 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 7024 if (!ecomdel) {
7025 vty_out(vty, "%% Malformed Route Target list\n");
7026 return CMD_WARNING;
7027 }
5bc2ed52 7028 ecommunity_str(ecomdel);
d62a17ae 7029
7030 if (rt_type == RT_TYPE_IMPORT) {
7031 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
df6a97a6 7032 ecommunity_free(&ecomdel);
d62a17ae 7033 vty_out(vty,
7034 "%% RT specified does not match configuration for this VNI\n");
7035 return CMD_WARNING;
7036 }
7037 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7038 } else if (rt_type == RT_TYPE_EXPORT) {
7039 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
df6a97a6 7040 ecommunity_free(&ecomdel);
d62a17ae 7041 vty_out(vty,
7042 "%% RT specified does not match configuration for this VNI\n");
7043 return CMD_WARNING;
7044 }
7045 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7046 } else if (rt_type == RT_TYPE_BOTH) {
7047 found_ecomdel = 0;
7048
7049 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7050 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7051 found_ecomdel = 1;
7052 }
7053
7054 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7055 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7056 found_ecomdel = 1;
7057 }
7058
7059 if (!found_ecomdel) {
df6a97a6 7060 ecommunity_free(&ecomdel);
d62a17ae 7061 vty_out(vty,
7062 "%% RT specified does not match configuration for this VNI\n");
7063 return CMD_WARNING;
7064 }
7065 }
7066
7067 return CMD_SUCCESS;
90e60aa7 7068}
7069
7070DEFUN (no_bgp_evpn_vni_rt_without_val,
7071 no_bgp_evpn_vni_rt_without_val_cmd,
7072 "no route-target <import|export>",
7073 NO_STR
7074 "Route Target\n"
7075 "import\n"
7076 "export\n")
7077{
d62a17ae 7078 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7079 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
7080 int rt_type;
7081
06fe25f4 7082 if (!bgp)
d62a17ae 7083 return CMD_WARNING;
7084
f920dd6d 7085 if (!EVPN_ENABLED(bgp)) {
a2a8153f 7086 vty_out(vty,
530db8dc 7087 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
7088 return CMD_WARNING;
7089 }
7090
8034beff 7091 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 7092 rt_type = RT_TYPE_IMPORT;
8034beff 7093 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 7094 rt_type = RT_TYPE_EXPORT;
7095 } else {
7096 vty_out(vty, "%% Invalid Route Target type\n");
7097 return CMD_WARNING;
7098 }
7099
7100 /* Check if we should disallow. */
7101 if (rt_type == RT_TYPE_IMPORT) {
7102 if (!is_import_rt_configured(vpn)) {
7103 vty_out(vty,
7104 "%% Import RT is not configured for this VNI\n");
7105 return CMD_WARNING;
7106 }
7107 } else {
7108 if (!is_export_rt_configured(vpn)) {
7109 vty_out(vty,
7110 "%% Export RT is not configured for this VNI\n");
7111 return CMD_WARNING;
7112 }
7113 }
7114
7115 /* Unconfigure the RT. */
7116 if (rt_type == RT_TYPE_IMPORT)
7117 evpn_unconfigure_import_rt(bgp, vpn, NULL);
7118 else
7119 evpn_unconfigure_export_rt(bgp, vpn, NULL);
7120 return CMD_SUCCESS;
90e60aa7 7121}
568b6b44
QY
7122
7123static int vni_cmp(const void **a, const void **b)
7124{
7125 const struct bgpevpn *first = *a;
7126 const struct bgpevpn *secnd = *b;
7127
7128 return secnd->vni - first->vni;
7129}
7130
90e60aa7 7131/*
7132 * Output EVPN configuration information.
7133 */
d62a17ae 7134void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 7135 safi_t safi)
d62a17ae 7136{
e67df34d
CS
7137 if (bgp->advertise_all_vni)
7138 vty_out(vty, " advertise-all-vni\n");
7139
f33bf7c0 7140 if (hashcount(bgp->vnihash)) {
568b6b44
QY
7141 struct list *vnilist = hash_to_list(bgp->vnihash);
7142 struct listnode *ln;
7143 struct bgpevpn *data;
7144
7145 list_sort(vnilist, vni_cmp);
7146 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
7147 write_vni_config(vty, data);
7148
6a154c88 7149 list_delete(&vnilist);
568b6b44 7150 }
90e60aa7 7151
bf1061d8
VB
7152 if (bgp->advertise_autort_rfc8365)
7153 vty_out(vty, " autort rfc8365-compatible\n");
7154
2b791107 7155 if (bgp->advertise_gw_macip)
1a98c087 7156 vty_out(vty, " advertise-default-gw\n");
6ee86383 7157
24864e44
CS
7158 if (bgp->evpn_info->advertise_svi_macip)
7159 vty_out(vty, " advertise-svi-ip\n");
7160
dc6cef73
AD
7161 if (bgp->resolve_overlay_index)
7162 vty_out(vty, " enable-resolve-overlay-index\n");
7163
bb37eabe
AK
7164 if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
7165 vty_out(vty, " ead-es-frag evi-limit %u\n",
7166 bgp_mh_info->evi_per_es_frag);
7167
2867823e
AK
7168 if (bgp_mh_info->host_routes_use_l3nhg !=
7169 BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
7170 if (bgp_mh_info->host_routes_use_l3nhg)
7171 vty_out(vty, " use-es-l3nhg\n");
7172 else
7173 vty_out(vty, " no use-es-l3nhg\n");
7174 }
7175
fe8293c3
AK
7176 if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
7177 if (bgp_mh_info->ead_evi_rx)
7178 vty_out(vty, " no disable-ead-evi-rx\n");
7179 else
7180 vty_out(vty, " disable-ead-evi-rx\n");
7181 }
7182
7183 if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
7184 if (bgp_mh_info->ead_evi_tx)
7185 vty_out(vty, " no disable-ead-evi-tx\n");
7186 else
7187 vty_out(vty, " disable-ead-evi-tx\n");
7188 }
7189
0b9d9cd0
CS
7190 if (!bgp->evpn_info->dup_addr_detect)
7191 vty_out(vty, " no dup-addr-detection\n");
7192
7193 if (bgp->evpn_info->dad_max_moves !=
7194 EVPN_DAD_DEFAULT_MAX_MOVES ||
7195 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
7196 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
7197 bgp->evpn_info->dad_max_moves,
7198 bgp->evpn_info->dad_time);
7199
7200 if (bgp->evpn_info->dad_freeze) {
7201 if (bgp->evpn_info->dad_freeze_time)
7202 vty_out(vty,
7203 " dup-addr-detection freeze %u\n",
7204 bgp->evpn_info->dad_freeze_time);
7205 else
7206 vty_out(vty,
7207 " dup-addr-detection freeze permanent\n");
7208 }
7209
fd069644
DS
7210 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
7211 vty_out(vty, " flooding disable\n");
7212
154faa50 7213 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3 7214 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
d2a0075a
MK
7215 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7216 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
7217 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7218 else
d4a88de3
AD
7219 vty_out(vty,
7220 " advertise ipv4 unicast\n");
7221 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7222 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
7223 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7224 vty_out(vty,
7225 " advertise ipv4 unicast gateway-ip route-map %s\n",
7226 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7227 else
7228 vty_out(vty, " advertise ipv4 unicast gateway-ip\n");
d2a0075a 7229 }
6ee86383 7230
f4a5218d
AK
7231 /* EAD ES export route-target */
7232 if (listcount(bgp_mh_info->ead_es_export_rtl)) {
7233 struct ecommunity *ecom;
7234 char *ecom_str;
7235 struct listnode *node;
7236
7237 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
7238 ecom)) {
7239
7240 ecom_str = ecommunity_ecom2str(
7241 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7242 vty_out(vty, " ead-es-route-target export %s\n",
7243 ecom_str);
7244 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7245 }
7246 }
7247
154faa50 7248 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3 7249 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
d2a0075a 7250 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
d4a88de3
AD
7251 vty_out(vty,
7252 " advertise ipv6 unicast route-map %s\n",
7253 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7254 else
7255 vty_out(vty,
7256 " advertise ipv6 unicast\n");
7257 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7258 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
7259 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7260 vty_out(vty,
7261 " advertise ipv6 unicast gateway-ip route-map %s\n",
d2a0075a
MK
7262 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7263 else
d4a88de3 7264 vty_out(vty, " advertise ipv6 unicast gateway-ip\n");
d2a0075a 7265 }
486456ca
MK
7266
7267 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7268 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
7269 vty_out(vty, " default-originate ipv4\n");
7270
7271 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7272 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
7273 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 7274
5394a276
CS
7275 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
7276 if (!bgp->evpn_info->advertise_pip)
7277 vty_out(vty, " no advertise-pip\n");
7278 if (bgp->evpn_info->advertise_pip) {
0137a3d8
CS
7279 if (bgp->evpn_info->pip_ip_static.s_addr
7280 != INADDR_ANY) {
07380148
DA
7281 vty_out(vty, " advertise-pip ip %pI4",
7282 &bgp->evpn_info->pip_ip_static);
0137a3d8
CS
7283 if (!is_zero_mac(&(
7284 bgp->evpn_info->pip_rmac_static))) {
7285 char buf[ETHER_ADDR_STRLEN];
7286
7287 vty_out(vty, " mac %s",
7288 prefix_mac2str(
7289 &bgp->evpn_info
7290 ->pip_rmac,
7291 buf, sizeof(buf)));
7292 }
7293 vty_out(vty, "\n");
5394a276 7294 }
5394a276
CS
7295 }
7296 }
a75c2553 7297 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
fa566a94 7298 vty_out(vty, " rd %s\n", bgp->vrf_prd_pretty);
a75c2553 7299
db29a4a8
MK
7300 /* import route-target */
7301 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
7302 char *ecom_str;
7303 struct listnode *node, *nnode;
ca337b46 7304 struct vrf_route_target *l3rt;
db29a4a8
MK
7305
7306 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
ca337b46 7307 l3rt)) {
58d8948c
SW
7308
7309 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7310 continue;
7311
db29a4a8 7312 ecom_str = ecommunity_ecom2str(
ca337b46 7313 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
58d8948c
SW
7314
7315 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
7316 char *vni_str = NULL;
7317
20e81e18 7318 vni_str = strchr(ecom_str, ':');
ed8862ad 7319 if (!vni_str) {
7320 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7321 continue;
7322 }
58d8948c 7323
20e81e18
SW
7324 /* Move pointer to vni */
7325 vni_str += 1;
7326
58d8948c
SW
7327 vty_out(vty, " route-target import *:%s\n",
7328 vni_str);
7329
7330 } else
7331 vty_out(vty, " route-target import %s\n",
7332 ecom_str);
7333
db29a4a8
MK
7334 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7335 }
7336 }
7337
58d8948c
SW
7338 /* import route-target auto */
7339 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
7340 vty_out(vty, " route-target import auto\n");
7341
db29a4a8
MK
7342 /* export route-target */
7343 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
7344 char *ecom_str;
7345 struct listnode *node, *nnode;
ca337b46 7346 struct vrf_route_target *l3rt;
db29a4a8
MK
7347
7348 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
ca337b46 7349 l3rt)) {
58d8948c
SW
7350
7351 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7352 continue;
7353
db29a4a8 7354 ecom_str = ecommunity_ecom2str(
ca337b46 7355 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
530e8a6e 7356 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
7357 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7358 }
7359 }
58d8948c
SW
7360
7361 /* export route-target auto */
7362 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
7363 vty_out(vty, " route-target export auto\n");
90e60aa7 7364}
7365
4d0e6ece 7366void bgp_ethernetvpn_init(void)
784d3a42 7367{
d62a17ae 7368 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
7369 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
7370 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
7371 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
7372 install_element(VIEW_NODE,
dcc1615e 7373 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
d62a17ae 7374 install_element(VIEW_NODE,
7375 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
7376 install_element(
7377 VIEW_NODE,
dcc1615e 7378 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
d62a17ae 7379 install_element(
7380 VIEW_NODE,
7381 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
7382 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
7383 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
7384 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
7385 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
d62a17ae 7386 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
7387 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
bf1061d8
VB
7388 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
7389 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
1a98c087
MK
7390 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
7391 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
24864e44 7392 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
342dd0c6 7393 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
7394 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
7395 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
7396 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
0b9d9cd0
CS
7397 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
7398 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
7399 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
fd069644 7400 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5394a276 7401 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
2867823e 7402 install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
fe8293c3
AK
7403 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
7404 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
dc6cef73
AD
7405 install_element(BGP_EVPN_NODE,
7406 &bgp_evpn_enable_resolve_overlay_index_cmd);
d62a17ae 7407
50f74cf1 7408 /* test commands */
b5e140c8
AK
7409 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
7410 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
50f74cf1 7411
f2d62262 7412 /* "show bgp l2vpn evpn" commands. */
50f74cf1 7413 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
b5e140c8 7414 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
229587fb 7415 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
090efa2f 7416 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
f2d62262 7417 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
021b6596
AD
7418 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
7419 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
f2d62262 7420 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
7421 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
7422 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
7423 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
50f74cf1 7424 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
f2d62262 7425 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
7426 install_element(VIEW_NODE,
7427 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
7428 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
7429 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
d656e0ae
AK
7430 install_element(VIEW_NODE,
7431 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
58bff4d1
AK
7432 install_element(VIEW_NODE,
7433 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
f2d62262 7434 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 7435 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 7436
852d9f97
SW
7437 /* "show bgp vni" commands. */
7438 install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
7439 install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
7440 install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
7441 install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
7442 install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
7443 install_element(VIEW_NODE, &show_bgp_vni_cmd);
7444 install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
7445 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
7446 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
7447 install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
7448 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
7449 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
7450
5014d96f
DW
7451 /* "show bgp evpn" commands. */
7452 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
7453 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
7454 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
7455 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
7456 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
7457 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
7458 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
7459 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
7460 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
7461 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 7462 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7f433a5e 7463 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
5014d96f 7464
d62a17ae 7465 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
7466 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
7467 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
7468 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
7469 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
7470 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
7471 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
7472 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
7473 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
7474 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
7475 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 7476 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
7477 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
7478 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
7022da35
SW
7479 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
7480 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
f4a5218d
AK
7481 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
7482 install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
bb37eabe 7483 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
24864e44 7484 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
1a98c087
MK
7485 install_element(BGP_EVPN_VNI_NODE,
7486 &bgp_evpn_advertise_default_gw_vni_cmd);
7487 install_element(BGP_EVPN_VNI_NODE,
7488 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
7489 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
7490 install_element(BGP_EVPN_VNI_NODE,
7491 &no_bgp_evpn_advertise_vni_subnet_cmd);
784d3a42 7492}