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