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