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