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