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