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