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