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