]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn_vty.c
bgpd: display hostname capabilities as advertised and received
[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"
25
26#include "bgpd/bgpd.h"
27#include "bgpd/bgp_table.h"
28#include "bgpd/bgp_attr.h"
29#include "bgpd/bgp_route.h"
30#include "bgpd/bgp_mplsvpn.h"
31#include "bgpd/bgp_vpn.h"
32#include "bgpd/bgp_evpn_vty.h"
3da6fcd5 33#include "bgpd/bgp_evpn.h"
7724c0a1 34#include "bgpd/bgp_evpn_private.h"
35#include "bgpd/bgp_zebra.h"
520d5d76 36#include "bgpd/bgp_vty.h"
784d3a42 37
784d3a42
PG
38#define SHOW_DISPLAY_STANDARD 0
39#define SHOW_DISPLAY_TAGS 1
40#define SHOW_DISPLAY_OVERLAY 2
9c92b5f7 41#define VNI_STR_LEN 32
784d3a42 42
520d5d76 43/*
44 * Context for VNI hash walk - used by callbacks.
45 */
d62a17ae 46struct vni_walk_ctx {
47 struct bgp *bgp;
48 struct vty *vty;
49 struct in_addr vtep_ip;
9c92b5f7 50 json_object *json;
520d5d76 51};
52
d62a17ae 53struct evpn_config_write {
54 int write;
55 struct vty *vty;
90e60aa7 56};
57
d62a17ae 58#if defined(HAVE_CUMULUS)
9c92b5f7
MK
59static void display_import_rt(struct vty *vty, struct irt_node *irt,
60 json_object *json)
d62a17ae 61{
62 u_char *pnt;
63 u_char type, sub_type;
64 struct ecommunity_as {
65 as_t as;
66 u_int32_t val;
67 } eas;
68 struct ecommunity_ip {
69 struct in_addr ip;
70 u_int16_t val;
71 } eip;
72 struct listnode *node, *nnode;
73 struct bgpevpn *tmp_vpn;
9c92b5f7
MK
74 json_object *json_rt = NULL;
75 json_object *json_vnis = NULL;
76 char rt_buf[RT_ADDRSTRLEN];
d62a17ae 77
9c92b5f7
MK
78 if (json) {
79 json_rt = json_object_new_object ();
80 json_vnis = json_object_new_array ();
81 }
d62a17ae 82
83 /* TODO: This needs to go into a function */
84
85 pnt = (u_char *)&irt->rt.val;
86 type = *pnt++;
87 sub_type = *pnt++;
88 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
89 return;
90
91 switch (type) {
92 case ECOMMUNITY_ENCODE_AS:
93 eas.as = (*pnt++ << 8);
94 eas.as |= (*pnt++);
95
96 eas.val = (*pnt++ << 24);
97 eas.val |= (*pnt++ << 16);
98 eas.val |= (*pnt++ << 8);
99 eas.val |= (*pnt++);
100
9c92b5f7
MK
101 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
102
103 if (json)
104 json_object_string_add(json_rt, "rt", rt_buf);
105 else
106 vty_out(vty, "Route-target: %s", rt_buf);
107
d62a17ae 108 break;
109
110 case ECOMMUNITY_ENCODE_IP:
111 memcpy(&eip.ip, pnt, 4);
112 pnt += 4;
113 eip.val = (*pnt++ << 8);
114 eip.val |= (*pnt++);
115
9c92b5f7
MK
116 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
117 eip.val);
118
119 if (json)
120 json_object_string_add(json_rt, "rt", rt_buf);
121 else
122 vty_out(vty, "Route-target: %s", rt_buf);
123
d62a17ae 124 break;
125
126 case ECOMMUNITY_ENCODE_AS4:
127 eas.as = (*pnt++ << 24);
128 eas.as |= (*pnt++ << 16);
129 eas.as |= (*pnt++ << 8);
130 eas.as |= (*pnt++);
131
132 eas.val = (*pnt++ << 8);
133 eas.val |= (*pnt++);
134
9c92b5f7
MK
135 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
136
137 if (json)
138 json_object_string_add(json_rt, "rt", rt_buf);
139 else
140 vty_out(vty, "Route-target: %s", rt_buf);
141
d62a17ae 142 break;
143
144 default:
145 return;
146 }
147
9c92b5f7
MK
148 if (!json) {
149 vty_out(vty,
150 "\nList of VNIs importing routes with this route-target:\n");
151 }
152
153 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
154 if (json)
155 json_object_array_add(
156 json_vnis, json_object_new_int64(tmp_vpn->vni));
157 else
158 vty_out(vty, " %u\n", tmp_vpn->vni);
159 }
160
161 if (json) {
162 json_object_object_add(json_rt, "vnis", json_vnis);
163 json_object_object_add(json, rt_buf, json_rt);
164 }
d62a17ae 165
d62a17ae 166}
167
9c92b5f7 168static void show_import_rt_entry(struct hash_backet *backet, void *args[])
520d5d76 169{
9c92b5f7
MK
170 json_object *json = NULL;
171 struct vty *vty = NULL;
d62a17ae 172 struct irt_node *irt = (struct irt_node *)backet->data;
9c92b5f7
MK
173
174 vty = args[0];
175 json = args[1];
176
d62a17ae 177 display_import_rt(vty, irt);
9c92b5f7
MK
178
179 return;
d62a17ae 180}
520d5d76 181
d62a17ae 182static void bgp_evpn_show_route_rd_header(struct vty *vty,
9c92b5f7
MK
183 struct bgp_node *rd_rn,
184 json_object *json)
d62a17ae 185{
186 u_int16_t type;
187 struct rd_as rd_as;
188 struct rd_ip rd_ip;
189 u_char *pnt;
9c92b5f7 190 char rd_str[RD_ADDRSTRLEN];
520d5d76 191
d62a17ae 192 pnt = rd_rn->p.u.val;
520d5d76 193
d62a17ae 194 /* Decode RD type. */
195 type = decode_rd_type(pnt);
520d5d76 196
9c92b5f7
MK
197 if (json)
198 return;
199
d62a17ae 200 vty_out(vty, "Route Distinguisher: ");
520d5d76 201
d62a17ae 202 switch (type) {
203 case RD_TYPE_AS:
204 decode_rd_as(pnt + 2, &rd_as);
9c92b5f7 205 snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
d62a17ae 206 break;
520d5d76 207
d62a17ae 208 case RD_TYPE_IP:
209 decode_rd_ip(pnt + 2, &rd_ip);
9c92b5f7
MK
210 snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
211 rd_ip.val);
d62a17ae 212 break;
520d5d76 213
d62a17ae 214 default:
9c92b5f7 215 snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
d62a17ae 216 break;
217 }
218
9c92b5f7 219 vty_out(vty, "%s\n", rd_str);
d62a17ae 220}
221
9c92b5f7
MK
222static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
223 json_object *json)
d62a17ae 224{
225 char ri_header[] =
226 " Network Next Hop Metric LocPrf Weight Path\n";
520d5d76 227
9c92b5f7
MK
228 if (json)
229 return;
230
231
d62a17ae 232 vty_out(vty, "BGP table version is 0, local router ID is %s\n",
233 inet_ntoa(bgp->router_id));
234 vty_out(vty,
235 "Status codes: s suppressed, d damped, h history, "
236 "* valid, > best, i - internal\n");
237 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
238 vty_out(vty,
239 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
240 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
241 vty_out(vty, "%s", ri_header);
242}
520d5d76 243
9c92b5f7 244static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
d62a17ae 245{
246 char buf1[INET6_ADDRSTRLEN];
247 char *ecom_str;
248 struct listnode *node, *nnode;
249 struct ecommunity *ecom;
9c92b5f7
MK
250 json_object *json_import_rtl;
251 json_object *json_export_rtl;
252
253 if (json) {
254 json_import_rtl = json_object_new_array();
255 json_export_rtl = json_object_new_array();
256 json_object_int_add(json, "vni", vpn->vni);
257 json_object_string_add(json, "kernelFlag",
258 is_vni_live(vpn) ? "Yes" : "No");
259 json_object_string_add(
260 json, "rd",
261 prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
262 json_object_string_add(json, "originatorIp",
263 inet_ntoa(vpn->originator_ip));
264 json_object_string_add(json, "advertiseGatewayMacip",
265 vpn->advertise_gw_macip ? "Yes" : "No");
266 } else {
267 vty_out(vty, "VNI: %d", vpn->vni);
268 if (is_vni_live(vpn))
269 vty_out(vty, " (known to the kernel)");
270 vty_out(vty, "\n");
271
272 vty_out(vty, " RD: %s\n",
273 prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
274 vty_out(vty, " Originator IP: %s\n",
275 inet_ntoa(vpn->originator_ip));
276 vty_out(vty, " Advertise-gw-macip : %s\n",
277 vpn->advertise_gw_macip ? "Yes" : "No");
278 }
520d5d76 279
9c92b5f7
MK
280 if (!json)
281 vty_out(vty, " Import Route Target:\n");
520d5d76 282
d62a17ae 283 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
284 ecom_str = ecommunity_ecom2str(ecom,
285 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
286
287 if (json)
288 json_object_array_add(json_import_rtl,
289 json_object_new_string(ecom_str));
290 else
291 vty_out(vty, " %s\n", ecom_str);
292
d62a17ae 293 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
294 }
520d5d76 295
9c92b5f7
MK
296 if (json)
297 json_object_object_add(json, "importRts", json_import_rtl);
298 else
299 vty_out(vty, " Export Route Target:\n");
300
d62a17ae 301 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
302 ecom_str = ecommunity_ecom2str(ecom,
303 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
9c92b5f7
MK
304
305 if (json)
306 json_object_array_add(json_export_rtl,
307 json_object_new_string(ecom_str));
308 else
309 vty_out(vty, " %s\n", ecom_str);
310
d62a17ae 311 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
312 }
9c92b5f7
MK
313
314 if (json)
315 json_object_object_add(json, "exportRts", json_export_rtl);
520d5d76 316}
d62a17ae 317
318static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
9c92b5f7
MK
319 struct vty *vty, struct in_addr vtep_ip,
320 json_object *json)
520d5d76 321{
d62a17ae 322 struct bgp_node *rn;
323 struct bgp_info *ri;
324 int header = 1;
325 u_int32_t prefix_cnt, path_cnt;
326
327 prefix_cnt = path_cnt = 0;
328
329 for (rn = bgp_table_top(vpn->route_table); rn;
330 rn = bgp_route_next(rn)) {
331 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
9c92b5f7
MK
332 int add_prefix_to_json = 0;
333 char prefix_str[BUFSIZ];
334 json_object *json_paths = NULL;
335 json_object *json_prefix = NULL;
336
337 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
338 sizeof(prefix_str));
d62a17ae 339
340 if (type && evp->prefix.route_type != type)
341 continue;
342
9c92b5f7
MK
343 if (json)
344 json_prefix = json_object_new_object();
345
d62a17ae 346 if (rn->info) {
347 /* Overall header/legend displayed once. */
348 if (header) {
9c92b5f7 349 bgp_evpn_show_route_header(vty, bgp, json);
d62a17ae 350 header = 0;
351 }
352
353 prefix_cnt++;
354 }
355
9c92b5f7
MK
356 if (json)
357 json_paths = json_object_new_array();
358
d62a17ae 359 /* For EVPN, the prefix is displayed for each path (to fit in
360 * with code that already exists).
361 */
362 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
363 json_object *json_path = NULL;
364
d62a17ae 365 if (vtep_ip.s_addr
366 && !IPV4_ADDR_SAME(&(vtep_ip),
367 &(ri->attr->nexthop)))
368 continue;
369
9c92b5f7
MK
370 if (json)
371 json_path = json_object_new_array();
372
373 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
374
375 if (json)
376 json_object_array_add(json_paths, json_path);
377
d62a17ae 378 path_cnt++;
9c92b5f7
MK
379 add_prefix_to_json = 1;
380 }
381
382 if (json && add_prefix_to_json) {
383 json_object_string_add(json_prefix, "prefix",
384 prefix_str);
385 json_object_int_add(json_prefix, "prefixLen",
386 rn->p.prefixlen);
387 json_object_object_add(json_prefix, "paths",
388 json_paths);
389 json_object_object_add(json, prefix_str, json_prefix);
d62a17ae 390 }
391 }
392
9c92b5f7
MK
393 if (json) {
394 json_object_int_add(json, "numPrefix", prefix_cnt);
395 json_object_int_add(json, "numPaths", path_cnt);
396 } else {
397 if (prefix_cnt == 0)
398 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
399 type ? "(of requested type) " : "");
400 else
401 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s",
402 prefix_cnt, path_cnt,
403 type ? " (of requested type)" : "");
404 }
520d5d76 405}
406
d62a17ae 407static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
520d5d76 408{
d62a17ae 409 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
410 struct vni_walk_ctx *wctx = arg;
411 struct vty *vty = wctx->vty;
9c92b5f7
MK
412 json_object *json = wctx->json;
413 json_object *json_vni = NULL;
414 char vni_str[VNI_STR_LEN];
415
416 snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
417 if (json) {
418 json_vni = json_object_new_object();
419 json_object_int_add(json_vni, "vni", vpn->vni);
420 } else {
421 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
422 }
423
424 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni);
520d5d76 425
9c92b5f7
MK
426 if (json)
427 json_object_object_add(json, vni_str, json_vni);
520d5d76 428}
429
9c92b5f7 430static void show_vni_entry(struct hash_backet *backet, void *args[])
520d5d76 431{
9c92b5f7
MK
432 struct vty *vty;
433 json_object *json;
434 json_object *json_vni;
435 json_object *json_import_rtl;
436 json_object *json_export_rtl;
d62a17ae 437 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
438 char buf1[10];
439 char buf2[INET6_ADDRSTRLEN];
440 char rt_buf[25];
441 char *ecom_str;
442 struct listnode *node, *nnode;
443 struct ecommunity *ecom;
520d5d76 444
9c92b5f7
MK
445 vty = args[0];
446 json = args[1];
447
448 if (json) {
449 json_vni = json_object_new_object();
450 json_import_rtl = json_object_new_array();
451 json_export_rtl = json_object_new_array();
452 }
453
d62a17ae 454 buf1[0] = '\0';
455 if (is_vni_live(vpn))
456 sprintf(buf1, "*");
520d5d76 457
9c92b5f7
MK
458 if (json) {
459 json_object_int_add(json_vni, "vni", vpn->vni);
460 json_object_string_add(json_vni, "inKernel",
461 is_vni_live(vpn) ? "True" : "False");
462 json_object_string_add(json_vni, "originatorIp",
463 inet_ntoa(vpn->originator_ip));
464 json_object_string_add(
465 json_vni, "rd",
466 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
467 } else {
468 vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
469 inet_ntoa(vpn->originator_ip),
470 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
471 }
520d5d76 472
d62a17ae 473 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
474 ecom_str = ecommunity_ecom2str(ecom,
475 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
520d5d76 476
9c92b5f7
MK
477 if (json) {
478 json_object_array_add(json_import_rtl,
479 json_object_new_string(ecom_str));
480 } else {
481 if (listcount(vpn->import_rtl) > 1)
482 sprintf(rt_buf, "%s, ...", ecom_str);
483 else
484 sprintf(rt_buf, "%s", ecom_str);
485 vty_out(vty, " %-25s", rt_buf);
486 }
520d5d76 487
d62a17ae 488 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
489
490 /* If there are multiple import RTs we break here and show only
491 * one */
492 if (!json)
493 break;
d62a17ae 494 }
495
9c92b5f7
MK
496 if (json)
497 json_object_object_add(json_vni, "importRTs", json_import_rtl);
498
d62a17ae 499 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
500 ecom_str = ecommunity_ecom2str(ecom,
501 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
502
9c92b5f7
MK
503 if (json) {
504 json_object_array_add(json_export_rtl,
505 json_object_new_string(ecom_str));
506 } else {
507 if (listcount(vpn->export_rtl) > 1)
508 sprintf(rt_buf, "%s, ...", ecom_str);
509 else
510 sprintf(rt_buf, "%s", ecom_str);
511 vty_out(vty, " %-25s", rt_buf);
512 }
d62a17ae 513
514 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
9c92b5f7
MK
515
516 /* If there are multiple export RTs we break here and show only
517 * one */
518 if (!json)
519 break;
520 }
521
522 if (json) {
523 char vni_str[VNI_STR_LEN];
524 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
525 snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
526 json_object_object_add(json, vni_str, json_vni);
527 } else {
528 vty_out(vty, "\n");
d62a17ae 529 }
520d5d76 530}
8c197128 531#endif /* HAVE_CUMULUS */
520d5d76 532
d62a17ae 533static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
534 enum bgp_show_type type, void *output_arg,
535 int option, u_char use_json)
784d3a42 536{
4d0e6ece
PG
537 afi_t afi = AFI_L2VPN;
538 struct bgp *bgp;
539 struct bgp_table *table;
540 struct bgp_node *rn;
541 struct bgp_node *rm;
542 struct bgp_info *ri;
543 int rd_header;
544 int header = 1;
4d0e6ece
PG
545
546 unsigned long output_count = 0;
547 unsigned long total_count = 0;
548 json_object *json = NULL;
549 json_object *json_nroute = NULL;
550 json_object *json_array = NULL;
551 json_object *json_scode = NULL;
552 json_object *json_ocode = NULL;
553
554 bgp = bgp_get_default();
555 if (bgp == NULL) {
556 if (!use_json)
d62a17ae 557 vty_out(vty, "No BGP process is configured\n");
16307668
RW
558 else
559 vty_out(vty, "{}\n");
4d0e6ece
PG
560 return CMD_WARNING;
561 }
562
563 if (use_json) {
564 json_scode = json_object_new_object();
565 json_ocode = json_object_new_object();
566 json = json_object_new_object();
567 json_nroute = json_object_new_object();
568
569 json_object_string_add(json_scode, "suppressed", "s");
570 json_object_string_add(json_scode, "damped", "d");
571 json_object_string_add(json_scode, "history", "h");
572 json_object_string_add(json_scode, "valid", "*");
573 json_object_string_add(json_scode, "best", ">");
574 json_object_string_add(json_scode, "internal", "i");
575
576 json_object_string_add(json_ocode, "igp", "i");
577 json_object_string_add(json_ocode, "egp", "e");
578 json_object_string_add(json_ocode, "incomplete", "?");
579 }
580
581 for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
582 rn = bgp_route_next(rn)) {
583 if (use_json)
d62a17ae 584 continue; /* XXX json TODO */
4d0e6ece
PG
585
586 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
587 continue;
588
589 if ((table = rn->info) != NULL) {
590 rd_header = 1;
591
592 for (rm = bgp_table_top(table); rm;
593 rm = bgp_route_next(rm))
594 for (ri = rm->info; ri; ri = ri->next) {
595 total_count++;
596 if (type == bgp_show_type_neighbor) {
597 union sockunion *su =
d62a17ae 598 output_arg;
4d0e6ece
PG
599
600 if (ri->peer->su_remote == NULL
d62a17ae 601 || !sockunion_same(
602 ri->peer->su_remote,
603 su))
4d0e6ece
PG
604 continue;
605 }
606 if (header == 0) {
607 if (use_json) {
d62a17ae 608 if (option
609 == SHOW_DISPLAY_TAGS) {
610 json_object_int_add(
611 json,
612 "bgpTableVersion",
613 0);
614 json_object_string_add(
615 json,
616 "bgpLocalRouterId",
617 inet_ntoa(
618 bgp->router_id));
619 json_object_object_add(
620 json,
621 "bgpStatusCodes",
622 json_scode);
623 json_object_object_add(
624 json,
625 "bgpOriginCodes",
626 json_ocode);
4d0e6ece
PG
627 }
628 } else {
d62a17ae 629 if (option
630 == SHOW_DISPLAY_TAGS)
631 vty_out(vty,
632 V4_HEADER_TAG);
633 else if (
634 option
635 == SHOW_DISPLAY_OVERLAY)
636 vty_out(vty,
637 V4_HEADER_OVERLAY);
4d0e6ece 638 else {
d62a17ae 639 vty_out(vty,
5c7571d4 640 "BGP table version is 0, local router ID is %s\n",
d62a17ae 641 inet_ntoa(
642 bgp->router_id));
643 vty_out(vty,
5c7571d4 644 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
d62a17ae 645 vty_out(vty,
61b7d449 646 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
d62a17ae 647 vty_out(vty,
648 V4_HEADER);
4d0e6ece
PG
649 }
650 }
651 header = 0;
652 }
653 if (rd_header) {
654 u_int16_t type;
655 struct rd_as rd_as;
656 struct rd_ip rd_ip;
657 u_char *pnt;
658
659 pnt = rn->p.u.val;
660
661 /* Decode RD type. */
662 type = decode_rd_type(pnt);
663 /* Decode RD value. */
664 if (type == RD_TYPE_AS)
665 decode_rd_as(pnt + 2,
666 &rd_as);
667 else if (type == RD_TYPE_AS4)
668 decode_rd_as4(pnt + 2,
669 &rd_as);
670 else if (type == RD_TYPE_IP)
671 decode_rd_ip(pnt + 2,
672 &rd_ip);
673 if (use_json) {
674 char buffer[BUFSIZ];
675 if (type == RD_TYPE_AS
d62a17ae 676 || type == RD_TYPE_AS4)
4d0e6ece
PG
677 sprintf(buffer,
678 "%u:%d",
d62a17ae 679 rd_as.as,
680 rd_as.val);
681 else if (type
682 == RD_TYPE_IP)
4d0e6ece
PG
683 sprintf(buffer,
684 "%s:%d",
d62a17ae 685 inet_ntoa(
686 rd_ip.ip),
687 rd_ip.val);
688 json_object_string_add(
689 json_nroute,
690 "routeDistinguisher",
691 buffer);
4d0e6ece
PG
692 } else {
693 vty_out(vty,
694 "Route Distinguisher: ");
695 if (type == RD_TYPE_AS)
696 vty_out(vty,
697 "as2 %u:%d",
d62a17ae 698 rd_as.as,
699 rd_as.val);
700 else if (type
701 == RD_TYPE_AS4)
4d0e6ece
PG
702 vty_out(vty,
703 "as4 %u:%d",
d62a17ae 704 rd_as.as,
705 rd_as.val);
706 else if (type
707 == RD_TYPE_IP)
4d0e6ece
PG
708 vty_out(vty,
709 "ip %s:%d",
d62a17ae 710 inet_ntoa(
711 rd_ip.ip),
712 rd_ip.val);
713 vty_out(vty, "\n\n");
4d0e6ece
PG
714 }
715 rd_header = 0;
716 }
717 if (use_json)
718 json_array =
d62a17ae 719 json_object_new_array();
4d0e6ece
PG
720 else
721 json_array = NULL;
722 if (option == SHOW_DISPLAY_TAGS)
d62a17ae 723 route_vty_out_tag(
724 vty, &rm->p, ri, 0,
725 SAFI_EVPN, json_array);
4d0e6ece 726 else if (option == SHOW_DISPLAY_OVERLAY)
d62a17ae 727 route_vty_out_overlay(
728 vty, &rm->p, ri, 0,
729 json_array);
4d0e6ece
PG
730 else
731 route_vty_out(vty, &rm->p, ri,
732 0, SAFI_EVPN,
733 json_array);
734 output_count++;
735 }
736 /* XXX json */
737 }
738 }
739 if (output_count == 0)
d62a17ae 740 vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
4d0e6ece 741 else
d62a17ae 742 vty_out(vty, "\nDisplayed %ld out of %ld total prefixes\n",
743 output_count, total_count);
4d0e6ece 744 return CMD_SUCCESS;
784d3a42
PG
745}
746
4d0e6ece
PG
747DEFUN(show_ip_bgp_l2vpn_evpn,
748 show_ip_bgp_l2vpn_evpn_cmd,
749 "show [ip] bgp l2vpn evpn [json]",
750 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
784d3a42 751{
4d0e6ece
PG
752 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
753 use_json(argc, argv));
784d3a42
PG
754}
755
4d0e6ece
PG
756DEFUN(show_ip_bgp_l2vpn_evpn_rd,
757 show_ip_bgp_l2vpn_evpn_rd_cmd,
758 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
759 SHOW_STR
760 IP_STR
761 BGP_STR
762 L2VPN_HELP_STR
763 EVPN_HELP_STR
764 "Display information for a route distinguisher\n"
765 "VPN Route Distinguisher\n" JSON_STR)
784d3a42 766{
313605cb 767 int idx_ext_community = 0;
4d0e6ece
PG
768 int ret;
769 struct prefix_rd prd;
770
d62a17ae 771 argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
313605cb 772
4d0e6ece
PG
773 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
774 if (!ret) {
d62a17ae 775 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
776 return CMD_WARNING;
777 }
778 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
779 use_json(argc, argv));
784d3a42
PG
780}
781
4d0e6ece
PG
782DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
783 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
784 "show [ip] bgp l2vpn evpn all tags",
785 SHOW_STR
786 IP_STR
787 BGP_STR
788 L2VPN_HELP_STR
789 EVPN_HELP_STR
790 "Display information about all EVPN NLRIs\n"
791 "Display BGP tags for prefixes\n")
784d3a42 792{
4d0e6ece
PG
793 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
794 0);
784d3a42
PG
795}
796
4d0e6ece
PG
797DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
798 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
799 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
800 SHOW_STR
801 IP_STR
802 BGP_STR
803 L2VPN_HELP_STR
804 EVPN_HELP_STR
805 "Display information for a route distinguisher\n"
806 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
784d3a42 807{
313605cb 808 int idx_ext_community = 0;
4d0e6ece
PG
809 int ret;
810 struct prefix_rd prd;
811
d62a17ae 812 argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
313605cb 813
4d0e6ece
PG
814 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
815 if (!ret) {
d62a17ae 816 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
817 return CMD_WARNING;
818 }
819 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
820 0);
784d3a42
PG
821}
822
4d0e6ece
PG
823DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
824 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd,
825 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
826 SHOW_STR
827 IP_STR
828 BGP_STR
829 L2VPN_HELP_STR
830 EVPN_HELP_STR
831 "Display information about all EVPN NLRIs\n"
832 "Detailed information on TCP and BGP neighbor connections\n"
833 "Neighbor to display information about\n"
834 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 835{
313605cb 836 int idx_ipv4 = 0;
4d0e6ece
PG
837 union sockunion su;
838 struct peer *peer;
839 int ret;
840 u_char uj = use_json(argc, argv);
841
d62a17ae 842 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
313605cb 843
4d0e6ece
PG
844 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
845 if (ret < 0) {
846 if (uj) {
847 json_object *json_no = NULL;
848 json_no = json_object_new_object();
849 json_object_string_add(json_no, "warning",
850 "Malformed address");
d62a17ae 851 vty_out(vty, "%s\n",
96ade3ed 852 json_object_to_json_string(json_no));
4d0e6ece
PG
853 json_object_free(json_no);
854 } else
d62a17ae 855 vty_out(vty, "Malformed address: %s\n",
96ade3ed 856 argv[idx_ipv4]->arg);
4d0e6ece
PG
857 return CMD_WARNING;
858 }
859
860 peer = peer_lookup(NULL, &su);
861 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
862 if (uj) {
863 json_object *json_no = NULL;
864 json_no = json_object_new_object();
d62a17ae 865 json_object_string_add(
866 json_no, "warning",
867 "No such neighbor or address family");
868 vty_out(vty, "%s\n",
96ade3ed 869 json_object_to_json_string(json_no));
4d0e6ece
PG
870 json_object_free(json_no);
871 } else
d62a17ae 872 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
873 return CMD_WARNING;
874 }
875
876 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, &su, 0,
877 uj);
784d3a42
PG
878}
879
4d0e6ece
PG
880DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
881 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
882 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
883 SHOW_STR
884 IP_STR
885 BGP_STR
886 L2VPN_HELP_STR
887 EVPN_HELP_STR
888 "Display information for a route distinguisher\n"
889 "VPN Route Distinguisher\n"
890 "Detailed information on TCP and BGP neighbor connections\n"
891 "Neighbor to display information about\n"
892 "Display routes learned from neighbor\n" JSON_STR)
784d3a42 893{
313605cb
RW
894 int idx_ext_community = 0;
895 int idx_ipv4 = 0;
4d0e6ece
PG
896 int ret;
897 union sockunion su;
898 struct peer *peer;
899 struct prefix_rd prd;
900 u_char uj = use_json(argc, argv);
901
d62a17ae 902 argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
903 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
313605cb 904
4d0e6ece
PG
905 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
906 if (!ret) {
907 if (uj) {
908 json_object *json_no = NULL;
909 json_no = json_object_new_object();
910 json_object_string_add(json_no, "warning",
911 "Malformed Route Distinguisher");
d62a17ae 912 vty_out(vty, "%s\n",
96ade3ed 913 json_object_to_json_string(json_no));
4d0e6ece
PG
914 json_object_free(json_no);
915 } else
d62a17ae 916 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
917 return CMD_WARNING;
918 }
919
920 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
921 if (ret < 0) {
922 if (uj) {
923 json_object *json_no = NULL;
924 json_no = json_object_new_object();
925 json_object_string_add(json_no, "warning",
926 "Malformed address");
d62a17ae 927 vty_out(vty, "%s\n",
96ade3ed 928 json_object_to_json_string(json_no));
4d0e6ece
PG
929 json_object_free(json_no);
930 } else
d62a17ae 931 vty_out(vty, "Malformed address: %s\n",
96ade3ed 932 argv[idx_ext_community]->arg);
4d0e6ece
PG
933 return CMD_WARNING;
934 }
935
936 peer = peer_lookup(NULL, &su);
937 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
938 if (uj) {
939 json_object *json_no = NULL;
940 json_no = json_object_new_object();
d62a17ae 941 json_object_string_add(
942 json_no, "warning",
943 "No such neighbor or address family");
944 vty_out(vty, "%s\n",
96ade3ed 945 json_object_to_json_string(json_no));
4d0e6ece
PG
946 json_object_free(json_no);
947 } else
d62a17ae 948 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
949 return CMD_WARNING;
950 }
951
952 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, &su, 0,
953 uj);
784d3a42
PG
954}
955
4d0e6ece
PG
956DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
957 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd,
958 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
959 SHOW_STR
960 IP_STR
961 BGP_STR
962 L2VPN_HELP_STR
963 EVPN_HELP_STR
964 "Display information about all EVPN NLRIs\n"
965 "Detailed information on TCP and BGP neighbor connections\n"
966 "Neighbor to display information about\n"
967 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 968{
313605cb 969 int idx_ipv4 = 0;
4d0e6ece
PG
970 int ret;
971 struct peer *peer;
972 union sockunion su;
973 u_char uj = use_json(argc, argv);
974
d62a17ae 975 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
313605cb 976
4d0e6ece
PG
977 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
978 if (ret < 0) {
979 if (uj) {
980 json_object *json_no = NULL;
981 json_no = json_object_new_object();
982 json_object_string_add(json_no, "warning",
983 "Malformed address");
d62a17ae 984 vty_out(vty, "%s\n",
96ade3ed 985 json_object_to_json_string(json_no));
4d0e6ece
PG
986 json_object_free(json_no);
987 } else
d62a17ae 988 vty_out(vty, "Malformed address: %s\n",
96ade3ed 989 argv[idx_ipv4]->arg);
4d0e6ece
PG
990 return CMD_WARNING;
991 }
992 peer = peer_lookup(NULL, &su);
993 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
994 if (uj) {
995 json_object *json_no = NULL;
996 json_no = json_object_new_object();
d62a17ae 997 json_object_string_add(
998 json_no, "warning",
999 "No such neighbor or address family");
1000 vty_out(vty, "%s\n",
96ade3ed 1001 json_object_to_json_string(json_no));
4d0e6ece
PG
1002 json_object_free(json_no);
1003 } else
d62a17ae 1004 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1005 return CMD_WARNING;
1006 }
1007
1008 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1009}
1010
4d0e6ece
PG
1011DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1012 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1013 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
1014 SHOW_STR
1015 IP_STR
1016 BGP_STR
1017 L2VPN_HELP_STR
1018 EVPN_HELP_STR
1019 "Display information for a route distinguisher\n"
1020 "VPN Route Distinguisher\n"
1021 "Detailed information on TCP and BGP neighbor connections\n"
1022 "Neighbor to display information about\n"
1023 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
784d3a42 1024{
313605cb
RW
1025 int idx_ext_community = 0;
1026 int idx_ipv4 = 0;
4d0e6ece
PG
1027 int ret;
1028 struct peer *peer;
1029 struct prefix_rd prd;
1030 union sockunion su;
1031 u_char uj = use_json(argc, argv);
1032
d62a17ae 1033 argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
1034 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
313605cb 1035
4d0e6ece
PG
1036 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1037 if (ret < 0) {
1038 if (uj) {
1039 json_object *json_no = NULL;
1040 json_no = json_object_new_object();
1041 json_object_string_add(json_no, "warning",
1042 "Malformed address");
d62a17ae 1043 vty_out(vty, "%s\n",
96ade3ed 1044 json_object_to_json_string(json_no));
4d0e6ece
PG
1045 json_object_free(json_no);
1046 } else
d62a17ae 1047 vty_out(vty, "Malformed address: %s\n",
96ade3ed 1048 argv[idx_ext_community]->arg);
4d0e6ece
PG
1049 return CMD_WARNING;
1050 }
1051 peer = peer_lookup(NULL, &su);
1052 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1053 if (uj) {
1054 json_object *json_no = NULL;
1055 json_no = json_object_new_object();
d62a17ae 1056 json_object_string_add(
1057 json_no, "warning",
1058 "No such neighbor or address family");
1059 vty_out(vty, "%s\n",
96ade3ed 1060 json_object_to_json_string(json_no));
4d0e6ece
PG
1061 json_object_free(json_no);
1062 } else
d62a17ae 1063 vty_out(vty, "%% No such neighbor or address family\n");
4d0e6ece
PG
1064 return CMD_WARNING;
1065 }
1066
1067 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1068 if (!ret) {
1069 if (uj) {
1070 json_object *json_no = NULL;
1071 json_no = json_object_new_object();
1072 json_object_string_add(json_no, "warning",
1073 "Malformed Route Distinguisher");
d62a17ae 1074 vty_out(vty, "%s\n",
96ade3ed 1075 json_object_to_json_string(json_no));
4d0e6ece
PG
1076 json_object_free(json_no);
1077 } else
d62a17ae 1078 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1079 return CMD_WARNING;
1080 }
1081
1082 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
784d3a42
PG
1083}
1084
4d0e6ece
PG
1085DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1086 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1087 "show [ip] bgp l2vpn evpn all overlay",
1088 SHOW_STR
1089 IP_STR
1090 BGP_STR
1091 L2VPN_HELP_STR
1092 EVPN_HELP_STR
1093 "Display information about all EVPN NLRIs\n"
1094 "Display BGP Overlay Information for prefixes\n")
784d3a42 1095{
4d0e6ece 1096 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
d62a17ae 1097 SHOW_DISPLAY_OVERLAY,
1098 use_json(argc, argv));
784d3a42
PG
1099}
1100
4d0e6ece
PG
1101DEFUN(show_ip_bgp_evpn_rd_overlay,
1102 show_ip_bgp_evpn_rd_overlay_cmd,
1103 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
1104 SHOW_STR
1105 IP_STR
1106 BGP_STR
1107 L2VPN_HELP_STR
1108 EVPN_HELP_STR
1109 "Display information for a route distinguisher\n"
1110 "VPN Route Distinguisher\n"
1111 "Display BGP Overlay Information for prefixes\n")
784d3a42 1112{
313605cb 1113 int idx_ext_community = 0;
4d0e6ece
PG
1114 int ret;
1115 struct prefix_rd prd;
1116
d62a17ae 1117 argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community);
313605cb 1118
4d0e6ece
PG
1119 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1120 if (!ret) {
d62a17ae 1121 vty_out(vty, "%% Malformed Route Distinguisher\n");
4d0e6ece
PG
1122 return CMD_WARNING;
1123 }
1124 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
d62a17ae 1125 SHOW_DISPLAY_OVERLAY,
1126 use_json(argc, argv));
784d3a42
PG
1127}
1128
3da6fcd5 1129/* For testing purpose, static route of MPLS-VPN. */
4d0e6ece
PG
1130DEFUN(evpnrt5_network,
1131 evpnrt5_network_cmd,
1132 "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]",
1133 "Specify a network to announce via BGP\n"
1134 "IP prefix\n"
1135 "IPv6 prefix\n"
1136 "Specify Route Distinguisher\n"
1137 "VPN Route Distinguisher\n"
1138 "Ethernet Tag\n"
1139 "Ethernet Tag Value\n"
1140 "BGP label\n"
1141 "label value\n"
1142 "Ethernet Segment Identifier\n"
1143 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1144 "Gateway IP\n"
1145 "Gateway IP ( A.B.C.D )\n"
1146 "Gateway IPv6 ( X:X::X:X )\n"
1147 "Router Mac Ext Comm\n"
55daa605
DS
1148 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1149 "Route-map to modify the attributes\n"
1150 "Name of the route map\n")
3da6fcd5 1151{
4d0e6ece
PG
1152 int idx_ipv4_prefixlen = 1;
1153 int idx_ext_community = 3;
1154 int idx_word = 7;
1155 int idx_esi = 9;
1156 int idx_gwip = 11;
1157 int idx_ethtag = 5;
1158 int idx_routermac = 13;
1159 int idx_rmap = 15;
d62a17ae 1160 return bgp_static_set_safi(
1161 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1162 argv[idx_ext_community]->arg, argv[idx_word]->arg,
1163 argv[idx_rmap] ? argv[idx_gwip]->arg : NULL,
1164 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1165 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1166 argv[idx_routermac]->arg);
3da6fcd5
PG
1167}
1168
1169/* For testing purpose, static route of MPLS-VPN. */
4d0e6ece
PG
1170DEFUN(no_evpnrt5_network,
1171 no_evpnrt5_network_cmd,
1172 "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>",
1173 NO_STR
1174 "Specify a network to announce via BGP\n"
1175 "IP prefix\n"
1176 "IPv6 prefix\n"
1177 "Specify Route Distinguisher\n"
1178 "VPN Route Distinguisher\n"
1179 "Ethernet Tag\n"
1180 "Ethernet Tag Value\n"
1181 "BGP label\n"
1182 "label value\n"
1183 "Ethernet Segment Identifier\n"
1184 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1185 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
3da6fcd5 1186{
4d0e6ece
PG
1187 int idx_ipv4_prefixlen = 2;
1188 int idx_ext_community = 4;
1189 int idx_label = 8;
1190 int idx_ethtag = 6;
1191 int idx_esi = 10;
1192 int idx_gwip = 12;
d62a17ae 1193 return bgp_static_unset_safi(
1194 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1195 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1196 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1197 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
3da6fcd5
PG
1198}
1199
8c197128 1200#if defined(HAVE_CUMULUS)
d62a17ae 1201static void evpn_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn,
1202 struct list *rtl)
90e60aa7 1203{
d62a17ae 1204 struct listnode *node, *nnode, *node_to_del;
1205 struct ecommunity *ecom, *ecom_auto;
1206 struct ecommunity_val eval;
90e60aa7 1207
d62a17ae 1208 encode_route_target_as((bgp->as & 0xFFFF), vpn->vni, &eval);
90e60aa7 1209
d62a17ae 1210 ecom_auto = ecommunity_new();
1211 ecommunity_add_val(ecom_auto, &eval);
1212 node_to_del = NULL;
90e60aa7 1213
d62a17ae 1214 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
1215 if (ecommunity_match(ecom, ecom_auto)) {
1216 ecommunity_free(&ecom);
1217 node_to_del = node;
1218 }
1219 }
90e60aa7 1220
d62a17ae 1221 if (node_to_del)
1222 list_delete_node(rtl, node_to_del);
90e60aa7 1223
d62a17ae 1224 ecommunity_free(&ecom_auto);
90e60aa7 1225}
1226
d62a17ae 1227static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1228{
d62a17ae 1229 evpn_rt_delete_auto(bgp, vpn, vpn->import_rtl);
90e60aa7 1230}
1231
d62a17ae 1232static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1233{
d62a17ae 1234 evpn_rt_delete_auto(bgp, vpn, vpn->export_rtl);
90e60aa7 1235}
1236
1237/*
1238 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1239 * check that this is a change.
1240 */
d62a17ae 1241static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1242 struct ecommunity *ecomadd)
90e60aa7 1243{
d62a17ae 1244 /* If the VNI is "live", we need to uninstall routes using the current
1245 * import RT(s) first before we update the import RT, and subsequently
1246 * install routes.
1247 */
1248 if (is_vni_live(vpn))
1249 bgp_evpn_uninstall_routes(bgp, vpn);
90e60aa7 1250
d62a17ae 1251 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1252 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
90e60aa7 1253
d62a17ae 1254 /* If the auto route-target is in use we must remove it */
1255 evpn_import_rt_delete_auto(bgp, vpn);
90e60aa7 1256
d62a17ae 1257 /* Add new RT and rebuild the RT to VNI mapping */
1258 listnode_add_sort(vpn->import_rtl, ecomadd);
90e60aa7 1259
d62a17ae 1260 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1261 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
90e60aa7 1262
d62a17ae 1263 /* Install routes that match new import RT */
1264 if (is_vni_live(vpn))
1265 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 1266}
1267
1268/*
1269 * Unconfigure Import RT(s) for a VNI (vty handler).
1270 */
d62a17ae 1271static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1272 struct ecommunity *ecomdel)
1273{
1274 struct listnode *node, *nnode, *node_to_del;
1275 struct ecommunity *ecom;
1276
1277 /* Along the lines of "configure" except we have to reset to the
1278 * automatic value.
1279 */
1280 if (is_vni_live(vpn))
1281 bgp_evpn_uninstall_routes(bgp, vpn);
1282
1283 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1284 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1285
1286 /* Delete all import RTs */
1287 if (ecomdel == NULL) {
1288 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom))
1289 ecommunity_free(&ecom);
1290
1291 list_delete_all_node(vpn->import_rtl);
1292 }
1293
1294 /* Delete a specific import RT */
1295 else {
1296 node_to_del = NULL;
1297
1298 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1299 if (ecommunity_match(ecom, ecomdel)) {
1300 ecommunity_free(&ecom);
1301 node_to_del = node;
1302 break;
1303 }
1304 }
1305
1306 if (node_to_del)
1307 list_delete_node(vpn->import_rtl, node_to_del);
1308 }
1309
1310 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1311 if (list_isempty(vpn->import_rtl)) {
1312 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1313 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1314 }
1315 /* Rebuild the RT to VNI mapping */
1316 else
1317 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1318
1319 /* Install routes that match new import RT */
1320 if (is_vni_live(vpn))
1321 bgp_evpn_install_routes(bgp, vpn);
90e60aa7 1322}
1323
1324/*
1325 * Configure the Export RT for a VNI (vty handler). Caller expected to
1326 * check that this is a change. Note that only a single export RT is
1327 * allowed for a VNI and any change to configuration is implemented as
1328 * a "replace" (similar to other configuration).
1329 */
d62a17ae 1330static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1331 struct ecommunity *ecomadd)
90e60aa7 1332{
d62a17ae 1333 /* If the auto route-target is in use we must remove it */
1334 evpn_export_rt_delete_auto(bgp, vpn);
90e60aa7 1335
d62a17ae 1336 listnode_add_sort(vpn->export_rtl, ecomadd);
1337 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
90e60aa7 1338
d62a17ae 1339 if (is_vni_live(vpn))
1340 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 1341}
1342
1343/*
1344 * Unconfigure the Export RT for a VNI (vty handler)
1345 */
d62a17ae 1346static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1347 struct ecommunity *ecomdel)
1348{
1349 struct listnode *node, *nnode, *node_to_del;
1350 struct ecommunity *ecom;
1351
1352 /* Delete all export RTs */
1353 if (ecomdel == NULL) {
1354 /* Reset to default and process all routes. */
1355 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
1356 ecommunity_free(&ecom);
1357
1358 list_delete_all_node(vpn->export_rtl);
1359 }
1360
1361 /* Delete a specific export RT */
1362 else {
1363 node_to_del = NULL;
1364
1365 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1366 if (ecommunity_match(ecom, ecomdel)) {
1367 ecommunity_free(&ecom);
1368 node_to_del = node;
1369 break;
1370 }
1371 }
1372
1373 if (node_to_del)
1374 list_delete_node(vpn->export_rtl, node_to_del);
1375 }
1376
1377 if (list_isempty(vpn->export_rtl)) {
1378 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1379 bgp_evpn_derive_auto_rt_export(bgp, vpn);
1380 }
1381
1382 if (is_vni_live(vpn))
1383 bgp_evpn_handle_export_rt_change(bgp, vpn);
90e60aa7 1384}
1385
1386/*
1387 * Configure RD for a VNI (vty handler)
1388 */
d62a17ae 1389static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
1390 struct prefix_rd *rd)
90e60aa7 1391{
d62a17ae 1392 /* If the VNI is "live", we need to delete and withdraw this VNI's
1393 * local routes with the prior RD first. Then, after updating RD,
1394 * need to re-advertise.
1395 */
1396 if (is_vni_live(vpn))
1397 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 1398
d62a17ae 1399 /* update RD */
1400 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
1401 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
90e60aa7 1402
d62a17ae 1403 if (is_vni_live(vpn))
1404 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 1405}
1406
1407/*
1408 * Unconfigure RD for a VNI (vty handler)
1409 */
d62a17ae 1410static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1411{
d62a17ae 1412 /* If the VNI is "live", we need to delete and withdraw this VNI's
1413 * local routes with the prior RD first. Then, after resetting RD
1414 * to automatic value, need to re-advertise.
1415 */
1416 if (is_vni_live(vpn))
1417 bgp_evpn_handle_rd_change(bgp, vpn, 1);
90e60aa7 1418
d62a17ae 1419 /* reset RD to default */
1420 bgp_evpn_derive_auto_rd(bgp, vpn);
90e60aa7 1421
d62a17ae 1422 if (is_vni_live(vpn))
1423 bgp_evpn_handle_rd_change(bgp, vpn, 0);
90e60aa7 1424}
1425
1426/*
1427 * Create VNI, if not already present (VTY handler). Mark as configured.
1428 */
d62a17ae 1429static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
90e60aa7 1430{
d62a17ae 1431 struct bgpevpn *vpn;
90e60aa7 1432
d62a17ae 1433 if (!bgp->vnihash)
1434 return NULL;
90e60aa7 1435
d62a17ae 1436 vpn = bgp_evpn_lookup_vni(bgp, vni);
1437 if (!vpn) {
1438 vpn = bgp_evpn_new(bgp, vni, bgp->router_id);
1439 if (!vpn) {
1440 zlog_err(
1441 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1442 bgp->vrf_id, vni);
1443 return NULL;
1444 }
1445 }
90e60aa7 1446
d62a17ae 1447 /* Mark as configured. */
1448 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1449 return vpn;
90e60aa7 1450}
1451
1452/*
1453 * Delete VNI. If VNI does not exist in the system (i.e., just
1454 * configuration), all that is needed is to free it. Otherwise,
1455 * any parameters configured for the VNI need to be reset (with
1456 * appropriate action) and the VNI marked as unconfigured; the
1457 * VNI will continue to exist, purely as a "learnt" entity.
1458 */
d62a17ae 1459static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
90e60aa7 1460{
d62a17ae 1461 assert(bgp->vnihash);
90e60aa7 1462
d62a17ae 1463 if (!is_vni_live(vpn)) {
1464 bgp_evpn_free(bgp, vpn);
1465 return 0;
1466 }
90e60aa7 1467
d62a17ae 1468 /* We need to take the unconfigure action for each parameter of this VNI
1469 * that is configured. Some optimization is possible, but not worth the
1470 * additional code for an operation that should be pretty rare.
1471 */
1472 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
90e60aa7 1473
d62a17ae 1474 /* First, deal with the export side - RD and export RT changes. */
1475 if (is_rd_configured(vpn))
1476 evpn_unconfigure_rd(bgp, vpn);
1477 if (is_export_rt_configured(vpn))
1478 evpn_unconfigure_export_rt(bgp, vpn, NULL);
90e60aa7 1479
d62a17ae 1480 /* Next, deal with the import side. */
1481 if (is_import_rt_configured(vpn))
1482 evpn_unconfigure_import_rt(bgp, vpn, NULL);
90e60aa7 1483
d62a17ae 1484 return 0;
90e60aa7 1485}
1486
520d5d76 1487/*
1488 * Display import RT mapping to VNIs (vty handler)
1489 */
9c92b5f7
MK
1490static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
1491 json_object *json)
520d5d76 1492{
9c92b5f7
MK
1493 void *args[2];
1494
1495 args[0] = vty;
1496 args[1] = json;
1497
d62a17ae 1498 hash_iterate(
1499 bgp->import_rt_hash,
1500 (void (*)(struct hash_backet *, void *))show_import_rt_entry,
9c92b5f7 1501 args);
520d5d76 1502}
1503
1504/*
1505 * Display EVPN routes for all VNIs - vty handler.
1506 */
d62a17ae 1507static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
1508 struct in_addr vtep_ip,
1509 json_object *json)
520d5d76 1510{
d62a17ae 1511 u_int32_t num_vnis;
1512 struct vni_walk_ctx wctx;
520d5d76 1513
d62a17ae 1514 num_vnis = hashcount(bgp->vnihash);
1515 if (!num_vnis)
1516 return;
1517 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
1518 wctx.bgp = bgp;
1519 wctx.vty = vty;
1520 wctx.vtep_ip = vtep_ip;
9c92b5f7 1521 wctx.json = json;
9d303b37
DL
1522 hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
1523 void *))show_vni_routes_hash,
1524 &wctx);
520d5d76 1525}
1526
1527/*
1528 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1529 */
d62a17ae 1530static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
1531 vni_t vni, struct in_addr orig_ip,
1532 json_object *json)
d62a17ae 1533{
1534 struct bgpevpn *vpn;
1535 struct prefix_evpn p;
1536 struct bgp_node *rn;
1537 struct bgp_info *ri;
1538 u_int32_t path_cnt = 0;
1539 afi_t afi;
1540 safi_t safi;
9c92b5f7 1541 json_object *json_paths = NULL;
d62a17ae 1542
1543 afi = AFI_L2VPN;
1544 safi = SAFI_EVPN;
1545
1546 /* Locate VNI. */
1547 vpn = bgp_evpn_lookup_vni(bgp, vni);
1548 if (!vpn) {
1549 vty_out(vty, "VNI not found\n");
1550 return;
1551 }
1552
1553 /* See if route exists. */
1554 build_evpn_type3_prefix(&p, orig_ip);
1555 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1556 if (!rn || !rn->info) {
9c92b5f7
MK
1557 if (!json)
1558 vty_out(vty, "%% Network not in table\n");
d62a17ae 1559 return;
1560 }
1561
9c92b5f7
MK
1562 if (json)
1563 json_paths = json_object_new_array();
1564
d62a17ae 1565 /* Prefix and num paths displayed once per prefix. */
9c92b5f7 1566 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
d62a17ae 1567
1568 /* Display each path for this prefix. */
1569 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
1570 json_object *json_path = NULL;
1571
1572 if (json)
1573 json_path = json_object_new_array();
1574
1575 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1576 json_path);
1577
1578 if (json)
1579 json_object_array_add(json_paths, json_path);
1580
d62a17ae 1581 path_cnt++;
1582 }
1583
9c92b5f7
MK
1584 if (json) {
1585 if (path_cnt)
1586 json_object_object_add(json, "paths", json_paths);
1587
1588 json_object_int_add(json, "numPaths", path_cnt);
1589 } else {
1590 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1591 path_cnt);
1592 }
520d5d76 1593}
1594
1595/*
1596 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1597 * By definition, only matching type-2 route will be displayed.
1598 */
d62a17ae 1599static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
1600 vni_t vni, struct ethaddr *mac,
9c92b5f7 1601 struct ipaddr *ip, json_object *json)
d62a17ae 1602{
1603 struct bgpevpn *vpn;
1604 struct prefix_evpn p;
1605 struct bgp_node *rn;
1606 struct bgp_info *ri;
1607 u_int32_t path_cnt = 0;
1608 afi_t afi;
1609 safi_t safi;
9c92b5f7 1610 json_object *json_paths = NULL;
d62a17ae 1611
1612 afi = AFI_L2VPN;
1613 safi = SAFI_EVPN;
1614
1615 /* Locate VNI. */
1616 vpn = bgp_evpn_lookup_vni(bgp, vni);
1617 if (!vpn) {
9c92b5f7
MK
1618 if (!json)
1619 vty_out(vty, "VNI not found\n");
d62a17ae 1620 return;
1621 }
1622
1623 /* See if route exists. Look for both non-sticky and sticky. */
1624 build_evpn_type2_prefix(&p, mac, ip);
1625 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1626 if (!rn || !rn->info) {
9c92b5f7
MK
1627 if (!json)
1628 vty_out(vty, "%% Network not in table\n");
d62a17ae 1629 return;
1630 }
1631
9c92b5f7
MK
1632 if (json)
1633 json_paths = json_object_new_array();
1634
d62a17ae 1635 /* Prefix and num paths displayed once per prefix. */
9c92b5f7 1636 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
d62a17ae 1637
1638 /* Display each path for this prefix. */
1639 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
1640 json_object *json_path = NULL;
1641
1642 if (json)
1643 json_path = json_object_new_array();
1644
1645 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1646 json_path);
1647
1648 if (json)
1649 json_object_array_add(json_paths, json_path);
1650
d62a17ae 1651 path_cnt++;
1652 }
1653
9c92b5f7
MK
1654 if (json) {
1655 if (path_cnt)
1656 json_object_object_add(json, "paths", json_paths);
1657
1658 json_object_int_add(json, "numPaths", path_cnt);
1659 } else {
1660 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1661 path_cnt);
1662 }
520d5d76 1663}
1664
1665/*
1666 * Display EVPN routes for a VNI - vty handler.
1667 * If 'type' is non-zero, only routes matching that type are shown.
1668 * If the vtep_ip is non zero, only routes behind that vtep are shown
1669 */
d62a17ae 1670static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
9c92b5f7
MK
1671 int type, struct in_addr vtep_ip,
1672 json_object *json)
520d5d76 1673{
d62a17ae 1674 struct bgpevpn *vpn;
520d5d76 1675
d62a17ae 1676 /* Locate VNI. */
1677 vpn = bgp_evpn_lookup_vni(bgp, vni);
1678 if (!vpn) {
9c92b5f7
MK
1679 if (!json)
1680 vty_out(vty, "VNI not found\n");
d62a17ae 1681 return;
1682 }
520d5d76 1683
d62a17ae 1684 /* Walk this VNI's route table and display appropriate routes. */
9c92b5f7 1685 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
520d5d76 1686}
1687
1688/*
1689 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1690 * IP (vty handler). By definition, only matching type-2 route will be
1691 * displayed.
1692 */
d62a17ae 1693static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
1694 struct prefix_rd *prd, struct ethaddr *mac,
9c92b5f7 1695 struct ipaddr *ip, json_object *json)
d62a17ae 1696{
1697 struct prefix_evpn p;
1698 struct bgp_node *rn;
1699 struct bgp_info *ri;
1700 afi_t afi;
1701 safi_t safi;
1702 u_int32_t path_cnt = 0;
9c92b5f7
MK
1703 json_object *json_paths = NULL;
1704 char prefix_str[BUFSIZ];
d62a17ae 1705
1706 afi = AFI_L2VPN;
1707 safi = SAFI_EVPN;
1708
1709 /* See if route exists. Look for both non-sticky and sticky. */
1710 build_evpn_type2_prefix(&p, mac, ip);
1711 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
1712 (struct prefix *)&p, prd);
1713 if (!rn || !rn->info) {
9c92b5f7
MK
1714 if (!json)
1715 vty_out(vty, "%% Network not in table\n");
d62a17ae 1716 return;
1717 }
1718
9c92b5f7
MK
1719 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
1720 sizeof(prefix_str));
1721
d62a17ae 1722 /* Prefix and num paths displayed once per prefix. */
9c92b5f7
MK
1723 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
1724
1725 if (json)
1726 json_paths = json_object_new_array();
d62a17ae 1727
1728 /* Display each path for this prefix. */
1729 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
1730 json_object *json_path = NULL;
1731
1732 if (json)
1733 json_path = json_object_new_array();
1734
1735 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1736 json_path);
1737
1738 if (json)
1739 json_object_array_add(json_paths, json_path);
1740
d62a17ae 1741 path_cnt++;
1742 }
1743
9c92b5f7
MK
1744 if (json && path_cnt) {
1745 if (path_cnt)
1746 json_object_object_add(json, prefix_str, json_paths);
1747 json_object_int_add(json, "numPaths", path_cnt);
1748 } else {
1749 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1750 path_cnt);
1751 }
520d5d76 1752}
1753
1754/*
1755 * Display BGP EVPN routing table -- for specific RD (vty handler)
1756 * If 'type' is non-zero, only routes matching that type are shown.
1757 */
d62a17ae 1758static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
9c92b5f7
MK
1759 struct prefix_rd *prd, int type,
1760 json_object *json)
d62a17ae 1761{
1762 struct bgp_node *rd_rn;
1763 struct bgp_table *table;
1764 struct bgp_node *rn;
1765 struct bgp_info *ri;
1766 int rd_header = 1;
1767 afi_t afi;
1768 safi_t safi;
1769 u_int32_t prefix_cnt, path_cnt;
9c92b5f7
MK
1770 char rd_str[RD_ADDRSTRLEN];
1771 json_object *json_rd = NULL;
1772 int add_rd_to_json = 0;
d62a17ae 1773
1774 afi = AFI_L2VPN;
1775 safi = SAFI_EVPN;
1776 prefix_cnt = path_cnt = 0;
1777
9c92b5f7
MK
1778 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
1779
d62a17ae 1780 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
1781 if (!rd_rn)
1782 return;
9c92b5f7 1783
d62a17ae 1784 table = (struct bgp_table *)rd_rn->info;
1785 if (table == NULL)
1786 return;
1787
9c92b5f7
MK
1788 if (json) {
1789 json_rd = json_object_new_object();
1790 json_object_string_add(json_rd, "rd", rd_str);
1791 }
1792
d62a17ae 1793 /* Display all prefixes with this RD. */
1794 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
1795 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
9c92b5f7
MK
1796 json_object *json_prefix = NULL;
1797 json_object *json_paths = NULL;
1798 char prefix_str[BUFSIZ];
1799 int add_prefix_to_json = 0;
1800
1801 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
1802 sizeof(prefix_str));
d62a17ae 1803
1804 if (type && evp->prefix.route_type != type)
1805 continue;
1806
9c92b5f7
MK
1807 if (json)
1808 json_prefix = json_object_new_object();
1809
d62a17ae 1810 if (rn->info) {
1811 /* RD header and legend - once overall. */
9c92b5f7 1812 if (rd_header && !json) {
d62a17ae 1813 vty_out(vty,
1814 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1815 "[MAC]\n");
1816 vty_out(vty,
1817 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1818 "[OrigIP]\n\n");
1819 rd_header = 0;
1820 }
1821
1822 /* Prefix and num paths displayed once per prefix. */
1823 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
9c92b5f7 1824 safi, json_prefix);
d62a17ae 1825
1826 prefix_cnt++;
1827 }
1828
9c92b5f7
MK
1829 if (json)
1830 json_paths = json_object_new_array();
1831
d62a17ae 1832 /* Display each path for this prefix. */
1833 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7
MK
1834 json_object *json_path = NULL;
1835
1836 if (json)
1837 json_path = json_object_new_array();
1838
d62a17ae 1839 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
9c92b5f7
MK
1840 json_path);
1841
1842 if (json)
1843 json_object_array_add(json_paths, json_path);
1844
d62a17ae 1845 path_cnt++;
9c92b5f7
MK
1846 add_prefix_to_json = 1;
1847 add_rd_to_json = 1;
1848 }
1849
1850 if (json && add_prefix_to_json) {
1851 json_object_object_add(json_prefix, "paths",
1852 json_paths);
1853 json_object_object_add(json_rd, prefix_str,
1854 json_prefix);
d62a17ae 1855 }
1856 }
1857
9c92b5f7
MK
1858 if (json && add_rd_to_json)
1859 json_object_object_add(json, rd_str, json_rd);
1860
1861 if (json) {
1862 json_object_int_add(json, "numPrefix", prefix_cnt);
1863 json_object_int_add(json, "numPaths", path_cnt);
1864 } else {
1865 if (prefix_cnt == 0)
1866 vty_out(vty, "No prefixes exist with this RD%s\n",
1867 type ? " (of requested type)" : "");
1868 else
1869 vty_out(vty,
1870 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
1871 prefix_cnt, path_cnt,
1872 type ? " (of requested type)" : "");
1873 }
520d5d76 1874}
1875
1876/*
1877 * Display BGP EVPN routing table - all routes (vty handler).
1878 * If 'type' is non-zero, only routes matching that type are shown.
1879 */
9c92b5f7
MK
1880static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
1881 json_object *json)
d62a17ae 1882{
1883 struct bgp_node *rd_rn;
1884 struct bgp_table *table;
1885 struct bgp_node *rn;
1886 struct bgp_info *ri;
1887 int header = 1;
1888 int rd_header;
1889 afi_t afi;
1890 safi_t safi;
1891 u_int32_t prefix_cnt, path_cnt;
1892
1893 afi = AFI_L2VPN;
1894 safi = SAFI_EVPN;
1895 prefix_cnt = path_cnt = 0;
1896
1897 /* EVPN routing table is a 2-level table with the first level being
1898 * the RD.
1899 */
1900 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
1901 rd_rn = bgp_route_next(rd_rn)) {
9c92b5f7
MK
1902 char rd_str[RD_ADDRSTRLEN];
1903 json_object *json_rd = NULL; /* contains routes for an RD */
1904 int add_rd_to_json = 0;
1905
d62a17ae 1906 table = (struct bgp_table *)rd_rn->info;
1907 if (table == NULL)
1908 continue;
1909
9c92b5f7
MK
1910 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
1911 sizeof(rd_str));
1912
1913 if (json) {
1914 json_rd = json_object_new_object();
1915 json_object_string_add(json_rd, "rd", rd_str);
1916 }
1917
d62a17ae 1918 rd_header = 1;
1919
1920 /* Display all prefixes for an RD */
1921 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
9c92b5f7
MK
1922 json_object *json_prefix =
1923 NULL; /* contains prefix under a RD */
1924 json_object *json_paths =
1925 NULL; /* array of paths under a prefix*/
d62a17ae 1926 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
9c92b5f7
MK
1927 char prefix_str[BUFSIZ];
1928 int add_prefix_to_json = 0;
1929
1930 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
1931 prefix_str, sizeof(prefix_str));
d62a17ae 1932
1933 if (type && evp->prefix.route_type != type)
1934 continue;
1935
1936 if (rn->info) {
1937 /* Overall header/legend displayed once. */
1938 if (header) {
9c92b5f7
MK
1939 bgp_evpn_show_route_header(vty, bgp,
1940 json);
d62a17ae 1941 header = 0;
1942 }
1943
1944 /* RD header - per RD. */
1945 if (rd_header) {
9c92b5f7
MK
1946 bgp_evpn_show_route_rd_header(
1947 vty, rd_rn, json);
d62a17ae 1948 rd_header = 0;
1949 }
1950
1951 prefix_cnt++;
1952 }
1953
9c92b5f7
MK
1954 if (json) {
1955 json_prefix = json_object_new_object();
1956 json_paths = json_object_new_array();
1957 json_object_string_add(json_prefix, "prefix",
1958 prefix_str);
1959 json_object_int_add(json_prefix, "prefixLen",
1960 rn->p.prefixlen);
1961 }
1962
d62a17ae 1963 /* For EVPN, the prefix is displayed for each path (to
1964 * fit in
1965 * with code that already exists).
1966 */
1967 for (ri = rn->info; ri; ri = ri->next) {
9c92b5f7 1968 json_object *json_path = NULL;
d62a17ae 1969 path_cnt++;
9c92b5f7
MK
1970 add_prefix_to_json = 1;
1971 add_rd_to_json = 1;
1972
1973 if (json)
1974 json_path = json_object_new_array();
1975
d62a17ae 1976 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
9c92b5f7
MK
1977 json_path);
1978
1979 if (json)
1980 json_object_array_add(json_paths,
1981 json_path);
1982 }
1983
1984 if (json && add_prefix_to_json) {
1985 json_object_object_add(json_prefix, "paths",
1986 json_paths);
1987 json_object_object_add(json_rd, prefix_str,
1988 json_prefix);
d62a17ae 1989 }
1990 }
9c92b5f7
MK
1991
1992 if (json && add_rd_to_json)
1993 json_object_object_add(json, rd_str, json_rd);
d62a17ae 1994 }
1995
9c92b5f7
MK
1996 if (json) {
1997 json_object_int_add(json, "numPrefix", prefix_cnt);
1998 json_object_int_add(json, "numPaths", path_cnt);
1999 } else {
2000 if (prefix_cnt == 0) {
2001 vty_out(vty, "No EVPN prefixes %sexist\n",
2002 type ? "(of requested type) " : "");
2003 } else {
2004 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2005 prefix_cnt, path_cnt,
2006 type ? " (of requested type)" : "");
2007 }
2008 }
520d5d76 2009}
2010
2011/*
2012 * Display specified VNI (vty handler)
2013 */
9c92b5f7
MK
2014static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2015 json_object *json)
520d5d76 2016{
d62a17ae 2017 struct bgpevpn *vpn;
520d5d76 2018
d62a17ae 2019 vpn = bgp_evpn_lookup_vni(bgp, vni);
2020 if (!vpn) {
9c92b5f7
MK
2021 if (json) {
2022 vty_out(vty, "{}\n");
2023 } else {
2024 vty_out(vty, "VNI not found\n");
2025 return;
2026 }
d62a17ae 2027 }
520d5d76 2028
9c92b5f7 2029 display_vni(vty, vpn, json);
520d5d76 2030}
2031
2032/*
2033 * Display a VNI (upon user query).
2034 */
9c92b5f7
MK
2035static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2036 json_object *json)
520d5d76 2037{
d62a17ae 2038 u_int32_t num_vnis;
9c92b5f7 2039 void *args[2];
520d5d76 2040
d62a17ae 2041 num_vnis = hashcount(bgp->vnihash);
2042 if (!num_vnis)
2043 return;
9c92b5f7
MK
2044
2045 if (json) {
2046 json_object_int_add(json, "numVnis", num_vnis);
2047 } else {
2048 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
2049 vty_out(vty, "Flags: * - Kernel\n");
2050 vty_out(vty, " %-10s %-15s %-21s %-25s %-25s\n", "VNI",
2051 "Orig IP", "RD", "Import RT", "Export RT");
2052 }
2053
2054 args[0] = vty;
2055 args[1] = json;
d62a17ae 2056 hash_iterate(bgp->vnihash,
2057 (void (*)(struct hash_backet *, void *))show_vni_entry,
9c92b5f7 2058 args);
520d5d76 2059}
2060
1a98c087
MK
2061/*
2062 * evpn - enable advertisement of default g/w
2063 */
2064static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2065{
2066 if (!vpn) {
2067 if (bgp->advertise_gw_macip)
2068 return;
2069
2070 bgp->advertise_gw_macip = 1;
2071 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2072 } else {
2073 if (vpn->advertise_gw_macip)
2074 return;
2075
2076 vpn->advertise_gw_macip = 1;
2077 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2078 vpn->vni);
2079 }
2080 return;
2081}
2082
2083/*
2084 * evpn - disable advertisement of default g/w
2085 */
2086static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2087 struct bgpevpn *vpn)
2088{
2089 if (!vpn) {
2090 if (!bgp->advertise_gw_macip)
2091 return;
2092
2093 bgp->advertise_gw_macip = 0;
2094 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2095 } else {
2096 if (!vpn->advertise_gw_macip)
2097 return;
2098
2099 vpn->advertise_gw_macip = 0;
2100 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2101 vpn->vni);
2102 }
2103 return;
2104}
2105
7724c0a1 2106/*
2107 * EVPN (VNI advertisement) enabled. Register with zebra.
2108 */
d62a17ae 2109static void evpn_set_advertise_all_vni(struct bgp *bgp)
7724c0a1 2110{
d62a17ae 2111 bgp->advertise_all_vni = 1;
2112 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
7724c0a1 2113}
2114
2115/*
2116 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2117 * cache, EVPN routes (delete and withdraw from peers).
2118 */
d62a17ae 2119static void evpn_unset_advertise_all_vni(struct bgp *bgp)
7724c0a1 2120{
d62a17ae 2121 bgp->advertise_all_vni = 0;
2122 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2123 bgp_evpn_cleanup_on_disable(bgp);
7724c0a1 2124}
8c197128 2125#endif /* HAVE_CUMULUS */
7724c0a1 2126
d62a17ae 2127static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write)
2128{
2129 char buf1[INET6_ADDRSTRLEN];
2130 afi_t afi = AFI_L2VPN;
2131 safi_t safi = SAFI_EVPN;
2132 char *ecom_str;
2133 struct listnode *node, *nnode;
2134 struct ecommunity *ecom;
2135
2136 if (is_vni_configured(vpn)) {
2137 bgp_config_write_family_header(vty, afi, safi, write);
2138 vty_out(vty, " vni %d\n", vpn->vni);
2139 if (is_rd_configured(vpn))
2140 vty_out(vty, " rd %s\n",
2141 prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN));
2142
2143 if (is_import_rt_configured(vpn)) {
2144 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2145 ecom)) {
2146 ecom_str = ecommunity_ecom2str(
2147 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2148 vty_out(vty, " route-target import %s\n",
2149 ecom_str);
2150 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2151 }
2152 }
2153
2154 if (is_export_rt_configured(vpn)) {
2155 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2156 ecom)) {
2157 ecom_str = ecommunity_ecom2str(
2158 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
640751c7 2159 vty_out(vty, " route-target export %s\n",
d62a17ae 2160 ecom_str);
2161 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2162 }
2163 }
2164
1a98c087
MK
2165 if (vpn->advertise_gw_macip)
2166 vty_out(vty, " advertise-default-gw\n");
2167
d62a17ae 2168 vty_out(vty, " exit-vni\n");
2169 }
2170}
2171
2172static void write_vni_config_for_entry(struct hash_backet *backet,
2173 struct evpn_config_write *cfg)
2174{
2175 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
2176 write_vni_config(cfg->vty, vpn, &cfg->write);
2177}
2178
2179#if defined(HAVE_CUMULUS)
1a98c087
MK
2180DEFUN (bgp_evpn_advertise_default_gw_vni,
2181 bgp_evpn_advertise_default_gw_vni_cmd,
2182 "advertise-default-gw",
2183 "Advertise defualt g/w mac-ip routes in EVPN for a VNI\n")
2184{
2185 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2186 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2187
2188 if (!bgp)
2189 return CMD_WARNING;
2190
2191 if (!vpn)
2192 return CMD_WARNING;
2193
2194 evpn_set_advertise_default_gw(bgp, vpn);
2195
2196 return CMD_SUCCESS;
2197}
2198
2199DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2200 no_bgp_evpn_advertise_default_gw_vni_cmd,
2201 "no advertise-default-gw",
2202 NO_STR
2203 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2204{
2205 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2206 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2207
2208 if (!bgp)
2209 return CMD_WARNING;
2210
2211 if (!vpn)
2212 return CMD_WARNING;
2213
2214 evpn_unset_advertise_default_gw(bgp, vpn);
2215
2216 return CMD_SUCCESS;
2217}
2218
2219
2220DEFUN (bgp_evpn_advertise_default_gw,
2221 bgp_evpn_advertise_default_gw_cmd,
2222 "advertise-default-gw",
2223 "Advertise All defualt g/w mac-ip routes in EVPN\n")
2224{
2225 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2226
2227 if (!bgp)
2228 return CMD_WARNING;
2229
2230 evpn_set_advertise_default_gw(bgp, NULL);
2231
2232 return CMD_SUCCESS;
2233}
2234
2235DEFUN (no_bgp_evpn_advertise_default_gw,
2236 no_bgp_evpn_advertise_default_gw_cmd,
2237 "no advertise-default-gw",
2238 NO_STR
2239 "Withdraw All default g/w mac-ip routes from EVPN\n")
2240{
2241 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2242
2243 if (!bgp)
2244 return CMD_WARNING;
2245
2246 evpn_unset_advertise_default_gw(bgp, NULL);
2247
2248 return CMD_SUCCESS;
2249}
2250
7724c0a1 2251DEFUN (bgp_evpn_advertise_all_vni,
2252 bgp_evpn_advertise_all_vni_cmd,
2253 "advertise-all-vni",
2254 "Advertise All local VNIs\n")
2255{
d62a17ae 2256 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2257
d62a17ae 2258 if (!bgp)
2259 return CMD_WARNING;
2260 evpn_set_advertise_all_vni(bgp);
2261 return CMD_SUCCESS;
7724c0a1 2262}
2263
2264DEFUN (no_bgp_evpn_advertise_all_vni,
2265 no_bgp_evpn_advertise_all_vni_cmd,
2266 "no advertise-all-vni",
2267 NO_STR
2268 "Advertise All local VNIs\n")
2269{
d62a17ae 2270 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7724c0a1 2271
d62a17ae 2272 if (!bgp)
2273 return CMD_WARNING;
2274 evpn_unset_advertise_all_vni(bgp);
2275 return CMD_SUCCESS;
7724c0a1 2276}
2277
f2d62262 2278/*
2279 * Display VNI information - for all or a specific VNI
2280 */
9c92b5f7
MK
2281DEFUN(show_bgp_l2vpn_evpn_vni,
2282 show_bgp_l2vpn_evpn_vni_cmd,
2283 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2284 SHOW_STR
2285 BGP_STR
2286 L2VPN_HELP_STR
2287 EVPN_HELP_STR
2288 "Show VNI\n"
2289 "VNI number\n"
2290 JSON_STR)
520d5d76 2291{
d62a17ae 2292 struct bgp *bgp;
f2d62262 2293 vni_t vni;
2294 int idx = 0;
9c92b5f7
MK
2295 u_char uj = 0;
2296 json_object *json = NULL;
2297
2298 uj = use_json(argc, argv);
520d5d76 2299
d62a17ae 2300 bgp = bgp_get_default();
2301 if (!bgp)
2302 return CMD_WARNING;
520d5d76 2303
f2d62262 2304 if (!argv_find(argv, argc, "evpn", &idx))
2305 return CMD_WARNING;
2306
9c92b5f7
MK
2307 if (uj)
2308 json = json_object_new_object();
1a98c087 2309
9c92b5f7
MK
2310 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
2311 if (uj) {
2312 json_object_string_add(json, "advertiseGatewayMacip",
2313 bgp->advertise_gw_macip
2314 ? "Enabled"
2315 : "Disabled");
2316 json_object_string_add(json, "advertiseAllVnis",
2317 bgp->advertise_all_vni
2318 ? "Enabled"
2319 : "Disabled");
2320 } else {
2321 vty_out(vty, "Advertise Gateway Macip: %s\n",
2322 bgp->advertise_gw_macip ? "Enabled"
2323 : "Disabled");
2324
2325 /* Display all VNIs */
2326 vty_out(vty, "Advertise All VNI flag: %s\n",
2327 bgp->advertise_all_vni ? "Enabled"
2328 : "Disabled");
2329 }
2330
2331 evpn_show_all_vnis(vty, bgp, json);
f2d62262 2332 } else {
9c92b5f7
MK
2333 int vni_idx = 0;
2334
2335 if (!argv_find(argv, argc, "vni", &vni_idx))
2336 return CMD_WARNING;
2337
f2d62262 2338 /* Display specific VNI */
9c92b5f7
MK
2339 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
2340 evpn_show_vni(vty, bgp, vni, json);
2341 }
2342
2343 if (uj) {
2344 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2345 json, JSON_C_TO_STRING_PRETTY));
2346 json_object_free(json);
f2d62262 2347 }
520d5d76 2348
d62a17ae 2349 return CMD_SUCCESS;
520d5d76 2350}
2351
f2d62262 2352/*
2353 * Display EVPN neighbor summary.
2354 */
9c92b5f7
MK
2355DEFUN(show_bgp_l2vpn_evpn_summary,
2356 show_bgp_l2vpn_evpn_summary_cmd,
2357 "show bgp l2vpn evpn summary [json]",
2358 SHOW_STR
2359 BGP_STR
2360 L2VPN_HELP_STR
2361 EVPN_HELP_STR
2362 "Summary of BGP neighbor status\n"
2363 JSON_STR)
520d5d76 2364{
d62a17ae 2365 u_char uj = use_json(argc, argv);
2366 return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
520d5d76 2367}
2368
f2d62262 2369/*
2370 * Display global EVPN routing table.
2371 */
9c92b5f7
MK
2372DEFUN(show_bgp_l2vpn_evpn_route, show_bgp_l2vpn_evpn_route_cmd,
2373 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2374 SHOW_STR
2375 BGP_STR
2376 L2VPN_HELP_STR
2377 EVPN_HELP_STR
2378 "EVPN route information\n"
2379 "Specify Route type\n"
2380 "MAC-IP (Type-2) route\n"
2381 "Multicast (Type-3) route\n"
2382 JSON_STR)
520d5d76 2383{
d62a17ae 2384 struct bgp *bgp;
9c92b5f7 2385 int type_idx;
d62a17ae 2386 int type = 0;
9c92b5f7
MK
2387 u_char uj = 0;
2388 json_object *json = NULL;
2389
2390 uj = use_json(argc, argv);
520d5d76 2391
d62a17ae 2392 bgp = bgp_get_default();
2393 if (!bgp)
2394 return CMD_WARNING;
520d5d76 2395
9c92b5f7
MK
2396 if (uj)
2397 json = json_object_new_object();
f2d62262 2398
9c92b5f7
MK
2399 /* get the type */
2400 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 2401 /* Specific type is requested */
9c92b5f7 2402 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 2403 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 2404 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 2405 type = BGP_EVPN_IMET_ROUTE;
2406 else
2407 return CMD_WARNING;
2408 }
520d5d76 2409
9c92b5f7
MK
2410 evpn_show_all_routes(vty, bgp, type, json);
2411
2412 if (uj) {
2413 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2414 json, JSON_C_TO_STRING_PRETTY));
2415 json_object_free(json);
2416 }
2417
d62a17ae 2418 return CMD_SUCCESS;
520d5d76 2419}
2420
f2d62262 2421/*
2422 * Display global EVPN routing table for specific RD.
2423 */
9c92b5f7
MK
2424DEFUN(show_bgp_l2vpn_evpn_route_rd, show_bgp_l2vpn_evpn_route_rd_cmd,
2425 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]",
2426 SHOW_STR
2427 BGP_STR
2428 L2VPN_HELP_STR
2429 EVPN_HELP_STR
2430 "EVPN route information\n"
2431 "Route Distinguisher\n"
2432 "ASN:XX or A.B.C.D:XX\n"
2433 "Specify Route type\n"
2434 "MAC-IP (Type-2) route\n"
2435 "Multicast (Type-3) route\n"
2436 JSON_STR)
520d5d76 2437{
d62a17ae 2438 struct bgp *bgp;
2439 int ret;
2440 struct prefix_rd prd;
2441 int type = 0;
9c92b5f7
MK
2442 int rd_idx = 0;
2443 int type_idx = 0;
2444 int uj = 0;
2445 json_object *json = NULL;
520d5d76 2446
d62a17ae 2447 bgp = bgp_get_default();
2448 if (!bgp)
2449 return CMD_WARNING;
520d5d76 2450
9c92b5f7
MK
2451 /* check if we need json output */
2452 uj = use_json(argc, argv);
2453 if (uj)
2454 json = json_object_new_object();
f2d62262 2455
9c92b5f7
MK
2456 /* get the RD */
2457 if (argv_find(argv, argc, "rd", &rd_idx)) {
2458 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2459
2460 if (!ret) {
2461 vty_out(vty, "%% Malformed Route Distinguisher\n");
2462 return CMD_WARNING;
2463 }
d62a17ae 2464 }
520d5d76 2465
9c92b5f7
MK
2466 /* get the type */
2467 if (argv_find(argv, argc, "type", &type_idx)) {
f2d62262 2468 /* Specific type is requested */
9c92b5f7 2469 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
d62a17ae 2470 type = BGP_EVPN_MAC_IP_ROUTE;
9c92b5f7 2471 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
d62a17ae 2472 type = BGP_EVPN_IMET_ROUTE;
2473 else
2474 return CMD_WARNING;
2475 }
520d5d76 2476
9c92b5f7
MK
2477 evpn_show_route_rd(vty, bgp, &prd, type, json);
2478
2479 if (uj) {
2480 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2481 json, JSON_C_TO_STRING_PRETTY));
2482 json_object_free(json);
2483 }
2484
d62a17ae 2485 return CMD_SUCCESS;
520d5d76 2486}
2487
f2d62262 2488/*
2489 * Display global EVPN routing table for specific RD and MACIP.
2490 */
9c92b5f7
MK
2491DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
2492 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
2493 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]",
2494 SHOW_STR
2495 BGP_STR
2496 L2VPN_HELP_STR
2497 EVPN_HELP_STR
2498 "EVPN route information\n"
2499 "Route Distinguisher\n"
2500 "ASN:XX or A.B.C.D:XX\n"
2501 "MAC\n"
2502 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2503 "IP\n"
2504 "IP address (IPv4 or IPv6)\n"
2505 JSON_STR)
2506{
2507 struct bgp *bgp;
2508 int ret;
2509 struct prefix_rd prd;
2510 struct ethaddr mac;
2511 struct ipaddr ip;
2512 int rd_idx = 0;
2513 int mac_idx = 0;
2514 int ip_idx = 0;
2515 int uj = 0;
2516 json_object *json = NULL;
2517
2518 memset(&mac, 0, sizeof(struct ethaddr));
2519 memset(&ip, 0, sizeof(struct ipaddr));
d62a17ae 2520
2521 bgp = bgp_get_default();
2522 if (!bgp)
2523 return CMD_WARNING;
2524
9c92b5f7
MK
2525 /* check if we need json output */
2526 uj = use_json(argc, argv);
2527 if (uj)
2528 json = json_object_new_object();
f2d62262 2529
9c92b5f7
MK
2530 /* get the prd */
2531 if (argv_find(argv, argc, "rd", &rd_idx)) {
2532 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2533 if (!ret) {
2534 vty_out(vty, "%% Malformed Route Distinguisher\n");
2535 return CMD_WARNING;
2536 }
d62a17ae 2537 }
9c92b5f7
MK
2538
2539 /* get the mac */
2540 if (argv_find(argv, argc, "mac", &mac_idx)) {
2541 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
2542 vty_out(vty, "%% Malformed MAC address\n");
2543 return CMD_WARNING;
2544 }
d62a17ae 2545 }
9c92b5f7
MK
2546
2547 /* get the ip if specified */
2548 if (argv_find(argv, argc, "ip", &ip_idx)) {
2549 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
d62a17ae 2550 vty_out(vty, "%% Malformed IP address\n");
2551 return CMD_WARNING;
2552 }
2553 }
2554
9c92b5f7
MK
2555 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
2556
2557 if (uj) {
2558 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2559 json, JSON_C_TO_STRING_PRETTY));
2560 json_object_free(json);
2561 }
2562
d62a17ae 2563 return CMD_SUCCESS;
520d5d76 2564}
2565
f2d62262 2566/*
2567 * Display per-VNI EVPN routing table.
2568 */
9c92b5f7
MK
2569DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
2570 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2571 SHOW_STR
2572 BGP_STR
2573 L2VPN_HELP_STR
2574 EVPN_HELP_STR
2575 "EVPN route information\n"
2576 "VXLAN Network Identifier\n"
2577 "VNI number\n"
2578 "Specify Route type\n"
2579 "MAC-IP (Type-2) route\n"
2580 "Multicast (Type-3) route\n"
2581 "Remote VTEP\n"
2582 "Remote VTEP IP address\n"
2583 JSON_STR)
520d5d76 2584{
d62a17ae 2585 vni_t vni;
2586 struct bgp *bgp;
2587 struct in_addr vtep_ip;
2588 int type = 0;
f2d62262 2589 int idx = 0;
9c92b5f7
MK
2590 int uj = 0;
2591 json_object *json = NULL;
d62a17ae 2592
2593 bgp = bgp_get_default();
2594 if (!bgp)
2595 return CMD_WARNING;
2596
9c92b5f7
MK
2597 /* check if we need json output */
2598 uj = use_json(argc, argv);
2599 if (uj)
2600 json = json_object_new_object();
2601
f2d62262 2602 if (!argv_find(argv, argc, "evpn", &idx))
2603 return CMD_WARNING;
2604
d62a17ae 2605 vtep_ip.s_addr = 0;
2606
f2d62262 2607 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
d62a17ae 2608
9c92b5f7
MK
2609 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
2610 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
f2d62262 2611 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
2612 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
d62a17ae 2613 type = BGP_EVPN_MAC_IP_ROUTE;
f2d62262 2614 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
d62a17ae 2615 type = BGP_EVPN_IMET_ROUTE;
2616 else
2617 return CMD_WARNING;
f2d62262 2618 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
2619 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 2620 vty_out(vty, "%% Malformed VTEP IP address\n");
2621 return CMD_WARNING;
2622 }
2623 } else
2624 return CMD_WARNING;
2625 }
2626
9c92b5f7
MK
2627 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
2628
2629 if (uj) {
2630 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2631 json, JSON_C_TO_STRING_PRETTY));
2632 json_object_free(json);
2633 }
2634
d62a17ae 2635 return CMD_SUCCESS;
520d5d76 2636}
2637
f2d62262 2638/*
2639 * Display per-VNI EVPN routing table for specific MACIP.
2640 */
9c92b5f7
MK
2641DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
2642 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
2643 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2644 SHOW_STR
2645 BGP_STR
2646 L2VPN_HELP_STR
2647 EVPN_HELP_STR
2648 "EVPN route information\n"
2649 "VXLAN Network Identifier\n"
2650 "VNI number\n"
2651 "MAC\n"
2652 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2653 "IP\n"
2654 "IP address (IPv4 or IPv6)\n"
2655 JSON_STR)
520d5d76 2656{
d62a17ae 2657 vni_t vni;
2658 struct bgp *bgp;
2659 struct ethaddr mac;
2660 struct ipaddr ip;
f2d62262 2661 int idx = 0;
9c92b5f7
MK
2662 int uj = 0;
2663 json_object *json = NULL;
d62a17ae 2664
2665 bgp = bgp_get_default();
2666 if (!bgp)
2667 return CMD_WARNING;
2668
9c92b5f7
MK
2669 /* check if we need json output */
2670 uj = use_json(argc, argv);
2671 if (uj)
2672 json = json_object_new_object();
2673
f2d62262 2674 if (!argv_find(argv, argc, "evpn", &idx))
2675 return CMD_WARNING;
2676
9c92b5f7 2677 /* get the VNI */
f2d62262 2678 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
2679
2680 /* get the mac */
f2d62262 2681 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
d62a17ae 2682 vty_out(vty, "%% Malformed MAC address\n");
2683 return CMD_WARNING;
2684 }
9c92b5f7
MK
2685
2686 /* get the ip */
d62a17ae 2687 memset(&ip, 0, sizeof(ip));
9c92b5f7
MK
2688 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
2689 || (uj
2690 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
f2d62262 2691 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
d62a17ae 2692 vty_out(vty, "%% Malformed IP address\n");
2693 return CMD_WARNING;
2694 }
2695 }
2696
9c92b5f7
MK
2697 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
2698
2699 if (uj) {
2700 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2701 json, JSON_C_TO_STRING_PRETTY));
2702 json_object_free(json);
2703 }
2704
d62a17ae 2705 return CMD_SUCCESS;
520d5d76 2706}
2707
f2d62262 2708/*
2709 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
2710 */
9c92b5f7
MK
2711DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
2712 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
2713 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
2714 SHOW_STR
2715 BGP_STR
2716 L2VPN_HELP_STR
2717 EVPN_HELP_STR
2718 "EVPN route information\n"
2719 "VXLAN Network Identifier\n"
2720 "VNI number\n"
2721 "Multicast (Type-3) route\n"
2722 "Originating Router IP address\n"
2723 JSON_STR)
520d5d76 2724{
d62a17ae 2725 vni_t vni;
2726 struct bgp *bgp;
2727 int ret;
2728 struct in_addr orig_ip;
f2d62262 2729 int idx = 0;
9c92b5f7
MK
2730 int uj = 0;
2731 json_object *json = NULL;
520d5d76 2732
d62a17ae 2733 bgp = bgp_get_default();
2734 if (!bgp)
2735 return CMD_WARNING;
520d5d76 2736
9c92b5f7
MK
2737 /* check if we need json output */
2738 uj = use_json(argc, argv);
2739 if (uj)
2740 json = json_object_new_object();
2741
f2d62262 2742 if (!argv_find(argv, argc, "evpn", &idx))
2743 return CMD_WARNING;
2744
9c92b5f7 2745 /* get the VNI */
f2d62262 2746 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
9c92b5f7
MK
2747
2748 /* get the ip */
f2d62262 2749 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
d62a17ae 2750 if (!ret) {
2751 vty_out(vty, "%% Malformed Originating Router IP address\n");
2752 return CMD_WARNING;
2753 }
520d5d76 2754
9c92b5f7
MK
2755 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
2756
2757 if (uj) {
2758 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2759 json, JSON_C_TO_STRING_PRETTY));
2760 json_object_free(json);
2761 }
2762
d62a17ae 2763 return CMD_SUCCESS;
520d5d76 2764}
2765
f2d62262 2766/*
2767 * Display per-VNI EVPN routing table - for all VNIs.
2768 */
9c92b5f7
MK
2769DEFUN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_l2vpn_evpn_route_vni_all_cmd,
2770 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
2771 SHOW_STR
2772 BGP_STR
2773 L2VPN_HELP_STR
2774 EVPN_HELP_STR
2775 "EVPN route information\n"
2776 "VXLAN Network Identifier\n"
2777 "All VNIs\n"
2778 "Remote VTEP\n"
2779 "Remote VTEP IP address\n"
2780 JSON_STR)
520d5d76 2781{
d62a17ae 2782 struct bgp *bgp;
2783 struct in_addr vtep_ip;
f2d62262 2784 int idx = 0;
9c92b5f7
MK
2785 int uj = 0;
2786 json_object *json = NULL;
520d5d76 2787
d62a17ae 2788 bgp = bgp_get_default();
2789 if (!bgp)
2790 return CMD_WARNING;
520d5d76 2791
9c92b5f7
MK
2792 /* check if we need json output */
2793 uj = use_json(argc, argv);
2794 if (uj)
2795 json = json_object_new_object();
2796
f2d62262 2797 if (!argv_find(argv, argc, "evpn", &idx))
2798 return CMD_WARNING;
2799
d62a17ae 2800 vtep_ip.s_addr = 0;
9c92b5f7
MK
2801 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
2802 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
f2d62262 2803 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
d62a17ae 2804 vty_out(vty, "%% Malformed VTEP IP address\n");
2805 return CMD_WARNING;
2806 }
2807 }
520d5d76 2808
9c92b5f7
MK
2809 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
2810
2811 if (uj) {
2812 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2813 json, JSON_C_TO_STRING_PRETTY));
2814 json_object_free(json);
2815 }
2816
d62a17ae 2817 return CMD_SUCCESS;
520d5d76 2818}
2819
f2d62262 2820/*
2821 * Display EVPN import route-target hash table
2822 */
9c92b5f7
MK
2823DEFUN(show_bgp_l2vpn_evpn_import_rt, show_bgp_l2vpn_evpn_import_rt_cmd,
2824 "show bgp l2vpn evpn import-rt [json]",
2825 SHOW_STR
2826 BGP_STR
2827 L2VPN_HELP_STR
2828 EVPN_HELP_STR
2829 "Show import route target\n"
2830 JSON_STR)
520d5d76 2831{
d62a17ae 2832 struct bgp *bgp;
9c92b5f7
MK
2833 u_char uj = 0;
2834 json_object *json = NULL;
520d5d76 2835
d62a17ae 2836 bgp = bgp_get_default();
2837 if (!bgp)
2838 return CMD_WARNING;
520d5d76 2839
9c92b5f7
MK
2840 uj = use_json(argc, argv);
2841 if (uj)
2842 json = json_object_new_object();
2843
2844 evpn_show_import_rts(vty, bgp, json);
2845
2846 if (uj) {
2847 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2848 json, JSON_C_TO_STRING_PRETTY));
2849 json_object_free(json);
2850 }
2851
d62a17ae 2852 return CMD_SUCCESS;
520d5d76 2853}
2854
5014d96f
DW
2855#if defined(HAVE_CUMULUS)
2856ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
2857 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
2858 "Show VNI\n"
2859 "VNI number\n")
2860
2861ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
2862 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
2863 "Summary of BGP neighbor status\n"
a85b24cc 2864 JSON_STR)
5014d96f
DW
2865
2866ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
2867 "show bgp evpn route [type <macip|multicast>]",
2868 SHOW_STR BGP_STR EVPN_HELP_STR
2869 "EVPN route information\n"
2870 "Specify Route type\n"
2871 "MAC-IP (Type-2) route\n"
2872 "Multicast (Type-3) route\n")
2873
2874ALIAS_HIDDEN(
2875 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
2876 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
2877 SHOW_STR BGP_STR EVPN_HELP_STR
2878 "EVPN route information\n"
2879 "Route Distinguisher\n"
2880 "ASN:XX or A.B.C.D:XX\n"
2881 "Specify Route type\n"
2882 "MAC-IP (Type-2) route\n"
2883 "Multicast (Type-3) route\n")
2884
2885ALIAS_HIDDEN(
2886 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
2887 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
2888 SHOW_STR BGP_STR EVPN_HELP_STR
2889 "EVPN route information\n"
2890 "Route Distinguisher\n"
2891 "ASN:XX or A.B.C.D:XX\n"
2892 "MAC\n"
2893 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2894 "IP\n"
2895 "IP address (IPv4 or IPv6)\n")
2896
2897ALIAS_HIDDEN(
2898 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
2899 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
2900 SHOW_STR BGP_STR EVPN_HELP_STR
2901 "EVPN route information\n"
2902 "VXLAN Network Identifier\n"
2903 "VNI number\n"
2904 "Specify Route type\n"
2905 "MAC-IP (Type-2) route\n"
2906 "Multicast (Type-3) route\n"
2907 "Remote VTEP\n"
2908 "Remote VTEP IP address\n")
2909
2910ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
2911 show_bgp_evpn_route_vni_macip_cmd,
2912 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
2913 SHOW_STR BGP_STR EVPN_HELP_STR
2914 "EVPN route information\n"
2915 "VXLAN Network Identifier\n"
2916 "VNI number\n"
2917 "MAC\n"
2918 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2919 "IP\n"
2920 "IP address (IPv4 or IPv6)\n")
2921
2922ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
2923 show_bgp_evpn_route_vni_multicast_cmd,
2924 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2925 SHOW_STR BGP_STR EVPN_HELP_STR
2926 "EVPN route information\n"
2927 "VXLAN Network Identifier\n"
2928 "VNI number\n"
2929 "Multicast (Type-3) route\n"
2930 "Originating Router IP address\n")
2931
2932ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
2933 "show bgp evpn route vni all [vtep A.B.C.D]",
2934 SHOW_STR BGP_STR EVPN_HELP_STR
2935 "EVPN route information\n"
2936 "VXLAN Network Identifier\n"
2937 "All VNIs\n"
2938 "Remote VTEP\n"
2939 "Remote VTEP IP address\n")
2940
2941ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
2942 "show bgp evpn import-rt",
2943 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
2944#endif
2945
90e60aa7 2946DEFUN_NOSH (bgp_evpn_vni,
2947 bgp_evpn_vni_cmd,
2948 "vni (1-16777215)",
2949 "VXLAN Network Identifier\n"
2950 "VNI number\n")
2951{
d62a17ae 2952 vni_t vni;
2953 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2954 struct bgpevpn *vpn;
90e60aa7 2955
d62a17ae 2956 if (!bgp)
2957 return CMD_WARNING;
90e60aa7 2958
d62a17ae 2959 vni = strtoul(argv[1]->arg, NULL, 10);
90e60aa7 2960
d62a17ae 2961 /* Create VNI, or mark as configured. */
2962 vpn = evpn_create_update_vni(bgp, vni);
2963 if (!vpn) {
2964 vty_out(vty, "%% Failed to create VNI \n");
2965 return CMD_WARNING;
2966 }
90e60aa7 2967
d62a17ae 2968 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
2969 return CMD_SUCCESS;
90e60aa7 2970}
2971
2972DEFUN (no_bgp_evpn_vni,
2973 no_bgp_evpn_vni_cmd,
2974 "no vni (1-16777215)",
2975 NO_STR
2976 "VXLAN Network Identifier\n"
2977 "VNI number\n")
2978{
d62a17ae 2979 vni_t vni;
2980 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2981 struct bgpevpn *vpn;
90e60aa7 2982
d62a17ae 2983 if (!bgp)
2984 return CMD_WARNING;
90e60aa7 2985
d62a17ae 2986 vni = strtoul(argv[2]->arg, NULL, 10);
90e60aa7 2987
d62a17ae 2988 /* Check if we should disallow. */
2989 vpn = bgp_evpn_lookup_vni(bgp, vni);
2990 if (!vpn) {
2991 vty_out(vty, "%% Specified VNI does not exist\n");
2992 return CMD_WARNING;
2993 }
2994 if (!is_vni_configured(vpn)) {
2995 vty_out(vty, "%% Specified VNI is not configured\n");
2996 return CMD_WARNING;
2997 }
90e60aa7 2998
d62a17ae 2999 evpn_delete_vni(bgp, vpn);
3000 return CMD_SUCCESS;
90e60aa7 3001}
3002
3003DEFUN_NOSH (exit_vni,
3004 exit_vni_cmd,
3005 "exit-vni",
3006 "Exit from VNI mode\n")
3007{
d62a17ae 3008 if (vty->node == BGP_EVPN_VNI_NODE)
3009 vty->node = BGP_EVPN_NODE;
3010 return CMD_SUCCESS;
90e60aa7 3011}
3012
3013DEFUN (bgp_evpn_vni_rd,
3014 bgp_evpn_vni_rd_cmd,
3015 "rd ASN:nn_or_IP-address:nn",
3016 "Route Distinguisher\n"
3017 "ASN:XX or A.B.C.D:XX\n")
3018{
d62a17ae 3019 struct prefix_rd prd;
3020 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3021 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3022 int ret;
90e60aa7 3023
d62a17ae 3024 if (!bgp || !vpn)
3025 return CMD_WARNING;
90e60aa7 3026
d62a17ae 3027 ret = str2prefix_rd(argv[1]->arg, &prd);
3028 if (!ret) {
3029 vty_out(vty, "%% Malformed Route Distinguisher\n");
3030 return CMD_WARNING;
3031 }
90e60aa7 3032
d62a17ae 3033 /* If same as existing value, there is nothing more to do. */
3034 if (bgp_evpn_rd_matches_existing(vpn, &prd))
3035 return CMD_SUCCESS;
90e60aa7 3036
d62a17ae 3037 /* Configure or update the RD. */
3038 evpn_configure_rd(bgp, vpn, &prd);
3039 return CMD_SUCCESS;
90e60aa7 3040}
3041
3042DEFUN (no_bgp_evpn_vni_rd,
3043 no_bgp_evpn_vni_rd_cmd,
3044 "no rd ASN:nn_or_IP-address:nn",
3045 NO_STR
3046 "Route Distinguisher\n"
3047 "ASN:XX or A.B.C.D:XX\n")
3048{
d62a17ae 3049 struct prefix_rd prd;
3050 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3051 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3052 int ret;
90e60aa7 3053
d62a17ae 3054 if (!bgp || !vpn)
3055 return CMD_WARNING;
90e60aa7 3056
d62a17ae 3057 ret = str2prefix_rd(argv[2]->arg, &prd);
3058 if (!ret) {
3059 vty_out(vty, "%% Malformed Route Distinguisher\n");
3060 return CMD_WARNING;
3061 }
90e60aa7 3062
d62a17ae 3063 /* Check if we should disallow. */
3064 if (!is_rd_configured(vpn)) {
3065 vty_out(vty, "%% RD is not configured for this VNI\n");
3066 return CMD_WARNING;
3067 }
90e60aa7 3068
d62a17ae 3069 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
3070 vty_out(vty,
3071 "%% RD specified does not match configuration for this VNI\n");
3072 return CMD_WARNING;
3073 }
90e60aa7 3074
d62a17ae 3075 evpn_unconfigure_rd(bgp, vpn);
3076 return CMD_SUCCESS;
90e60aa7 3077}
3078
3079DEFUN (no_bgp_evpn_vni_rd_without_val,
3080 no_bgp_evpn_vni_rd_without_val_cmd,
3081 "no rd",
3082 NO_STR
3083 "Route Distinguisher\n")
3084{
d62a17ae 3085 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3086 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
90e60aa7 3087
d62a17ae 3088 if (!bgp || !vpn)
3089 return CMD_WARNING;
90e60aa7 3090
d62a17ae 3091 /* Check if we should disallow. */
3092 if (!is_rd_configured(vpn)) {
3093 vty_out(vty, "%% RD is not configured for this VNI\n");
3094 return CMD_WARNING;
3095 }
90e60aa7 3096
d62a17ae 3097 evpn_unconfigure_rd(bgp, vpn);
3098 return CMD_SUCCESS;
90e60aa7 3099}
3100
3101/*
3102 * Loop over all extended-communities in the route-target list rtl and
3103 * return 1 if we find ecomtarget
3104 */
d62a17ae 3105static int bgp_evpn_rt_matches_existing(struct list *rtl,
3106 struct ecommunity *ecomtarget)
90e60aa7 3107{
d62a17ae 3108 struct listnode *node, *nnode;
3109 struct ecommunity *ecom;
90e60aa7 3110
d62a17ae 3111 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
3112 if (ecommunity_match(ecom, ecomtarget))
3113 return 1;
3114 }
90e60aa7 3115
d62a17ae 3116 return 0;
90e60aa7 3117}
3118
3119
3120DEFUN (bgp_evpn_vni_rt,
3121 bgp_evpn_vni_rt_cmd,
3122 "route-target <both|import|export> RT",
3123 "Route Target\n"
3124 "import and export\n"
3125 "import\n"
3126 "export\n"
3127 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3128{
d62a17ae 3129 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3130 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3131 int rt_type;
3132 struct ecommunity *ecomadd = NULL;
3133
3134 if (!bgp || !vpn)
3135 return CMD_WARNING;
3136
3137 if (!strcmp(argv[1]->arg, "import"))
3138 rt_type = RT_TYPE_IMPORT;
3139 else if (!strcmp(argv[1]->arg, "export"))
3140 rt_type = RT_TYPE_EXPORT;
3141 else if (!strcmp(argv[1]->arg, "both"))
3142 rt_type = RT_TYPE_BOTH;
3143 else {
3144 vty_out(vty, "%% Invalid Route Target type\n");
3145 return CMD_WARNING;
3146 }
3147
3148 /* Add/update the import route-target */
3149 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3150 ecomadd = ecommunity_str2com(argv[2]->arg,
3151 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 3152 if (!ecomadd) {
3153 vty_out(vty, "%% Malformed Route Target list\n");
3154 return CMD_WARNING;
3155 }
5bc2ed52 3156 ecommunity_str(ecomadd);
d62a17ae 3157
3158 /* Do nothing if we already have this import route-target */
3159 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
3160 evpn_configure_import_rt(bgp, vpn, ecomadd);
3161 }
3162
3163 /* Add/update the export route-target */
3164 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3165 ecomadd = ecommunity_str2com(argv[2]->arg,
3166 ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 3167 if (!ecomadd) {
3168 vty_out(vty, "%% Malformed Route Target list\n");
3169 return CMD_WARNING;
3170 }
5bc2ed52 3171 ecommunity_str(ecomadd);
d62a17ae 3172
3173 /* Do nothing if we already have this export route-target */
3174 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
3175 evpn_configure_export_rt(bgp, vpn, ecomadd);
3176 }
3177
3178 return CMD_SUCCESS;
90e60aa7 3179}
3180
3181DEFUN (no_bgp_evpn_vni_rt,
3182 no_bgp_evpn_vni_rt_cmd,
3183 "no route-target <both|import|export> RT",
3184 NO_STR
3185 "Route Target\n"
3186 "import and export\n"
3187 "import\n"
3188 "export\n"
3189 "ASN:XX or A.B.C.D:XX\n")
3190{
d62a17ae 3191 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3192 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3193 int rt_type, found_ecomdel;
3194 struct ecommunity *ecomdel = NULL;
3195
3196 if (!bgp || !vpn)
3197 return CMD_WARNING;
3198
3199 if (!strcmp(argv[2]->arg, "import"))
3200 rt_type = RT_TYPE_IMPORT;
3201 else if (!strcmp(argv[2]->arg, "export"))
3202 rt_type = RT_TYPE_EXPORT;
3203 else if (!strcmp(argv[2]->arg, "both"))
3204 rt_type = RT_TYPE_BOTH;
3205 else {
3206 vty_out(vty, "%% Invalid Route Target type\n");
3207 return CMD_WARNING;
3208 }
3209
3210 /* The user did "no route-target import", check to see if there are any
3211 * import route-targets configured. */
3212 if (rt_type == RT_TYPE_IMPORT) {
3213 if (!is_import_rt_configured(vpn)) {
3214 vty_out(vty,
3215 "%% Import RT is not configured for this VNI\n");
3216 return CMD_WARNING;
3217 }
3218 } else if (rt_type == RT_TYPE_EXPORT) {
3219 if (!is_export_rt_configured(vpn)) {
3220 vty_out(vty,
3221 "%% Export RT is not configured for this VNI\n");
3222 return CMD_WARNING;
3223 }
3224 } else if (rt_type == RT_TYPE_BOTH) {
3225 if (!is_import_rt_configured(vpn)
3226 && !is_export_rt_configured(vpn)) {
3227 vty_out(vty,
3228 "%% Import/Export RT is not configured for this VNI\n");
3229 return CMD_WARNING;
3230 }
3231 }
3232
3233 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
d62a17ae 3234 if (!ecomdel) {
3235 vty_out(vty, "%% Malformed Route Target list\n");
3236 return CMD_WARNING;
3237 }
5bc2ed52 3238 ecommunity_str(ecomdel);
d62a17ae 3239
3240 if (rt_type == RT_TYPE_IMPORT) {
3241 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3242 vty_out(vty,
3243 "%% RT specified does not match configuration for this VNI\n");
3244 return CMD_WARNING;
3245 }
3246 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3247 } else if (rt_type == RT_TYPE_EXPORT) {
3248 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3249 vty_out(vty,
3250 "%% RT specified does not match configuration for this VNI\n");
3251 return CMD_WARNING;
3252 }
3253 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3254 } else if (rt_type == RT_TYPE_BOTH) {
3255 found_ecomdel = 0;
3256
3257 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3258 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3259 found_ecomdel = 1;
3260 }
3261
3262 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3263 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3264 found_ecomdel = 1;
3265 }
3266
3267 if (!found_ecomdel) {
3268 vty_out(vty,
3269 "%% RT specified does not match configuration for this VNI\n");
3270 return CMD_WARNING;
3271 }
3272 }
3273
3274 return CMD_SUCCESS;
90e60aa7 3275}
3276
3277DEFUN (no_bgp_evpn_vni_rt_without_val,
3278 no_bgp_evpn_vni_rt_without_val_cmd,
3279 "no route-target <import|export>",
3280 NO_STR
3281 "Route Target\n"
3282 "import\n"
3283 "export\n")
3284{
d62a17ae 3285 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3286 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3287 int rt_type;
3288
3289 if (!bgp || !vpn)
3290 return CMD_WARNING;
3291
3292 if (!strcmp(argv[2]->arg, "import")) {
3293 rt_type = RT_TYPE_IMPORT;
3294 } else if (!strcmp(argv[2]->arg, "export")) {
3295 rt_type = RT_TYPE_EXPORT;
3296 } else {
3297 vty_out(vty, "%% Invalid Route Target type\n");
3298 return CMD_WARNING;
3299 }
3300
3301 /* Check if we should disallow. */
3302 if (rt_type == RT_TYPE_IMPORT) {
3303 if (!is_import_rt_configured(vpn)) {
3304 vty_out(vty,
3305 "%% Import RT is not configured for this VNI\n");
3306 return CMD_WARNING;
3307 }
3308 } else {
3309 if (!is_export_rt_configured(vpn)) {
3310 vty_out(vty,
3311 "%% Export RT is not configured for this VNI\n");
3312 return CMD_WARNING;
3313 }
3314 }
3315
3316 /* Unconfigure the RT. */
3317 if (rt_type == RT_TYPE_IMPORT)
3318 evpn_unconfigure_import_rt(bgp, vpn, NULL);
3319 else
3320 evpn_unconfigure_export_rt(bgp, vpn, NULL);
3321 return CMD_SUCCESS;
90e60aa7 3322}
8c197128 3323#endif
90e60aa7 3324/*
3325 * Output EVPN configuration information.
3326 */
d62a17ae 3327void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
3328 safi_t safi, int *write)
3329{
3330 struct evpn_config_write cfg;
3331
3332 if (bgp->vnihash) {
3333 cfg.write = *write;
3334 cfg.vty = vty;
3335 hash_iterate(bgp->vnihash,
3336 (void (*)(struct hash_backet *,
3337 void *))write_vni_config_for_entry,
3338 &cfg);
3339 *write = cfg.write;
3340 }
90e60aa7 3341
d62a17ae 3342 if (bgp->advertise_all_vni) {
3343 bgp_config_write_family_header(vty, afi, safi, write);
3344 vty_out(vty, " advertise-all-vni\n");
3345 }
1a98c087
MK
3346
3347 if (bgp->advertise_gw_macip) {
3348 bgp_config_write_family_header(vty, afi, safi, write);
3349 vty_out(vty, " advertise-default-gw\n");
3350 }
90e60aa7 3351}
3352
4d0e6ece 3353void bgp_ethernetvpn_init(void)
784d3a42 3354{
d62a17ae 3355 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
3356 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
3357 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
3358 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
3359 install_element(VIEW_NODE,
3360 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
3361 install_element(VIEW_NODE,
3362 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
3363 install_element(
3364 VIEW_NODE,
3365 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
3366 install_element(
3367 VIEW_NODE,
3368 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
3369 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
3370 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
3371 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
3372 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
8c197128 3373#if defined(HAVE_CUMULUS)
d62a17ae 3374 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
3375 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
1a98c087
MK
3376 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
3377 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
d62a17ae 3378
f2d62262 3379 /* "show bgp l2vpn evpn" commands. */
3380 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
3381 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
3382 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
3383 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
3384 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
3385 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
3386 install_element(VIEW_NODE,
3387 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
3388 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
3389 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
3390 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
d62a17ae 3391
5014d96f
DW
3392 /* "show bgp evpn" commands. */
3393 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
3394 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
3395 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
3396 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
3397 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
3398 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
3399 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
3400 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
3401 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
3402 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
3403
d62a17ae 3404 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
3405 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
3406 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
3407 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
3408 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
3409 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
3410 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
3411 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
3412 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
1a98c087
MK
3413 install_element(BGP_EVPN_VNI_NODE,
3414 &bgp_evpn_advertise_default_gw_vni_cmd);
3415 install_element(BGP_EVPN_VNI_NODE,
3416 &no_bgp_evpn_advertise_default_gw_vni_cmd);
8c197128 3417#endif
784d3a42 3418}