]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
Merge pull request #12795 from pguibert6WIND/vpnv6_nexthop_encoding
[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);
9bcb3eef
DS
2719 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2720 (struct prefix *)&p, prd);
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);
2949 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2950 (struct prefix *)&ep,
2951 (struct prefix_rd *)rd_destp);
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,
21f3551e 3037 json_object *json, int detail)
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) {
d62a17ae 3095 /* Overall header/legend displayed once. */
3096 if (header) {
9c92b5f7 3097 bgp_evpn_show_route_header(vty, bgp,
2dd32217 3098 tbl_ver,
9c92b5f7 3099 json);
c684d477
CS
3100 if (!json)
3101 vty_out(vty,
3102 "%19s Extended Community\n"
6f214dd3 3103 , " ");
d62a17ae 3104 header = 0;
3105 }
3106
3107 /* RD header - per RD. */
3108 if (rd_header) {
9c92b5f7 3109 bgp_evpn_show_route_rd_header(
9bcb3eef 3110 vty, rd_dest, json_rd, rd_str,
c69e79f1 3111 RD_ADDRSTRLEN);
d62a17ae 3112 rd_header = 0;
3113 }
3114
3115 prefix_cnt++;
3116 }
3117
9c92b5f7
MK
3118 if (json) {
3119 json_prefix = json_object_new_object();
3120 json_paths = json_object_new_array();
511211bf
DA
3121 json_object_string_addf(json_prefix, "prefix",
3122 "%pFX", p);
9c92b5f7 3123 json_object_int_add(json_prefix, "prefixLen",
b54892e0 3124 p->prefixlen);
9c92b5f7
MK
3125 }
3126
21f3551e
NS
3127 /* Prefix and num paths displayed once per prefix. */
3128 if (detail)
3129 route_vty_out_detail_header(
9bcb3eef 3130 vty, bgp, dest,
34c7f35f 3131 bgp_dest_get_prefix(dest),
9bcb3eef 3132 (struct prefix_rd *)rd_destp, AFI_L2VPN,
f9f2d188 3133 SAFI_EVPN, json_prefix, false);
21f3551e 3134
d62a17ae 3135 /* For EVPN, the prefix is displayed for each path (to
3136 * fit in
3137 * with code that already exists).
3138 */
6f94b685 3139 for (; pi; pi = pi->next) {
9c92b5f7 3140 json_object *json_path = NULL;
a111dd97 3141
d62a17ae 3142 path_cnt++;
9c92b5f7
MK
3143 add_prefix_to_json = 1;
3144 add_rd_to_json = 1;
3145
3146 if (json)
3147 json_path = json_object_new_array();
3148
21f3551e
NS
3149 if (detail) {
3150 route_vty_out_detail(
34c7f35f
SW
3151 vty, bgp, dest,
3152 bgp_dest_get_prefix(dest), pi,
3153 AFI_L2VPN, SAFI_EVPN,
3154 RPKI_NOT_BEING_USED, json_path);
21f3551e 3155 } else
b54892e0 3156 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
ae248832 3157 json_path, false);
9c92b5f7
MK
3158
3159 if (json)
3160 json_object_array_add(json_paths,
3161 json_path);
3162 }
3163
a1df2ac5
CS
3164 if (json) {
3165 if (add_prefix_to_json) {
3166 json_object_object_add(json_prefix,
3167 "paths",
3168 json_paths);
511211bf
DA
3169 json_object_object_addf(json_rd,
3170 json_prefix,
3171 "%pFX", p);
a1df2ac5
CS
3172 } else {
3173 json_object_free(json_prefix);
3174 json_object_free(json_paths);
3175 json_prefix = NULL;
3176 json_paths = NULL;
3177 }
d62a17ae 3178 }
3179 }
9c92b5f7 3180
a1df2ac5
CS
3181 if (json) {
3182 if (add_rd_to_json)
3183 json_object_object_add(json, rd_str, json_rd);
3184 else {
3185 json_object_free(json_rd);
3186 json_rd = NULL;
3187 }
3188 }
d62a17ae 3189 }
3190
9c92b5f7
MK
3191 if (json) {
3192 json_object_int_add(json, "numPrefix", prefix_cnt);
3193 json_object_int_add(json, "numPaths", path_cnt);
3194 } else {
3195 if (prefix_cnt == 0) {
3196 vty_out(vty, "No EVPN prefixes %sexist\n",
3197 type ? "(of requested type) " : "");
3198 } else {
3199 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
3200 prefix_cnt, path_cnt,
3201 type ? " (of requested type)" : "");
3202 }
3203 }
520d5d76 3204}
3205
0adc5bbb
LS
3206int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3207 bool use_json, int detail)
3208{
3209 json_object *json = NULL;
3210
3211 if (use_json)
3212 json = json_object_new_object();
3213
3214 evpn_show_all_routes(vty, bgp, type, json, detail);
3215
3216 if (use_json)
3217 vty_json(vty, json);
3218 return CMD_SUCCESS;
3219}
3220
520d5d76 3221/*
3222 * Display specified VNI (vty handler)
3223 */
9c92b5f7
MK
3224static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
3225 json_object *json)
520d5d76 3226{
d7c0a89a 3227 uint8_t found = 0;
d62a17ae 3228 struct bgpevpn *vpn;
520d5d76 3229
d62a17ae 3230 vpn = bgp_evpn_lookup_vni(bgp, vni);
4cce389e
MK
3231 if (vpn) {
3232 found = 1;
3233 display_vni(vty, vpn, json);
3234 } else {
3235 struct bgp *bgp_temp;
3236 struct listnode *node = NULL;
3237
3238 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3239 if (bgp_temp->l3vni == vni) {
3240 found = 1;
3241 display_l3vni(vty, bgp_temp, json);
3242 }
3243 }
3244 }
3245
3246 if (!found) {
9c92b5f7
MK
3247 if (json) {
3248 vty_out(vty, "{}\n");
3249 } else {
3250 vty_out(vty, "VNI not found\n");
3251 return;
3252 }
d62a17ae 3253 }
520d5d76 3254}
3255
3256/*
3257 * Display a VNI (upon user query).
3258 */
9c92b5f7
MK
3259static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
3260 json_object *json)
520d5d76 3261{
9c92b5f7 3262 void *args[2];
4cce389e
MK
3263 struct bgp *bgp_temp = NULL;
3264 struct listnode *node;
520d5d76 3265
9c92b5f7 3266
4cce389e 3267 if (!json) {
9c92b5f7 3268 vty_out(vty, "Flags: * - Kernel\n");
4cce389e 3269 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
996c9314 3270 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
9c92b5f7
MK
3271 }
3272
4cce389e 3273 /* print all L2 VNIS */
9c92b5f7
MK
3274 args[0] = vty;
3275 args[1] = json;
d62a17ae 3276 hash_iterate(bgp->vnihash,
e3b78da8 3277 (void (*)(struct hash_bucket *, void *))show_vni_entry,
9c92b5f7 3278 args);
4cce389e
MK
3279
3280 /* print all L3 VNIs */
3281 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
3282 show_l3vni_entry(vty, bgp_temp, json);
520d5d76 3283}
3284
24864e44
CS
3285/*
3286 * evpn - enable advertisement of svi MAC-IP
3287 */
3288static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
3289 uint32_t set)
3290{
3291 if (!vpn) {
3292 if (set && bgp->evpn_info->advertise_svi_macip)
3293 return;
3294 else if (!set && !bgp->evpn_info->advertise_svi_macip)
3295 return;
3296
3297 bgp->evpn_info->advertise_svi_macip = set;
3298 bgp_zebra_advertise_svi_macip(bgp,
3299 bgp->evpn_info->advertise_svi_macip, 0);
3300 } else {
3301 if (set && vpn->advertise_svi_macip)
3302 return;
3303 else if (!set && !vpn->advertise_svi_macip)
3304 return;
3305
3306 vpn->advertise_svi_macip = set;
3307 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
3308 vpn->vni);
3309 }
3310}
3311
1a98c087
MK
3312/*
3313 * evpn - enable advertisement of default g/w
3314 */
3315static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
3316{
3317 if (!vpn) {
3318 if (bgp->advertise_gw_macip)
3319 return;
3320
3321 bgp->advertise_gw_macip = 1;
3322 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3323 } else {
3324 if (vpn->advertise_gw_macip)
3325 return;
3326
3327 vpn->advertise_gw_macip = 1;
3328 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3329 vpn->vni);
3330 }
3331 return;
3332}
3333
3334/*
3335 * evpn - disable advertisement of default g/w
3336 */
3337static void evpn_unset_advertise_default_gw(struct bgp *bgp,
3338 struct bgpevpn *vpn)
3339{
3340 if (!vpn) {
3341 if (!bgp->advertise_gw_macip)
3342 return;
3343
3344 bgp->advertise_gw_macip = 0;
3345 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3346 } else {
3347 if (!vpn->advertise_gw_macip)
3348 return;
3349
3350 vpn->advertise_gw_macip = 0;
3351 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3352 vpn->vni);
3353 }
3354 return;
3355}
3356
486456ca
MK
3357/*
3358 * evpn - enable advertisement of default g/w
3359 */
3360static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
5fd9c12b 3361 afi_t afi, bool add)
486456ca 3362{
486456ca
MK
3363 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
3364
486456ca
MK
3365 if (add) {
3366 /* bail if we are already advertising default route */
3367 if (evpn_default_originate_set(bgp_vrf, afi, safi))
3368 return;
3369
3370 if (afi == AFI_IP)
3371 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3372 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3373 else if (afi == AFI_IP6)
3374 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3375 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca
MK
3376 } else {
3377 /* bail out if we havent advertised the default route */
3378 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
3379 return;
3380 if (afi == AFI_IP)
3381 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3382 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3383 else if (afi == AFI_IP6)
3384 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
486456ca 3386 }
5fd9c12b
KA
3387
3388 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
486456ca
MK
3389}
3390
31310b25
MK
3391/*
3392 * evpn - enable advertisement of default g/w
3393 */
3394static void evpn_set_advertise_subnet(struct bgp *bgp,
3395 struct bgpevpn *vpn)
3396{
3397 if (vpn->advertise_subnet)
3398 return;
3399
3400 vpn->advertise_subnet = 1;
3401 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3402}
3403
3404/*
3405 * evpn - disable advertisement of default g/w
3406 */
996c9314 3407static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
31310b25
MK
3408{
3409 if (!vpn->advertise_subnet)
3410 return;
3411
3412 vpn->advertise_subnet = 0;
3413 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3414}
3415
7724c0a1 3416/*
3417 * EVPN (VNI advertisement) enabled. Register with zebra.
3418 */
d62a17ae 3419static void evpn_set_advertise_all_vni(struct bgp *bgp)
7724c0a1 3420{
d62a17ae 3421 bgp->advertise_all_vni = 1;
e2f3a930 3422 bgp_set_evpn(bgp);
d62a17ae 3423 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
7724c0a1 3424}
3425
3426/*
3427 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3428 * cache, EVPN routes (delete and withdraw from peers).
3429 */
d62a17ae 3430static void evpn_unset_advertise_all_vni(struct bgp *bgp)
7724c0a1 3431{
d62a17ae 3432 bgp->advertise_all_vni = 0;
e2f3a930 3433 bgp_set_evpn(bgp_get_default());
d62a17ae 3434 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3435 bgp_evpn_cleanup_on_disable(bgp);
7724c0a1 3436}
bf1061d8 3437
dc6cef73
AD
3438/* Set resolve overlay index flag */
3439static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
3440{
3441 if (set == bgp->resolve_overlay_index)
3442 return;
3443
3444 if (set) {
3445 bgp->resolve_overlay_index = true;
3446 hash_iterate(bgp->vnihash,
3447 (void (*)(struct hash_bucket *, void *))
3448 bgp_evpn_handle_resolve_overlay_index_set,
3449 NULL);
3450 } else {
3451 hash_iterate(
3452 bgp->vnihash,
3453 (void (*)(struct hash_bucket *, void *))
3454 bgp_evpn_handle_resolve_overlay_index_unset,
3455 NULL);
3456 bgp->resolve_overlay_index = false;
3457 }
3458}
3459
bf1061d8
VB
3460/*
3461 * EVPN - use RFC8365 to auto-derive RT
3462 */
3463static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3464{
3465 bgp->advertise_autort_rfc8365 = 1;
3466 bgp_evpn_handle_autort_change(bgp);
3467}
3468
3469/*
3470 * EVPN - don't use RFC8365 to auto-derive RT
3471 */
3472static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3473{
3474 bgp->advertise_autort_rfc8365 = 0;
3475 bgp_evpn_handle_autort_change(bgp);
3476}
7724c0a1 3477
2b791107 3478static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
d62a17ae 3479{
d62a17ae 3480 char *ecom_str;
3481 struct listnode *node, *nnode;
3482 struct ecommunity *ecom;
3483
3484 if (is_vni_configured(vpn)) {
339af96e 3485 vty_out(vty, " vni %u\n", vpn->vni);
d62a17ae 3486 if (is_rd_configured(vpn))
fa566a94 3487 vty_out(vty, " rd %s\n", vpn->prd_pretty);
d62a17ae 3488
3489 if (is_import_rt_configured(vpn)) {
3490 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3491 ecom)) {
3492 ecom_str = ecommunity_ecom2str(
3493 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3494 vty_out(vty, " route-target import %s\n",
3495 ecom_str);
3496 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3497 }
3498 }
3499
3500 if (is_export_rt_configured(vpn)) {
3501 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3502 ecom)) {
3503 ecom_str = ecommunity_ecom2str(
3504 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 3505 vty_out(vty, " route-target export %s\n",
d62a17ae 3506 ecom_str);
3507 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3508 }
3509 }
3510
1a98c087
MK
3511 if (vpn->advertise_gw_macip)
3512 vty_out(vty, " advertise-default-gw\n");
3513
24864e44
CS
3514 if (vpn->advertise_svi_macip)
3515 vty_out(vty, " advertise-svi-ip\n");
3516
31310b25
MK
3517 if (vpn->advertise_subnet)
3518 vty_out(vty, " advertise-subnet\n");
3519
d62a17ae 3520 vty_out(vty, " exit-vni\n");
3521 }
3522}
3523
fd069644 3524#include "bgpd/bgp_evpn_vty_clippy.c"
fd069644
DS
3525
3526DEFPY(bgp_evpn_flood_control,
3527 bgp_evpn_flood_control_cmd,
3528 "[no$no] flooding <disable$disable|head-end-replication$her>",
3529 NO_STR
3530 "Specify handling for BUM packets\n"
3531 "Do not flood any BUM packets\n"
3532 "Flood BUM packets using head-end replication\n")
3533{
3534 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3535 enum vxlan_flood_control flood_ctrl;
3536
3537 if (!bgp)
3538 return CMD_WARNING;
3539
3540 if (disable && !no)
3541 flood_ctrl = VXLAN_FLOOD_DISABLED;
3542 else if (her || no)
3543 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3544 else
3545 return CMD_WARNING;
3546
3547 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3548 return CMD_SUCCESS;
3549
3550 bgp->vxlan_flood_ctrl = flood_ctrl;
3551 bgp_evpn_flood_control_change(bgp);
3552
3553 return CMD_SUCCESS;
3554}
3555
1a98c087
MK
3556DEFUN (bgp_evpn_advertise_default_gw_vni,
3557 bgp_evpn_advertise_default_gw_vni_cmd,
3558 "advertise-default-gw",
078af92e 3559 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
1a98c087
MK
3560{
3561 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3562 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3563
3564 if (!bgp)
3565 return CMD_WARNING;
3566
1a98c087
MK
3567 evpn_set_advertise_default_gw(bgp, vpn);
3568
3569 return CMD_SUCCESS;
3570}
3571
3572DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3573 no_bgp_evpn_advertise_default_gw_vni_cmd,
3574 "no advertise-default-gw",
3575 NO_STR
3576 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3577{
3578 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3579 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3580
3581 if (!bgp)
3582 return CMD_WARNING;
3583
1a98c087
MK
3584 evpn_unset_advertise_default_gw(bgp, vpn);
3585
3586 return CMD_SUCCESS;
3587}
3588
3589
3590DEFUN (bgp_evpn_advertise_default_gw,
3591 bgp_evpn_advertise_default_gw_cmd,
3592 "advertise-default-gw",
078af92e 3593 "Advertise All default g/w mac-ip routes in EVPN\n")
1a98c087
MK
3594{
3595 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3596
3597 if (!bgp)
3598 return CMD_WARNING;
3599
f920dd6d 3600 if (!EVPN_ENABLED(bgp)) {
7da47d66 3601 vty_out(vty,
530db8dc 3602 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3603 return CMD_WARNING;
3604 }
3605
1a98c087
MK
3606 evpn_set_advertise_default_gw(bgp, NULL);
3607
3608 return CMD_SUCCESS;
3609}
3610
3611DEFUN (no_bgp_evpn_advertise_default_gw,
3612 no_bgp_evpn_advertise_default_gw_cmd,
3613 "no advertise-default-gw",
3614 NO_STR
3615 "Withdraw All default g/w mac-ip routes from EVPN\n")
3616{
3617 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3618
3619 if (!bgp)
3620 return CMD_WARNING;
3621
3622 evpn_unset_advertise_default_gw(bgp, NULL);
3623
3624 return CMD_SUCCESS;
3625}
3626
7724c0a1 3627DEFUN (bgp_evpn_advertise_all_vni,
3628 bgp_evpn_advertise_all_vni_cmd,
3629 "advertise-all-vni",
3630 "Advertise All local VNIs\n")
3631{
d62a17ae 3632 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
e2f3a930 3633 struct bgp *bgp_evpn = NULL;
7724c0a1 3634
d62a17ae 3635 if (!bgp)
3636 return CMD_WARNING;
e2f3a930
T
3637
3638 bgp_evpn = bgp_get_evpn();
3639 if (bgp_evpn && bgp_evpn != bgp) {
2b94e4b6 3640 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3641 bgp_evpn->name_pretty);
e2f3a930
T
3642 return CMD_WARNING_CONFIG_FAILED;
3643 }
3644
d62a17ae 3645 evpn_set_advertise_all_vni(bgp);
3646 return CMD_SUCCESS;
7724c0a1 3647}
3648
3649DEFUN (no_bgp_evpn_advertise_all_vni,
3650 no_bgp_evpn_advertise_all_vni_cmd,
3651 "no advertise-all-vni",
3652 NO_STR
3653 "Advertise All local VNIs\n")
3654{
d62a17ae 3655 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 3656
d62a17ae 3657 if (!bgp)
3658 return CMD_WARNING;
3659 evpn_unset_advertise_all_vni(bgp);
3660 return CMD_SUCCESS;
7724c0a1 3661}
3662
bf1061d8
VB
3663DEFUN (bgp_evpn_advertise_autort_rfc8365,
3664 bgp_evpn_advertise_autort_rfc8365_cmd,
3665 "autort rfc8365-compatible",
3666 "Auto-derivation of RT\n"
3667 "Auto-derivation of RT using RFC8365\n")
3668{
3669 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3670
3671 if (!bgp)
3672 return CMD_WARNING;
3673 evpn_set_advertise_autort_rfc8365(bgp);
3674 return CMD_SUCCESS;
3675}
3676
3677DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3678 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3679 "no autort rfc8365-compatible",
3680 NO_STR
3681 "Auto-derivation of RT\n"
3682 "Auto-derivation of RT using RFC8365\n")
3683{
3684 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3685
3686 if (!bgp)
3687 return CMD_WARNING;
3688 evpn_unset_advertise_autort_rfc8365(bgp);
3689 return CMD_SUCCESS;
3690}
3691
486456ca
MK
3692DEFUN (bgp_evpn_default_originate,
3693 bgp_evpn_default_originate_cmd,
3694 "default-originate <ipv4 | ipv6>",
3695 "originate a default route\n"
3696 "ipv4 address family\n"
3697 "ipv6 address family\n")
3698{
3699 afi_t afi = 0;
3700 int idx_afi = 0;
3701 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3702
3703 if (!bgp_vrf)
3704 return CMD_WARNING;
3705 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3706 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
486456ca
MK
3707 return CMD_SUCCESS;
3708}
3709
3710DEFUN (no_bgp_evpn_default_originate,
3711 no_bgp_evpn_default_originate_cmd,
3712 "no default-originate <ipv4 | ipv6>",
3713 NO_STR
3714 "withdraw a default route\n"
3715 "ipv4 address family\n"
3716 "ipv6 address family\n")
3717{
3718 afi_t afi = 0;
3719 int idx_afi = 0;
3720 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3721
3722 if (!bgp_vrf)
3723 return CMD_WARNING;
3724 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
5fd9c12b 3725 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
486456ca
MK
3726 return CMD_SUCCESS;
3727}
3728
0b9d9cd0
CS
3729DEFPY (dup_addr_detection,
3730 dup_addr_detection_cmd,
3731 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3732 "Duplicate address detection\n"
979777b2 3733 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3734 "Num of max allowed moves (2-1000) default 5\n"
3735 "Duplicate address detection time\n"
3736 "Time in seconds (2-1800) default 180\n")
3737{
3738 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3739
3740 if (!bgp_vrf)
3741 return CMD_WARNING;
3742
f920dd6d 3743 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3744 vty_out(vty,
530db8dc 3745 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3746 return CMD_WARNING;
3747 }
3748
0b9d9cd0
CS
3749 bgp_vrf->evpn_info->dup_addr_detect = true;
3750
3751 if (time_val)
3752 bgp_vrf->evpn_info->dad_time = time_val;
3753 if (max_moves_val)
3754 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3755
3756 bgp_zebra_dup_addr_detection(bgp_vrf);
3757
3758 return CMD_SUCCESS;
3759}
3760
3761DEFPY (dup_addr_detection_auto_recovery,
3762 dup_addr_detection_auto_recovery_cmd,
3763 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3764 "Duplicate address detection\n"
3765 "Duplicate address detection freeze\n"
3766 "Duplicate address detection permanent freeze\n"
3767 "Duplicate address detection freeze time (30-3600)\n")
3768{
3769 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3770 uint32_t freeze_time = freeze_time_val;
3771
3772 if (!bgp_vrf)
3773 return CMD_WARNING;
3774
f920dd6d 3775 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3776 vty_out(vty,
530db8dc 3777 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3778 return CMD_WARNING;
3779 }
3780
0b9d9cd0
CS
3781 bgp_vrf->evpn_info->dup_addr_detect = true;
3782 bgp_vrf->evpn_info->dad_freeze = true;
3783 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3784
3785 bgp_zebra_dup_addr_detection(bgp_vrf);
3786
3787 return CMD_SUCCESS;
3788}
3789
3790DEFPY (no_dup_addr_detection,
3791 no_dup_addr_detection_cmd,
3792 "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>]",
3793 NO_STR
3794 "Duplicate address detection\n"
979777b2 3795 "Max allowed moves before address detected as duplicate\n"
0b9d9cd0
CS
3796 "Num of max allowed moves (2-1000) default 5\n"
3797 "Duplicate address detection time\n"
3798 "Time in seconds (2-1800) default 180\n"
3799 "Duplicate address detection freeze\n"
3800 "Duplicate address detection permanent freeze\n"
3801 "Duplicate address detection freeze time (30-3600)\n")
3802{
3803 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3804 uint32_t max_moves = (uint32_t)max_moves_val;
3805 uint32_t freeze_time = (uint32_t)freeze_time_val;
3806
3807 if (!bgp_vrf)
3808 return CMD_WARNING;
3809
f920dd6d 3810 if (!EVPN_ENABLED(bgp_vrf)) {
7da47d66 3811 vty_out(vty,
530db8dc 3812 "This command is only supported under the EVPN VRF\n");
7da47d66
CS
3813 return CMD_WARNING;
3814 }
3815
0b9d9cd0
CS
3816 if (argc == 2) {
3817 if (!bgp_vrf->evpn_info->dup_addr_detect)
3818 return CMD_SUCCESS;
3819 /* Reset all parameters to default. */
3820 bgp_vrf->evpn_info->dup_addr_detect = false;
3821 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3822 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3823 bgp_vrf->evpn_info->dad_freeze = false;
3824 bgp_vrf->evpn_info->dad_freeze_time = 0;
3825 } else {
3826 if (max_moves) {
3827 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3828 vty_out(vty,
3829 "%% Value does not match with config\n");
3830 return CMD_SUCCESS;
3831 }
3832 bgp_vrf->evpn_info->dad_max_moves =
3833 EVPN_DAD_DEFAULT_MAX_MOVES;
3834 }
3835
3836 if (time_val) {
3837 if (bgp_vrf->evpn_info->dad_time != time_val) {
3838 vty_out(vty,
3839 "%% Value does not match with config\n");
3840 return CMD_SUCCESS;
3841 }
3842 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3843 }
3844
3845 if (freeze_time) {
3846 if (bgp_vrf->evpn_info->dad_freeze_time
3847 != freeze_time) {
3848 vty_out(vty,
3849 "%% Value does not match with config\n");
3850 return CMD_SUCCESS;
3851 }
3852 bgp_vrf->evpn_info->dad_freeze_time = 0;
3853 bgp_vrf->evpn_info->dad_freeze = false;
3854 }
3855
3856 if (permanent_val) {
3857 if (bgp_vrf->evpn_info->dad_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 = false;
3863 }
3864 }
3865
3866 bgp_zebra_dup_addr_detection(bgp_vrf);
3867
3868 return CMD_SUCCESS;
3869}
3870
24864e44
CS
3871DEFPY(bgp_evpn_advertise_svi_ip,
3872 bgp_evpn_advertise_svi_ip_cmd,
3873 "[no$no] advertise-svi-ip",
3874 NO_STR
3875 "Advertise svi mac-ip routes in EVPN\n")
3876{
3877 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3878
3879 if (!bgp)
3880 return CMD_WARNING;
3881
24864e44
CS
3882 if (no)
3883 evpn_set_advertise_svi_macip(bgp, NULL, 0);
e5aee151
TA
3884 else {
3885 if (!EVPN_ENABLED(bgp)) {
3886 vty_out(vty,
3887 "This command is only supported under EVPN VRF\n");
3888 return CMD_WARNING;
3889 }
24864e44 3890 evpn_set_advertise_svi_macip(bgp, NULL, 1);
e5aee151 3891 }
24864e44
CS
3892
3893 return CMD_SUCCESS;
3894}
3895
3896DEFPY(bgp_evpn_advertise_svi_ip_vni,
3897 bgp_evpn_advertise_svi_ip_vni_cmd,
3898 "[no$no] advertise-svi-ip",
3899 NO_STR
3900 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3901{
3902 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3903 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3904
3905 if (!bgp)
3906 return CMD_WARNING;
3907
24864e44
CS
3908 if (no)
3909 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3910 else
3911 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3912
3913 return CMD_SUCCESS;
3914}
3915
689b5101
MK
3916DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3917 bgp_evpn_advertise_vni_subnet_cmd,
3918 "advertise-subnet",
3919 "Advertise the subnet corresponding to VNI\n")
31310b25
MK
3920{
3921 struct bgp *bgp_vrf = NULL;
3922 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3923 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3924
3925 if (!bgp)
3926 return CMD_WARNING;
3927
31310b25
MK
3928 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3929 if (!bgp_vrf)
3930 return CMD_WARNING;
3931
31310b25
MK
3932 evpn_set_advertise_subnet(bgp, vpn);
3933 return CMD_SUCCESS;
3934}
3935
689b5101
MK
3936DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3937 no_bgp_evpn_advertise_vni_subnet_cmd,
3938 "no advertise-subnet",
3939 NO_STR
3940 "Advertise All local VNIs\n")
31310b25
MK
3941{
3942 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3943 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3944
3945 if (!bgp)
3946 return CMD_WARNING;
3947
31310b25
MK
3948 evpn_unset_advertise_subnet(bgp, vpn);
3949 return CMD_SUCCESS;
3950}
3951
342dd0c6 3952DEFUN (bgp_evpn_advertise_type5,
3953 bgp_evpn_advertise_type5_cmd,
70dd370f 3954 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
342dd0c6 3955 "Advertise prefix routes\n"
053905d2 3956 BGP_AFI_HELP_STR
53c84f78 3957 BGP_SAFI_HELP_STR
d4a88de3 3958 "advertise gateway IP overlay index\n"
53c84f78
MK
3959 "route-map for filtering specific routes\n"
3960 "Name of the route map\n")
342dd0c6 3961{
3962 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
3963 int idx_afi = 0;
3964 int idx_safi = 0;
53c84f78 3965 int idx_rmap = 0;
053905d2
MK
3966 afi_t afi = 0;
3967 safi_t safi = 0;
53c84f78
MK
3968 int ret = 0;
3969 int rmap_changed = 0;
d4a88de3
AD
3970 enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3971 int idx_oly = 0;
3972 bool adv_flag_changed = false;
053905d2
MK
3973
3974 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3975 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
d4a88de3
AD
3976 argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3977
53c84f78
MK
3978 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3979 if (ret) {
3980 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3981 rmap_changed = 1;
3982 else if (strcmp(argv[idx_rmap + 1]->arg,
996c9314
LB
3983 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3984 != 0)
53c84f78
MK
3985 rmap_changed = 1;
3986 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3987 rmap_changed = 1;
3988 }
053905d2 3989
e779dc76 3990 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2 3991 vty_out(vty,
664b6f18 3992 "%% Only ipv4 or ipv6 address families are supported\n");
342dd0c6 3993 return CMD_WARNING;
3994 }
3995
053905d2
MK
3996 if (safi != SAFI_UNICAST) {
3997 vty_out(vty,
664b6f18 3998 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
053905d2
MK
3999 return CMD_WARNING;
4000 }
4001
d4a88de3
AD
4002 if ((oly != OVERLAY_INDEX_TYPE_NONE)
4003 && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
664b6f18 4004 vty_out(vty, "%% Unknown overlay-index type specified\n");
d4a88de3
AD
4005 return CMD_WARNING;
4006 }
4007
053905d2 4008 if (afi == AFI_IP) {
d4a88de3
AD
4009 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4010 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
4011 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4012 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4013
4014 /*
4015 * this is the case for first time ever configuration
4016 * adv ipv4 unicast is enabled for the first time.
4017 * So no need to reset any flag
4018 */
4019 if (oly == OVERLAY_INDEX_TYPE_NONE)
4020 SET_FLAG(
4021 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4022 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4023 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4024 SET_FLAG(
4025 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4027 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4028 && (!CHECK_FLAG(
4029 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4030 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
4031
4032 /*
4033 * This is modify case from gateway-ip
4034 * to no overlay index
4035 */
4036 adv_flag_changed = true;
4037 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4038 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4039 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4040 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4041 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4042 && (!CHECK_FLAG(
4043 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4044 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4045
4046 /*
4047 * This is modify case from no overlay index
4048 * to gateway-ip
4049 */
4050 adv_flag_changed = true;
4051 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4052 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4053 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4054 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4055 } else {
342dd0c6 4056
d4a88de3
AD
4057 /*
4058 * Command is issued with the same option
4059 * (no overlay index or gateway-ip) which was
4060 * already configured. So nothing to do.
4061 * However, route-map may have been modified.
4062 * check if route-map has been modified.
4063 * If not, return an error
4064 */
4065 if (!rmap_changed)
4066 return CMD_WARNING;
4067 }
342dd0c6 4068 } else {
d4a88de3
AD
4069 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4070 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
4071 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4072 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4073
4074 /*
4075 * this is the case for first time ever configuration
4076 * adv ipv6 unicast is enabled for the first time.
4077 * So no need to reset any flag
4078 */
4079 if (oly == OVERLAY_INDEX_TYPE_NONE)
4080 SET_FLAG(
4081 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4083 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4084 SET_FLAG(
4085 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4086 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4087 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4088 && (!CHECK_FLAG(
4089 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4090 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
4091
4092 /*
4093 * This is modify case from gateway-ip
4094 * to no overlay index
4095 */
4096 adv_flag_changed = true;
4097 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4098 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4099 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4100 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4101 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4102 && (!CHECK_FLAG(
4103 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4104 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4105
4106 /*
4107 * This is modify case from no overlay index
4108 * to gateway-ip
4109 */
4110 adv_flag_changed = true;
4111 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4112 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4113 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4114 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4115 } else {
342dd0c6 4116
d4a88de3
AD
4117 /*
4118 * Command is issued with the same option
4119 * (no overlay index or gateway-ip) which was
4120 * already configured. So nothing to do.
4121 * However, route-map may have been modified.
4122 * check if route-map has been modified.
4123 * If not, return an error
4124 */
4125 if (!rmap_changed)
4126 return CMD_WARNING;
4127 }
53c84f78
MK
4128 }
4129
d4a88de3
AD
4130 if ((rmap_changed) || (adv_flag_changed)) {
4131
4132 /* If either of these are changed, then FRR needs to
4133 * withdraw already advertised type5 routes.
4134 */
53c84f78 4135 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4a88de3
AD
4136 if (rmap_changed) {
4137 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4138 XFREE(MTYPE_ROUTE_MAP_NAME,
4139 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4140 route_map_counter_decrement(
b4897fa5 4141 bgp_vrf->adv_cmd_rmap[afi][safi].map);
d4a88de3
AD
4142 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4143 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4144 }
342dd0c6 4145 }
4146 }
53c84f78
MK
4147
4148 /* set the route-map for advertise command */
4149 if (ret && argv[idx_rmap + 1]->arg) {
4150 bgp_vrf->adv_cmd_rmap[afi][safi].name =
996c9314 4151 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
53c84f78
MK
4152 bgp_vrf->adv_cmd_rmap[afi][safi].map =
4153 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
b4897fa5 4154 route_map_counter_increment(
4155 bgp_vrf->adv_cmd_rmap[afi][safi].map);
53c84f78
MK
4156 }
4157
4158 /* advertise type-5 routes */
456a4697
AK
4159 if (advertise_type5_routes(bgp_vrf, afi))
4160 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
342dd0c6 4161 return CMD_SUCCESS;
4162}
4163
4164DEFUN (no_bgp_evpn_advertise_type5,
4165 no_bgp_evpn_advertise_type5_cmd,
24df3379 4166 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
342dd0c6 4167 NO_STR
4168 "Advertise prefix routes\n"
053905d2 4169 BGP_AFI_HELP_STR
24df3379
SW
4170 BGP_SAFI_HELP_STR
4171 "route-map for filtering specific routes\n"
4172 "Name of the route map\n")
342dd0c6 4173{
4174 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
053905d2
MK
4175 int idx_afi = 0;
4176 int idx_safi = 0;
4177 afi_t afi = 0;
4178 safi_t safi = 0;
4179
3e140309
DS
4180 if (!bgp_vrf)
4181 return CMD_WARNING;
4182
053905d2
MK
4183 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4184 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4185
1ec31309 4186 if (!(afi == AFI_IP || afi == AFI_IP6)) {
053905d2 4187 vty_out(vty,
664b6f18 4188 "%% Only ipv4 or ipv6 address families are supported\n");
053905d2
MK
4189 return CMD_WARNING;
4190 }
4191
4192 if (safi != SAFI_UNICAST) {
4193 vty_out(vty,
664b6f18 4194 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
342dd0c6 4195 return CMD_WARNING;
4196 }
4197
053905d2 4198 if (afi == AFI_IP) {
342dd0c6 4199
fdf19f06 4200 /* if we are not advertising ipv4 prefix as type-5
523cafc4 4201 * nothing to do
4202 */
d4a88de3
AD
4203 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4204 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4205 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
053905d2 4207 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
154faa50 4208 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3
AD
4209 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4210 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4211 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
342dd0c6 4212 }
4213 } else {
4214
fdf19f06 4215 /* if we are not advertising ipv6 prefix as type-5
523cafc4 4216 * nothing to do
4217 */
d4a88de3
AD
4218 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4219 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4220 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4221 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
053905d2 4222 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
d4f7497e 4223 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3
AD
4224 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4225 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4226 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
342dd0c6 4227 }
4228 }
53c84f78
MK
4229
4230 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4231 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4232 XFREE(MTYPE_ROUTE_MAP_NAME,
4233 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4234 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4235 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4236 }
4237
342dd0c6 4238 return CMD_SUCCESS;
4239}
4240
2867823e
AK
4241DEFPY (bgp_evpn_use_es_l3nhg,
4242 bgp_evpn_use_es_l3nhg_cmd,
4243 "[no$no] use-es-l3nhg",
4244 NO_STR
4245 "use L3 nexthop group for host routes with ES destination\n")
4246{
4247 bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4248 return CMD_SUCCESS;
4249}
4250
fe8293c3
AK
4251DEFPY (bgp_evpn_ead_evi_rx_disable,
4252 bgp_evpn_ead_evi_rx_disable_cmd,
4253 "[no$no] disable-ead-evi-rx",
4254 NO_STR
4255 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4256{
acd1d9bc
AD
4257 bool ead_evi_rx = no? true :false;
4258
4259 if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4260 bgp_mh_info->ead_evi_rx = ead_evi_rx;
4261 bgp_evpn_switch_ead_evi_rx();
4262 }
fe8293c3
AK
4263 return CMD_SUCCESS;
4264}
4265
4266DEFPY (bgp_evpn_ead_evi_tx_disable,
4267 bgp_evpn_ead_evi_tx_disable_cmd,
4268 "[no$no] disable-ead-evi-tx",
4269 NO_STR
4270 "Don't advertise EAD-EVI for local ESs\n")
4271{
4272 bgp_mh_info->ead_evi_tx = no? true :false;
4273 return CMD_SUCCESS;
4274}
4275
dc6cef73
AD
4276DEFPY (bgp_evpn_enable_resolve_overlay_index,
4277 bgp_evpn_enable_resolve_overlay_index_cmd,
4278 "[no$no] enable-resolve-overlay-index",
4279 NO_STR
4280 "Enable Recursive Resolution of type-5 route overlay index\n")
4281{
4282 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4283
4284 if (bgp != bgp_get_evpn()) {
4285 vty_out(vty, "This command is only supported under EVPN VRF\n");
4286 return CMD_WARNING;
4287 }
4288
4289 bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4290 return CMD_SUCCESS;
4291}
4292
5394a276
CS
4293DEFPY (bgp_evpn_advertise_pip_ip_mac,
4294 bgp_evpn_advertise_pip_ip_mac_cmd,
4295 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4296 NO_STR
4297 "evpn system primary IP\n"
4298 IP_STR
4299 "ip address\n"
4300 MAC_STR MAC_STR MAC_STR)
4301{
4302 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4303 struct bgp *bgp_evpn = NULL;
4304
4305 if (EVPN_ENABLED(bgp_vrf)) {
4306 vty_out(vty,
4307 "This command is supported under L3VNI BGP EVPN VRF\n");
a6e7677e 4308 return CMD_WARNING_CONFIG_FAILED;
5394a276
CS
4309 }
4310 bgp_evpn = bgp_get_evpn();
4311
4312 if (!no) {
4313 /* pip is already enabled */
4314 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4315 return CMD_SUCCESS;
4316
4317 bgp_vrf->evpn_info->advertise_pip = true;
4318 if (ip.s_addr != INADDR_ANY) {
4319 /* Already configured with same IP */
4320 if (IPV4_ADDR_SAME(&ip,
4321 &bgp_vrf->evpn_info->pip_ip_static))
4322 return CMD_SUCCESS;
4323
4324 bgp_vrf->evpn_info->pip_ip_static = ip;
4325 bgp_vrf->evpn_info->pip_ip = ip;
4326 } else {
4327 bgp_vrf->evpn_info->pip_ip_static.s_addr
4328 = INADDR_ANY;
4329 /* default instance router-id assignemt */
4330 if (bgp_evpn)
4331 bgp_vrf->evpn_info->pip_ip =
4332 bgp_evpn->router_id;
4333 }
4334 /* parse sys mac */
4335 if (!is_zero_mac(&mac->eth_addr)) {
4336 /* Already configured with same MAC */
4337 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4338 &mac->eth_addr, ETH_ALEN) == 0)
4339 return CMD_SUCCESS;
4340
4341 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4342 &mac->eth_addr, ETH_ALEN);
4343 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4344 &bgp_vrf->evpn_info->pip_rmac_static,
4345 ETH_ALEN);
4346 } else {
4347 /* Copy zebra sys mac */
4348 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4349 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4350 &bgp_vrf->evpn_info->pip_rmac_zebra,
4351 ETH_ALEN);
4352 }
4353 } else {
4354 if (argc == 2) {
4355 if (!bgp_vrf->evpn_info->advertise_pip)
4356 return CMD_SUCCESS;
4357 /* Disable PIP feature */
4358 bgp_vrf->evpn_info->advertise_pip = false;
4359 /* copy anycast mac */
4360 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4361 &bgp_vrf->rmac, ETH_ALEN);
4362 } else {
4363 /* remove MAC-IP option retain PIP knob. */
4364 if ((ip.s_addr != INADDR_ANY) &&
4365 !IPV4_ADDR_SAME(&ip,
4366 &bgp_vrf->evpn_info->pip_ip_static)) {
4367 vty_out(vty,
4368 "%% BGP EVPN PIP IP does not match\n");
4369 return CMD_WARNING_CONFIG_FAILED;
4370 }
4371
4372 if (!is_zero_mac(&mac->eth_addr) &&
4373 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4374 &mac->eth_addr, ETH_ALEN) != 0) {
4375 vty_out(vty,
4376 "%% BGP EVPN PIP MAC does not match\n");
4377 return CMD_WARNING_CONFIG_FAILED;
4378 }
4379 /* pip_rmac can carry vrr_rmac reset only if it matches
4380 * with static value.
4381 */
4382 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4383 &bgp_vrf->evpn_info->pip_rmac_static,
4384 ETH_ALEN) == 0) {
4385 /* Copy zebra sys mac */
4386 if (!is_zero_mac(
4387 &bgp_vrf->evpn_info->pip_rmac_zebra))
4388 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4389 &bgp_vrf->evpn_info->pip_rmac_zebra,
4390 ETH_ALEN);
4391 else {
4392 /* copy anycast mac */
4393 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4394 &bgp_vrf->rmac, ETH_ALEN);
4395 }
4396 }
4397 }
4398 /* reset user configured sys MAC */
4399 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4400 /* reset user configured sys IP */
4401 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4402 /* Assign default PIP IP (bgp instance router-id) */
4403 if (bgp_evpn)
4404 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4405 else
4406 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4407 }
4408
4409 if (is_evpn_enabled()) {
0ca10580
CS
4410 struct listnode *node = NULL;
4411 struct bgpevpn *vpn = NULL;
4412
5f140efe
DS
4413 /*
4414 * At this point if bgp_evpn is NULL and evpn is enabled
4415 * something stupid has gone wrong
4416 */
4417 assert(bgp_evpn);
4418
5394a276 4419 update_advertise_vrf_routes(bgp_vrf);
0ca10580
CS
4420
4421 /* Update (svi) type-2 routes */
4422 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4423 if (!bgp_evpn_is_svi_macip_enabled(vpn))
4424 continue;
4425 update_routes_for_vni(bgp_evpn, vpn);
4426 }
5394a276
CS
4427 }
4428
4429 return CMD_SUCCESS;
4430}
4431
f2d62262 4432/*
4433 * Display VNI information - for all or a specific VNI
4434 */
9c92b5f7
MK
4435DEFUN(show_bgp_l2vpn_evpn_vni,
4436 show_bgp_l2vpn_evpn_vni_cmd,
093e3f23 4437 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
9c92b5f7
MK
4438 SHOW_STR
4439 BGP_STR
4440 L2VPN_HELP_STR
4441 EVPN_HELP_STR
4442 "Show VNI\n"
4443 "VNI number\n"
4444 JSON_STR)
520d5d76 4445{
5e53dce3 4446 struct bgp *bgp_evpn;
f2d62262 4447 vni_t vni;
4448 int idx = 0;
9f049418 4449 bool uj = false;
9c92b5f7 4450 json_object *json = NULL;
d7c0a89a
QY
4451 uint32_t num_l2vnis = 0;
4452 uint32_t num_l3vnis = 0;
d4454626 4453 uint32_t num_vnis = 0;
4cce389e
MK
4454 struct listnode *node = NULL;
4455 struct bgp *bgp_temp = NULL;
9c92b5f7
MK
4456
4457 uj = use_json(argc, argv);
520d5d76 4458
5e53dce3
T
4459 bgp_evpn = bgp_get_evpn();
4460 if (!bgp_evpn)
d62a17ae 4461 return CMD_WARNING;
520d5d76 4462
f2d62262 4463 if (!argv_find(argv, argc, "evpn", &idx))
4464 return CMD_WARNING;
4465
9c92b5f7
MK
4466 if (uj)
4467 json = json_object_new_object();
1a98c087 4468
9c92b5f7 4469 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4cce389e 4470
5e53dce3 4471 num_l2vnis = hashcount(bgp_evpn->vnihash);
4cce389e
MK
4472
4473 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4474 if (bgp_temp->l3vni)
4475 num_l3vnis++;
4476 }
d4454626 4477 num_vnis = num_l2vnis + num_l3vnis;
9c92b5f7
MK
4478 if (uj) {
4479 json_object_string_add(json, "advertiseGatewayMacip",
5e53dce3 4480 bgp_evpn->advertise_gw_macip
9c92b5f7
MK
4481 ? "Enabled"
4482 : "Disabled");
0b509723 4483 json_object_string_add(json, "advertiseSviMacIp",
cbdbb1ca
CS
4484 bgp_evpn->evpn_info->advertise_svi_macip
4485 ? "Enabled" : "Disabled");
9c92b5f7 4486 json_object_string_add(json, "advertiseAllVnis",
996c9314
LB
4487 is_evpn_enabled() ? "Enabled"
4488 : "Disabled");
fd069644
DS
4489 json_object_string_add(
4490 json, "flooding",
02dd2dd6
P
4491 bgp_evpn->vxlan_flood_ctrl ==
4492 VXLAN_FLOOD_HEAD_END_REPL
fd069644
DS
4493 ? "Head-end replication"
4494 : "Disabled");
02dd2dd6
P
4495 json_object_string_add(
4496 json, "vxlanFlooding",
6f086a7f
P
4497 bgp_evpn->vxlan_flood_ctrl ==
4498 VXLAN_FLOOD_HEAD_END_REPL
4499 ? "Enabled"
fd069644 4500 : "Disabled");
d4454626 4501 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
4502 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4503 json_object_int_add(json, "numL3Vnis", num_l3vnis);
9c92b5f7
MK
4504 } else {
4505 vty_out(vty, "Advertise Gateway Macip: %s\n",
5e53dce3 4506 bgp_evpn->advertise_gw_macip ? "Enabled"
996c9314 4507 : "Disabled");
24864e44 4508 vty_out(vty, "Advertise SVI Macip: %s\n",
5e53dce3 4509 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
24864e44 4510 : "Disabled");
9c92b5f7 4511 vty_out(vty, "Advertise All VNI flag: %s\n",
94c2f693 4512 is_evpn_enabled() ? "Enabled" : "Disabled");
fd069644 4513 vty_out(vty, "BUM flooding: %s\n",
02dd2dd6
P
4514 bgp_evpn->vxlan_flood_ctrl ==
4515 VXLAN_FLOOD_HEAD_END_REPL
fd069644
DS
4516 ? "Head-end replication"
4517 : "Disabled");
02dd2dd6 4518 vty_out(vty, "VXLAN flooding: %s\n",
6f086a7f
P
4519 bgp_evpn->vxlan_flood_ctrl ==
4520 VXLAN_FLOOD_HEAD_END_REPL
4521 ? "Enabled"
fd069644 4522 : "Disabled");
4cce389e
MK
4523 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4524 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
9c92b5f7 4525 }
5e53dce3 4526 evpn_show_all_vnis(vty, bgp_evpn, json);
f2d62262 4527 } else {
9c92b5f7
MK
4528 int vni_idx = 0;
4529
4530 if (!argv_find(argv, argc, "vni", &vni_idx))
4531 return CMD_WARNING;
4532
f2d62262 4533 /* Display specific VNI */
9c92b5f7 4534 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
5e53dce3 4535 evpn_show_vni(vty, bgp_evpn, vni, json);
9c92b5f7
MK
4536 }
4537
c48349e3 4538 if (uj)
75eeda93 4539 vty_json(vty, json);
520d5d76 4540
d62a17ae 4541 return CMD_SUCCESS;
520d5d76 4542}
4543
021b6596
AD
4544DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4545 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4546 "show bgp l2vpn evpn vni remote-ip-hash",
4547 SHOW_STR
4548 BGP_STR
4549 L2VPN_HELP_STR
4550 EVPN_HELP_STR
4551 "Show VNI\n"
4552 "Remote IP hash\n")
4553{
4554 struct bgp *bgp_evpn;
4555 int idx = 0;
4556
4557 bgp_evpn = bgp_get_evpn();
4558 if (!bgp_evpn)
4559 return CMD_WARNING;
4560
4561 if (!argv_find(argv, argc, "evpn", &idx))
4562 return CMD_WARNING;
4563
4564 hash_iterate(bgp_evpn->vnihash,
4565 (void (*)(struct hash_bucket *,
4566 void *))bgp_evpn_show_remote_ip_hash,
4567 vty);
4568
4569 return CMD_SUCCESS;
4570}
4571
4572DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4573 show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4574 "show bgp l2vpn evpn vni-svi-hash",
4575 SHOW_STR
4576 BGP_STR
4577 L2VPN_HELP_STR
4578 EVPN_HELP_STR
4579 "Show vni-svi-hash\n")
4580{
4581 struct bgp *bgp_evpn;
4582 int idx = 0;
4583
4584 bgp_evpn = bgp_get_evpn();
4585 if (!bgp_evpn)
4586 return CMD_WARNING;
4587
4588 if (!argv_find(argv, argc, "evpn", &idx))
4589 return CMD_WARNING;
4590
4591 hash_iterate(bgp_evpn->vni_svi_hash,
4592 (void (*)(struct hash_bucket *,
4593 void *))bgp_evpn_show_vni_svi_hash,
4594 vty);
4595
4596 return CMD_SUCCESS;
4597}
4598
b5e140c8
AK
4599DEFPY(show_bgp_l2vpn_evpn_es_evi,
4600 show_bgp_l2vpn_evpn_es_evi_cmd,
4601 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4602 SHOW_STR
4603 BGP_STR
4604 L2VPN_HELP_STR
4605 EVPN_HELP_STR
4606 "ES per EVI\n"
4607 "VxLAN Network Identifier\n"
4608 "VNI\n"
4609 JSON_STR
4610 "Detailed information\n")
4611{
4612 if (vni)
4613 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4614 else
4615 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4616
4617 return CMD_SUCCESS;
4618}
4619
4620DEFPY(show_bgp_l2vpn_evpn_es,
50f74cf1 4621 show_bgp_l2vpn_evpn_es_cmd,
b5e140c8 4622 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
50f74cf1 4623 SHOW_STR
4624 BGP_STR
4625 L2VPN_HELP_STR
4626 EVPN_HELP_STR
b5e140c8
AK
4627 "Ethernet Segment\n"
4628 "ES ID\n"
4629 "Detailed information\n"
b482a7fd 4630 JSON_STR)
50f74cf1 4631{
6a527b2f 4632 esi_t esi;
50f74cf1 4633
b5e140c8
AK
4634 if (esi_str) {
4635 if (!str_to_esi(esi_str, &esi)) {
664b6f18 4636 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 4637 return CMD_WARNING;
4638 }
b5e140c8
AK
4639 bgp_evpn_es_show_esi(vty, &esi, uj);
4640 } else {
50f74cf1 4641
b5e140c8 4642 bgp_evpn_es_show(vty, uj, !!detail);
50f74cf1 4643 }
4644
4645 return CMD_SUCCESS;
4646}
4647
229587fb
AK
4648DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4649 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4650 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4651 "Ethernet Segment\n"
4652 "ES ID\n" JSON_STR)
4653{
4654 esi_t esi;
4655
4656 if (esi_str) {
4657 if (!str_to_esi(esi_str, &esi)) {
664b6f18 4658 vty_out(vty, "%% Malformed ESI\n");
229587fb
AK
4659 return CMD_WARNING;
4660 }
4661 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4662 } else {
4663
4664 bgp_evpn_es_vrf_show(vty, uj, NULL);
4665 }
4666
4667 return CMD_SUCCESS;
4668}
4669
090efa2f
AK
4670DEFPY(show_bgp_l2vpn_evpn_nh,
4671 show_bgp_l2vpn_evpn_nh_cmd,
4672 "show bgp l2vpn evpn next-hops [json$uj]",
4673 SHOW_STR
4674 BGP_STR
4675 L2VPN_HELP_STR
4676 EVPN_HELP_STR
4677 "Nexthops\n"
4678 JSON_STR)
4679{
4680 bgp_evpn_nh_show(vty, uj);
4681
4682 return CMD_SUCCESS;
4683}
4684
f2d62262 4685/*
4686 * Display EVPN neighbor summary.
4687 */
8c1d4cd5 4688DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
96c81f66 4689 "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 4690 SHOW_STR BGP_STR
ee851c8c 4691 "bgp vrf\n"
8c1d4cd5 4692 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
9c92b5f7 4693 "Summary of BGP neighbor status\n"
10b49f14 4694 "Show only sessions in Established state\n"
3577f1c5 4695 "Show only sessions not in Established state\n"
8c1d4cd5
LS
4696 "Show only the specified neighbor session\n"
4697 "Neighbor to display information about\n"
4698 "Neighbor to display information about\n"
4699 "Neighbor on BGP configured interface\n"
4700 "Show only the specified remote AS sessions\n"
4701 "AS number\n"
4702 "Internal (iBGP) AS sessions\n"
4703 "External (eBGP) AS sessions\n"
96c81f66 4704 "Shorten the information on BGP instances\n"
8c1d4cd5 4705 "Increase table width for longer output\n" JSON_STR)
520d5d76 4706{
ee851c8c 4707 int idx_vrf = 0;
85eeb029 4708 int idx = 0;
ee851c8c 4709 char *vrf = NULL;
8c1d4cd5
LS
4710 char *neighbor = NULL;
4711 as_t as = 0; /* 0 means AS filter not set */
4712 int as_type = AS_UNSPECIFIED;
96c81f66 4713 uint16_t show_flags = 0;
ee851c8c
MK
4714
4715 if (argv_find(argv, argc, "vrf", &idx_vrf))
4716 vrf = argv[++idx_vrf]->arg;
10b49f14 4717
85eeb029
DA
4718 if (argv_find(argv, argc, "failed", &idx))
4719 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4720
4721 if (argv_find(argv, argc, "established", &idx))
4722 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4723
8c1d4cd5
LS
4724
4725 if (argv_find(argv, argc, "neighbor", &idx))
4726 neighbor = argv[idx + 1]->arg;
4727
4728 if (argv_find(argv, argc, "remote-as", &idx)) {
4729 if (argv[idx + 1]->arg[0] == 'i')
4730 as_type = AS_INTERNAL;
4731 else if (argv[idx + 1]->arg[0] == 'e')
4732 as_type = AS_EXTERNAL;
4733 else
4734 as = (as_t)atoi(argv[idx + 1]->arg);
4735 }
4736
96c81f66
LS
4737 if (argv_find(argv, argc, "terse", &idx))
4738 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4739
85eeb029
DA
4740 if (argv_find(argv, argc, "wide", &idx))
4741 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4742
4743 if (use_json(argc, argv))
4744 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4745
8c1d4cd5
LS
4746 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4747 as_type, as, show_flags);
520d5d76 4748}
4749
852d9f97
SW
4750static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
4751{
4752 if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
4753 *type = BGP_EVPN_MAC_IP_ROUTE;
4754 else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
4755 *type = BGP_EVPN_IMET_ROUTE;
4756 else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
4757 *type = BGP_EVPN_ES_ROUTE;
4758 else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
4759 *type = BGP_EVPN_AD_ROUTE;
4760 else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
4761 *type = BGP_EVPN_IP_PREFIX_ROUTE;
4762 else
4763 return -1;
4764
4765 return 0;
4766}
4767
15dc08a6 4768int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
2b1364e1
SW
4769{
4770 int type_idx = 0;
4771
4772 if (argv_find(argv, argc, "type", &type_idx)) {
4773 /* Specific type is requested */
852d9f97
SW
4774 if (bgp_evpn_cli_parse_type_cmp(type,
4775 argv[type_idx + 1]->arg) != 0)
2b1364e1
SW
4776 return -1;
4777 }
4778
4779 return 0;
4780}
4781
f2d62262 4782/*
4783 * Display global EVPN routing table.
4784 */
60466a63
QY
4785DEFUN(show_bgp_l2vpn_evpn_route,
4786 show_bgp_l2vpn_evpn_route_cmd,
2b1364e1 4787 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
9c92b5f7
MK
4788 SHOW_STR
4789 BGP_STR
4790 L2VPN_HELP_STR
4791 EVPN_HELP_STR
f5dc0b1a 4792 EVPN_RT_HELP_STR
21f3551e 4793 "Display Detailed Information\n"
f5dc0b1a 4794 EVPN_TYPE_HELP_STR
2b1364e1 4795 EVPN_TYPE_ALL_LIST_HELP_STR
9c92b5f7 4796 JSON_STR)
520d5d76 4797{
d62a17ae 4798 struct bgp *bgp;
21f3551e 4799 int detail = 0;
d62a17ae 4800 int type = 0;
9f049418 4801 bool uj = false;
9c92b5f7
MK
4802 json_object *json = NULL;
4803
4804 uj = use_json(argc, argv);
520d5d76 4805
530db8dc 4806 bgp = bgp_get_evpn();
d62a17ae 4807 if (!bgp)
4808 return CMD_WARNING;
520d5d76 4809
9c92b5f7
MK
4810 if (uj)
4811 json = json_object_new_object();
f2d62262 4812
15dc08a6 4813 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1 4814 return CMD_WARNING;
520d5d76 4815
21f3551e
NS
4816 if (argv_find(argv, argc, "detail", &detail))
4817 detail = 1;
4818
4819 evpn_show_all_routes(vty, bgp, type, json, detail);
9c92b5f7 4820
2d4460de
DS
4821 /*
4822 * This is an extremely expensive operation at scale
4823 * and as such we need to save as much time as is
4824 * possible.
4825 */
4826 if (uj)
4827 vty_json_no_pretty(vty, json);
3cdb03fb 4828
d62a17ae 4829 return CMD_SUCCESS;
520d5d76 4830}
4831
f2d62262 4832/*
4833 * Display global EVPN routing table for specific RD.
4834 */
60466a63
QY
4835DEFUN(show_bgp_l2vpn_evpn_route_rd,
4836 show_bgp_l2vpn_evpn_route_rd_cmd,
a111dd97 4837 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
9c92b5f7
MK
4838 SHOW_STR
4839 BGP_STR
4840 L2VPN_HELP_STR
4841 EVPN_HELP_STR
f5dc0b1a
SW
4842 EVPN_RT_HELP_STR
4843 EVPN_RT_DIST_HELP_STR
10794c49 4844 EVPN_ASN_IP_HELP_STR
a111dd97 4845 "All VPN Route Distinguishers\n"
f5dc0b1a 4846 EVPN_TYPE_HELP_STR
2b1364e1 4847 EVPN_TYPE_ALL_LIST_HELP_STR
9c92b5f7 4848 JSON_STR)
520d5d76 4849{
d62a17ae 4850 struct bgp *bgp;
9b01d289 4851 int ret = 0;
d62a17ae 4852 struct prefix_rd prd;
4853 int type = 0;
9f049418 4854 bool uj = false;
9c92b5f7 4855 json_object *json = NULL;
a111dd97
TA
4856 int idx_ext_community = 0;
4857 int rd_all = 0;
520d5d76 4858
530db8dc 4859 bgp = bgp_get_evpn();
d62a17ae 4860 if (!bgp)
4861 return CMD_WARNING;
520d5d76 4862
9c92b5f7
MK
4863 /* check if we need json output */
4864 uj = use_json(argc, argv);
4865 if (uj)
4866 json = json_object_new_object();
f2d62262 4867
8923315d 4868 if (!argv_find(argv, argc, "all", &rd_all)) {
a111dd97 4869 /* get the RD */
9b01d289
DA
4870 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4871 &idx_ext_community)) {
4872 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4873 if (!ret) {
4874 vty_out(vty,
4875 "%% Malformed Route Distinguisher\n");
4876 return CMD_WARNING;
4877 }
9c92b5f7 4878 }
d62a17ae 4879 }
520d5d76 4880
15dc08a6 4881 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1 4882 return CMD_WARNING;
520d5d76 4883
a111dd97
TA
4884 if (rd_all)
4885 evpn_show_all_routes(vty, bgp, type, json, 1);
4886 else
4887 evpn_show_route_rd(vty, bgp, &prd, type, json);
9c92b5f7 4888
c48349e3 4889 if (uj)
75eeda93 4890 vty_json(vty, json);
9c92b5f7 4891
d62a17ae 4892 return CMD_SUCCESS;
520d5d76 4893}
4894
f2d62262 4895/*
4896 * Display global EVPN routing table for specific RD and MACIP.
4897 */
9c92b5f7
MK
4898DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4899 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
a111dd97 4900 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
9c92b5f7
MK
4901 SHOW_STR
4902 BGP_STR
4903 L2VPN_HELP_STR
4904 EVPN_HELP_STR
f5dc0b1a
SW
4905 EVPN_RT_HELP_STR
4906 EVPN_RT_DIST_HELP_STR
10794c49 4907 EVPN_ASN_IP_HELP_STR
a111dd97 4908 "All VPN Route Distinguishers\n"
9c92b5f7
MK
4909 "MAC\n"
4910 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4911 "IP\n"
4912 "IP address (IPv4 or IPv6)\n"
4913 JSON_STR)
4914{
0291c246 4915 struct bgp *bgp;
9b01d289 4916 int ret = 0;
0291c246
MK
4917 struct prefix_rd prd;
4918 struct ethaddr mac;
4919 struct ipaddr ip;
a111dd97 4920 int idx_ext_community = 0;
0291c246
MK
4921 int mac_idx = 0;
4922 int ip_idx = 0;
9f049418 4923 bool uj = false;
0291c246 4924 json_object *json = NULL;
a111dd97 4925 int rd_all = 0;
9c92b5f7
MK
4926
4927 memset(&mac, 0, sizeof(struct ethaddr));
4928 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 4929
530db8dc 4930 bgp = bgp_get_evpn();
d62a17ae 4931 if (!bgp)
4932 return CMD_WARNING;
4933
9c92b5f7
MK
4934 /* check if we need json output */
4935 uj = use_json(argc, argv);
4936 if (uj)
4937 json = json_object_new_object();
f2d62262 4938
9c92b5f7 4939 /* get the prd */
8923315d 4940 if (!argv_find(argv, argc, "all", &rd_all)) {
9b01d289
DA
4941 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4942 &idx_ext_community)) {
4943 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4944 if (!ret) {
4945 vty_out(vty,
4946 "%% Malformed Route Distinguisher\n");
4947 return CMD_WARNING;
4948 }
9c92b5f7 4949 }
d62a17ae 4950 }
9c92b5f7
MK
4951
4952 /* get the mac */
4953 if (argv_find(argv, argc, "mac", &mac_idx)) {
4954 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4955 vty_out(vty, "%% Malformed MAC address\n");
4956 return CMD_WARNING;
4957 }
d62a17ae 4958 }
9c92b5f7
MK
4959
4960 /* get the ip if specified */
4961 if (argv_find(argv, argc, "ip", &ip_idx)) {
4962 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 4963 vty_out(vty, "%% Malformed IP address\n");
4964 return CMD_WARNING;
4965 }
4966 }
4967
a111dd97
TA
4968 if (rd_all)
4969 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4970 else
4971 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
9c92b5f7 4972
c48349e3 4973 if (uj)
75eeda93 4974 vty_json(vty, json);
9c92b5f7 4975
d62a17ae 4976 return CMD_SUCCESS;
520d5d76 4977}
4978
50f74cf1 4979/* Display per ESI routing table */
4980DEFUN(show_bgp_l2vpn_evpn_route_esi,
4981 show_bgp_l2vpn_evpn_route_esi_cmd,
4982 "show bgp l2vpn evpn route esi ESI [json]",
4983 SHOW_STR
4984 BGP_STR
4985 L2VPN_HELP_STR
4986 EVPN_HELP_STR
f5dc0b1a 4987 EVPN_RT_HELP_STR
50f74cf1 4988 "Ethernet Segment Identifier\n"
4989 "ESI ID\n"
4990 JSON_STR)
4991{
9f049418 4992 bool uj = false;
6a527b2f 4993 esi_t esi;
50f74cf1 4994 struct bgp *bgp = NULL;
4995 json_object *json = NULL;
4996
6a527b2f 4997 memset(&esi, 0, sizeof(esi));
530db8dc 4998 bgp = bgp_get_evpn();
50f74cf1 4999 if (!bgp)
5000 return CMD_WARNING;
5001
5002 uj = use_json(argc, argv);
5003 if (uj)
5004 json = json_object_new_object();
5005
5006 /* get the ESI - ESI-ID is at argv[6] */
5007 if (!str_to_esi(argv[6]->arg, &esi)) {
5008 vty_out(vty, "%% Malformed ESI\n");
5009 return CMD_WARNING;
5010 }
5011
5012 evpn_show_routes_esi(vty, bgp, &esi, json);
5013
c48349e3 5014 if (uj)
75eeda93 5015 vty_json(vty, json);
50f74cf1 5016
5017 return CMD_SUCCESS;
5018}
5019
5020
f2d62262 5021/*
5022 * Display per-VNI EVPN routing table.
5023 */
9c92b5f7 5024DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
2b1364e1 5025 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
9c92b5f7
MK
5026 SHOW_STR
5027 BGP_STR
5028 L2VPN_HELP_STR
5029 EVPN_HELP_STR
f5dc0b1a 5030 EVPN_RT_HELP_STR
9c92b5f7
MK
5031 "VXLAN Network Identifier\n"
5032 "VNI number\n"
f5dc0b1a
SW
5033 EVPN_TYPE_HELP_STR
5034 EVPN_TYPE_1_HELP_STR
2b1364e1 5035 EVPN_TYPE_1_HELP_STR
f5dc0b1a 5036 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5037 EVPN_TYPE_2_HELP_STR
5038 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5039 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
5040 "Remote VTEP\n"
5041 "Remote VTEP IP address\n"
5042 JSON_STR)
520d5d76 5043{
d62a17ae 5044 vni_t vni;
5045 struct bgp *bgp;
5046 struct in_addr vtep_ip;
5047 int type = 0;
f2d62262 5048 int idx = 0;
2b1364e1 5049 int vtep_idx = 0;
9f049418 5050 bool uj = false;
9c92b5f7 5051 json_object *json = NULL;
d62a17ae 5052
530db8dc 5053 bgp = bgp_get_evpn();
d62a17ae 5054 if (!bgp)
5055 return CMD_WARNING;
5056
9c92b5f7
MK
5057 /* check if we need json output */
5058 uj = use_json(argc, argv);
5059 if (uj)
5060 json = json_object_new_object();
5061
f2d62262 5062 if (!argv_find(argv, argc, "evpn", &idx))
5063 return CMD_WARNING;
5064
d62a17ae 5065 vtep_ip.s_addr = 0;
5066
f2d62262 5067 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 5068
15dc08a6 5069 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
2b1364e1
SW
5070 return CMD_WARNING;
5071
5072 if (argv_find(argv, argc, "vtep", &vtep_idx)) {
5073 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
5074 vty_out(vty, "%% Malformed VTEP IP address\n");
d62a17ae 5075 return CMD_WARNING;
2b1364e1 5076 }
d62a17ae 5077 }
5078
852d9f97 5079 evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
9c92b5f7 5080
c48349e3 5081 if (uj)
75eeda93 5082 vty_json(vty, json);
9c92b5f7 5083
d62a17ae 5084 return CMD_SUCCESS;
520d5d76 5085}
5086
f2d62262 5087/*
5088 * Display per-VNI EVPN routing table for specific MACIP.
5089 */
9c92b5f7
MK
5090DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
5091 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
093e3f23 5092 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
9c92b5f7
MK
5093 SHOW_STR
5094 BGP_STR
5095 L2VPN_HELP_STR
5096 EVPN_HELP_STR
f5dc0b1a 5097 EVPN_RT_HELP_STR
9c92b5f7
MK
5098 "VXLAN Network Identifier\n"
5099 "VNI number\n"
5100 "MAC\n"
5101 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5102 "IP\n"
5103 "IP address (IPv4 or IPv6)\n"
5104 JSON_STR)
520d5d76 5105{
d62a17ae 5106 vni_t vni;
5107 struct bgp *bgp;
5108 struct ethaddr mac;
5109 struct ipaddr ip;
f2d62262 5110 int idx = 0;
9f049418 5111 bool uj = false;
9c92b5f7 5112 json_object *json = NULL;
d62a17ae 5113
530db8dc 5114 bgp = bgp_get_evpn();
d62a17ae 5115 if (!bgp)
5116 return CMD_WARNING;
5117
9c92b5f7
MK
5118 /* check if we need json output */
5119 uj = use_json(argc, argv);
5120 if (uj)
5121 json = json_object_new_object();
5122
f2d62262 5123 if (!argv_find(argv, argc, "evpn", &idx))
5124 return CMD_WARNING;
5125
9c92b5f7 5126 /* get the VNI */
f2d62262 5127 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
5128
5129 /* get the mac */
f2d62262 5130 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 5131 vty_out(vty, "%% Malformed MAC address\n");
5132 return CMD_WARNING;
5133 }
9c92b5f7
MK
5134
5135 /* get the ip */
d62a17ae 5136 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
5137 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
5138 || (uj
5139 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 5140 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 5141 vty_out(vty, "%% Malformed IP address\n");
5142 return CMD_WARNING;
5143 }
5144 }
5145
9c92b5f7
MK
5146 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
5147
c48349e3 5148 if (uj)
75eeda93 5149 vty_json(vty, json);
9c92b5f7 5150
d62a17ae 5151 return CMD_SUCCESS;
520d5d76 5152}
5153
f2d62262 5154/*
5155 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5156 */
9c92b5f7
MK
5157DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
5158 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
093e3f23 5159 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
9c92b5f7
MK
5160 SHOW_STR
5161 BGP_STR
5162 L2VPN_HELP_STR
5163 EVPN_HELP_STR
f5dc0b1a 5164 EVPN_RT_HELP_STR
9c92b5f7
MK
5165 "VXLAN Network Identifier\n"
5166 "VNI number\n"
f5dc0b1a 5167 EVPN_TYPE_3_HELP_STR
9c92b5f7
MK
5168 "Originating Router IP address\n"
5169 JSON_STR)
520d5d76 5170{
d62a17ae 5171 vni_t vni;
5172 struct bgp *bgp;
5173 int ret;
5174 struct in_addr orig_ip;
f2d62262 5175 int idx = 0;
9f049418 5176 bool uj = false;
9c92b5f7 5177 json_object *json = NULL;
520d5d76 5178
530db8dc 5179 bgp = bgp_get_evpn();
d62a17ae 5180 if (!bgp)
5181 return CMD_WARNING;
520d5d76 5182
9c92b5f7
MK
5183 /* check if we need json output */
5184 uj = use_json(argc, argv);
5185 if (uj)
5186 json = json_object_new_object();
5187
f2d62262 5188 if (!argv_find(argv, argc, "evpn", &idx))
5189 return CMD_WARNING;
5190
9c92b5f7 5191 /* get the VNI */
f2d62262 5192 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
5193
5194 /* get the ip */
f2d62262 5195 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 5196 if (!ret) {
5197 vty_out(vty, "%% Malformed Originating Router IP address\n");
5198 return CMD_WARNING;
5199 }
520d5d76 5200
9c92b5f7
MK
5201 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5202
c48349e3 5203 if (uj)
75eeda93 5204 vty_json(vty, json);
9c92b5f7 5205
d62a17ae 5206 return CMD_SUCCESS;
520d5d76 5207}
5208
f2d62262 5209/*
5210 * Display per-VNI EVPN routing table - for all VNIs.
5211 */
60466a63
QY
5212DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5213 show_bgp_l2vpn_evpn_route_vni_all_cmd,
c7ef6cf2 5214 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
9c92b5f7
MK
5215 SHOW_STR
5216 BGP_STR
5217 L2VPN_HELP_STR
5218 EVPN_HELP_STR
f5dc0b1a 5219 EVPN_RT_HELP_STR
9c92b5f7
MK
5220 "VXLAN Network Identifier\n"
5221 "All VNIs\n"
c7ef6cf2 5222 "Print Detailed Output\n"
9c92b5f7
MK
5223 "Remote VTEP\n"
5224 "Remote VTEP IP address\n"
5225 JSON_STR)
520d5d76 5226{
d62a17ae 5227 struct bgp *bgp;
5228 struct in_addr vtep_ip;
f2d62262 5229 int idx = 0;
9f049418 5230 bool uj = false;
9c92b5f7 5231 json_object *json = NULL;
c7ef6cf2
NS
5232 /* Detail Adjust. Adjust indexes according to detail option */
5233 int da = 0;
520d5d76 5234
530db8dc 5235 bgp = bgp_get_evpn();
d62a17ae 5236 if (!bgp)
5237 return CMD_WARNING;
520d5d76 5238
9c92b5f7
MK
5239 /* check if we need json output */
5240 uj = use_json(argc, argv);
5241 if (uj)
5242 json = json_object_new_object();
5243
f2d62262 5244 if (!argv_find(argv, argc, "evpn", &idx))
5245 return CMD_WARNING;
5246
c7ef6cf2
NS
5247 if (argv_find(argv, argc, "detail", &da))
5248 da = 1;
5249
5250 /* vtep-ip position depends on detail option */
d62a17ae 5251 vtep_ip.s_addr = 0;
c7ef6cf2
NS
5252 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5253 || (uj
5254 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5255 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
d62a17ae 5256 vty_out(vty, "%% Malformed VTEP IP address\n");
5257 return CMD_WARNING;
5258 }
5259 }
520d5d76 5260
852d9f97 5261 evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
9c92b5f7 5262
852d9f97 5263 if (uj) {
75eeda93 5264 vty_json(vty, json);
852d9f97
SW
5265 json_object_free(json);
5266 }
5267
5268 return CMD_SUCCESS;
5269}
5270
5271/*
5272 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5273 */
5274DEFPY(show_bgp_vni_all,
5275 show_bgp_vni_all_cmd,
15919b89 5276 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
852d9f97
SW
5277 SHOW_STR
5278 BGP_STR
5279 VNI_HELP_STR
5280 VNI_ALL_HELP_STR
5281 VTEP_HELP_STR
5282 VTEP_IP_HELP_STR
15919b89
SW
5283 DETAIL_HELP_STR
5284 JSON_STR)
852d9f97
SW
5285{
5286 struct bgp *bgp;
5287 json_object *json = NULL;
5288
5289 bgp = bgp_get_evpn();
5290 if (!bgp)
5291 return CMD_WARNING;
5292
5293 /* check if we need json output */
852d9f97
SW
5294 if (uj)
5295 json = json_object_new_object();
852d9f97
SW
5296
5297 evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
5298
d950d224
SW
5299 if (uj)
5300 vty_json(vty, json);
852d9f97
SW
5301
5302 return CMD_SUCCESS;
5303}
5304
5305/*
5306 * Display per-VNI EVPN EAD routing table - for all VNIs.
5307 */
5308DEFPY(show_bgp_vni_all_ead,
5309 show_bgp_vni_all_ead_cmd,
5310 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5311 SHOW_STR
5312 BGP_STR
5313 VNI_HELP_STR
5314 VNI_ALL_HELP_STR
5315 EVPN_TYPE_HELP_STR
5316 EVPN_TYPE_1_HELP_STR
5317 EVPN_TYPE_1_HELP_STR
5318 VTEP_HELP_STR
5319 VTEP_IP_HELP_STR
5320 DETAIL_HELP_STR
5321 JSON_STR)
5322{
5323 struct bgp *bgp;
5324 json_object *json = NULL;
5325
5326 bgp = bgp_get_evpn();
5327 if (!bgp)
5328 return CMD_WARNING;
5329
5330 /* check if we need json output */
5331 if (uj)
5332 json = json_object_new_object();
5333
5334 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
5335 !!detail);
5336
d950d224
SW
5337 if (uj)
5338 vty_json(vty, json);
852d9f97
SW
5339
5340 return CMD_SUCCESS;
5341}
5342
5343/*
5344 * Display per-VNI EVPN MAC routing table - for all VNIs.
5345 */
5346DEFPY(show_bgp_vni_all_macip_mac,
5347 show_bgp_vni_all_macip_mac_cmd,
5348 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5349 SHOW_STR
5350 BGP_STR
5351 VNI_HELP_STR
5352 VNI_ALL_HELP_STR
5353 EVPN_TYPE_HELP_STR
5354 EVPN_TYPE_2_HELP_STR
5355 EVPN_TYPE_2_HELP_STR
5356 "MAC Table\n"
5357 VTEP_HELP_STR
5358 VTEP_IP_HELP_STR
5359 DETAIL_HELP_STR
5360 JSON_STR)
5361{
5362 struct bgp *bgp;
5363 json_object *json = NULL;
5364
5365 bgp = bgp_get_evpn();
5366 if (!bgp)
5367 return CMD_WARNING;
5368
5369 /* check if we need json output */
5370 if (uj)
5371 json = json_object_new_object();
5372
5373 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5374 json, !!detail);
5375
d950d224
SW
5376 if (uj)
5377 vty_json(vty, json);
852d9f97
SW
5378
5379 return CMD_SUCCESS;
5380}
5381
5382/*
5383 * Display per-VNI EVPN IP routing table - for all VNIs.
5384 */
5385DEFPY(show_bgp_vni_all_macip_ip,
5386 show_bgp_vni_all_macip_ip_cmd,
5387 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5388 SHOW_STR
5389 BGP_STR
5390 VNI_HELP_STR
5391 VNI_ALL_HELP_STR
5392 EVPN_TYPE_HELP_STR
5393 EVPN_TYPE_2_HELP_STR
5394 EVPN_TYPE_2_HELP_STR
5395 "IP Table\n"
5396 VTEP_HELP_STR
5397 VTEP_IP_HELP_STR
5398 DETAIL_HELP_STR
5399 JSON_STR)
5400{
5401 struct bgp *bgp;
5402 json_object *json = NULL;
5403
5404 bgp = bgp_get_evpn();
5405 if (!bgp)
5406 return CMD_WARNING;
5407
5408 /* check if we need json output */
5409 if (uj)
5410 json = json_object_new_object();
5411
5412 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5413 json, !!detail);
5414
d950d224
SW
5415 if (uj)
5416 vty_json(vty, json);
852d9f97
SW
5417
5418 return CMD_SUCCESS;
5419}
5420
5421/*
5422 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5423 */
5424DEFPY(show_bgp_vni_all_imet,
5425 show_bgp_vni_all_imet_cmd,
5426 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5427 SHOW_STR
5428 BGP_STR
5429 VNI_HELP_STR
5430 VNI_ALL_HELP_STR
5431 EVPN_TYPE_HELP_STR
5432 EVPN_TYPE_3_HELP_STR
5433 EVPN_TYPE_3_HELP_STR
5434 VTEP_HELP_STR
5435 VTEP_IP_HELP_STR
5436 DETAIL_HELP_STR
5437 JSON_STR)
5438{
5439 struct bgp *bgp;
5440 json_object *json = NULL;
5441
5442 bgp = bgp_get_evpn();
5443 if (!bgp)
5444 return CMD_WARNING;
5445
5446 /* check if we need json output */
5447 if (uj)
5448 json = json_object_new_object();
5449
5450 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
5451 json, !!detail);
5452
d950d224
SW
5453 if (uj)
5454 vty_json(vty, json);
852d9f97
SW
5455
5456 return CMD_SUCCESS;
5457}
5458
5459/*
5460 * Display per-VNI EVPN ALL routing tables - for select VNI
5461 */
5462DEFPY(show_bgp_vni,
5463 show_bgp_vni_cmd,
15919b89 5464 "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
852d9f97
SW
5465 SHOW_STR
5466 BGP_STR
5467 VNI_HELP_STR
5468 VNI_NUM_HELP_STR
5469 VTEP_HELP_STR
15919b89
SW
5470 VTEP_IP_HELP_STR
5471 JSON_STR)
852d9f97
SW
5472{
5473 struct bgp *bgp;
15919b89
SW
5474 json_object *json = NULL;
5475 json_object *json_mac = NULL;
852d9f97
SW
5476
5477 bgp = bgp_get_evpn();
5478 if (!bgp)
5479 return CMD_WARNING;
5480
15919b89
SW
5481 /* check if we need json output */
5482 if (uj) {
5483 json = json_object_new_object();
5484 json_mac = json_object_new_object();
5485 }
5486
5487 evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
5488
5489 if (!uj)
5490 vty_out(vty, "\n\nMAC Table:\n\n");
5491
5492 evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
5493
5494 if (uj) {
5495 json_object_object_add(json, "macTable", json_mac);
d950d224 5496 vty_json(vty, json);
15919b89 5497 }
852d9f97
SW
5498
5499 return CMD_SUCCESS;
5500}
5501
5502/*
5503 * Display per-VNI EVPN EAD routing table - for select VNI
5504 */
5505DEFPY(show_bgp_vni_ead,
5506 show_bgp_vni_ead_cmd,
5507 "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5508 SHOW_STR
5509 BGP_STR
5510 VNI_HELP_STR
5511 VNI_NUM_HELP_STR
5512 EVPN_TYPE_HELP_STR
5513 EVPN_TYPE_1_HELP_STR
5514 EVPN_TYPE_1_HELP_STR
5515 VTEP_HELP_STR
5516 VTEP_IP_HELP_STR
5517 JSON_STR)
5518{
5519 struct bgp *bgp;
5520 json_object *json = NULL;
5521
5522 bgp = bgp_get_evpn();
5523 if (!bgp)
5524 return CMD_WARNING;
5525
5526 /* check if we need json output */
5527 if (uj)
5528 json = json_object_new_object();
5529
5530 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
5531 json);
5532
d950d224
SW
5533 if (uj)
5534 vty_json(vty, json);
852d9f97
SW
5535
5536 return CMD_SUCCESS;
5537}
5538
5539/*
5540 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5541 */
5542DEFPY(show_bgp_vni_macip_mac,
5543 show_bgp_vni_macip_mac_cmd,
5544 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5545 SHOW_STR
5546 BGP_STR
5547 VNI_HELP_STR
5548 VNI_NUM_HELP_STR
5549 EVPN_TYPE_HELP_STR
5550 EVPN_TYPE_2_HELP_STR
5551 EVPN_TYPE_2_HELP_STR
5552 "MAC Table\n"
5553 VTEP_HELP_STR
5554 VTEP_IP_HELP_STR
5555 JSON_STR)
5556{
5557 struct bgp *bgp;
5558 json_object *json = NULL;
5559
5560 bgp = bgp_get_evpn();
5561 if (!bgp)
5562 return CMD_WARNING;
5563
5564 /* check if we need json output */
5565 if (uj)
5566 json = json_object_new_object();
5567
5568 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5569 json);
5570
d950d224
SW
5571 if (uj)
5572 vty_json(vty, json);
852d9f97
SW
5573
5574 return CMD_SUCCESS;
5575}
5576
5577/*
5578 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5579 */
5580DEFPY(show_bgp_vni_macip_ip,
5581 show_bgp_vni_macip_ip_cmd,
5582 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5583 SHOW_STR
5584 BGP_STR
5585 VNI_HELP_STR
5586 VNI_NUM_HELP_STR
5587 EVPN_TYPE_HELP_STR
5588 EVPN_TYPE_2_HELP_STR
5589 EVPN_TYPE_2_HELP_STR
5590 "IP Table\n"
5591 VTEP_HELP_STR
5592 VTEP_IP_HELP_STR
5593 JSON_STR)
5594{
5595 struct bgp *bgp;
5596 json_object *json = NULL;
5597
5598 bgp = bgp_get_evpn();
5599 if (!bgp)
5600 return CMD_WARNING;
5601
5602 /* check if we need json output */
5603 if (uj)
5604 json = json_object_new_object();
5605
5606 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5607 json);
5608
d950d224
SW
5609 if (uj)
5610 vty_json(vty, json);
852d9f97
SW
5611
5612 return CMD_SUCCESS;
5613}
5614
5615/*
5616 * Display per-VNI EVPN Multicast routing table - for select VNI
5617 */
5618DEFPY(show_bgp_vni_imet,
5619 show_bgp_vni_imet_cmd,
5620 "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5621 SHOW_STR
5622 BGP_STR
5623 VNI_HELP_STR
5624 VNI_NUM_HELP_STR
5625 EVPN_TYPE_HELP_STR
5626 EVPN_TYPE_3_HELP_STR
5627 EVPN_TYPE_3_HELP_STR
5628 VTEP_HELP_STR
5629 VTEP_IP_HELP_STR
5630 JSON_STR)
5631{
5632 struct bgp *bgp;
5633 json_object *json = NULL;
5634
5635 bgp = bgp_get_evpn();
5636 if (!bgp)
5637 return CMD_WARNING;
5638
5639 /* check if we need json output */
5640 if (uj)
5641 json = json_object_new_object();
5642
5643 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
5644 json);
5645
d950d224
SW
5646 if (uj)
5647 vty_json(vty, json);
852d9f97
SW
5648
5649 return CMD_SUCCESS;
5650}
5651
5652/*
5653 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5654 */
5655DEFPY(show_bgp_vni_macip_mac_addr,
5656 show_bgp_vni_macip_mac_addr_cmd,
5657 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5658 SHOW_STR
5659 BGP_STR
5660 VNI_HELP_STR
5661 VNI_NUM_HELP_STR
5662 EVPN_TYPE_HELP_STR
5663 EVPN_TYPE_2_HELP_STR
5664 EVPN_TYPE_2_HELP_STR
5665 "MAC Table\n"
5666 MAC_STR
5667 JSON_STR)
5668{
5669 struct bgp *bgp;
5670 json_object *json = NULL;
5671
5672 bgp = bgp_get_evpn();
5673 if (!bgp)
5674 return CMD_WARNING;
5675
5676 /* check if we need json output */
5677 if (uj)
5678 json = json_object_new_object();
5679
5680 evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
5681
d950d224
SW
5682 if (uj)
5683 vty_json(vty, json);
852d9f97
SW
5684
5685 return CMD_SUCCESS;
5686}
5687
5688/*
5689 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5690 */
5691DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
5692 "show bgp vni " CMD_VNI_RANGE
5693 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5694 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5695 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5696 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
5697{
5698 struct bgp *bgp;
5699 json_object *json = NULL;
5700 struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
5701
5702 bgp = bgp_get_evpn();
5703 if (!bgp)
5704 return CMD_WARNING;
5705
5706 /* check if we need json output */
5707 if (uj)
5708 json = json_object_new_object();
5709
5710 if (sockunion_family(ip) == AF_INET) {
5711 ip_addr.ipa_type = IPADDR_V4;
5712 ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
5713 } else {
5714 ip_addr.ipa_type = IPADDR_V6;
5715 memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
5716 sizeof(struct in6_addr));
5717 }
5718 evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
9c92b5f7 5719
c48349e3 5720 if (uj)
75eeda93 5721 vty_json(vty, json);
9c92b5f7 5722
d62a17ae 5723 return CMD_SUCCESS;
520d5d76 5724}
5725
229587fb 5726DEFPY_HIDDEN(
d656e0ae
AK
5727 show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5728 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5729 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
229587fb
AK
5730 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5731 "EVPN route information\n"
d656e0ae 5732 "MAC IP routes in the EVI tables linked to the ES\n"
229587fb
AK
5733 "ES ID\n"
5734 "Detailed information\n" JSON_STR)
5735{
5736 esi_t esi;
5737 esi_t *esi_p;
5738 json_object *json = NULL;
5739
5740 if (esi_str) {
5741 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5742 vty_out(vty, "%% Malformed ESI\n");
229587fb
AK
5743 return CMD_WARNING;
5744 }
5745 esi_p = &esi;
5746 } else {
5747 esi_p = NULL;
5748 }
5749
5750 if (uj)
5751 json = json_object_new_object();
d656e0ae 5752 bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
c48349e3 5753 if (uj)
75eeda93 5754 vty_json(vty, json);
229587fb
AK
5755
5756 return CMD_SUCCESS;
5757}
5758
58bff4d1
AK
5759DEFPY_HIDDEN(
5760 show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5761 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5762 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5763 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5764 "EVPN route information\n"
5765 "MAC IP routes in the global table linked to the ES\n"
5766 "ES ID\n"
5767 "Detailed information\n" JSON_STR)
5768{
5769 esi_t esi;
5770 esi_t *esi_p;
5771 json_object *json = NULL;
5772
5773 if (esi_str) {
5774 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5775 vty_out(vty, "%% Malformed ESI\n");
58bff4d1
AK
5776 return CMD_WARNING;
5777 }
5778 esi_p = &esi;
5779 } else {
5780 esi_p = NULL;
5781 }
5782
5783 if (uj)
5784 json = json_object_new_object();
5785 bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
c48349e3 5786 if (uj)
75eeda93 5787 vty_json(vty, json);
58bff4d1
AK
5788
5789 return CMD_SUCCESS;
5790}
5791
10ebe1ab
MK
5792/*
5793 * Display EVPN import route-target hash table
5794 */
5795DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5796 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5797 "show bgp l2vpn evpn vrf-import-rt [json]",
5798 SHOW_STR
5799 BGP_STR
5800 L2VPN_HELP_STR
5801 EVPN_HELP_STR
5802 "Show vrf import route target\n"
5803 JSON_STR)
5804{
9f049418 5805 bool uj = false;
5e53dce3 5806 struct bgp *bgp_evpn = NULL;
10ebe1ab
MK
5807 json_object *json = NULL;
5808
5e53dce3
T
5809 bgp_evpn = bgp_get_evpn();
5810 if (!bgp_evpn)
10ebe1ab
MK
5811 return CMD_WARNING;
5812
5813 uj = use_json(argc, argv);
5814 if (uj)
5815 json = json_object_new_object();
5816
5e53dce3 5817 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
10ebe1ab 5818
c48349e3 5819 if (uj)
75eeda93 5820 vty_json(vty, json);
10ebe1ab
MK
5821
5822 return CMD_SUCCESS;
5823}
5824
f2d62262 5825/*
5826 * Display EVPN import route-target hash table
5827 */
60466a63
QY
5828DEFUN(show_bgp_l2vpn_evpn_import_rt,
5829 show_bgp_l2vpn_evpn_import_rt_cmd,
9c92b5f7
MK
5830 "show bgp l2vpn evpn import-rt [json]",
5831 SHOW_STR
5832 BGP_STR
5833 L2VPN_HELP_STR
5834 EVPN_HELP_STR
5835 "Show import route target\n"
5836 JSON_STR)
520d5d76 5837{
d62a17ae 5838 struct bgp *bgp;
9f049418 5839 bool uj = false;
9c92b5f7 5840 json_object *json = NULL;
520d5d76 5841
530db8dc 5842 bgp = bgp_get_evpn();
d62a17ae 5843 if (!bgp)
5844 return CMD_WARNING;
520d5d76 5845
9c92b5f7
MK
5846 uj = use_json(argc, argv);
5847 if (uj)
5848 json = json_object_new_object();
5849
5850 evpn_show_import_rts(vty, bgp, json);
5851
c48349e3 5852 if (uj)
75eeda93 5853 vty_json(vty, json);
9c92b5f7 5854
d62a17ae 5855 return CMD_SUCCESS;
520d5d76 5856}
5857
1673a90d 5858DEFPY_HIDDEN(test_es_add,
b5e140c8
AK
5859 test_es_add_cmd,
5860 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5861 NO_STR
5862 "Test\n"
50f74cf1 5863 "Ethernet-segment\n"
b5e140c8
AK
5864 "Ethernet-Segment Identifier\n"
5865 "ES link state\n"
5866 "up|down\n"
5867)
50f74cf1 5868{
5869 int ret = 0;
5870 esi_t esi;
5871 struct bgp *bgp;
b5e140c8
AK
5872 struct in_addr vtep_ip;
5873 bool oper_up;
50f74cf1 5874
530db8dc 5875 bgp = bgp_get_evpn();
50f74cf1 5876 if (!bgp) {
664b6f18 5877 vty_out(vty, "%% EVPN BGP instance not yet created\n");
50f74cf1 5878 return CMD_WARNING;
5879 }
5880
b5e140c8 5881 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5882 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 5883 return CMD_WARNING;
5884 }
5885
b5e140c8
AK
5886 if (no) {
5887 ret = bgp_evpn_local_es_del(bgp, &esi);
5888 if (ret == -1) {
664b6f18 5889 vty_out(vty, "%% Failed to delete ES\n");
b5e140c8
AK
5890 return CMD_WARNING;
5891 }
5892 } else {
5893 if (state_str && !strcmp(state_str, "up"))
5894 oper_up = true;
5895 else
5896 oper_up = false;
5897 vtep_ip = bgp->router_id;
50f74cf1 5898
74e2bd89 5899 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
74be8313 5900 EVPN_MH_DF_PREF_MIN, false);
b5e140c8 5901 if (ret == -1) {
664b6f18 5902 vty_out(vty, "%% Failed to add ES\n");
b5e140c8
AK
5903 return CMD_WARNING;
5904 }
50f74cf1 5905 }
5906 return CMD_SUCCESS;
5907}
5908
1673a90d 5909DEFPY_HIDDEN(test_es_vni_add,
b5e140c8
AK
5910 test_es_vni_add_cmd,
5911 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5912 NO_STR
5913 "Test\n"
50f74cf1 5914 "Ethernet-segment\n"
b5e140c8
AK
5915 "Ethernet-Segment Identifier\n"
5916 "VNI\n"
5917 "1-16777215\n"
5918)
50f74cf1 5919{
5920 int ret = 0;
5921 esi_t esi;
5922 struct bgp *bgp;
50f74cf1 5923
530db8dc 5924 bgp = bgp_get_evpn();
50f74cf1 5925 if (!bgp) {
664b6f18 5926 vty_out(vty, "%% EVPN BGP instance not yet created\n");
50f74cf1 5927 return CMD_WARNING;
5928 }
5929
b5e140c8 5930 if (!str_to_esi(esi_str, &esi)) {
664b6f18 5931 vty_out(vty, "%% Malformed ESI\n");
50f74cf1 5932 return CMD_WARNING;
5933 }
5934
b5e140c8
AK
5935 if (no) {
5936 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5937 if (ret == -1) {
664b6f18 5938 vty_out(vty, "%% Failed to deref ES VNI\n");
b5e140c8
AK
5939 return CMD_WARNING;
5940 }
5941 } else {
5942 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5943 if (ret == -1) {
664b6f18 5944 vty_out(vty, "%% Failed to ref ES VNI\n");
b5e140c8
AK
5945 return CMD_WARNING;
5946 }
50f74cf1 5947 }
5948 return CMD_SUCCESS;
5949}
5950
5014d96f 5951ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
093e3f23 5952 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5014d96f
DW
5953 "Show VNI\n"
5954 "VNI number\n")
5955
5956ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5957 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
996c9314 5958 "Summary of BGP neighbor status\n" JSON_STR)
5014d96f
DW
5959
5960ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
2b1364e1 5961 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5014d96f 5962 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 5963 EVPN_RT_HELP_STR
21f3551e 5964 "Display Detailed Information\n"
f5dc0b1a
SW
5965 EVPN_TYPE_HELP_STR
5966 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5967 EVPN_TYPE_2_HELP_STR
5968 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5969 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
5970
5971ALIAS_HIDDEN(
5972 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
2b1364e1 5973 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5014d96f 5974 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
5975 EVPN_RT_HELP_STR
5976 EVPN_RT_DIST_HELP_STR
5977 EVPN_ASN_IP_HELP_STR
5978 EVPN_TYPE_HELP_STR
5979 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
5980 EVPN_TYPE_2_HELP_STR
5981 EVPN_TYPE_3_HELP_STR
f5dc0b1a 5982 EVPN_TYPE_3_HELP_STR)
5014d96f
DW
5983
5984ALIAS_HIDDEN(
5985 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
d114b977 5986 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5014d96f 5987 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a
SW
5988 EVPN_RT_HELP_STR
5989 EVPN_RT_DIST_HELP_STR
5990 EVPN_ASN_IP_HELP_STR
5014d96f
DW
5991 "MAC\n"
5992 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5993 "IP\n"
5994 "IP address (IPv4 or IPv6)\n")
5995
5996ALIAS_HIDDEN(
5997 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
2b1364e1 5998 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5014d96f 5999 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6000 EVPN_RT_HELP_STR
5014d96f
DW
6001 "VXLAN Network Identifier\n"
6002 "VNI number\n"
f5dc0b1a
SW
6003 EVPN_TYPE_HELP_STR
6004 EVPN_TYPE_2_HELP_STR
2b1364e1
SW
6005 EVPN_TYPE_2_HELP_STR
6006 EVPN_TYPE_3_HELP_STR
f5dc0b1a 6007 EVPN_TYPE_3_HELP_STR
5014d96f
DW
6008 "Remote VTEP\n"
6009 "Remote VTEP IP address\n")
6010
6011ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
6012 show_bgp_evpn_route_vni_macip_cmd,
093e3f23 6013 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
5014d96f 6014 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6015 EVPN_RT_HELP_STR
5014d96f
DW
6016 "VXLAN Network Identifier\n"
6017 "VNI number\n"
6018 "MAC\n"
6019 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6020 "IP\n"
6021 "IP address (IPv4 or IPv6)\n")
6022
6023ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
6024 show_bgp_evpn_route_vni_multicast_cmd,
093e3f23 6025 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
5014d96f 6026 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6027 EVPN_RT_HELP_STR
5014d96f
DW
6028 "VXLAN Network Identifier\n"
6029 "VNI number\n"
f5dc0b1a 6030 EVPN_TYPE_3_HELP_STR
5014d96f
DW
6031 "Originating Router IP address\n")
6032
6033ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
c7ef6cf2 6034 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5014d96f 6035 SHOW_STR BGP_STR EVPN_HELP_STR
f5dc0b1a 6036 EVPN_RT_HELP_STR
5014d96f
DW
6037 "VXLAN Network Identifier\n"
6038 "All VNIs\n"
c7ef6cf2 6039 "Print Detailed Output\n"
5014d96f
DW
6040 "Remote VTEP\n"
6041 "Remote VTEP IP address\n")
6042
6043ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
6044 "show bgp evpn import-rt",
6045 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5014d96f 6046
90e60aa7 6047DEFUN_NOSH (bgp_evpn_vni,
6048 bgp_evpn_vni_cmd,
093e3f23 6049 "vni " CMD_VNI_RANGE,
90e60aa7 6050 "VXLAN Network Identifier\n"
6051 "VNI number\n")
6052{
d62a17ae 6053 vni_t vni;
6054 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6055 struct bgpevpn *vpn;
90e60aa7 6056
d62a17ae 6057 if (!bgp)
6058 return CMD_WARNING;
90e60aa7 6059
d62a17ae 6060 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 6061
d62a17ae 6062 /* Create VNI, or mark as configured. */
6063 vpn = evpn_create_update_vni(bgp, vni);
6064 if (!vpn) {
6065 vty_out(vty, "%% Failed to create VNI \n");
6066 return CMD_WARNING;
6067 }
90e60aa7 6068
d62a17ae 6069 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
6070 return CMD_SUCCESS;
90e60aa7 6071}
6072
6073DEFUN (no_bgp_evpn_vni,
6074 no_bgp_evpn_vni_cmd,
093e3f23 6075 "no vni " CMD_VNI_RANGE,
90e60aa7 6076 NO_STR
6077 "VXLAN Network Identifier\n"
6078 "VNI number\n")
6079{
d62a17ae 6080 vni_t vni;
6081 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6082 struct bgpevpn *vpn;
90e60aa7 6083
d62a17ae 6084 if (!bgp)
6085 return CMD_WARNING;
90e60aa7 6086
d62a17ae 6087 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 6088
d62a17ae 6089 /* Check if we should disallow. */
6090 vpn = bgp_evpn_lookup_vni(bgp, vni);
6091 if (!vpn) {
6092 vty_out(vty, "%% Specified VNI does not exist\n");
6093 return CMD_WARNING;
6094 }
6095 if (!is_vni_configured(vpn)) {
6096 vty_out(vty, "%% Specified VNI is not configured\n");
6097 return CMD_WARNING;
6098 }
90e60aa7 6099
d62a17ae 6100 evpn_delete_vni(bgp, vpn);
6101 return CMD_SUCCESS;
90e60aa7 6102}
6103
6104DEFUN_NOSH (exit_vni,
6105 exit_vni_cmd,
6106 "exit-vni",
6107 "Exit from VNI mode\n")
6108{
d62a17ae 6109 if (vty->node == BGP_EVPN_VNI_NODE)
6110 vty->node = BGP_EVPN_NODE;
6111 return CMD_SUCCESS;
90e60aa7 6112}
6113
676f83b9 6114DEFUN (bgp_evpn_vrf_rd,
6115 bgp_evpn_vrf_rd_cmd,
6116 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
6117 EVPN_RT_DIST_HELP_STR
6118 EVPN_ASN_IP_HELP_STR)
676f83b9 6119{
6120 int ret;
6121 struct prefix_rd prd;
6122 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6123
6124 if (!bgp_vrf)
6125 return CMD_WARNING;
6126
6127 ret = str2prefix_rd(argv[1]->arg, &prd);
6128 if (!ret) {
6129 vty_out(vty, "%% Malformed Route Distinguisher\n");
6130 return CMD_WARNING;
6131 }
6132
6133 /* If same as existing value, there is nothing more to do. */
6134 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
6135 return CMD_SUCCESS;
6136
6137 /* Configure or update the RD. */
fa566a94 6138 evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);
676f83b9 6139 return CMD_SUCCESS;
6140}
6141
6142DEFUN (no_bgp_evpn_vrf_rd,
6143 no_bgp_evpn_vrf_rd_cmd,
6144 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6145 NO_STR
f5dc0b1a
SW
6146 EVPN_RT_DIST_HELP_STR
6147 EVPN_ASN_IP_HELP_STR)
676f83b9 6148{
6149 int ret;
6150 struct prefix_rd prd;
6151 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6152
6153 if (!bgp_vrf)
6154 return CMD_WARNING;
6155
6156 ret = str2prefix_rd(argv[2]->arg, &prd);
6157 if (!ret) {
6158 vty_out(vty, "%% Malformed Route Distinguisher\n");
6159 return CMD_WARNING;
6160 }
6161
6162 /* Check if we should disallow. */
6163 if (!is_vrf_rd_configured(bgp_vrf)) {
6164 vty_out(vty, "%% RD is not configured for this VRF\n");
6165 return CMD_WARNING;
6166 }
6167
6168 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
6169 vty_out(vty,
6170 "%% RD specified does not match configuration for this VRF\n");
6171 return CMD_WARNING;
6172 }
6173
6174 evpn_unconfigure_vrf_rd(bgp_vrf);
6175 return CMD_SUCCESS;
6176}
6177
6178DEFUN (no_bgp_evpn_vrf_rd_without_val,
6179 no_bgp_evpn_vrf_rd_without_val_cmd,
6180 "no rd",
6181 NO_STR
f5dc0b1a 6182 EVPN_RT_DIST_HELP_STR)
676f83b9 6183{
6184 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6185
6186 if (!bgp_vrf)
6187 return CMD_WARNING;
6188
6189 /* Check if we should disallow. */
6190 if (!is_vrf_rd_configured(bgp_vrf)) {
6191 vty_out(vty, "%% RD is not configured for this VRF\n");
6192 return CMD_WARNING;
6193 }
6194
6195 evpn_unconfigure_vrf_rd(bgp_vrf);
6196 return CMD_SUCCESS;
6197}
6198
90e60aa7 6199DEFUN (bgp_evpn_vni_rd,
6200 bgp_evpn_vni_rd_cmd,
d114b977 6201 "rd ASN:NN_OR_IP-ADDRESS:NN",
f5dc0b1a
SW
6202 EVPN_RT_DIST_HELP_STR
6203 EVPN_ASN_IP_HELP_STR)
90e60aa7 6204{
d62a17ae 6205 struct prefix_rd prd;
6206 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6207 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6208 int ret;
90e60aa7 6209
06fe25f4 6210 if (!bgp)
d62a17ae 6211 return CMD_WARNING;
90e60aa7 6212
f920dd6d 6213 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6214 vty_out(vty,
530db8dc 6215 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6216 return CMD_WARNING;
6217 }
6218
d62a17ae 6219 ret = str2prefix_rd(argv[1]->arg, &prd);
6220 if (!ret) {
6221 vty_out(vty, "%% Malformed Route Distinguisher\n");
6222 return CMD_WARNING;
6223 }
90e60aa7 6224
d62a17ae 6225 /* If same as existing value, there is nothing more to do. */
6226 if (bgp_evpn_rd_matches_existing(vpn, &prd))
6227 return CMD_SUCCESS;
90e60aa7 6228
d62a17ae 6229 /* Configure or update the RD. */
fa566a94 6230 evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);
d62a17ae 6231 return CMD_SUCCESS;
90e60aa7 6232}
6233
6234DEFUN (no_bgp_evpn_vni_rd,
6235 no_bgp_evpn_vni_rd_cmd,
d114b977 6236 "no rd ASN:NN_OR_IP-ADDRESS:NN",
90e60aa7 6237 NO_STR
f5dc0b1a
SW
6238 EVPN_RT_DIST_HELP_STR
6239 EVPN_ASN_IP_HELP_STR)
90e60aa7 6240{
d62a17ae 6241 struct prefix_rd prd;
6242 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6243 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6244 int ret;
90e60aa7 6245
06fe25f4 6246 if (!bgp)
d62a17ae 6247 return CMD_WARNING;
90e60aa7 6248
f920dd6d 6249 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6250 vty_out(vty,
530db8dc 6251 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6252 return CMD_WARNING;
6253 }
6254
d62a17ae 6255 ret = str2prefix_rd(argv[2]->arg, &prd);
6256 if (!ret) {
6257 vty_out(vty, "%% Malformed Route Distinguisher\n");
6258 return CMD_WARNING;
6259 }
90e60aa7 6260
d62a17ae 6261 /* Check if we should disallow. */
6262 if (!is_rd_configured(vpn)) {
6263 vty_out(vty, "%% RD is not configured for this VNI\n");
6264 return CMD_WARNING;
6265 }
90e60aa7 6266
d62a17ae 6267 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
6268 vty_out(vty,
6269 "%% RD specified does not match configuration for this VNI\n");
6270 return CMD_WARNING;
6271 }
90e60aa7 6272
d62a17ae 6273 evpn_unconfigure_rd(bgp, vpn);
6274 return CMD_SUCCESS;
90e60aa7 6275}
6276
6277DEFUN (no_bgp_evpn_vni_rd_without_val,
6278 no_bgp_evpn_vni_rd_without_val_cmd,
6279 "no rd",
6280 NO_STR
f5dc0b1a 6281 EVPN_RT_DIST_HELP_STR)
90e60aa7 6282{
d62a17ae 6283 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6284 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 6285
06fe25f4 6286 if (!bgp)
d62a17ae 6287 return CMD_WARNING;
90e60aa7 6288
f920dd6d 6289 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6290 vty_out(vty,
530db8dc 6291 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6292 return CMD_WARNING;
6293 }
6294
d62a17ae 6295 /* Check if we should disallow. */
6296 if (!is_rd_configured(vpn)) {
6297 vty_out(vty, "%% RD is not configured for this VNI\n");
6298 return CMD_WARNING;
6299 }
90e60aa7 6300
d62a17ae 6301 evpn_unconfigure_rd(bgp, vpn);
6302 return CMD_SUCCESS;
90e60aa7 6303}
6304
6305/*
6306 * Loop over all extended-communities in the route-target list rtl and
6307 * return 1 if we find ecomtarget
6308 */
ca337b46
SW
6309static bool bgp_evpn_rt_matches_existing(struct list *rtl,
6310 struct ecommunity *ecomtarget)
90e60aa7 6311{
ca337b46 6312 struct listnode *node;
d62a17ae 6313 struct ecommunity *ecom;
90e60aa7 6314
ca337b46 6315 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
d62a17ae 6316 if (ecommunity_match(ecom, ecomtarget))
ca337b46 6317 return true;
d62a17ae 6318 }
90e60aa7 6319
ca337b46
SW
6320 return false;
6321}
6322
6323/*
6324 * L3 RT version of above.
6325 */
6326static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
6327 struct ecommunity *ecomtarget)
6328{
6329 struct listnode *node;
6330 struct vrf_route_target *l3rt;
6331
6332 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
6333 if (ecommunity_match(l3rt->ecom, ecomtarget))
6334 return true;
6335 }
6336
6337 return false;
90e60aa7 6338}
6339
c581d8b0
MK
6340/* display L3VNI related info for a VRF instance */
6341DEFUN (show_bgp_vrf_l3vni_info,
6342 show_bgp_vrf_l3vni_info_cmd,
4cce389e 6343 "show bgp vrf VRFNAME vni [json]",
c581d8b0
MK
6344 SHOW_STR
6345 BGP_STR
6346 "show bgp vrf\n"
6347 "VRF Name\n"
6348 "L3-VNI\n"
ceb9a921 6349 JSON_STR)
c581d8b0
MK
6350{
6351 char buf[ETHER_ADDR_STRLEN];
6352 int idx_vrf = 3;
6353 const char *name = NULL;
6354 struct bgp *bgp = NULL;
6355 struct listnode *node = NULL;
6a8657d0 6356 struct bgpevpn *vpn = NULL;
ca337b46 6357 struct vrf_route_target *l3rt;
ceb9a921
MK
6358 json_object *json = NULL;
6359 json_object *json_vnis = NULL;
6360 json_object *json_export_rts = NULL;
6361 json_object *json_import_rts = NULL;
9f049418 6362 bool uj = use_json(argc, argv);
ceb9a921
MK
6363
6364 if (uj) {
6365 json = json_object_new_object();
6366 json_vnis = json_object_new_array();
6367 json_export_rts = json_object_new_array();
6368 json_import_rts = json_object_new_array();
6369 }
c581d8b0
MK
6370
6371 name = argv[idx_vrf]->arg;
6372 bgp = bgp_lookup_by_name(name);
4a5271a5 6373 if (strmatch(name, VRF_DEFAULT_NAME))
6374 bgp = bgp_get_default();
6375
c581d8b0 6376 if (!bgp) {
ceb9a921 6377 if (!uj)
4a5271a5 6378 vty_out(vty, "BGP instance for VRF %s not found\n",
6379 name);
ceb9a921
MK
6380 else {
6381 json_object_string_add(json, "warning",
6382 "BGP instance not found");
996c9314 6383 vty_out(vty, "%s\n", json_object_to_json_string(json));
ceb9a921
MK
6384 json_object_free(json);
6385 }
c581d8b0
MK
6386 return CMD_WARNING;
6387 }
6388
ceb9a921
MK
6389 if (!json) {
6390 vty_out(vty, "BGP VRF: %s\n", name);
23d0a753 6391 vty_out(vty, " Local-Ip: %pI4\n", &bgp->originator_ip);
ceb9a921
MK
6392 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
6393 vty_out(vty, " Rmac: %s\n",
6394 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
c48d9f5f
MK
6395 vty_out(vty, " VNI Filter: %s\n",
6396 CHECK_FLAG(bgp->vrf_flags,
996c9314
LB
6397 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6398 ? "prefix-routes-only"
6399 : "none");
ceb9a921
MK
6400 vty_out(vty, " L2-VNI List:\n");
6401 vty_out(vty, " ");
6402 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6403 vty_out(vty, "%u ", vpn->vni);
6404 vty_out(vty, "\n");
6405 vty_out(vty, " Export-RTs:\n");
6406 vty_out(vty, " ");
ca337b46
SW
6407 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6408 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
ceb9a921
MK
6409 vty_out(vty, "\n");
6410 vty_out(vty, " Import-RTs:\n");
6411 vty_out(vty, " ");
ca337b46
SW
6412 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6413 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
ceb9a921 6414 vty_out(vty, "\n");
4a8cd6ad
PG
6415 vty_out(vty, " RD: ");
6416 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd);
6417 vty_out(vty, "\n");
ceb9a921
MK
6418 } else {
6419 json_object_string_add(json, "vrf", name);
c949c771
DA
6420 json_object_string_addf(json, "local-ip", "%pI4",
6421 &bgp->originator_ip);
ceb9a921 6422 json_object_int_add(json, "l3vni", bgp->l3vni);
996c9314
LB
6423 json_object_string_add(
6424 json, "rmac",
6425 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6426 json_object_string_add(
6427 json, "vniFilter",
6428 CHECK_FLAG(bgp->vrf_flags,
6429 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6430 ? "prefix-routes-only"
6431 : "none");
ceb9a921
MK
6432 /* list of l2vnis */
6433 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6434 json_object_array_add(json_vnis,
6435 json_object_new_int(vpn->vni));
6436 json_object_object_add(json, "l2vnis", json_vnis);
6437
6438 /* export rts */
ca337b46 6439 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
996c9314
LB
6440 json_object_array_add(
6441 json_export_rts,
ca337b46
SW
6442 json_object_new_string(
6443 ecommunity_str(l3rt->ecom)));
ceb9a921
MK
6444 json_object_object_add(json, "export-rts", json_export_rts);
6445
6446 /* import rts */
ca337b46 6447 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
996c9314
LB
6448 json_object_array_add(
6449 json_import_rts,
ca337b46
SW
6450 json_object_new_string(
6451 ecommunity_str(l3rt->ecom)));
ceb9a921 6452 json_object_object_add(json, "import-rts", json_import_rts);
4a8cd6ad
PG
6453 json_object_string_addf(json, "rd",
6454 BGP_RD_AS_FORMAT(bgp->asnotation),
6455 &bgp->vrf_prd);
ceb9a921 6456 }
c581d8b0 6457
c48349e3 6458 if (uj)
75eeda93 6459 vty_json(vty, json);
c581d8b0
MK
6460 return CMD_SUCCESS;
6461}
6462
58d8948c
SW
6463static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
6464 bool is_wildcard)
7022da35
SW
6465{
6466 /* Do nothing if we already have this route-target */
6467 if (is_import) {
ca337b46
SW
6468 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6469 ecom))
58d8948c
SW
6470 bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
6471 is_wildcard);
7022da35
SW
6472 else
6473 return -1;
6474 } else {
ca337b46
SW
6475 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6476 ecom))
7022da35
SW
6477 bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
6478 else
6479 return -1;
6480 }
6481
6482 return 0;
6483}
6484
6485static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
6486{
6487 /* Verify we already have this route-target */
6488 if (is_import) {
ca337b46
SW
6489 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6490 ecom))
7022da35
SW
6491 return -1;
6492
6493 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
6494 } else {
ca337b46
SW
6495 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6496 ecom))
7022da35
SW
6497 return -1;
6498
6499 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
6500 }
6501
6502 return 0;
6503}
6504
6505static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
6506 struct cmd_token **argv, int rt_idx, bool is_add,
6507 bool is_import)
6508{
6509 int ret = CMD_SUCCESS;
58d8948c 6510 bool is_wildcard = false;
7022da35
SW
6511 struct ecommunity *ecom = NULL;
6512
6513 for (int i = rt_idx; i < argc; i++) {
58d8948c
SW
6514 is_wildcard = false;
6515
6516 /*
6517 * Special handling for wildcard '*' here.
6518 *
6519 * Let's just convert it to 0 here so we dont have to modify
6520 * the ecommunity parser.
6521 */
6522 if ((argv[i]->arg)[0] == '*') {
58d8948c
SW
6523 (argv[i]->arg)[0] = '0';
6524 is_wildcard = true;
6525 }
6526
7022da35
SW
6527 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
6528 0);
6529
58d8948c
SW
6530 /* Put it back as was */
6531 if (is_wildcard)
6532 (argv[i]->arg)[0] = '*';
6533
7022da35
SW
6534 if (!ecom) {
6535 vty_out(vty, "%% Malformed Route Target list\n");
6536 ret = CMD_WARNING;
6537 continue;
6538 }
6539
6540 ecommunity_str(ecom);
6541
6542 if (is_add) {
58d8948c 6543 if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
7022da35
SW
6544 vty_out(vty,
6545 "%% RT specified already configured for this VRF: %s\n",
6546 argv[i]->arg);
6547 ecommunity_free(&ecom);
6548 ret = CMD_WARNING;
6549 }
6550
6551 } else {
6552 if (del_rt(bgp, ecom, is_import) != 0) {
6553 vty_out(vty,
6554 "%% RT specified does not match configuration for this VRF: %s\n",
6555 argv[i]->arg);
6556 ret = CMD_WARNING;
6557 }
6558
6559 ecommunity_free(&ecom);
6560 }
6561 }
6562
6563 return ret;
6564}
6565
c581d8b0
MK
6566/* import/export rt for l3vni-vrf */
6567DEFUN (bgp_evpn_vrf_rt,
6568 bgp_evpn_vrf_rt_cmd,
7022da35 6569 "route-target <both|import|export> RTLIST...",
c581d8b0
MK
6570 "Route Target\n"
6571 "import and export\n"
6572 "import\n"
6573 "export\n"
58d8948c 6574 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
c581d8b0 6575{
7022da35
SW
6576 int ret = CMD_SUCCESS;
6577 int tmp_ret = CMD_SUCCESS;
c581d8b0
MK
6578 int rt_type;
6579 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
c581d8b0
MK
6580
6581 if (!bgp)
7022da35 6582 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6583
6584 if (!strcmp(argv[1]->arg, "import"))
6585 rt_type = RT_TYPE_IMPORT;
6586 else if (!strcmp(argv[1]->arg, "export"))
6587 rt_type = RT_TYPE_EXPORT;
6588 else if (!strcmp(argv[1]->arg, "both"))
6589 rt_type = RT_TYPE_BOTH;
6590 else {
6591 vty_out(vty, "%% Invalid Route Target type\n");
7022da35 6592 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6593 }
6594
58d8948c
SW
6595 if (strmatch(argv[2]->arg, "auto")) {
6596 vty_out(vty, "%% `auto` cannot be configured via list\n");
6597 return CMD_WARNING_CONFIG_FAILED;
3b7e8d0f 6598 }
3b7e8d0f 6599
7231b9ab 6600 if (rt_type != RT_TYPE_IMPORT) {
6601 for (int i = 2; i < argc; i++) {
6602 if ((argv[i]->arg)[0] == '*') {
6603 vty_out(vty,
6604 "%% Wildcard '*' only applicable for import\n");
6605 return CMD_WARNING_CONFIG_FAILED;
6606 }
6607 }
6608 }
6609
c581d8b0 6610 /* Add/update the import route-target */
7022da35
SW
6611 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6612 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
c581d8b0 6613
7022da35
SW
6614 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6615 ret = tmp_ret;
c581d8b0 6616
7022da35
SW
6617 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6618 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
6619
6620 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6621 ret = tmp_ret;
6622
6623 return ret;
6624}
6625
a5d7012c 6626DEFPY (bgp_evpn_vrf_rt_auto,
7022da35 6627 bgp_evpn_vrf_rt_auto_cmd,
a5d7012c 6628 "route-target <both|import|export>$type auto",
7022da35
SW
6629 "Route Target\n"
6630 "import and export\n"
6631 "import\n"
6632 "export\n"
6633 "Automatically derive route target\n")
6634{
58d8948c
SW
6635 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6636 int rt_type;
6637
6638 if (!bgp)
6639 return CMD_WARNING_CONFIG_FAILED;
6640
a5d7012c 6641 if (strmatch(type, "import"))
58d8948c 6642 rt_type = RT_TYPE_IMPORT;
a5d7012c 6643 else if (strmatch(type, "export"))
58d8948c 6644 rt_type = RT_TYPE_EXPORT;
a5d7012c 6645 else if (strmatch(type, "both"))
58d8948c
SW
6646 rt_type = RT_TYPE_BOTH;
6647 else {
6648 vty_out(vty, "%% Invalid Route Target type\n");
6649 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6650 }
6651
58d8948c
SW
6652 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6653 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6654
6655 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6656 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6657
c581d8b0
MK
6658 return CMD_SUCCESS;
6659}
6660
6661DEFUN (no_bgp_evpn_vrf_rt,
6662 no_bgp_evpn_vrf_rt_cmd,
7022da35 6663 "no route-target <both|import|export> RTLIST...",
c581d8b0
MK
6664 NO_STR
6665 "Route Target\n"
6666 "import and export\n"
6667 "import\n"
6668 "export\n"
7022da35 6669 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
c581d8b0
MK
6670{
6671 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7022da35
SW
6672 int ret = CMD_SUCCESS;
6673 int tmp_ret = CMD_SUCCESS;
6674 int rt_type;
c581d8b0
MK
6675
6676 if (!bgp)
58d8948c 6677 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6678
6679 if (!strcmp(argv[2]->arg, "import"))
6680 rt_type = RT_TYPE_IMPORT;
6681 else if (!strcmp(argv[2]->arg, "export"))
6682 rt_type = RT_TYPE_EXPORT;
6683 else if (!strcmp(argv[2]->arg, "both"))
6684 rt_type = RT_TYPE_BOTH;
6685 else {
6686 vty_out(vty, "%% Invalid Route Target type\n");
7022da35 6687 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6688 }
6689
58d8948c
SW
6690 if (!strcmp(argv[3]->arg, "auto")) {
6691 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6692 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6693 }
6694
6695 if (rt_type == RT_TYPE_IMPORT) {
6696 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6697 vty_out(vty,
6698 "%% Import RT is not configured for this VRF\n");
58d8948c 6699 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6700 }
6701 } else if (rt_type == RT_TYPE_EXPORT) {
6702 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6703 vty_out(vty,
6704 "%% Export RT is not configured for this VRF\n");
58d8948c 6705 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6706 }
6707 } else if (rt_type == RT_TYPE_BOTH) {
6708 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6709 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6710 vty_out(vty,
6711 "%% Import/Export RT is not configured for this VRF\n");
58d8948c 6712 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6713 }
6714 }
6715
7231b9ab 6716 if (rt_type != RT_TYPE_IMPORT) {
6717 for (int i = 3; i < argc; i++) {
6718 if ((argv[i]->arg)[0] == '*') {
6719 vty_out(vty,
6720 "%% Wildcard '*' only applicable for import\n");
6721 return CMD_WARNING_CONFIG_FAILED;
6722 }
6723 }
6724 }
6725
7022da35
SW
6726 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6727 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
c581d8b0 6728
7022da35
SW
6729 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6730 ret = tmp_ret;
c581d8b0 6731
7022da35
SW
6732 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6733 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
c581d8b0 6734
7022da35
SW
6735 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6736 ret = tmp_ret;
c581d8b0 6737
7022da35
SW
6738 return ret;
6739}
c581d8b0 6740
a5d7012c 6741DEFPY (no_bgp_evpn_vrf_rt_auto,
7022da35 6742 no_bgp_evpn_vrf_rt_auto_cmd,
a5d7012c 6743 "no route-target <both|import|export>$type auto",
7022da35
SW
6744 NO_STR
6745 "Route Target\n"
6746 "import and export\n"
6747 "import\n"
6748 "export\n"
6749 "Automatically derive route target\n")
6750{
58d8948c
SW
6751 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6752 int rt_type;
6753
6754 if (!bgp)
6755 return CMD_WARNING_CONFIG_FAILED;
6756
a5d7012c 6757 if (strmatch(type, "import"))
58d8948c 6758 rt_type = RT_TYPE_IMPORT;
a5d7012c 6759 else if (strmatch(type, "export"))
58d8948c 6760 rt_type = RT_TYPE_EXPORT;
a5d7012c 6761 else if (strmatch(type, "both"))
58d8948c
SW
6762 rt_type = RT_TYPE_BOTH;
6763 else {
6764 vty_out(vty, "%% Invalid Route Target type\n");
6765 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6766 }
c581d8b0
MK
6767
6768 if (rt_type == RT_TYPE_IMPORT) {
58d8948c 6769 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
c581d8b0 6770 vty_out(vty,
58d8948c
SW
6771 "%% Import AUTO RT is not configured for this VRF\n");
6772 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6773 }
c581d8b0 6774 } else if (rt_type == RT_TYPE_EXPORT) {
58d8948c 6775 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
c581d8b0 6776 vty_out(vty,
58d8948c
SW
6777 "%% Export AUTO RT is not configured for this VRF\n");
6778 return CMD_WARNING_CONFIG_FAILED;
c581d8b0 6779 }
c581d8b0 6780 } else if (rt_type == RT_TYPE_BOTH) {
58d8948c
SW
6781 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6782 !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
c581d8b0 6783 vty_out(vty,
58d8948c
SW
6784 "%% Import/Export AUTO RT is not configured for this VRF\n");
6785 return CMD_WARNING_CONFIG_FAILED;
c581d8b0
MK
6786 }
6787 }
6788
58d8948c
SW
6789 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6790 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6791
6792 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6793 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6794
c581d8b0
MK
6795 return CMD_SUCCESS;
6796}
90e60aa7 6797
bb37eabe
AK
6798DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6799 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6800 NO_STR
6801 "EAD ES fragment config\n"
6802 "EVIs per-fragment\n"
6803 "limit\n")
6804{
6805 bgp_mh_info->evi_per_es_frag =
6806 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6807
6808 return CMD_SUCCESS;
6809}
6810
f4a5218d
AK
6811DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6812 "ead-es-route-target export RT",
6813 "EAD ES Route Target\n"
6814 "export\n"
6815 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6816{
6817 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6818 struct ecommunity *ecomadd = NULL;
6819
6820 if (!bgp)
6821 return CMD_WARNING;
6822
6823 if (!EVPN_ENABLED(bgp)) {
6824 vty_out(vty, "This command is only supported under EVPN VRF\n");
6825 return CMD_WARNING;
6826 }
6827
6828 /* Add/update the export route-target */
6829 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6830 if (!ecomadd) {
6831 vty_out(vty, "%% Malformed Route Target list\n");
6832 return CMD_WARNING;
6833 }
6834 ecommunity_str(ecomadd);
6835
6836 /* Do nothing if we already have this export route-target */
6837 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6838 ecomadd))
6839 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6840
6841 return CMD_SUCCESS;
6842}
6843
6844DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6845 "no ead-es-route-target export RT",
6846 NO_STR
6847 "EAD ES Route Target\n"
6848 "export\n" EVPN_ASN_IP_HELP_STR)
6849{
6850 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6851 struct ecommunity *ecomdel = NULL;
6852
6853 if (!bgp)
6854 return CMD_WARNING;
6855
6856 if (!EVPN_ENABLED(bgp)) {
6857 vty_out(vty, "This command is only supported under EVPN VRF\n");
6858 return CMD_WARNING;
6859 }
6860
6861 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6862 if (!ecomdel) {
6863 vty_out(vty, "%% Malformed Route Target list\n");
6864 return CMD_WARNING;
6865 }
6866 ecommunity_str(ecomdel);
6867
6868 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6869 ecomdel)) {
df6a97a6 6870 ecommunity_free(&ecomdel);
f4a5218d
AK
6871 vty_out(vty,
6872 "%% RT specified does not match EAD-ES RT configuration\n");
6873 return CMD_WARNING;
6874 }
6875 bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6876
6877 return CMD_SUCCESS;
6878}
6879
90e60aa7 6880DEFUN (bgp_evpn_vni_rt,
6881 bgp_evpn_vni_rt_cmd,
6882 "route-target <both|import|export> RT",
6883 "Route Target\n"
6884 "import and export\n"
6885 "import\n"
6886 "export\n"
6887 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6888{
d62a17ae 6889 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6890 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6891 int rt_type;
6892 struct ecommunity *ecomadd = NULL;
6893
06fe25f4 6894 if (!bgp)
d62a17ae 6895 return CMD_WARNING;
6896
f920dd6d 6897 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6898 vty_out(vty,
530db8dc 6899 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6900 return CMD_WARNING;
6901 }
6902
8034beff 6903 if (!strcmp(argv[1]->text, "import"))
d62a17ae 6904 rt_type = RT_TYPE_IMPORT;
8034beff 6905 else if (!strcmp(argv[1]->text, "export"))
d62a17ae 6906 rt_type = RT_TYPE_EXPORT;
8034beff 6907 else if (!strcmp(argv[1]->text, "both"))
d62a17ae 6908 rt_type = RT_TYPE_BOTH;
6909 else {
6910 vty_out(vty, "%% Invalid Route Target type\n");
6911 return CMD_WARNING;
6912 }
6913
6914 /* Add/update the import route-target */
6915 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
432ff4b0 6916 /* Note that first of the two RTs is created for "both" type */
6917 ecomadd = ecommunity_str2com(argv[2]->arg,
6918 ECOMMUNITY_ROUTE_TARGET, 0);
6919 if (!ecomadd) {
6920 vty_out(vty, "%% Malformed Route Target list\n");
6921 return CMD_WARNING;
6922 }
6923 ecommunity_str(ecomadd);
6924
d62a17ae 6925 /* Do nothing if we already have this import route-target */
6926 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6927 evpn_configure_import_rt(bgp, vpn, ecomadd);
6928 }
6929
6930 /* Add/update the export route-target */
6931 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
432ff4b0 6932 /* Note that second 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 export route-target */
6942 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6943 evpn_configure_export_rt(bgp, vpn, ecomadd);
6944 }
6945
6946 return CMD_SUCCESS;
90e60aa7 6947}
6948
6949DEFUN (no_bgp_evpn_vni_rt,
6950 no_bgp_evpn_vni_rt_cmd,
6951 "no route-target <both|import|export> RT",
6952 NO_STR
6953 "Route Target\n"
6954 "import and export\n"
6955 "import\n"
6956 "export\n"
f5dc0b1a 6957 EVPN_ASN_IP_HELP_STR)
90e60aa7 6958{
d62a17ae 6959 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6960 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6961 int rt_type, found_ecomdel;
6962 struct ecommunity *ecomdel = NULL;
6963
06fe25f4 6964 if (!bgp)
d62a17ae 6965 return CMD_WARNING;
6966
f920dd6d 6967 if (!EVPN_ENABLED(bgp)) {
a2a8153f 6968 vty_out(vty,
530db8dc 6969 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
6970 return CMD_WARNING;
6971 }
6972
8034beff 6973 if (!strcmp(argv[2]->text, "import"))
d62a17ae 6974 rt_type = RT_TYPE_IMPORT;
8034beff 6975 else if (!strcmp(argv[2]->text, "export"))
d62a17ae 6976 rt_type = RT_TYPE_EXPORT;
8034beff 6977 else if (!strcmp(argv[2]->text, "both"))
d62a17ae 6978 rt_type = RT_TYPE_BOTH;
6979 else {
6980 vty_out(vty, "%% Invalid Route Target type\n");
6981 return CMD_WARNING;
6982 }
6983
6984 /* The user did "no route-target import", check to see if there are any
6985 * import route-targets configured. */
6986 if (rt_type == RT_TYPE_IMPORT) {
6987 if (!is_import_rt_configured(vpn)) {
6988 vty_out(vty,
6989 "%% Import RT is not configured for this VNI\n");
6990 return CMD_WARNING;
6991 }
6992 } else if (rt_type == RT_TYPE_EXPORT) {
6993 if (!is_export_rt_configured(vpn)) {
6994 vty_out(vty,
6995 "%% Export RT is not configured for this VNI\n");
6996 return CMD_WARNING;
6997 }
6998 } else if (rt_type == RT_TYPE_BOTH) {
6999 if (!is_import_rt_configured(vpn)
7000 && !is_export_rt_configured(vpn)) {
7001 vty_out(vty,
7002 "%% Import/Export RT is not configured for this VNI\n");
7003 return CMD_WARNING;
7004 }
7005 }
7006
7007 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 7008 if (!ecomdel) {
7009 vty_out(vty, "%% Malformed Route Target list\n");
7010 return CMD_WARNING;
7011 }
5bc2ed52 7012 ecommunity_str(ecomdel);
d62a17ae 7013
7014 if (rt_type == RT_TYPE_IMPORT) {
7015 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
df6a97a6 7016 ecommunity_free(&ecomdel);
d62a17ae 7017 vty_out(vty,
7018 "%% RT specified does not match configuration for this VNI\n");
7019 return CMD_WARNING;
7020 }
7021 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7022 } else if (rt_type == RT_TYPE_EXPORT) {
7023 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
df6a97a6 7024 ecommunity_free(&ecomdel);
d62a17ae 7025 vty_out(vty,
7026 "%% RT specified does not match configuration for this VNI\n");
7027 return CMD_WARNING;
7028 }
7029 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7030 } else if (rt_type == RT_TYPE_BOTH) {
7031 found_ecomdel = 0;
7032
7033 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7034 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7035 found_ecomdel = 1;
7036 }
7037
7038 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7039 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7040 found_ecomdel = 1;
7041 }
7042
7043 if (!found_ecomdel) {
df6a97a6 7044 ecommunity_free(&ecomdel);
d62a17ae 7045 vty_out(vty,
7046 "%% RT specified does not match configuration for this VNI\n");
7047 return CMD_WARNING;
7048 }
7049 }
7050
7051 return CMD_SUCCESS;
90e60aa7 7052}
7053
7054DEFUN (no_bgp_evpn_vni_rt_without_val,
7055 no_bgp_evpn_vni_rt_without_val_cmd,
7056 "no route-target <import|export>",
7057 NO_STR
7058 "Route Target\n"
7059 "import\n"
7060 "export\n")
7061{
d62a17ae 7062 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7063 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
7064 int rt_type;
7065
06fe25f4 7066 if (!bgp)
d62a17ae 7067 return CMD_WARNING;
7068
f920dd6d 7069 if (!EVPN_ENABLED(bgp)) {
a2a8153f 7070 vty_out(vty,
530db8dc 7071 "This command is only supported under EVPN VRF\n");
a2a8153f
CS
7072 return CMD_WARNING;
7073 }
7074
8034beff 7075 if (!strcmp(argv[2]->text, "import")) {
d62a17ae 7076 rt_type = RT_TYPE_IMPORT;
8034beff 7077 } else if (!strcmp(argv[2]->text, "export")) {
d62a17ae 7078 rt_type = RT_TYPE_EXPORT;
7079 } else {
7080 vty_out(vty, "%% Invalid Route Target type\n");
7081 return CMD_WARNING;
7082 }
7083
7084 /* Check if we should disallow. */
7085 if (rt_type == RT_TYPE_IMPORT) {
7086 if (!is_import_rt_configured(vpn)) {
7087 vty_out(vty,
7088 "%% Import RT is not configured for this VNI\n");
7089 return CMD_WARNING;
7090 }
7091 } else {
7092 if (!is_export_rt_configured(vpn)) {
7093 vty_out(vty,
7094 "%% Export RT is not configured for this VNI\n");
7095 return CMD_WARNING;
7096 }
7097 }
7098
7099 /* Unconfigure the RT. */
7100 if (rt_type == RT_TYPE_IMPORT)
7101 evpn_unconfigure_import_rt(bgp, vpn, NULL);
7102 else
7103 evpn_unconfigure_export_rt(bgp, vpn, NULL);
7104 return CMD_SUCCESS;
90e60aa7 7105}
568b6b44
QY
7106
7107static int vni_cmp(const void **a, const void **b)
7108{
7109 const struct bgpevpn *first = *a;
7110 const struct bgpevpn *secnd = *b;
7111
7112 return secnd->vni - first->vni;
7113}
7114
90e60aa7 7115/*
7116 * Output EVPN configuration information.
7117 */
d62a17ae 7118void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
2b791107 7119 safi_t safi)
d62a17ae 7120{
e67df34d
CS
7121 if (bgp->advertise_all_vni)
7122 vty_out(vty, " advertise-all-vni\n");
7123
f33bf7c0 7124 if (hashcount(bgp->vnihash)) {
568b6b44
QY
7125 struct list *vnilist = hash_to_list(bgp->vnihash);
7126 struct listnode *ln;
7127 struct bgpevpn *data;
7128
7129 list_sort(vnilist, vni_cmp);
7130 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
7131 write_vni_config(vty, data);
7132
6a154c88 7133 list_delete(&vnilist);
568b6b44 7134 }
90e60aa7 7135
bf1061d8
VB
7136 if (bgp->advertise_autort_rfc8365)
7137 vty_out(vty, " autort rfc8365-compatible\n");
7138
2b791107 7139 if (bgp->advertise_gw_macip)
1a98c087 7140 vty_out(vty, " advertise-default-gw\n");
6ee86383 7141
24864e44
CS
7142 if (bgp->evpn_info->advertise_svi_macip)
7143 vty_out(vty, " advertise-svi-ip\n");
7144
dc6cef73
AD
7145 if (bgp->resolve_overlay_index)
7146 vty_out(vty, " enable-resolve-overlay-index\n");
7147
bb37eabe
AK
7148 if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
7149 vty_out(vty, " ead-es-frag evi-limit %u\n",
7150 bgp_mh_info->evi_per_es_frag);
7151
2867823e
AK
7152 if (bgp_mh_info->host_routes_use_l3nhg !=
7153 BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
7154 if (bgp_mh_info->host_routes_use_l3nhg)
7155 vty_out(vty, " use-es-l3nhg\n");
7156 else
7157 vty_out(vty, " no use-es-l3nhg\n");
7158 }
7159
fe8293c3
AK
7160 if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
7161 if (bgp_mh_info->ead_evi_rx)
7162 vty_out(vty, " no disable-ead-evi-rx\n");
7163 else
7164 vty_out(vty, " disable-ead-evi-rx\n");
7165 }
7166
7167 if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
7168 if (bgp_mh_info->ead_evi_tx)
7169 vty_out(vty, " no disable-ead-evi-tx\n");
7170 else
7171 vty_out(vty, " disable-ead-evi-tx\n");
7172 }
7173
0b9d9cd0
CS
7174 if (!bgp->evpn_info->dup_addr_detect)
7175 vty_out(vty, " no dup-addr-detection\n");
7176
7177 if (bgp->evpn_info->dad_max_moves !=
7178 EVPN_DAD_DEFAULT_MAX_MOVES ||
7179 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
7180 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
7181 bgp->evpn_info->dad_max_moves,
7182 bgp->evpn_info->dad_time);
7183
7184 if (bgp->evpn_info->dad_freeze) {
7185 if (bgp->evpn_info->dad_freeze_time)
7186 vty_out(vty,
7187 " dup-addr-detection freeze %u\n",
7188 bgp->evpn_info->dad_freeze_time);
7189 else
7190 vty_out(vty,
7191 " dup-addr-detection freeze permanent\n");
7192 }
7193
fd069644
DS
7194 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
7195 vty_out(vty, " flooding disable\n");
7196
154faa50 7197 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3 7198 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
d2a0075a
MK
7199 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7200 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
7201 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7202 else
d4a88de3
AD
7203 vty_out(vty,
7204 " advertise ipv4 unicast\n");
7205 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
7207 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7208 vty_out(vty,
7209 " advertise ipv4 unicast gateway-ip route-map %s\n",
7210 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7211 else
7212 vty_out(vty, " advertise ipv4 unicast gateway-ip\n");
d2a0075a 7213 }
6ee86383 7214
f4a5218d
AK
7215 /* EAD ES export route-target */
7216 if (listcount(bgp_mh_info->ead_es_export_rtl)) {
7217 struct ecommunity *ecom;
7218 char *ecom_str;
7219 struct listnode *node;
7220
7221 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
7222 ecom)) {
7223
7224 ecom_str = ecommunity_ecom2str(
7225 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7226 vty_out(vty, " ead-es-route-target export %s\n",
7227 ecom_str);
7228 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7229 }
7230 }
7231
154faa50 7232 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
d4a88de3 7233 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
d2a0075a 7234 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
d4a88de3
AD
7235 vty_out(vty,
7236 " advertise ipv6 unicast route-map %s\n",
7237 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7238 else
7239 vty_out(vty,
7240 " advertise ipv6 unicast\n");
7241 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7242 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
7243 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7244 vty_out(vty,
7245 " advertise ipv6 unicast gateway-ip route-map %s\n",
d2a0075a
MK
7246 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7247 else
d4a88de3 7248 vty_out(vty, " advertise ipv6 unicast gateway-ip\n");
d2a0075a 7249 }
486456ca
MK
7250
7251 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7252 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
7253 vty_out(vty, " default-originate ipv4\n");
7254
7255 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7256 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
7257 vty_out(vty, " default-originate ipv6\n");
58f9e4d3 7258
5394a276
CS
7259 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
7260 if (!bgp->evpn_info->advertise_pip)
7261 vty_out(vty, " no advertise-pip\n");
7262 if (bgp->evpn_info->advertise_pip) {
0137a3d8
CS
7263 if (bgp->evpn_info->pip_ip_static.s_addr
7264 != INADDR_ANY) {
07380148
DA
7265 vty_out(vty, " advertise-pip ip %pI4",
7266 &bgp->evpn_info->pip_ip_static);
0137a3d8
CS
7267 if (!is_zero_mac(&(
7268 bgp->evpn_info->pip_rmac_static))) {
7269 char buf[ETHER_ADDR_STRLEN];
7270
7271 vty_out(vty, " mac %s",
7272 prefix_mac2str(
7273 &bgp->evpn_info
7274 ->pip_rmac,
7275 buf, sizeof(buf)));
7276 }
7277 vty_out(vty, "\n");
5394a276 7278 }
5394a276
CS
7279 }
7280 }
a75c2553 7281 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
fa566a94 7282 vty_out(vty, " rd %s\n", bgp->vrf_prd_pretty);
a75c2553 7283
db29a4a8
MK
7284 /* import route-target */
7285 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
7286 char *ecom_str;
7287 struct listnode *node, *nnode;
ca337b46 7288 struct vrf_route_target *l3rt;
db29a4a8
MK
7289
7290 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
ca337b46 7291 l3rt)) {
58d8948c
SW
7292
7293 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7294 continue;
7295
db29a4a8 7296 ecom_str = ecommunity_ecom2str(
ca337b46 7297 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
58d8948c
SW
7298
7299 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
7300 char *vni_str = NULL;
7301
20e81e18 7302 vni_str = strchr(ecom_str, ':');
ed8862ad 7303 if (!vni_str) {
7304 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7305 continue;
7306 }
58d8948c 7307
20e81e18
SW
7308 /* Move pointer to vni */
7309 vni_str += 1;
7310
58d8948c
SW
7311 vty_out(vty, " route-target import *:%s\n",
7312 vni_str);
7313
7314 } else
7315 vty_out(vty, " route-target import %s\n",
7316 ecom_str);
7317
db29a4a8
MK
7318 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7319 }
7320 }
7321
58d8948c
SW
7322 /* import route-target auto */
7323 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
7324 vty_out(vty, " route-target import auto\n");
7325
db29a4a8
MK
7326 /* export route-target */
7327 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
7328 char *ecom_str;
7329 struct listnode *node, *nnode;
ca337b46 7330 struct vrf_route_target *l3rt;
db29a4a8
MK
7331
7332 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
ca337b46 7333 l3rt)) {
58d8948c
SW
7334
7335 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7336 continue;
7337
db29a4a8 7338 ecom_str = ecommunity_ecom2str(
ca337b46 7339 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
530e8a6e 7340 vty_out(vty, " route-target export %s\n", ecom_str);
db29a4a8
MK
7341 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7342 }
7343 }
58d8948c
SW
7344
7345 /* export route-target auto */
7346 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
7347 vty_out(vty, " route-target export auto\n");
90e60aa7 7348}
7349
4d0e6ece 7350void bgp_ethernetvpn_init(void)
784d3a42 7351{
d62a17ae 7352 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
7353 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
7354 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
7355 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
7356 install_element(VIEW_NODE,
dcc1615e 7357 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
d62a17ae 7358 install_element(VIEW_NODE,
7359 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
7360 install_element(
7361 VIEW_NODE,
dcc1615e 7362 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
d62a17ae 7363 install_element(
7364 VIEW_NODE,
7365 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
7366 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
7367 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
7368 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
7369 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
d62a17ae 7370 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
7371 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
bf1061d8
VB
7372 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
7373 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
1a98c087
MK
7374 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
7375 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
24864e44 7376 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
342dd0c6 7377 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
7378 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
486456ca
MK
7379 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
7380 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
0b9d9cd0
CS
7381 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
7382 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
7383 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
fd069644 7384 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5394a276 7385 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
2867823e 7386 install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
fe8293c3
AK
7387 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
7388 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
dc6cef73
AD
7389 install_element(BGP_EVPN_NODE,
7390 &bgp_evpn_enable_resolve_overlay_index_cmd);
d62a17ae 7391
50f74cf1 7392 /* test commands */
b5e140c8
AK
7393 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
7394 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
50f74cf1 7395
f2d62262 7396 /* "show bgp l2vpn evpn" commands. */
50f74cf1 7397 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
b5e140c8 7398 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
229587fb 7399 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
090efa2f 7400 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
f2d62262 7401 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
021b6596
AD
7402 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
7403 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
f2d62262 7404 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
7405 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
7406 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
7407 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
50f74cf1 7408 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
f2d62262 7409 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
7410 install_element(VIEW_NODE,
7411 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
7412 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
7413 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
d656e0ae
AK
7414 install_element(VIEW_NODE,
7415 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
58bff4d1
AK
7416 install_element(VIEW_NODE,
7417 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
f2d62262 7418 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
10ebe1ab 7419 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
d62a17ae 7420
852d9f97
SW
7421 /* "show bgp vni" commands. */
7422 install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
7423 install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
7424 install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
7425 install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
7426 install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
7427 install_element(VIEW_NODE, &show_bgp_vni_cmd);
7428 install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
7429 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
7430 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
7431 install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
7432 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
7433 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
7434
5014d96f
DW
7435 /* "show bgp evpn" commands. */
7436 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
7437 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
7438 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
7439 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
7440 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
7441 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
7442 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
7443 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
7444 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
7445 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
c581d8b0 7446 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7f433a5e 7447 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
5014d96f 7448
d62a17ae 7449 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
7450 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
7451 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
7452 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
7453 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
7454 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
7455 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
7456 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
7457 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
bf48830b
MK
7458 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
7459 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
676f83b9 7460 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
df399d1c
MK
7461 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
7462 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
7022da35
SW
7463 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
7464 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
f4a5218d
AK
7465 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
7466 install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
bb37eabe 7467 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
24864e44 7468 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
1a98c087
MK
7469 install_element(BGP_EVPN_VNI_NODE,
7470 &bgp_evpn_advertise_default_gw_vni_cmd);
7471 install_element(BGP_EVPN_VNI_NODE,
7472 &no_bgp_evpn_advertise_default_gw_vni_cmd);
31310b25
MK
7473 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
7474 install_element(BGP_EVPN_VNI_NODE,
7475 &no_bgp_evpn_advertise_vni_subnet_cmd);
784d3a42 7476}