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