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