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