]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
Merge pull request #5119 from lkrishnamoor/community-list
[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 #include "stream.h"
26
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
42
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
47
48 /*
49 * Context for VNI hash walk - used by callbacks.
50 */
51 struct vni_walk_ctx {
52 struct bgp *bgp;
53 struct vty *vty;
54 struct in_addr vtep_ip;
55 json_object *json;
56 int detail;
57 };
58
59 static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
60 json_object *json)
61 {
62 uint8_t *pnt;
63 uint8_t type, sub_type;
64 struct ecommunity_as eas;
65 struct ecommunity_ip eip;
66 struct listnode *node, *nnode;
67 struct bgp *tmp_bgp_vrf = NULL;
68 json_object *json_rt = NULL;
69 json_object *json_vrfs = NULL;
70 char rt_buf[RT_ADDRSTRLEN];
71
72 if (json) {
73 json_rt = json_object_new_object();
74 json_vrfs = json_object_new_array();
75 }
76
77 pnt = (uint8_t *)&irt->rt.val;
78 type = *pnt++;
79 sub_type = *pnt++;
80 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
81 return;
82
83 memset(&eas, 0, sizeof(eas));
84 switch (type) {
85 case ECOMMUNITY_ENCODE_AS:
86 eas.as = (*pnt++ << 8);
87 eas.as |= (*pnt++);
88 ptr_get_be32(pnt, &eas.val);
89
90 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
91
92 if (json)
93 json_object_string_add(json_rt, "rt", rt_buf);
94 else
95 vty_out(vty, "Route-target: %s", rt_buf);
96
97 break;
98
99 case ECOMMUNITY_ENCODE_IP:
100 memcpy(&eip.ip, pnt, 4);
101 pnt += 4;
102 eip.val = (*pnt++ << 8);
103 eip.val |= (*pnt++);
104
105 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
106 eip.val);
107
108 if (json)
109 json_object_string_add(json_rt, "rt", rt_buf);
110 else
111 vty_out(vty, "Route-target: %s", rt_buf);
112
113 break;
114
115 case ECOMMUNITY_ENCODE_AS4:
116 pnt = ptr_get_be32(pnt, &eas.val);
117 eas.val = (*pnt++ << 8);
118 eas.val |= (*pnt++);
119
120 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
121
122 if (json)
123 json_object_string_add(json_rt, "rt", rt_buf);
124 else
125 vty_out(vty, "Route-target: %s", rt_buf);
126
127 break;
128
129 default:
130 return;
131 }
132
133 if (!json) {
134 vty_out(vty,
135 "\nList of VRFs importing routes with this route-target:\n");
136 }
137
138 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
139 if (json)
140 json_object_array_add(
141 json_vrfs,
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
144 else
145 vty_out(vty, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
147 }
148
149 if (json) {
150 json_object_object_add(json_rt, "vrfs", json_vrfs);
151 json_object_object_add(json, rt_buf, json_rt);
152 }
153 }
154
155 static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
156 {
157 json_object *json = NULL;
158 struct vty *vty = NULL;
159 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
160
161 vty = (struct vty *)args[0];
162 json = (struct json_object *)args[1];
163
164 display_vrf_import_rt(vty, irt, json);
165 }
166
167 static void display_import_rt(struct vty *vty, struct irt_node *irt,
168 json_object *json)
169 {
170 uint8_t *pnt;
171 uint8_t type, sub_type;
172 struct ecommunity_as eas;
173 struct ecommunity_ip eip;
174 struct listnode *node, *nnode;
175 struct bgpevpn *tmp_vpn;
176 json_object *json_rt = NULL;
177 json_object *json_vnis = NULL;
178 char rt_buf[RT_ADDRSTRLEN];
179
180 if (json) {
181 json_rt = json_object_new_object();
182 json_vnis = json_object_new_array();
183 }
184
185 /* TODO: This needs to go into a function */
186
187 pnt = (uint8_t *)&irt->rt.val;
188 type = *pnt++;
189 sub_type = *pnt++;
190 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191 return;
192
193 memset(&eas, 0, sizeof(eas));
194 switch (type) {
195 case ECOMMUNITY_ENCODE_AS:
196 eas.as = (*pnt++ << 8);
197 eas.as |= (*pnt++);
198 ptr_get_be32(pnt, &eas.val);
199
200 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
201
202 if (json)
203 json_object_string_add(json_rt, "rt", rt_buf);
204 else
205 vty_out(vty, "Route-target: %s", rt_buf);
206
207 break;
208
209 case ECOMMUNITY_ENCODE_IP:
210 memcpy(&eip.ip, pnt, 4);
211 pnt += 4;
212 eip.val = (*pnt++ << 8);
213 eip.val |= (*pnt++);
214
215 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
216 eip.val);
217
218 if (json)
219 json_object_string_add(json_rt, "rt", rt_buf);
220 else
221 vty_out(vty, "Route-target: %s", rt_buf);
222
223 break;
224
225 case ECOMMUNITY_ENCODE_AS4:
226 pnt = ptr_get_be32(pnt, &eas.val);
227 eas.val = (*pnt++ << 8);
228 eas.val |= (*pnt++);
229
230 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
231
232 if (json)
233 json_object_string_add(json_rt, "rt", rt_buf);
234 else
235 vty_out(vty, "Route-target: %s", rt_buf);
236
237 break;
238
239 default:
240 return;
241 }
242
243 if (!json) {
244 vty_out(vty,
245 "\nList of VNIs importing routes with this route-target:\n");
246 }
247
248 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
249 if (json)
250 json_object_array_add(
251 json_vnis, json_object_new_int(tmp_vpn->vni));
252 else
253 vty_out(vty, " %u\n", tmp_vpn->vni);
254 }
255
256 if (json) {
257 json_object_object_add(json_rt, "vnis", json_vnis);
258 json_object_object_add(json, rt_buf, json_rt);
259 }
260 }
261
262 static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
263 {
264 json_object *json = NULL;
265 struct vty *vty = NULL;
266 struct irt_node *irt = (struct irt_node *)bucket->data;
267
268 vty = args[0];
269 json = args[1];
270
271 display_import_rt(vty, irt, json);
272
273 return;
274 }
275
276 static void bgp_evpn_show_route_rd_header(struct vty *vty,
277 struct bgp_node *rd_rn,
278 json_object *json)
279 {
280 uint16_t type;
281 struct rd_as rd_as;
282 struct rd_ip rd_ip;
283 uint8_t *pnt;
284 char rd_str[RD_ADDRSTRLEN];
285
286 pnt = rd_rn->p.u.val;
287
288 /* Decode RD type. */
289 type = decode_rd_type(pnt);
290
291 if (json)
292 return;
293
294 vty_out(vty, "Route Distinguisher: ");
295
296 switch (type) {
297 case RD_TYPE_AS:
298 decode_rd_as(pnt + 2, &rd_as);
299 snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
300 break;
301
302 case RD_TYPE_IP:
303 decode_rd_ip(pnt + 2, &rd_ip);
304 snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
305 rd_ip.val);
306 break;
307
308 default:
309 snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
310 break;
311 }
312
313 vty_out(vty, "%s\n", rd_str);
314 }
315
316 static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
317 uint64_t tbl_ver, json_object *json)
318 {
319 char ri_header[] =
320 " Network Next Hop Metric LocPrf Weight Path\n";
321
322 if (json)
323 return;
324
325 vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n",
326 tbl_ver, inet_ntoa(bgp->router_id));
327 vty_out(vty,
328 "Status codes: s suppressed, d damped, h history, "
329 "* valid, > best, i - internal\n");
330 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
331 vty_out(vty,
332 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
333 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
334 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
335 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
336 vty_out(vty, "%s", ri_header);
337 }
338
339 static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
340 json_object *json)
341 {
342 char buf1[INET6_ADDRSTRLEN];
343 char *ecom_str;
344 struct listnode *node, *nnode;
345 struct ecommunity *ecom;
346 json_object *json_import_rtl = NULL;
347 json_object *json_export_rtl = NULL;
348
349 json_import_rtl = json_export_rtl = 0;
350
351 if (json) {
352 json_import_rtl = json_object_new_array();
353 json_export_rtl = json_object_new_array();
354 json_object_int_add(json, "vni", bgp_vrf->l3vni);
355 json_object_string_add(json, "type", "L3");
356 json_object_string_add(json, "kernelFlag", "Yes");
357 json_object_string_add(
358 json, "rd",
359 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
360 json_object_string_add(json, "originatorIp",
361 inet_ntoa(bgp_vrf->originator_ip));
362 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
363 } else {
364 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
365 vty_out(vty, " (known to the kernel)");
366 vty_out(vty, "\n");
367
368 vty_out(vty, " Type: %s\n", "L3");
369 vty_out(vty, " Tenant VRF: %s\n",
370 vrf_id_to_name(bgp_vrf->vrf_id));
371 vty_out(vty, " RD: %s\n",
372 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
373 vty_out(vty, " Originator IP: %s\n",
374 inet_ntoa(bgp_vrf->originator_ip));
375 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
376 }
377
378 if (!json)
379 vty_out(vty, " Import Route Target:\n");
380
381 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) {
382 ecom_str = ecommunity_ecom2str(ecom,
383 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
384
385 if (json)
386 json_object_array_add(json_import_rtl,
387 json_object_new_string(ecom_str));
388 else
389 vty_out(vty, " %s\n", ecom_str);
390
391 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
392 }
393
394 if (json)
395 json_object_object_add(json, "importRts", json_import_rtl);
396 else
397 vty_out(vty, " Export Route Target:\n");
398
399 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) {
400 ecom_str = ecommunity_ecom2str(ecom,
401 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
402
403 if (json)
404 json_object_array_add(json_export_rtl,
405 json_object_new_string(ecom_str));
406 else
407 vty_out(vty, " %s\n", ecom_str);
408
409 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
410 }
411
412 if (json)
413 json_object_object_add(json, "exportRts", json_export_rtl);
414 }
415
416 static void display_es(struct vty *vty, struct evpnes *es, json_object *json)
417 {
418 struct in_addr *vtep;
419 char buf[ESI_STR_LEN];
420 char buf1[RD_ADDRSTRLEN];
421 char buf2[INET6_ADDRSTRLEN];
422 struct listnode *node = NULL;
423 json_object *json_vteps = NULL;
424
425 if (json) {
426 json_vteps = json_object_new_array();
427 json_object_string_add(json, "esi",
428 esi_to_str(&es->esi, buf, sizeof(buf)));
429 json_object_string_add(json, "rd",
430 prefix_rd2str(&es->prd, buf1,
431 sizeof(buf1)));
432 json_object_string_add(
433 json, "originatorIp",
434 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
435 if (es->vtep_list) {
436 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
437 json_object_array_add(
438 json_vteps, json_object_new_string(
439 inet_ntoa(*vtep)));
440 }
441 json_object_object_add(json, "vteps", json_vteps);
442 } else {
443 vty_out(vty, "ESI: %s\n",
444 esi_to_str(&es->esi, buf, sizeof(buf)));
445 vty_out(vty, " RD: %s\n", prefix_rd2str(&es->prd, buf1,
446 sizeof(buf1)));
447 vty_out(vty, " Originator-IP: %s\n",
448 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
449 if (es->vtep_list) {
450 vty_out(vty, " VTEP List:\n");
451 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
452 vty_out(vty, " %s\n", inet_ntoa(*vtep));
453 }
454 }
455 }
456
457 static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
458 {
459 char buf1[RD_ADDRSTRLEN];
460 char *ecom_str;
461 struct listnode *node, *nnode;
462 struct ecommunity *ecom;
463 json_object *json_import_rtl = NULL;
464 json_object *json_export_rtl = NULL;
465
466 if (json) {
467 json_import_rtl = json_object_new_array();
468 json_export_rtl = json_object_new_array();
469 json_object_int_add(json, "vni", vpn->vni);
470 json_object_string_add(json, "type", "L2");
471 json_object_string_add(json, "kernelFlag",
472 is_vni_live(vpn) ? "Yes" : "No");
473 json_object_string_add(
474 json, "rd",
475 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
476 json_object_string_add(json, "originatorIp",
477 inet_ntoa(vpn->originator_ip));
478 json_object_string_add(json, "mcastGroup",
479 inet_ntoa(vpn->mcast_grp));
480 json_object_string_add(json, "advertiseGatewayMacip",
481 vpn->advertise_gw_macip ? "Yes" : "No");
482 } else {
483 vty_out(vty, "VNI: %d", vpn->vni);
484 if (is_vni_live(vpn))
485 vty_out(vty, " (known to the kernel)");
486 vty_out(vty, "\n");
487
488 vty_out(vty, " Type: %s\n", "L2");
489 vty_out(vty, " Tenant-Vrf: %s\n",
490 vrf_id_to_name(vpn->tenant_vrf_id));
491 vty_out(vty, " RD: %s\n",
492 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
493 vty_out(vty, " Originator IP: %s\n",
494 inet_ntoa(vpn->originator_ip));
495 vty_out(vty, " Mcast group: %s\n",
496 inet_ntoa(vpn->mcast_grp));
497 vty_out(vty, " Advertise-gw-macip : %s\n",
498 vpn->advertise_gw_macip ? "Yes" : "No");
499 vty_out(vty, " Advertise-svi-macip : %s\n",
500 vpn->advertise_svi_macip ? "Yes" : "No");
501 }
502
503 if (!json)
504 vty_out(vty, " Import Route Target:\n");
505
506 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
507 ecom_str = ecommunity_ecom2str(ecom,
508 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
509
510 if (json)
511 json_object_array_add(json_import_rtl,
512 json_object_new_string(ecom_str));
513 else
514 vty_out(vty, " %s\n", ecom_str);
515
516 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
517 }
518
519 if (json)
520 json_object_object_add(json, "importRts", json_import_rtl);
521 else
522 vty_out(vty, " Export Route Target:\n");
523
524 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
525 ecom_str = ecommunity_ecom2str(ecom,
526 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
527
528 if (json)
529 json_object_array_add(json_export_rtl,
530 json_object_new_string(ecom_str));
531 else
532 vty_out(vty, " %s\n", ecom_str);
533
534 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
535 }
536
537 if (json)
538 json_object_object_add(json, "exportRts", json_export_rtl);
539 }
540
541 static void show_esi_routes(struct bgp *bgp,
542 struct evpnes *es,
543 struct vty *vty,
544 json_object *json)
545 {
546 int header = 1;
547 struct bgp_node *rn;
548 struct bgp_path_info *pi;
549 uint32_t prefix_cnt, path_cnt;
550 uint64_t tbl_ver;
551
552 prefix_cnt = path_cnt = 0;
553
554 tbl_ver = es->route_table->version;
555 for (rn = bgp_table_top(es->route_table); rn;
556 rn = bgp_route_next(rn)) {
557 int add_prefix_to_json = 0;
558 char prefix_str[BUFSIZ];
559 json_object *json_paths = NULL;
560 json_object *json_prefix = NULL;
561
562 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
563 sizeof(prefix_str));
564
565 if (json)
566 json_prefix = json_object_new_object();
567
568 pi = bgp_node_get_bgp_path_info(rn);
569 if (pi) {
570 /* Overall header/legend displayed once. */
571 if (header) {
572 bgp_evpn_show_route_header(vty, bgp,
573 tbl_ver, json);
574 header = 0;
575 }
576
577 prefix_cnt++;
578 }
579
580 if (json)
581 json_paths = json_object_new_array();
582
583 /* For EVPN, the prefix is displayed for each path (to fit in
584 * with code that already exists).
585 */
586 for (; pi; pi = pi->next) {
587 json_object *json_path = NULL;
588
589 if (json)
590 json_path = json_object_new_array();
591
592 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
593
594 if (json)
595 json_object_array_add(json_paths, json_path);
596
597 path_cnt++;
598 add_prefix_to_json = 1;
599 }
600
601 if (json && add_prefix_to_json) {
602 json_object_string_add(json_prefix, "prefix",
603 prefix_str);
604 json_object_int_add(json_prefix, "prefixLen",
605 rn->p.prefixlen);
606 json_object_object_add(json_prefix, "paths",
607 json_paths);
608 json_object_object_add(json, prefix_str, json_prefix);
609 }
610 }
611
612 if (json) {
613 json_object_int_add(json, "numPrefix", prefix_cnt);
614 json_object_int_add(json, "numPaths", path_cnt);
615 } else {
616 if (prefix_cnt == 0)
617 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
618 else
619 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
620 prefix_cnt, path_cnt);
621 }
622 }
623
624 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
625 struct vty *vty, struct in_addr vtep_ip,
626 json_object *json, int detail)
627 {
628 struct bgp_node *rn;
629 struct bgp_path_info *pi;
630 struct bgp_table *table;
631 int header = detail ? 0 : 1;
632 uint64_t tbl_ver;
633 uint32_t prefix_cnt, path_cnt;
634
635 prefix_cnt = path_cnt = 0;
636
637 table = vpn->route_table;
638 tbl_ver = table->version;
639 for (rn = bgp_table_top(table); rn;
640 rn = bgp_route_next(rn)) {
641 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
642 int add_prefix_to_json = 0;
643 char prefix_str[BUFSIZ];
644 json_object *json_paths = NULL;
645 json_object *json_prefix = NULL;
646
647 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
648 sizeof(prefix_str));
649
650 if (type && evp->prefix.route_type != type)
651 continue;
652
653 if (json)
654 json_prefix = json_object_new_object();
655
656 pi = bgp_node_get_bgp_path_info(rn);
657 if (pi) {
658 /* Overall header/legend displayed once. */
659 if (header) {
660 bgp_evpn_show_route_header(vty, bgp,
661 tbl_ver, json);
662 header = 0;
663 }
664
665 prefix_cnt++;
666 }
667
668 if (json)
669 json_paths = json_object_new_array();
670
671 /* For EVPN, the prefix is displayed for each path (to fit in
672 * with code that already exists).
673 */
674 for (; pi; pi = pi->next) {
675 json_object *json_path = NULL;
676
677 if (vtep_ip.s_addr
678 && !IPV4_ADDR_SAME(&(vtep_ip),
679 &(pi->attr->nexthop)))
680 continue;
681
682 if (json)
683 json_path = json_object_new_array();
684
685 if (detail)
686 route_vty_out_detail(vty, bgp, rn, pi,
687 AFI_L2VPN, SAFI_EVPN,
688 json_path);
689 else
690 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
691 json_path);
692
693 if (json)
694 json_object_array_add(json_paths, json_path);
695
696 path_cnt++;
697 add_prefix_to_json = 1;
698 }
699
700 if (json && add_prefix_to_json) {
701 json_object_string_add(json_prefix, "prefix",
702 prefix_str);
703 json_object_int_add(json_prefix, "prefixLen",
704 rn->p.prefixlen);
705 json_object_object_add(json_prefix, "paths",
706 json_paths);
707 json_object_object_add(json, prefix_str, json_prefix);
708 }
709 }
710
711 if (json) {
712 json_object_int_add(json, "numPrefix", prefix_cnt);
713 json_object_int_add(json, "numPaths", path_cnt);
714 } else {
715 if (prefix_cnt == 0)
716 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
717 type ? "(of requested type) " : "");
718 else
719 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
720 prefix_cnt, path_cnt,
721 type ? " (of requested type)" : "");
722 vty_out(vty, "\n");
723 }
724 }
725
726 static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
727 {
728 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
729 struct vni_walk_ctx *wctx = arg;
730 struct vty *vty = wctx->vty;
731 json_object *json = wctx->json;
732 json_object *json_vni = NULL;
733 char vni_str[VNI_STR_LEN];
734
735 snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
736 if (json) {
737 json_vni = json_object_new_object();
738 json_object_int_add(json_vni, "vni", vpn->vni);
739 } else {
740 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
741 }
742
743 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni,
744 wctx->detail);
745
746 if (json)
747 json_object_object_add(json, vni_str, json_vni);
748 }
749
750 static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
751 json_object *json)
752 {
753 json_object *json_vni = NULL;
754 json_object *json_import_rtl = NULL;
755 json_object *json_export_rtl = NULL;
756 char buf1[10];
757 char buf2[INET6_ADDRSTRLEN];
758 char rt_buf[25];
759 char *ecom_str;
760 struct listnode *node, *nnode;
761 struct ecommunity *ecom;
762
763 if (!bgp->l3vni)
764 return;
765
766 if (json) {
767 json_vni = json_object_new_object();
768 json_import_rtl = json_object_new_array();
769 json_export_rtl = json_object_new_array();
770 }
771
772 /* if an l3vni is present in bgp it is live */
773 buf1[0] = '\0';
774 sprintf(buf1, "*");
775
776 if (json) {
777 json_object_int_add(json_vni, "vni", bgp->l3vni);
778 json_object_string_add(json_vni, "type", "L3");
779 json_object_string_add(json_vni, "inKernel", "True");
780 json_object_string_add(json_vni, "originatorIp",
781 inet_ntoa(bgp->originator_ip));
782 json_object_string_add(
783 json_vni, "rd",
784 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
785 } else {
786 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
787 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
788 }
789
790 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
791 ecom_str = ecommunity_ecom2str(ecom,
792 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
793
794 if (json) {
795 json_object_array_add(json_import_rtl,
796 json_object_new_string(ecom_str));
797 } else {
798 if (listcount(bgp->vrf_import_rtl) > 1)
799 sprintf(rt_buf, "%s, ...", ecom_str);
800 else
801 sprintf(rt_buf, "%s", ecom_str);
802 vty_out(vty, " %-25s", rt_buf);
803 }
804
805 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
806
807 /* If there are multiple import RTs we break here and show only
808 * one */
809 if (!json)
810 break;
811 }
812
813 if (json)
814 json_object_object_add(json_vni, "importRTs", json_import_rtl);
815
816 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) {
817 ecom_str = ecommunity_ecom2str(ecom,
818 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
819
820 if (json) {
821 json_object_array_add(json_export_rtl,
822 json_object_new_string(ecom_str));
823 } else {
824 if (listcount(bgp->vrf_export_rtl) > 1)
825 sprintf(rt_buf, "%s, ...", ecom_str);
826 else
827 sprintf(rt_buf, "%s", ecom_str);
828 vty_out(vty, " %-25s", rt_buf);
829 }
830
831 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
832
833 /* If there are multiple export RTs we break here and show only
834 * one */
835 if (!json)
836 break;
837 }
838
839 if (!json)
840 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
841
842 if (json) {
843 char vni_str[VNI_STR_LEN];
844
845 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
846 snprintf(vni_str, VNI_STR_LEN, "%u", bgp->l3vni);
847 json_object_object_add(json, vni_str, json_vni);
848 } else {
849 vty_out(vty, "\n");
850 }
851 }
852
853 static void show_es_entry(struct hash_bucket *bucket, void *args[])
854 {
855 char buf[ESI_STR_LEN];
856 char buf1[RD_ADDRSTRLEN];
857 char buf2[INET6_ADDRSTRLEN];
858 struct in_addr *vtep = NULL;
859 struct vty *vty = args[0];
860 json_object *json = args[1];
861 json_object *json_vteps = NULL;
862 struct listnode *node = NULL;
863 struct evpnes *es = (struct evpnes *)bucket->data;
864
865 if (json) {
866 json_vteps = json_object_new_array();
867 json_object_string_add(json, "esi",
868 esi_to_str(&es->esi, buf, sizeof(buf)));
869 json_object_string_add(json, "type",
870 is_es_local(es) ? "Local" : "Remote");
871 json_object_string_add(json, "rd",
872 prefix_rd2str(&es->prd, buf1,
873 sizeof(buf1)));
874 json_object_string_add(
875 json, "originatorIp",
876 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
877 if (es->vtep_list) {
878 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
879 json_object_array_add(json_vteps,
880 json_object_new_string(
881 inet_ntoa(*vtep)));
882 }
883 json_object_object_add(json, "vteps", json_vteps);
884 } else {
885 vty_out(vty, "%-30s %-6s %-21s %-15s %-6d\n",
886 esi_to_str(&es->esi, buf, sizeof(buf)),
887 is_es_local(es) ? "Local" : "Remote",
888 prefix_rd2str(&es->prd, buf1, sizeof(buf1)),
889 ipaddr2str(&es->originator_ip, buf2,
890 sizeof(buf2)),
891 es->vtep_list ? listcount(es->vtep_list) : 0);
892 }
893 }
894
895 static void show_vni_entry(struct hash_bucket *bucket, void *args[])
896 {
897 struct vty *vty;
898 json_object *json;
899 json_object *json_vni = NULL;
900 json_object *json_import_rtl = NULL;
901 json_object *json_export_rtl = NULL;
902 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
903 char buf1[10];
904 char buf2[RD_ADDRSTRLEN];
905 char rt_buf[25];
906 char *ecom_str;
907 struct listnode *node, *nnode;
908 struct ecommunity *ecom;
909
910 vty = args[0];
911 json = args[1];
912
913 if (json) {
914 json_vni = json_object_new_object();
915 json_import_rtl = json_object_new_array();
916 json_export_rtl = json_object_new_array();
917 }
918
919 buf1[0] = '\0';
920 if (is_vni_live(vpn))
921 sprintf(buf1, "*");
922
923 if (json) {
924 json_object_int_add(json_vni, "vni", vpn->vni);
925 json_object_string_add(json_vni, "type", "L2");
926 json_object_string_add(json_vni, "inKernel",
927 is_vni_live(vpn) ? "True" : "False");
928 json_object_string_add(json_vni, "originatorIp",
929 inet_ntoa(vpn->originator_ip));
930 json_object_string_add(json_vni, "originatorIp",
931 inet_ntoa(vpn->originator_ip));
932 json_object_string_add(
933 json_vni, "rd",
934 prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
935 } else {
936 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
937 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
938 }
939
940 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
941 ecom_str = ecommunity_ecom2str(ecom,
942 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
943
944 if (json) {
945 json_object_array_add(json_import_rtl,
946 json_object_new_string(ecom_str));
947 } else {
948 if (listcount(vpn->import_rtl) > 1)
949 sprintf(rt_buf, "%s, ...", ecom_str);
950 else
951 sprintf(rt_buf, "%s", ecom_str);
952 vty_out(vty, " %-25s", rt_buf);
953 }
954
955 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
956
957 /* If there are multiple import RTs we break here and show only
958 * one */
959 if (!json)
960 break;
961 }
962
963 if (json)
964 json_object_object_add(json_vni, "importRTs", json_import_rtl);
965
966 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
967 ecom_str = ecommunity_ecom2str(ecom,
968 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
969
970 if (json) {
971 json_object_array_add(json_export_rtl,
972 json_object_new_string(ecom_str));
973 } else {
974 if (listcount(vpn->export_rtl) > 1)
975 sprintf(rt_buf, "%s, ...", ecom_str);
976 else
977 sprintf(rt_buf, "%s", ecom_str);
978 vty_out(vty, " %-25s", rt_buf);
979 }
980
981 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
982
983 /* If there are multiple export RTs we break here and show only
984 * one */
985 if (!json)
986 break;
987 }
988
989 if (!json)
990 vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
991
992 if (json) {
993 char vni_str[VNI_STR_LEN];
994
995 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
996 snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
997 json_object_object_add(json, vni_str, json_vni);
998 } else {
999 vty_out(vty, "\n");
1000 }
1001 }
1002
1003 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1004 enum bgp_show_type type, void *output_arg,
1005 int option, bool use_json)
1006 {
1007 afi_t afi = AFI_L2VPN;
1008 struct bgp *bgp;
1009 struct bgp_table *table;
1010 struct bgp_node *rn;
1011 struct bgp_node *rm;
1012 struct bgp_path_info *pi;
1013 int rd_header;
1014 int header = 1;
1015 char rd_str[BUFSIZ];
1016 char buf[BUFSIZ];
1017 int no_display;
1018
1019 unsigned long output_count = 0;
1020 unsigned long total_count = 0;
1021 json_object *json = NULL;
1022 json_object *json_nroute = NULL;
1023 json_object *json_array = NULL;
1024 json_object *json_prefix_info = NULL;
1025
1026 memset(rd_str, 0, BUFSIZ);
1027
1028 bgp = bgp_get_evpn();
1029 if (bgp == NULL) {
1030 if (!use_json)
1031 vty_out(vty, "No BGP process is configured\n");
1032 else
1033 vty_out(vty, "{}\n");
1034 return CMD_WARNING;
1035 }
1036
1037 if (use_json)
1038 json = json_object_new_object();
1039
1040 for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
1041 rn = bgp_route_next(rn)) {
1042 uint64_t tbl_ver;
1043
1044 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
1045 continue;
1046
1047 table = bgp_node_get_bgp_table_info(rn);
1048 if (!table)
1049 continue;
1050
1051 rd_header = 1;
1052 tbl_ver = table->version;
1053
1054 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
1055 pi = bgp_node_get_bgp_path_info(rm);
1056 if (pi == NULL)
1057 continue;
1058
1059 no_display = 0;
1060 if (use_json) {
1061 json_array = json_object_new_array();
1062 json_prefix_info = json_object_new_object();
1063
1064 json_object_string_add(json_prefix_info,
1065 "prefix", bgp_evpn_route2str(
1066 (struct prefix_evpn *)&rm->p, buf,
1067 BUFSIZ));
1068
1069 json_object_int_add(json_prefix_info,
1070 "prefixLen", rm->p.prefixlen);
1071
1072 if (rd_header)
1073 json_nroute = json_object_new_object();
1074 }
1075
1076 for (; pi; pi = pi->next) {
1077 total_count++;
1078 if (type == bgp_show_type_neighbor) {
1079 struct peer *peer = output_arg;
1080
1081 if (peer_cmp(peer, pi->peer) != 0)
1082 continue;
1083 }
1084 if (type == bgp_show_type_lcommunity_exact) {
1085 struct lcommunity *lcom = output_arg;
1086
1087 if (!pi->attr->lcommunity ||
1088 !lcommunity_cmp(
1089 pi->attr->lcommunity, lcom))
1090 continue;
1091 }
1092 if (type == bgp_show_type_lcommunity) {
1093 struct lcommunity *lcom = output_arg;
1094
1095 if (!pi->attr->lcommunity ||
1096 !lcommunity_match(
1097 pi->attr->lcommunity, lcom))
1098 continue;
1099 }
1100 if (type == bgp_show_type_community) {
1101 struct community *com = output_arg;
1102
1103 if (!pi->attr->community ||
1104 !community_match(
1105 pi->attr->community, com))
1106 continue;
1107 }
1108 if (type == bgp_show_type_community_exact) {
1109 struct community *com = output_arg;
1110
1111 if (!pi->attr->community ||
1112 !community_cmp(
1113 pi->attr->community, com))
1114 continue;
1115 }
1116 if (header) {
1117 if (use_json) {
1118 json_object_int_add(
1119 json, "bgpTableVersion",
1120 tbl_ver);
1121 json_object_string_add(
1122 json,
1123 "bgpLocalRouterId",
1124 inet_ntoa(
1125 bgp->router_id));
1126 json_object_int_add(
1127 json,
1128 "defaultLocPrf",
1129 bgp->default_local_pref);
1130 json_object_int_add(
1131 json, "localAS",
1132 bgp->as);
1133 } else {
1134 if (option == SHOW_DISPLAY_TAGS)
1135 vty_out(vty,
1136 V4_HEADER_TAG);
1137 else if (
1138 option
1139 == SHOW_DISPLAY_OVERLAY)
1140 vty_out(vty,
1141 V4_HEADER_OVERLAY);
1142 else {
1143 bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
1144 }
1145 }
1146 header = 0;
1147 }
1148 if (rd_header) {
1149 uint16_t type;
1150 struct rd_as rd_as;
1151 struct rd_ip rd_ip;
1152 uint8_t *pnt;
1153
1154 pnt = rn->p.u.val;
1155
1156 /* Decode RD type. */
1157 type = decode_rd_type(pnt);
1158 /* Decode RD value. */
1159 if (type == RD_TYPE_AS)
1160 decode_rd_as(pnt + 2, &rd_as);
1161 else if (type == RD_TYPE_AS4)
1162 decode_rd_as4(pnt + 2, &rd_as);
1163 else if (type == RD_TYPE_IP)
1164 decode_rd_ip(pnt + 2, &rd_ip);
1165 if (use_json) {
1166 if (type == RD_TYPE_AS
1167 || type == RD_TYPE_AS4)
1168 sprintf(rd_str, "%u:%d",
1169 rd_as.as,
1170 rd_as.val);
1171 else if (type == RD_TYPE_IP)
1172 sprintf(rd_str, "%s:%d",
1173 inet_ntoa(
1174 rd_ip.ip),
1175 rd_ip.val);
1176 json_object_string_add(
1177 json_nroute,
1178 "rd",
1179 rd_str);
1180
1181 } else {
1182 vty_out(vty,
1183 "Route Distinguisher: ");
1184 if (type == RD_TYPE_AS)
1185 vty_out(vty,
1186 "as2 %u:%d",
1187 rd_as.as,
1188 rd_as.val);
1189 else if (type == RD_TYPE_AS4)
1190 vty_out(vty,
1191 "as4 %u:%d",
1192 rd_as.as,
1193 rd_as.val);
1194 else if (type == RD_TYPE_IP)
1195 vty_out(vty, "ip %s:%d",
1196 inet_ntoa(
1197 rd_ip.ip),
1198 rd_ip.val);
1199 vty_out(vty, "\n\n");
1200 }
1201 rd_header = 0;
1202 }
1203
1204 if (option == SHOW_DISPLAY_TAGS)
1205 route_vty_out_tag(vty, &rm->p, pi,
1206 no_display, SAFI_EVPN,
1207 json_array);
1208 else if (option == SHOW_DISPLAY_OVERLAY)
1209 route_vty_out_overlay(vty, &rm->p, pi,
1210 no_display,
1211 json_array);
1212 else
1213 route_vty_out(vty, &rm->p, pi,
1214 no_display, SAFI_EVPN,
1215 json_array);
1216 no_display = 1;
1217 }
1218
1219 if (no_display)
1220 output_count++;
1221
1222 if (use_json) {
1223 json_object_object_add(json_prefix_info,
1224 "paths", json_array);
1225 json_object_object_add(json_nroute, buf,
1226 json_prefix_info);
1227 }
1228 }
1229
1230 if (use_json)
1231 json_object_object_add(json, rd_str, json_nroute);
1232 }
1233
1234 if (use_json) {
1235 json_object_int_add(json, "numPrefix", output_count);
1236 json_object_int_add(json, "totalPrefix", total_count);
1237 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1238 json, JSON_C_TO_STRING_PRETTY));
1239 json_object_free(json);
1240 } else {
1241 if (output_count == 0)
1242 vty_out(vty, "No prefixes displayed, %ld exist\n",
1243 total_count);
1244 else
1245 vty_out(vty,
1246 "\nDisplayed %ld out of %ld total prefixes\n",
1247 output_count, total_count);
1248 }
1249 return CMD_SUCCESS;
1250 }
1251
1252 DEFUN(show_ip_bgp_l2vpn_evpn,
1253 show_ip_bgp_l2vpn_evpn_cmd,
1254 "show [ip] bgp l2vpn evpn [json]",
1255 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
1256 {
1257 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
1258 use_json(argc, argv));
1259 }
1260
1261 DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1262 show_ip_bgp_l2vpn_evpn_rd_cmd,
1263 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1264 SHOW_STR
1265 IP_STR
1266 BGP_STR
1267 L2VPN_HELP_STR
1268 EVPN_HELP_STR
1269 "Display information for a route distinguisher\n"
1270 "VPN Route Distinguisher\n" JSON_STR)
1271 {
1272 int idx_ext_community = 0;
1273 int ret;
1274 struct prefix_rd prd;
1275
1276 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1277
1278 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1279 if (!ret) {
1280 vty_out(vty, "%% Malformed Route Distinguisher\n");
1281 return CMD_WARNING;
1282 }
1283 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
1284 use_json(argc, argv));
1285 }
1286
1287 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1288 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1289 "show [ip] bgp l2vpn evpn all tags",
1290 SHOW_STR
1291 IP_STR
1292 BGP_STR
1293 L2VPN_HELP_STR
1294 EVPN_HELP_STR
1295 "Display information about all EVPN NLRIs\n"
1296 "Display BGP tags for prefixes\n")
1297 {
1298 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
1299 0);
1300 }
1301
1302 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1303 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
1304 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1305 SHOW_STR
1306 IP_STR
1307 BGP_STR
1308 L2VPN_HELP_STR
1309 EVPN_HELP_STR
1310 "Display information for a route distinguisher\n"
1311 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1312 {
1313 int idx_ext_community = 0;
1314 int ret;
1315 struct prefix_rd prd;
1316
1317 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1318
1319 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1320 if (!ret) {
1321 vty_out(vty, "%% Malformed Route Distinguisher\n");
1322 return CMD_WARNING;
1323 }
1324 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
1325 0);
1326 }
1327
1328 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1329 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1330 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1331 SHOW_STR
1332 IP_STR
1333 BGP_STR
1334 L2VPN_HELP_STR
1335 EVPN_HELP_STR
1336 "Detailed information on TCP and BGP neighbor connections\n"
1337 "IPv4 Neighbor to display information about\n"
1338 "IPv6 Neighbor to display information about\n"
1339 "Neighbor on BGP configured interface\n"
1340 "Display routes learned from neighbor\n" JSON_STR)
1341 {
1342 int idx = 0;
1343 struct peer *peer;
1344 char *peerstr = NULL;
1345 bool uj = use_json(argc, argv);
1346 afi_t afi = AFI_L2VPN;
1347 safi_t safi = SAFI_EVPN;
1348 struct bgp *bgp = NULL;
1349
1350 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1351 &bgp, uj);
1352 if (!idx) {
1353 vty_out(vty, "No index\n");
1354 return CMD_WARNING;
1355 }
1356
1357 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1358 argv_find(argv, argc, "neighbors", &idx);
1359 peerstr = argv[++idx]->arg;
1360
1361 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1362 if (!peer) {
1363 if (uj) {
1364 json_object *json_no = NULL;
1365 json_no = json_object_new_object();
1366 json_object_string_add(json_no, "warning",
1367 "Malformed address");
1368 vty_out(vty, "%s\n",
1369 json_object_to_json_string(json_no));
1370 json_object_free(json_no);
1371 } else
1372 vty_out(vty, "Malformed address: %s\n",
1373 argv[idx]->arg);
1374 return CMD_WARNING;
1375 }
1376 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1377 if (uj) {
1378 json_object *json_no = NULL;
1379 json_no = json_object_new_object();
1380 json_object_string_add(
1381 json_no, "warning",
1382 "No such neighbor or address family");
1383 vty_out(vty, "%s\n",
1384 json_object_to_json_string(json_no));
1385 json_object_free(json_no);
1386 } else
1387 vty_out(vty, "%% No such neighbor or address family\n");
1388 return CMD_WARNING;
1389 }
1390
1391 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer, 0,
1392 uj);
1393 }
1394
1395 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1396 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1397 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1398 SHOW_STR
1399 IP_STR
1400 BGP_STR
1401 L2VPN_HELP_STR
1402 EVPN_HELP_STR
1403 "Display information for a route distinguisher\n"
1404 "VPN Route Distinguisher\n"
1405 "Detailed information on TCP and BGP neighbor connections\n"
1406 "IPv4 Neighbor to display information about\n"
1407 "IPv6 Neighbor to display information about\n"
1408 "Neighbor on BGP configured interface\n"
1409 "Display routes learned from neighbor\n" JSON_STR)
1410 {
1411 int idx_ext_community = 0;
1412 int idx = 0;
1413 int ret;
1414 struct peer *peer;
1415 char *peerstr = NULL;
1416 struct prefix_rd prd;
1417 bool uj = use_json(argc, argv);
1418 afi_t afi = AFI_L2VPN;
1419 safi_t safi = SAFI_EVPN;
1420 struct bgp *bgp = NULL;
1421
1422 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1423 &bgp, uj);
1424 if (!idx) {
1425 vty_out(vty, "No index\n");
1426 return CMD_WARNING;
1427 }
1428
1429 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1430 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1431 if (!ret) {
1432 if (uj) {
1433 json_object *json_no = NULL;
1434 json_no = json_object_new_object();
1435 json_object_string_add(json_no, "warning",
1436 "Malformed Route Distinguisher");
1437 vty_out(vty, "%s\n",
1438 json_object_to_json_string(json_no));
1439 json_object_free(json_no);
1440 } else
1441 vty_out(vty, "%% Malformed Route Distinguisher\n");
1442 return CMD_WARNING;
1443 }
1444
1445 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1446 argv_find(argv, argc, "neighbors", &idx);
1447 peerstr = argv[++idx]->arg;
1448
1449 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1450 if (!peer) {
1451 if (uj) {
1452 json_object *json_no = NULL;
1453 json_no = json_object_new_object();
1454 json_object_string_add(json_no, "warning",
1455 "Malformed address");
1456 vty_out(vty, "%s\n",
1457 json_object_to_json_string(json_no));
1458 json_object_free(json_no);
1459 } else
1460 vty_out(vty, "Malformed address: %s\n",
1461 argv[idx]->arg);
1462 return CMD_WARNING;
1463 }
1464 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1465 if (uj) {
1466 json_object *json_no = NULL;
1467 json_no = json_object_new_object();
1468 json_object_string_add(
1469 json_no, "warning",
1470 "No such neighbor or address family");
1471 vty_out(vty, "%s\n",
1472 json_object_to_json_string(json_no));
1473 json_object_free(json_no);
1474 } else
1475 vty_out(vty, "%% No such neighbor or address family\n");
1476 return CMD_WARNING;
1477 }
1478
1479 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, peer, 0,
1480 uj);
1481 }
1482
1483 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1484 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1485 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1486 SHOW_STR
1487 IP_STR
1488 BGP_STR
1489 L2VPN_HELP_STR
1490 EVPN_HELP_STR
1491 "Detailed information on TCP and BGP neighbor connections\n"
1492 "IPv4 Neighbor to display information about\n"
1493 "IPv6 Neighbor to display information about\n"
1494 "Neighbor on BGP configured interface\n"
1495 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1496 {
1497 int idx = 0;
1498 struct peer *peer;
1499 bool uj = use_json(argc, argv);
1500 struct bgp *bgp = NULL;
1501 afi_t afi = AFI_L2VPN;
1502 safi_t safi = SAFI_EVPN;
1503 char *peerstr = NULL;
1504
1505 if (uj)
1506 argc--;
1507
1508 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1509 &bgp, uj);
1510 if (!idx) {
1511 vty_out(vty, "No index\n");
1512 return CMD_WARNING;
1513 }
1514
1515 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1516 argv_find(argv, argc, "neighbors", &idx);
1517 peerstr = argv[++idx]->arg;
1518
1519 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1520 if (!peer) {
1521 if (uj) {
1522 json_object *json_no = NULL;
1523 json_no = json_object_new_object();
1524 json_object_string_add(json_no, "warning",
1525 "Malformed address");
1526 vty_out(vty, "%s\n",
1527 json_object_to_json_string(json_no));
1528 json_object_free(json_no);
1529 } else
1530 vty_out(vty, "Malformed address: %s\n",
1531 argv[idx]->arg);
1532 return CMD_WARNING;
1533 }
1534 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1535 if (uj) {
1536 json_object *json_no = NULL;
1537 json_no = json_object_new_object();
1538 json_object_string_add(
1539 json_no, "warning",
1540 "No such neighbor or address family");
1541 vty_out(vty, "%s\n",
1542 json_object_to_json_string(json_no));
1543 json_object_free(json_no);
1544 } else
1545 vty_out(vty, "%% No such neighbor or address family\n");
1546 return CMD_WARNING;
1547 }
1548
1549 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1550 }
1551
1552 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1553 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1554 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1555 SHOW_STR
1556 IP_STR
1557 BGP_STR
1558 L2VPN_HELP_STR
1559 EVPN_HELP_STR
1560 "Display information for a route distinguisher\n"
1561 "VPN Route Distinguisher\n"
1562 "Detailed information on TCP and BGP neighbor connections\n"
1563 "IPv4 Neighbor to display information about\n"
1564 "IPv6 Neighbor to display information about\n"
1565 "Neighbor on BGP configured interface\n"
1566 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1567 {
1568 int idx_ext_community = 0;
1569 int idx = 0;
1570 int ret;
1571 struct peer *peer;
1572 struct prefix_rd prd;
1573 struct bgp *bgp = NULL;
1574 bool uj = use_json(argc, argv);
1575 char *peerstr = NULL;
1576 afi_t afi = AFI_L2VPN;
1577 safi_t safi = SAFI_EVPN;
1578
1579 if (uj)
1580 argc--;
1581
1582 if (uj)
1583 argc--;
1584
1585 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1586 &bgp, uj);
1587 if (!idx) {
1588 vty_out(vty, "No index\n");
1589 return CMD_WARNING;
1590 }
1591
1592 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1593
1594 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1595 argv_find(argv, argc, "neighbors", &idx);
1596 peerstr = argv[++idx]->arg;
1597
1598 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1599 if (!peer) {
1600 if (uj) {
1601 json_object *json_no = NULL;
1602 json_no = json_object_new_object();
1603 json_object_string_add(json_no, "warning",
1604 "Malformed address");
1605 vty_out(vty, "%s\n",
1606 json_object_to_json_string(json_no));
1607 json_object_free(json_no);
1608 } else
1609 vty_out(vty, "Malformed address: %s\n",
1610 argv[idx]->arg);
1611 return CMD_WARNING;
1612 }
1613 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1614 if (uj) {
1615 json_object *json_no = NULL;
1616 json_no = json_object_new_object();
1617 json_object_string_add(
1618 json_no, "warning",
1619 "No such neighbor or address family");
1620 vty_out(vty, "%s\n",
1621 json_object_to_json_string(json_no));
1622 json_object_free(json_no);
1623 } else
1624 vty_out(vty, "%% No such neighbor or address family\n");
1625 return CMD_WARNING;
1626 }
1627
1628 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1629 if (!ret) {
1630 if (uj) {
1631 json_object *json_no = NULL;
1632 json_no = json_object_new_object();
1633 json_object_string_add(json_no, "warning",
1634 "Malformed Route Distinguisher");
1635 vty_out(vty, "%s\n",
1636 json_object_to_json_string(json_no));
1637 json_object_free(json_no);
1638 } else
1639 vty_out(vty, "%% Malformed Route Distinguisher\n");
1640 return CMD_WARNING;
1641 }
1642
1643 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1644 }
1645
1646 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1647 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1648 "show [ip] bgp l2vpn evpn all overlay [json]",
1649 SHOW_STR
1650 IP_STR
1651 BGP_STR
1652 L2VPN_HELP_STR
1653 EVPN_HELP_STR
1654 "Display information about all EVPN NLRIs\n"
1655 "Display BGP Overlay Information for prefixes\n"
1656 JSON_STR)
1657 {
1658 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1659 SHOW_DISPLAY_OVERLAY,
1660 use_json(argc, argv));
1661 }
1662
1663 DEFUN(show_ip_bgp_evpn_rd_overlay,
1664 show_ip_bgp_evpn_rd_overlay_cmd,
1665 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1666 SHOW_STR
1667 IP_STR
1668 BGP_STR
1669 L2VPN_HELP_STR
1670 EVPN_HELP_STR
1671 "Display information for a route distinguisher\n"
1672 "VPN Route Distinguisher\n"
1673 "Display BGP Overlay Information for prefixes\n")
1674 {
1675 int idx_ext_community = 0;
1676 int ret;
1677 struct prefix_rd prd;
1678
1679 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1680
1681 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1682 if (!ret) {
1683 vty_out(vty, "%% Malformed Route Distinguisher\n");
1684 return CMD_WARNING;
1685 }
1686 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1687 SHOW_DISPLAY_OVERLAY,
1688 use_json(argc, argv));
1689 }
1690
1691 DEFUN(show_bgp_l2vpn_evpn_com,
1692 show_bgp_l2vpn_evpn_com_cmd,
1693 "show bgp l2vpn evpn \
1694 <community AA:NN|large-community AA:BB:CC> \
1695 [exact-match] [json]",
1696 SHOW_STR
1697 BGP_STR
1698 L2VPN_HELP_STR
1699 EVPN_HELP_STR
1700 "Display routes matching the community\n"
1701 "Community number where AA and NN are (0-65535)\n"
1702 "Display routes matching the large-community\n"
1703 "List of large-community numbers\n"
1704 "Exact match of the communities\n"
1705 JSON_STR)
1706 {
1707 int idx = 0;
1708 int ret = 0;
1709 const char *clist_number_or_name;
1710 int show_type = bgp_show_type_normal;
1711 struct community *com;
1712 struct lcommunity *lcom;
1713
1714 if (argv_find(argv, argc, "large-community", &idx)) {
1715 clist_number_or_name = argv[++idx]->arg;
1716 show_type = bgp_show_type_lcommunity;
1717
1718 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1719 show_type = bgp_show_type_lcommunity_exact;
1720
1721 lcom = lcommunity_str2com(clist_number_or_name);
1722 if (!lcom) {
1723 vty_out(vty, "%% Large-community malformed\n");
1724 return CMD_WARNING;
1725 }
1726
1727 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1728 SHOW_DISPLAY_STANDARD,
1729 use_json(argc, argv));
1730
1731 lcommunity_free(&lcom);
1732 } else if (argv_find(argv, argc, "community", &idx)) {
1733 clist_number_or_name = argv[++idx]->arg;
1734 show_type = bgp_show_type_community;
1735
1736 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1737 show_type = bgp_show_type_community_exact;
1738
1739 com = community_str2com(clist_number_or_name);
1740
1741 if (!com) {
1742 vty_out(vty, "%% Community malformed: %s\n",
1743 clist_number_or_name);
1744 return CMD_WARNING;
1745 }
1746
1747 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1748 SHOW_DISPLAY_STANDARD,
1749 use_json(argc, argv));
1750 community_free(&com);
1751 }
1752
1753 return ret;
1754 }
1755
1756 /* For testing purpose, static route of EVPN RT-5. */
1757 DEFUN(evpnrt5_network,
1758 evpnrt5_network_cmd,
1759 "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]",
1760 "Specify a network to announce via BGP\n"
1761 "IP prefix\n"
1762 "IPv6 prefix\n"
1763 "Specify Route Distinguisher\n"
1764 "VPN Route Distinguisher\n"
1765 "Ethernet Tag\n"
1766 "Ethernet Tag Value\n"
1767 "BGP label\n"
1768 "label value\n"
1769 "Ethernet Segment Identifier\n"
1770 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1771 "Gateway IP\n"
1772 "Gateway IP ( A.B.C.D )\n"
1773 "Gateway IPv6 ( X:X::X:X )\n"
1774 "Router Mac Ext Comm\n"
1775 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1776 "Route-map to modify the attributes\n"
1777 "Name of the route map\n")
1778 {
1779 int idx_ipv4_prefixlen = 1;
1780 int idx_route_distinguisher = 3;
1781 int idx_label = 7;
1782 int idx_esi = 9;
1783 int idx_gwip = 11;
1784 int idx_ethtag = 5;
1785 int idx_routermac = 13;
1786
1787 return bgp_static_set_safi(
1788 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1789 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
1790 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1791 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1792 argv[idx_routermac]->arg);
1793 }
1794
1795 /* For testing purpose, static route of EVPN RT-5. */
1796 DEFUN(no_evpnrt5_network,
1797 no_evpnrt5_network_cmd,
1798 "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>",
1799 NO_STR
1800 "Specify a network to announce via BGP\n"
1801 "IP prefix\n"
1802 "IPv6 prefix\n"
1803 "Specify Route Distinguisher\n"
1804 "VPN Route Distinguisher\n"
1805 "Ethernet Tag\n"
1806 "Ethernet Tag Value\n"
1807 "BGP label\n"
1808 "label value\n"
1809 "Ethernet Segment Identifier\n"
1810 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1811 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1812 {
1813 int idx_ipv4_prefixlen = 2;
1814 int idx_ext_community = 4;
1815 int idx_label = 8;
1816 int idx_ethtag = 6;
1817 int idx_esi = 10;
1818 int idx_gwip = 12;
1819 return bgp_static_unset_safi(
1820 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1821 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1822 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1823 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
1824 }
1825
1826 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1827 {
1828 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
1829 }
1830
1831 static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1832 {
1833 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl);
1834 }
1835
1836 /*
1837 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1838 * check that this is a change.
1839 */
1840 static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1841 struct ecommunity *ecomadd)
1842 {
1843 /* If the VNI is "live", we need to uninstall routes using the current
1844 * import RT(s) first before we update the import RT, and subsequently
1845 * install routes.
1846 */
1847 if (is_vni_live(vpn))
1848 bgp_evpn_uninstall_routes(bgp, vpn);
1849
1850 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1851 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1852
1853 /* If the auto route-target is in use we must remove it */
1854 evpn_import_rt_delete_auto(bgp, vpn);
1855
1856 /* Add new RT and rebuild the RT to VNI mapping */
1857 listnode_add_sort(vpn->import_rtl, ecomadd);
1858
1859 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1860 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1861
1862 /* Install routes that match new import RT */
1863 if (is_vni_live(vpn))
1864 bgp_evpn_install_routes(bgp, vpn);
1865 }
1866
1867 /*
1868 * Unconfigure Import RT(s) for a VNI (vty handler).
1869 */
1870 static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1871 struct ecommunity *ecomdel)
1872 {
1873 struct listnode *node, *nnode, *node_to_del;
1874 struct ecommunity *ecom;
1875
1876 /* Along the lines of "configure" except we have to reset to the
1877 * automatic value.
1878 */
1879 if (is_vni_live(vpn))
1880 bgp_evpn_uninstall_routes(bgp, vpn);
1881
1882 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1883 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1884
1885 /* Delete all import RTs */
1886 if (ecomdel == NULL) {
1887 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1888 ecommunity_free(&ecom);
1889 list_delete_node(vpn->import_rtl, node);
1890 }
1891 }
1892
1893 /* Delete a specific import RT */
1894 else {
1895 node_to_del = NULL;
1896
1897 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1898 if (ecommunity_match(ecom, ecomdel)) {
1899 ecommunity_free(&ecom);
1900 node_to_del = node;
1901 break;
1902 }
1903 }
1904
1905 if (node_to_del)
1906 list_delete_node(vpn->import_rtl, node_to_del);
1907 }
1908
1909 assert(vpn->import_rtl);
1910 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1911 if (list_isempty(vpn->import_rtl)) {
1912 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1913 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1914 }
1915 /* Rebuild the RT to VNI mapping */
1916 else
1917 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1918
1919 /* Install routes that match new import RT */
1920 if (is_vni_live(vpn))
1921 bgp_evpn_install_routes(bgp, vpn);
1922 }
1923
1924 /*
1925 * Configure the Export RT for a VNI (vty handler). Caller expected to
1926 * check that this is a change. Note that only a single export RT is
1927 * allowed for a VNI and any change to configuration is implemented as
1928 * a "replace" (similar to other configuration).
1929 */
1930 static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1931 struct ecommunity *ecomadd)
1932 {
1933 /* If the auto route-target is in use we must remove it */
1934 evpn_export_rt_delete_auto(bgp, vpn);
1935
1936 listnode_add_sort(vpn->export_rtl, ecomadd);
1937 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1938
1939 if (is_vni_live(vpn))
1940 bgp_evpn_handle_export_rt_change(bgp, vpn);
1941 }
1942
1943 /*
1944 * Unconfigure the Export RT for a VNI (vty handler)
1945 */
1946 static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1947 struct ecommunity *ecomdel)
1948 {
1949 struct listnode *node, *nnode, *node_to_del;
1950 struct ecommunity *ecom;
1951
1952 /* Delete all export RTs */
1953 if (ecomdel == NULL) {
1954 /* Reset to default and process all routes. */
1955 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1956 ecommunity_free(&ecom);
1957 list_delete_node(vpn->export_rtl, node);
1958 }
1959 }
1960
1961 /* Delete a specific export RT */
1962 else {
1963 node_to_del = NULL;
1964
1965 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1966 if (ecommunity_match(ecom, ecomdel)) {
1967 ecommunity_free(&ecom);
1968 node_to_del = node;
1969 break;
1970 }
1971 }
1972
1973 if (node_to_del)
1974 list_delete_node(vpn->export_rtl, node_to_del);
1975 }
1976
1977 assert(vpn->export_rtl);
1978 if (list_isempty(vpn->export_rtl)) {
1979 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1980 bgp_evpn_derive_auto_rt_export(bgp, vpn);
1981 }
1982
1983 if (is_vni_live(vpn))
1984 bgp_evpn_handle_export_rt_change(bgp, vpn);
1985 }
1986
1987 /*
1988 * Configure RD for VRF
1989 */
1990 static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
1991 {
1992 /* If we have already advertise type-5 routes with a diffrent RD, we
1993 * have to delete and withdraw them firs
1994 */
1995 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1996
1997 /* update RD */
1998 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
1999 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2000
2001 /* We have a new RD for VRF.
2002 * Advertise all type-5 routes again with the new RD
2003 */
2004 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2005 }
2006
2007 /*
2008 * Unconfigure RD for VRF
2009 */
2010 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2011 {
2012 /* If we have already advertise type-5 routes with a diffrent RD, we
2013 * have to delete and withdraw them firs
2014 */
2015 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2016
2017 /* fall back to default RD */
2018 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
2019 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2020
2021 /* We have a new RD for VRF.
2022 * Advertise all type-5 routes again with the new RD
2023 */
2024 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2025 }
2026
2027 /*
2028 * Configure RD for a VNI (vty handler)
2029 */
2030 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
2031 struct prefix_rd *rd)
2032 {
2033 /* If the VNI is "live", we need to delete and withdraw this VNI's
2034 * local routes with the prior RD first. Then, after updating RD,
2035 * need to re-advertise.
2036 */
2037 if (is_vni_live(vpn))
2038 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2039
2040 /* update RD */
2041 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
2042 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
2043
2044 if (is_vni_live(vpn))
2045 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2046 }
2047
2048 /*
2049 * Unconfigure RD for a VNI (vty handler)
2050 */
2051 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
2052 {
2053 /* If the VNI is "live", we need to delete and withdraw this VNI's
2054 * local routes with the prior RD first. Then, after resetting RD
2055 * to automatic value, need to re-advertise.
2056 */
2057 if (is_vni_live(vpn))
2058 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2059
2060 /* reset RD to default */
2061 bgp_evpn_derive_auto_rd(bgp, vpn);
2062
2063 if (is_vni_live(vpn))
2064 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2065 }
2066
2067 /*
2068 * Create VNI, if not already present (VTY handler). Mark as configured.
2069 */
2070 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
2071 {
2072 struct bgpevpn *vpn;
2073 struct in_addr mcast_grp = {INADDR_ANY};
2074
2075 if (!bgp->vnihash)
2076 return NULL;
2077
2078 vpn = bgp_evpn_lookup_vni(bgp, vni);
2079 if (!vpn) {
2080 /* Check if this L2VNI is already configured as L3VNI */
2081 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
2082 flog_err(
2083 EC_BGP_VNI,
2084 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2085 bgp->vrf_id, vni);
2086 return NULL;
2087 }
2088
2089 /* tenant vrf will be updated when we get local_vni_add from
2090 * zebra
2091 */
2092 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp);
2093 if (!vpn) {
2094 flog_err(
2095 EC_BGP_VNI,
2096 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2097 bgp->vrf_id, vni);
2098 return NULL;
2099 }
2100 }
2101
2102 /* Mark as configured. */
2103 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2104 return vpn;
2105 }
2106
2107 /*
2108 * Delete VNI. If VNI does not exist in the system (i.e., just
2109 * configuration), all that is needed is to free it. Otherwise,
2110 * any parameters configured for the VNI need to be reset (with
2111 * appropriate action) and the VNI marked as unconfigured; the
2112 * VNI will continue to exist, purely as a "learnt" entity.
2113 */
2114 static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
2115 {
2116 assert(bgp->vnihash);
2117
2118 if (!is_vni_live(vpn)) {
2119 bgp_evpn_free(bgp, vpn);
2120 return 0;
2121 }
2122
2123 /* We need to take the unconfigure action for each parameter of this VNI
2124 * that is configured. Some optimization is possible, but not worth the
2125 * additional code for an operation that should be pretty rare.
2126 */
2127 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2128
2129 /* First, deal with the export side - RD and export RT changes. */
2130 if (is_rd_configured(vpn))
2131 evpn_unconfigure_rd(bgp, vpn);
2132 if (is_export_rt_configured(vpn))
2133 evpn_unconfigure_export_rt(bgp, vpn, NULL);
2134
2135 /* Next, deal with the import side. */
2136 if (is_import_rt_configured(vpn))
2137 evpn_unconfigure_import_rt(bgp, vpn, NULL);
2138
2139 return 0;
2140 }
2141
2142 /*
2143 * Display import RT mapping to VRFs (vty handler)
2144 * bgp_evpn: evpn bgp instance
2145 */
2146 static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
2147 json_object *json)
2148 {
2149 void *args[2];
2150
2151 args[0] = vty;
2152 args[1] = json;
2153
2154 hash_iterate(bgp_evpn->vrf_import_rt_hash,
2155 (void (*)(struct hash_bucket *,
2156 void *))show_vrf_import_rt_entry,
2157 args);
2158 }
2159
2160 /*
2161 * Display import RT mapping to VNIs (vty handler)
2162 */
2163 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2164 json_object *json)
2165 {
2166 void *args[2];
2167
2168 args[0] = vty;
2169 args[1] = json;
2170
2171 hash_iterate(
2172 bgp->import_rt_hash,
2173 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
2174 args);
2175 }
2176
2177 /*
2178 * Display EVPN routes for all VNIs - vty handler.
2179 */
2180 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
2181 struct in_addr vtep_ip, json_object *json,
2182 int detail)
2183 {
2184 uint32_t num_vnis;
2185 struct vni_walk_ctx wctx;
2186
2187 num_vnis = hashcount(bgp->vnihash);
2188 if (!num_vnis)
2189 return;
2190 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2191 wctx.bgp = bgp;
2192 wctx.vty = vty;
2193 wctx.vtep_ip = vtep_ip;
2194 wctx.json = json;
2195 wctx.detail = detail;
2196 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
2197 void *))show_vni_routes_hash,
2198 &wctx);
2199 }
2200
2201 /*
2202 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2203 */
2204 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
2205 vni_t vni, struct in_addr orig_ip,
2206 json_object *json)
2207 {
2208 struct bgpevpn *vpn;
2209 struct prefix_evpn p;
2210 struct bgp_node *rn;
2211 struct bgp_path_info *pi;
2212 uint32_t path_cnt = 0;
2213 afi_t afi;
2214 safi_t safi;
2215 json_object *json_paths = NULL;
2216
2217 afi = AFI_L2VPN;
2218 safi = SAFI_EVPN;
2219
2220 /* Locate VNI. */
2221 vpn = bgp_evpn_lookup_vni(bgp, vni);
2222 if (!vpn) {
2223 vty_out(vty, "VNI not found\n");
2224 return;
2225 }
2226
2227 /* See if route exists. */
2228 build_evpn_type3_prefix(&p, orig_ip);
2229 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2230 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2231 if (!json)
2232 vty_out(vty, "%% Network not in table\n");
2233 return;
2234 }
2235
2236 if (json)
2237 json_paths = json_object_new_array();
2238
2239 /* Prefix and num paths displayed once per prefix. */
2240 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2241
2242 /* Display each path for this prefix. */
2243 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2244 json_object *json_path = NULL;
2245
2246 if (json)
2247 json_path = json_object_new_array();
2248
2249 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2250 json_path);
2251
2252 if (json)
2253 json_object_array_add(json_paths, json_path);
2254
2255 path_cnt++;
2256 }
2257
2258 if (json) {
2259 if (path_cnt)
2260 json_object_object_add(json, "paths", json_paths);
2261
2262 json_object_int_add(json, "numPaths", path_cnt);
2263 } else {
2264 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2265 path_cnt);
2266 }
2267 }
2268
2269 /*
2270 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2271 * By definition, only matching type-2 route will be displayed.
2272 */
2273 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2274 vni_t vni, struct ethaddr *mac,
2275 struct ipaddr *ip, json_object *json)
2276 {
2277 struct bgpevpn *vpn;
2278 struct prefix_evpn p;
2279 struct bgp_node *rn;
2280 struct bgp_path_info *pi;
2281 uint32_t path_cnt = 0;
2282 afi_t afi;
2283 safi_t safi;
2284 json_object *json_paths = NULL;
2285
2286 afi = AFI_L2VPN;
2287 safi = SAFI_EVPN;
2288
2289 /* Locate VNI. */
2290 vpn = bgp_evpn_lookup_vni(bgp, vni);
2291 if (!vpn) {
2292 if (!json)
2293 vty_out(vty, "VNI not found\n");
2294 return;
2295 }
2296
2297 /* See if route exists. Look for both non-sticky and sticky. */
2298 build_evpn_type2_prefix(&p, mac, ip);
2299 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2300 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2301 if (!json)
2302 vty_out(vty, "%% Network not in table\n");
2303 return;
2304 }
2305
2306 if (json)
2307 json_paths = json_object_new_array();
2308
2309 /* Prefix and num paths displayed once per prefix. */
2310 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2311
2312 /* Display each path for this prefix. */
2313 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2314 json_object *json_path = NULL;
2315
2316 if (json)
2317 json_path = json_object_new_array();
2318
2319 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2320 json_path);
2321
2322 if (json)
2323 json_object_array_add(json_paths, json_path);
2324
2325 path_cnt++;
2326 }
2327
2328 if (json) {
2329 if (path_cnt)
2330 json_object_object_add(json, "paths", json_paths);
2331
2332 json_object_int_add(json, "numPaths", path_cnt);
2333 } else {
2334 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2335 path_cnt);
2336 }
2337 }
2338
2339 /* Disaplay EVPN routes for a ESI - VTY handler */
2340 static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2341 esi_t *esi, json_object *json)
2342 {
2343 struct evpnes *es = NULL;
2344
2345 /* locate the ES */
2346 es = bgp_evpn_lookup_es(bgp, esi);
2347 if (!es) {
2348 if (!json)
2349 vty_out(vty, "ESI not found\n");
2350 return;
2351 }
2352
2353 show_esi_routes(bgp, es, vty, json);
2354 }
2355
2356 /*
2357 * Display EVPN routes for a VNI - vty handler.
2358 * If 'type' is non-zero, only routes matching that type are shown.
2359 * If the vtep_ip is non zero, only routes behind that vtep are shown
2360 */
2361 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2362 int type, struct in_addr vtep_ip,
2363 json_object *json)
2364 {
2365 struct bgpevpn *vpn;
2366
2367 /* Locate VNI. */
2368 vpn = bgp_evpn_lookup_vni(bgp, vni);
2369 if (!vpn) {
2370 if (!json)
2371 vty_out(vty, "VNI not found\n");
2372 return;
2373 }
2374
2375 /* Walk this VNI's route table and display appropriate routes. */
2376 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json, 0);
2377 }
2378
2379 /*
2380 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2381 * IP (vty handler). By definition, only matching type-2 route will be
2382 * displayed.
2383 */
2384 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2385 struct prefix_rd *prd, struct ethaddr *mac,
2386 struct ipaddr *ip, json_object *json)
2387 {
2388 struct prefix_evpn p;
2389 struct bgp_node *rn;
2390 struct bgp_path_info *pi;
2391 afi_t afi;
2392 safi_t safi;
2393 uint32_t path_cnt = 0;
2394 json_object *json_paths = NULL;
2395 char prefix_str[BUFSIZ];
2396
2397 afi = AFI_L2VPN;
2398 safi = SAFI_EVPN;
2399
2400 /* See if route exists. Look for both non-sticky and sticky. */
2401 build_evpn_type2_prefix(&p, mac, ip);
2402 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2403 (struct prefix *)&p, prd);
2404 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2405 if (!json)
2406 vty_out(vty, "%% Network not in table\n");
2407 return;
2408 }
2409
2410 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
2411 sizeof(prefix_str));
2412
2413 /* Prefix and num paths displayed once per prefix. */
2414 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
2415
2416 if (json)
2417 json_paths = json_object_new_array();
2418
2419 /* Display each path for this prefix. */
2420 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2421 json_object *json_path = NULL;
2422
2423 if (json)
2424 json_path = json_object_new_array();
2425
2426 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2427 json_path);
2428
2429 if (json)
2430 json_object_array_add(json_paths, json_path);
2431
2432 path_cnt++;
2433 }
2434
2435 if (json && path_cnt) {
2436 if (path_cnt)
2437 json_object_object_add(json, prefix_str, json_paths);
2438 json_object_int_add(json, "numPaths", path_cnt);
2439 } else {
2440 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2441 path_cnt);
2442 }
2443 }
2444
2445 /*
2446 * Display BGP EVPN routing table -- for specific RD (vty handler)
2447 * If 'type' is non-zero, only routes matching that type are shown.
2448 */
2449 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
2450 struct prefix_rd *prd, int type,
2451 json_object *json)
2452 {
2453 struct bgp_node *rd_rn;
2454 struct bgp_table *table;
2455 struct bgp_node *rn;
2456 struct bgp_path_info *pi;
2457 int rd_header = 1;
2458 afi_t afi;
2459 safi_t safi;
2460 uint32_t prefix_cnt, path_cnt;
2461 char rd_str[RD_ADDRSTRLEN];
2462 json_object *json_rd = NULL;
2463 int add_rd_to_json = 0;
2464
2465 afi = AFI_L2VPN;
2466 safi = SAFI_EVPN;
2467 prefix_cnt = path_cnt = 0;
2468
2469 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
2470
2471 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2472 if (!rd_rn)
2473 return;
2474
2475 table = bgp_node_get_bgp_table_info(rd_rn);
2476 if (table == NULL)
2477 return;
2478
2479 if (json) {
2480 json_rd = json_object_new_object();
2481 json_object_string_add(json_rd, "rd", rd_str);
2482 }
2483
2484 /* Display all prefixes with this RD. */
2485 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2486 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2487 json_object *json_prefix = NULL;
2488 json_object *json_paths = NULL;
2489 char prefix_str[BUFSIZ];
2490 int add_prefix_to_json = 0;
2491
2492 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
2493 sizeof(prefix_str));
2494
2495 if (type && evp->prefix.route_type != type)
2496 continue;
2497
2498 if (json)
2499 json_prefix = json_object_new_object();
2500
2501 pi = bgp_node_get_bgp_path_info(rn);
2502 if (pi) {
2503 /* RD header and legend - once overall. */
2504 if (rd_header && !json) {
2505 vty_out(vty,
2506 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2507 vty_out(vty,
2508 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2509 vty_out(vty,
2510 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2511 rd_header = 0;
2512 }
2513
2514 /* Prefix and num paths displayed once per prefix. */
2515 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
2516 safi, json_prefix);
2517
2518 prefix_cnt++;
2519 }
2520
2521 if (json)
2522 json_paths = json_object_new_array();
2523
2524 /* Display each path for this prefix. */
2525 for (; pi; pi = pi->next) {
2526 json_object *json_path = NULL;
2527
2528 if (json)
2529 json_path = json_object_new_array();
2530
2531 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2532 json_path);
2533
2534 if (json)
2535 json_object_array_add(json_paths, json_path);
2536
2537 path_cnt++;
2538 add_prefix_to_json = 1;
2539 add_rd_to_json = 1;
2540 }
2541
2542 if (json && add_prefix_to_json) {
2543 json_object_object_add(json_prefix, "paths",
2544 json_paths);
2545 json_object_object_add(json_rd, prefix_str,
2546 json_prefix);
2547 }
2548 }
2549
2550 if (json && add_rd_to_json)
2551 json_object_object_add(json, rd_str, json_rd);
2552
2553 if (json) {
2554 json_object_int_add(json, "numPrefix", prefix_cnt);
2555 json_object_int_add(json, "numPaths", path_cnt);
2556 } else {
2557 if (prefix_cnt == 0)
2558 vty_out(vty, "No prefixes exist with this RD%s\n",
2559 type ? " (of requested type)" : "");
2560 else
2561 vty_out(vty,
2562 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2563 prefix_cnt, path_cnt,
2564 type ? " (of requested type)" : "");
2565 }
2566 }
2567
2568 /*
2569 * Display BGP EVPN routing table - all routes (vty handler).
2570 * If 'type' is non-zero, only routes matching that type are shown.
2571 */
2572 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2573 json_object *json, int detail)
2574 {
2575 struct bgp_node *rd_rn;
2576 struct bgp_table *table;
2577 struct bgp_node *rn;
2578 struct bgp_path_info *pi;
2579 int header = detail ? 0 : 1;
2580 int rd_header;
2581 afi_t afi;
2582 safi_t safi;
2583 uint32_t prefix_cnt, path_cnt;
2584
2585 afi = AFI_L2VPN;
2586 safi = SAFI_EVPN;
2587 prefix_cnt = path_cnt = 0;
2588
2589 /* EVPN routing table is a 2-level table with the first level being
2590 * the RD.
2591 */
2592 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2593 rd_rn = bgp_route_next(rd_rn)) {
2594 char rd_str[RD_ADDRSTRLEN];
2595 json_object *json_rd = NULL; /* contains routes for an RD */
2596 int add_rd_to_json = 0;
2597 uint64_t tbl_ver;
2598
2599 table = bgp_node_get_bgp_table_info(rd_rn);
2600 if (table == NULL)
2601 continue;
2602
2603 tbl_ver = table->version;
2604 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2605 sizeof(rd_str));
2606
2607 if (json) {
2608 json_rd = json_object_new_object();
2609 json_object_string_add(json_rd, "rd", rd_str);
2610 }
2611
2612 rd_header = 1;
2613
2614 /* Display all prefixes for an RD */
2615 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2616 json_object *json_prefix =
2617 NULL; /* contains prefix under a RD */
2618 json_object *json_paths =
2619 NULL; /* array of paths under a prefix*/
2620 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2621 char prefix_str[BUFSIZ];
2622 int add_prefix_to_json = 0;
2623
2624 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2625 prefix_str, sizeof(prefix_str));
2626
2627 if (type && evp->prefix.route_type != type)
2628 continue;
2629
2630 pi = bgp_node_get_bgp_path_info(rn);
2631 if (pi) {
2632 /* Overall header/legend displayed once. */
2633 if (header) {
2634 bgp_evpn_show_route_header(vty, bgp,
2635 tbl_ver,
2636 json);
2637 if (!json)
2638 vty_out(vty,
2639 "%19s Extended Community\n"
2640 , " ");
2641 header = 0;
2642 }
2643
2644 /* RD header - per RD. */
2645 if (rd_header) {
2646 bgp_evpn_show_route_rd_header(
2647 vty, rd_rn, json);
2648 rd_header = 0;
2649 }
2650
2651 prefix_cnt++;
2652 }
2653
2654 if (json) {
2655 json_prefix = json_object_new_object();
2656 json_paths = json_object_new_array();
2657 json_object_string_add(json_prefix, "prefix",
2658 prefix_str);
2659 json_object_int_add(json_prefix, "prefixLen",
2660 rn->p.prefixlen);
2661 }
2662
2663 /* Prefix and num paths displayed once per prefix. */
2664 if (detail)
2665 route_vty_out_detail_header(
2666 vty, bgp, rn,
2667 (struct prefix_rd *)&rd_rn->p,
2668 AFI_L2VPN, SAFI_EVPN, json_prefix);
2669
2670 /* For EVPN, the prefix is displayed for each path (to
2671 * fit in
2672 * with code that already exists).
2673 */
2674 for (; pi; pi = pi->next) {
2675 json_object *json_path = NULL;
2676 path_cnt++;
2677 add_prefix_to_json = 1;
2678 add_rd_to_json = 1;
2679
2680 if (json)
2681 json_path = json_object_new_array();
2682
2683 if (detail) {
2684 route_vty_out_detail(
2685 vty, bgp, rn, pi, AFI_L2VPN,
2686 SAFI_EVPN, json_path);
2687 } else
2688 route_vty_out(vty, &rn->p, pi, 0,
2689 SAFI_EVPN, json_path);
2690
2691 if (json)
2692 json_object_array_add(json_paths,
2693 json_path);
2694 }
2695
2696 if (json && add_prefix_to_json) {
2697 json_object_object_add(json_prefix, "paths",
2698 json_paths);
2699 json_object_object_add(json_rd, prefix_str,
2700 json_prefix);
2701 }
2702 }
2703
2704 if (json && add_rd_to_json)
2705 json_object_object_add(json, rd_str, json_rd);
2706 }
2707
2708 if (json) {
2709 json_object_int_add(json, "numPrefix", prefix_cnt);
2710 json_object_int_add(json, "numPaths", path_cnt);
2711 } else {
2712 if (prefix_cnt == 0) {
2713 vty_out(vty, "No EVPN prefixes %sexist\n",
2714 type ? "(of requested type) " : "");
2715 } else {
2716 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2717 prefix_cnt, path_cnt,
2718 type ? " (of requested type)" : "");
2719 }
2720 }
2721 }
2722
2723 /* Display specific ES */
2724 static void evpn_show_es(struct vty *vty, struct bgp *bgp, esi_t *esi,
2725 json_object *json)
2726 {
2727 struct evpnes *es = NULL;
2728
2729 es = bgp_evpn_lookup_es(bgp, esi);
2730 if (es) {
2731 display_es(vty, es, json);
2732 } else {
2733 if (json) {
2734 vty_out(vty, "{}\n");
2735 } else {
2736 vty_out(vty, "ESI not found\n");
2737 return;
2738 }
2739 }
2740 }
2741
2742 /* Display all ESs */
2743 static void evpn_show_all_es(struct vty *vty, struct bgp *bgp,
2744 json_object *json)
2745 {
2746 void *args[2];
2747
2748 if (!json)
2749 vty_out(vty, "%-30s %-6s %-21s %-15s %-6s\n",
2750 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2751
2752 /* print all ESs */
2753 args[0] = vty;
2754 args[1] = json;
2755 hash_iterate(bgp->esihash,
2756 (void (*)(struct hash_bucket *, void *))show_es_entry,
2757 args);
2758 }
2759
2760 /*
2761 * Display specified VNI (vty handler)
2762 */
2763 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2764 json_object *json)
2765 {
2766 uint8_t found = 0;
2767 struct bgpevpn *vpn;
2768
2769 vpn = bgp_evpn_lookup_vni(bgp, vni);
2770 if (vpn) {
2771 found = 1;
2772 display_vni(vty, vpn, json);
2773 } else {
2774 struct bgp *bgp_temp;
2775 struct listnode *node = NULL;
2776
2777 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2778 if (bgp_temp->l3vni == vni) {
2779 found = 1;
2780 display_l3vni(vty, bgp_temp, json);
2781 }
2782 }
2783 }
2784
2785 if (!found) {
2786 if (json) {
2787 vty_out(vty, "{}\n");
2788 } else {
2789 vty_out(vty, "VNI not found\n");
2790 return;
2791 }
2792 }
2793 }
2794
2795 /*
2796 * Display a VNI (upon user query).
2797 */
2798 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2799 json_object *json)
2800 {
2801 void *args[2];
2802 struct bgp *bgp_temp = NULL;
2803 struct listnode *node;
2804
2805
2806 if (!json) {
2807 vty_out(vty, "Flags: * - Kernel\n");
2808 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2809 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2810 }
2811
2812 /* print all L2 VNIS */
2813 args[0] = vty;
2814 args[1] = json;
2815 hash_iterate(bgp->vnihash,
2816 (void (*)(struct hash_bucket *, void *))show_vni_entry,
2817 args);
2818
2819 /* print all L3 VNIs */
2820 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
2821 show_l3vni_entry(vty, bgp_temp, json);
2822 }
2823
2824 /*
2825 * evpn - enable advertisement of svi MAC-IP
2826 */
2827 static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
2828 uint32_t set)
2829 {
2830 if (!vpn) {
2831 if (set && bgp->evpn_info->advertise_svi_macip)
2832 return;
2833 else if (!set && !bgp->evpn_info->advertise_svi_macip)
2834 return;
2835
2836 bgp->evpn_info->advertise_svi_macip = set;
2837 bgp_zebra_advertise_svi_macip(bgp,
2838 bgp->evpn_info->advertise_svi_macip, 0);
2839 } else {
2840 if (set && vpn->advertise_svi_macip)
2841 return;
2842 else if (!set && !vpn->advertise_svi_macip)
2843 return;
2844
2845 vpn->advertise_svi_macip = set;
2846 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
2847 vpn->vni);
2848 }
2849 }
2850
2851 /*
2852 * evpn - enable advertisement of default g/w
2853 */
2854 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2855 {
2856 if (!vpn) {
2857 if (bgp->advertise_gw_macip)
2858 return;
2859
2860 bgp->advertise_gw_macip = 1;
2861 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2862 } else {
2863 if (vpn->advertise_gw_macip)
2864 return;
2865
2866 vpn->advertise_gw_macip = 1;
2867 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2868 vpn->vni);
2869 }
2870 return;
2871 }
2872
2873 /*
2874 * evpn - disable advertisement of default g/w
2875 */
2876 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2877 struct bgpevpn *vpn)
2878 {
2879 if (!vpn) {
2880 if (!bgp->advertise_gw_macip)
2881 return;
2882
2883 bgp->advertise_gw_macip = 0;
2884 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2885 } else {
2886 if (!vpn->advertise_gw_macip)
2887 return;
2888
2889 vpn->advertise_gw_macip = 0;
2890 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2891 vpn->vni);
2892 }
2893 return;
2894 }
2895
2896 /*
2897 * evpn - enable advertisement of default g/w
2898 */
2899 static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
2900 afi_t afi, bool add)
2901 {
2902 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
2903
2904 if (add) {
2905 /* bail if we are already advertising default route */
2906 if (evpn_default_originate_set(bgp_vrf, afi, safi))
2907 return;
2908
2909 if (afi == AFI_IP)
2910 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2911 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2912 else if (afi == AFI_IP6)
2913 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2914 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2915 } else {
2916 /* bail out if we havent advertised the default route */
2917 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
2918 return;
2919 if (afi == AFI_IP)
2920 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2921 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2922 else if (afi == AFI_IP6)
2923 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2924 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2925 }
2926
2927 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
2928 }
2929
2930 /*
2931 * evpn - enable advertisement of default g/w
2932 */
2933 static void evpn_set_advertise_subnet(struct bgp *bgp,
2934 struct bgpevpn *vpn)
2935 {
2936 if (vpn->advertise_subnet)
2937 return;
2938
2939 vpn->advertise_subnet = 1;
2940 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2941 }
2942
2943 /*
2944 * evpn - disable advertisement of default g/w
2945 */
2946 static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
2947 {
2948 if (!vpn->advertise_subnet)
2949 return;
2950
2951 vpn->advertise_subnet = 0;
2952 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2953 }
2954
2955 /*
2956 * EVPN (VNI advertisement) enabled. Register with zebra.
2957 */
2958 static void evpn_set_advertise_all_vni(struct bgp *bgp)
2959 {
2960 bgp->advertise_all_vni = 1;
2961 bgp_set_evpn(bgp);
2962 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2963 }
2964
2965 /*
2966 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2967 * cache, EVPN routes (delete and withdraw from peers).
2968 */
2969 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
2970 {
2971 bgp->advertise_all_vni = 0;
2972 bgp_set_evpn(bgp_get_default());
2973 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2974 bgp_evpn_cleanup_on_disable(bgp);
2975 }
2976
2977 /*
2978 * EVPN - use RFC8365 to auto-derive RT
2979 */
2980 static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
2981 {
2982 bgp->advertise_autort_rfc8365 = 1;
2983 bgp_evpn_handle_autort_change(bgp);
2984 }
2985
2986 /*
2987 * EVPN - don't use RFC8365 to auto-derive RT
2988 */
2989 static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
2990 {
2991 bgp->advertise_autort_rfc8365 = 0;
2992 bgp_evpn_handle_autort_change(bgp);
2993 }
2994
2995 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
2996 {
2997 char buf1[RD_ADDRSTRLEN];
2998 char *ecom_str;
2999 struct listnode *node, *nnode;
3000 struct ecommunity *ecom;
3001
3002 if (is_vni_configured(vpn)) {
3003 vty_out(vty, " vni %d\n", vpn->vni);
3004 if (is_rd_configured(vpn))
3005 vty_out(vty, " rd %s\n",
3006 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
3007
3008 if (is_import_rt_configured(vpn)) {
3009 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3010 ecom)) {
3011 ecom_str = ecommunity_ecom2str(
3012 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3013 vty_out(vty, " route-target import %s\n",
3014 ecom_str);
3015 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3016 }
3017 }
3018
3019 if (is_export_rt_configured(vpn)) {
3020 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3021 ecom)) {
3022 ecom_str = ecommunity_ecom2str(
3023 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3024 vty_out(vty, " route-target export %s\n",
3025 ecom_str);
3026 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3027 }
3028 }
3029
3030 if (vpn->advertise_gw_macip)
3031 vty_out(vty, " advertise-default-gw\n");
3032
3033 if (vpn->advertise_svi_macip)
3034 vty_out(vty, " advertise-svi-ip\n");
3035
3036 if (vpn->advertise_subnet)
3037 vty_out(vty, " advertise-subnet\n");
3038
3039 vty_out(vty, " exit-vni\n");
3040 }
3041 }
3042
3043 #ifndef VTYSH_EXTRACT_PL
3044 #include "bgpd/bgp_evpn_vty_clippy.c"
3045 #endif
3046
3047 DEFPY(bgp_evpn_flood_control,
3048 bgp_evpn_flood_control_cmd,
3049 "[no$no] flooding <disable$disable|head-end-replication$her>",
3050 NO_STR
3051 "Specify handling for BUM packets\n"
3052 "Do not flood any BUM packets\n"
3053 "Flood BUM packets using head-end replication\n")
3054 {
3055 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3056 enum vxlan_flood_control flood_ctrl;
3057
3058 if (!bgp)
3059 return CMD_WARNING;
3060
3061 if (disable && !no)
3062 flood_ctrl = VXLAN_FLOOD_DISABLED;
3063 else if (her || no)
3064 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3065 else
3066 return CMD_WARNING;
3067
3068 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3069 return CMD_SUCCESS;
3070
3071 bgp->vxlan_flood_ctrl = flood_ctrl;
3072 bgp_evpn_flood_control_change(bgp);
3073
3074 return CMD_SUCCESS;
3075 }
3076
3077 DEFUN (bgp_evpn_advertise_default_gw_vni,
3078 bgp_evpn_advertise_default_gw_vni_cmd,
3079 "advertise-default-gw",
3080 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3081 {
3082 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3083 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3084
3085 if (!bgp)
3086 return CMD_WARNING;
3087
3088 evpn_set_advertise_default_gw(bgp, vpn);
3089
3090 return CMD_SUCCESS;
3091 }
3092
3093 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3094 no_bgp_evpn_advertise_default_gw_vni_cmd,
3095 "no advertise-default-gw",
3096 NO_STR
3097 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3098 {
3099 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3100 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3101
3102 if (!bgp)
3103 return CMD_WARNING;
3104
3105 evpn_unset_advertise_default_gw(bgp, vpn);
3106
3107 return CMD_SUCCESS;
3108 }
3109
3110
3111 DEFUN (bgp_evpn_advertise_default_gw,
3112 bgp_evpn_advertise_default_gw_cmd,
3113 "advertise-default-gw",
3114 "Advertise All default g/w mac-ip routes in EVPN\n")
3115 {
3116 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3117
3118 if (!bgp)
3119 return CMD_WARNING;
3120
3121 if (!EVPN_ENABLED(bgp)) {
3122 vty_out(vty,
3123 "This command is only supported under the EVPN VRF\n");
3124 return CMD_WARNING;
3125 }
3126
3127 evpn_set_advertise_default_gw(bgp, NULL);
3128
3129 return CMD_SUCCESS;
3130 }
3131
3132 DEFUN (no_bgp_evpn_advertise_default_gw,
3133 no_bgp_evpn_advertise_default_gw_cmd,
3134 "no advertise-default-gw",
3135 NO_STR
3136 "Withdraw All default g/w mac-ip routes from EVPN\n")
3137 {
3138 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3139
3140 if (!bgp)
3141 return CMD_WARNING;
3142
3143 if (!EVPN_ENABLED(bgp)) {
3144 vty_out(vty,
3145 "This command is only supported under the EVPN VRF\n");
3146 return CMD_WARNING;
3147 }
3148
3149 evpn_unset_advertise_default_gw(bgp, NULL);
3150
3151 return CMD_SUCCESS;
3152 }
3153
3154 DEFUN (bgp_evpn_advertise_all_vni,
3155 bgp_evpn_advertise_all_vni_cmd,
3156 "advertise-all-vni",
3157 "Advertise All local VNIs\n")
3158 {
3159 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3160 struct bgp *bgp_evpn = NULL;
3161
3162 if (!bgp)
3163 return CMD_WARNING;
3164
3165 bgp_evpn = bgp_get_evpn();
3166 if (bgp_evpn && bgp_evpn != bgp) {
3167 vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n",
3168 bgp_evpn->name);
3169 return CMD_WARNING_CONFIG_FAILED;
3170 }
3171
3172 evpn_set_advertise_all_vni(bgp);
3173 return CMD_SUCCESS;
3174 }
3175
3176 DEFUN (no_bgp_evpn_advertise_all_vni,
3177 no_bgp_evpn_advertise_all_vni_cmd,
3178 "no advertise-all-vni",
3179 NO_STR
3180 "Advertise All local VNIs\n")
3181 {
3182 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3183
3184 if (!bgp)
3185 return CMD_WARNING;
3186 evpn_unset_advertise_all_vni(bgp);
3187 return CMD_SUCCESS;
3188 }
3189
3190 DEFUN (bgp_evpn_advertise_autort_rfc8365,
3191 bgp_evpn_advertise_autort_rfc8365_cmd,
3192 "autort rfc8365-compatible",
3193 "Auto-derivation of RT\n"
3194 "Auto-derivation of RT using RFC8365\n")
3195 {
3196 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3197
3198 if (!bgp)
3199 return CMD_WARNING;
3200 evpn_set_advertise_autort_rfc8365(bgp);
3201 return CMD_SUCCESS;
3202 }
3203
3204 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3205 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3206 "no autort rfc8365-compatible",
3207 NO_STR
3208 "Auto-derivation of RT\n"
3209 "Auto-derivation of RT using RFC8365\n")
3210 {
3211 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3212
3213 if (!bgp)
3214 return CMD_WARNING;
3215 evpn_unset_advertise_autort_rfc8365(bgp);
3216 return CMD_SUCCESS;
3217 }
3218
3219 DEFUN (bgp_evpn_default_originate,
3220 bgp_evpn_default_originate_cmd,
3221 "default-originate <ipv4 | ipv6>",
3222 "originate a default route\n"
3223 "ipv4 address family\n"
3224 "ipv6 address family\n")
3225 {
3226 afi_t afi = 0;
3227 int idx_afi = 0;
3228 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3229
3230 if (!bgp_vrf)
3231 return CMD_WARNING;
3232 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3233 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3234 return CMD_SUCCESS;
3235 }
3236
3237 DEFUN (no_bgp_evpn_default_originate,
3238 no_bgp_evpn_default_originate_cmd,
3239 "no default-originate <ipv4 | ipv6>",
3240 NO_STR
3241 "withdraw a default route\n"
3242 "ipv4 address family\n"
3243 "ipv6 address family\n")
3244 {
3245 afi_t afi = 0;
3246 int idx_afi = 0;
3247 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3248
3249 if (!bgp_vrf)
3250 return CMD_WARNING;
3251 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3252 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3253 return CMD_SUCCESS;
3254 }
3255
3256 DEFPY (dup_addr_detection,
3257 dup_addr_detection_cmd,
3258 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3259 "Duplicate address detection\n"
3260 "Max allowed moves before address detected as duplicate\n"
3261 "Num of max allowed moves (2-1000) default 5\n"
3262 "Duplicate address detection time\n"
3263 "Time in seconds (2-1800) default 180\n")
3264 {
3265 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3266
3267 if (!bgp_vrf)
3268 return CMD_WARNING;
3269
3270 if (!EVPN_ENABLED(bgp_vrf)) {
3271 vty_out(vty,
3272 "This command is only supported under the EVPN VRF\n");
3273 return CMD_WARNING;
3274 }
3275
3276 bgp_vrf->evpn_info->dup_addr_detect = true;
3277
3278 if (time_val)
3279 bgp_vrf->evpn_info->dad_time = time_val;
3280 if (max_moves_val)
3281 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3282
3283 bgp_zebra_dup_addr_detection(bgp_vrf);
3284
3285 return CMD_SUCCESS;
3286 }
3287
3288 DEFPY (dup_addr_detection_auto_recovery,
3289 dup_addr_detection_auto_recovery_cmd,
3290 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3291 "Duplicate address detection\n"
3292 "Duplicate address detection freeze\n"
3293 "Duplicate address detection permanent freeze\n"
3294 "Duplicate address detection freeze time (30-3600)\n")
3295 {
3296 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3297 uint32_t freeze_time = freeze_time_val;
3298
3299 if (!bgp_vrf)
3300 return CMD_WARNING;
3301
3302 if (!EVPN_ENABLED(bgp_vrf)) {
3303 vty_out(vty,
3304 "This command is only supported under the EVPN VRF\n");
3305 return CMD_WARNING;
3306 }
3307
3308 bgp_vrf->evpn_info->dup_addr_detect = true;
3309 bgp_vrf->evpn_info->dad_freeze = true;
3310 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3311
3312 bgp_zebra_dup_addr_detection(bgp_vrf);
3313
3314 return CMD_SUCCESS;
3315 }
3316
3317 DEFPY (no_dup_addr_detection,
3318 no_dup_addr_detection_cmd,
3319 "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3320 NO_STR
3321 "Duplicate address detection\n"
3322 "Max allowed moves before address detected as duplicate\n"
3323 "Num of max allowed moves (2-1000) default 5\n"
3324 "Duplicate address detection time\n"
3325 "Time in seconds (2-1800) default 180\n"
3326 "Duplicate address detection freeze\n"
3327 "Duplicate address detection permanent freeze\n"
3328 "Duplicate address detection freeze time (30-3600)\n")
3329 {
3330 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3331 uint32_t max_moves = (uint32_t)max_moves_val;
3332 uint32_t freeze_time = (uint32_t)freeze_time_val;
3333
3334 if (!bgp_vrf)
3335 return CMD_WARNING;
3336
3337 if (!EVPN_ENABLED(bgp_vrf)) {
3338 vty_out(vty,
3339 "This command is only supported under the EVPN VRF\n");
3340 return CMD_WARNING;
3341 }
3342
3343 if (argc == 2) {
3344 if (!bgp_vrf->evpn_info->dup_addr_detect)
3345 return CMD_SUCCESS;
3346 /* Reset all parameters to default. */
3347 bgp_vrf->evpn_info->dup_addr_detect = false;
3348 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3349 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3350 bgp_vrf->evpn_info->dad_freeze = false;
3351 bgp_vrf->evpn_info->dad_freeze_time = 0;
3352 } else {
3353 if (max_moves) {
3354 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3355 vty_out(vty,
3356 "%% Value does not match with config\n");
3357 return CMD_SUCCESS;
3358 }
3359 bgp_vrf->evpn_info->dad_max_moves =
3360 EVPN_DAD_DEFAULT_MAX_MOVES;
3361 }
3362
3363 if (time_val) {
3364 if (bgp_vrf->evpn_info->dad_time != time_val) {
3365 vty_out(vty,
3366 "%% Value does not match with config\n");
3367 return CMD_SUCCESS;
3368 }
3369 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3370 }
3371
3372 if (freeze_time) {
3373 if (bgp_vrf->evpn_info->dad_freeze_time
3374 != freeze_time) {
3375 vty_out(vty,
3376 "%% Value does not match with config\n");
3377 return CMD_SUCCESS;
3378 }
3379 bgp_vrf->evpn_info->dad_freeze_time = 0;
3380 bgp_vrf->evpn_info->dad_freeze = false;
3381 }
3382
3383 if (permanent_val) {
3384 if (bgp_vrf->evpn_info->dad_freeze_time) {
3385 vty_out(vty,
3386 "%% Value does not match with config\n");
3387 return CMD_SUCCESS;
3388 }
3389 bgp_vrf->evpn_info->dad_freeze = false;
3390 }
3391 }
3392
3393 bgp_zebra_dup_addr_detection(bgp_vrf);
3394
3395 return CMD_SUCCESS;
3396 }
3397
3398 DEFPY(bgp_evpn_advertise_svi_ip,
3399 bgp_evpn_advertise_svi_ip_cmd,
3400 "[no$no] advertise-svi-ip",
3401 NO_STR
3402 "Advertise svi mac-ip routes in EVPN\n")
3403 {
3404 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3405
3406 if (!bgp)
3407 return CMD_WARNING;
3408
3409 if (!EVPN_ENABLED(bgp)) {
3410 vty_out(vty,
3411 "This command is only supported under EVPN VRF\n");
3412 return CMD_WARNING;
3413 }
3414
3415 if (no)
3416 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3417 else
3418 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3419
3420 return CMD_SUCCESS;
3421 }
3422
3423 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3424 bgp_evpn_advertise_svi_ip_vni_cmd,
3425 "[no$no] advertise-svi-ip",
3426 NO_STR
3427 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3428 {
3429 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3430 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3431
3432 if (!bgp)
3433 return CMD_WARNING;
3434
3435 if (no)
3436 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3437 else
3438 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3439
3440 return CMD_SUCCESS;
3441 }
3442
3443 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3444 bgp_evpn_advertise_vni_subnet_cmd,
3445 "advertise-subnet",
3446 "Advertise the subnet corresponding to VNI\n")
3447 {
3448 struct bgp *bgp_vrf = NULL;
3449 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3450 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3451
3452 if (!bgp)
3453 return CMD_WARNING;
3454
3455 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3456 if (!bgp_vrf)
3457 return CMD_WARNING;
3458
3459 evpn_set_advertise_subnet(bgp, vpn);
3460 return CMD_SUCCESS;
3461 }
3462
3463 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3464 no_bgp_evpn_advertise_vni_subnet_cmd,
3465 "no advertise-subnet",
3466 NO_STR
3467 "Advertise All local VNIs\n")
3468 {
3469 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3470 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3471
3472 if (!bgp)
3473 return CMD_WARNING;
3474
3475 evpn_unset_advertise_subnet(bgp, vpn);
3476 return CMD_SUCCESS;
3477 }
3478
3479 DEFUN (bgp_evpn_advertise_type5,
3480 bgp_evpn_advertise_type5_cmd,
3481 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
3482 "Advertise prefix routes\n"
3483 BGP_AFI_HELP_STR
3484 BGP_SAFI_HELP_STR
3485 "route-map for filtering specific routes\n"
3486 "Name of the route map\n")
3487 {
3488 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3489 int idx_afi = 0;
3490 int idx_safi = 0;
3491 int idx_rmap = 0;
3492 afi_t afi = 0;
3493 safi_t safi = 0;
3494 int ret = 0;
3495 int rmap_changed = 0;
3496
3497 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3498 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3499 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3500 if (ret) {
3501 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3502 rmap_changed = 1;
3503 else if (strcmp(argv[idx_rmap + 1]->arg,
3504 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3505 != 0)
3506 rmap_changed = 1;
3507 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3508 rmap_changed = 1;
3509 }
3510
3511 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3512 vty_out(vty,
3513 "%%only ipv4 or ipv6 address families are supported");
3514 return CMD_WARNING;
3515 }
3516
3517 if (safi != SAFI_UNICAST) {
3518 vty_out(vty,
3519 "%%only ipv4 unicast or ipv6 unicast are supported");
3520 return CMD_WARNING;
3521 }
3522
3523 if (afi == AFI_IP) {
3524
3525 /* if we are already advertising ipv4 prefix as type-5
3526 * nothing to do
3527 */
3528 if (!rmap_changed &&
3529 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3530 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
3531 return CMD_WARNING;
3532 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3533 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3534 } else {
3535
3536 /* if we are already advertising ipv6 prefix as type-5
3537 * nothing to do
3538 */
3539 if (!rmap_changed &&
3540 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3541 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
3542 return CMD_WARNING;
3543 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3544 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3545 }
3546
3547 if (rmap_changed) {
3548 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3549 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3550 XFREE(MTYPE_ROUTE_MAP_NAME,
3551 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3552 route_map_counter_decrement(
3553 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3554 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3555 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3556 }
3557 }
3558
3559 /* set the route-map for advertise command */
3560 if (ret && argv[idx_rmap + 1]->arg) {
3561 bgp_vrf->adv_cmd_rmap[afi][safi].name =
3562 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
3563 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3564 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3565 route_map_counter_increment(
3566 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3567 }
3568
3569 /* advertise type-5 routes */
3570 if (advertise_type5_routes(bgp_vrf, afi))
3571 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
3572 return CMD_SUCCESS;
3573 }
3574
3575 DEFUN (no_bgp_evpn_advertise_type5,
3576 no_bgp_evpn_advertise_type5_cmd,
3577 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
3578 NO_STR
3579 "Advertise prefix routes\n"
3580 BGP_AFI_HELP_STR
3581 BGP_SAFI_HELP_STR)
3582 {
3583 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3584 int idx_afi = 0;
3585 int idx_safi = 0;
3586 afi_t afi = 0;
3587 safi_t safi = 0;
3588
3589 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3590 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3591
3592 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3593 vty_out(vty,
3594 "%%only ipv4 or ipv6 address families are supported");
3595 return CMD_WARNING;
3596 }
3597
3598 if (safi != SAFI_UNICAST) {
3599 vty_out(vty,
3600 "%%only ipv4 unicast or ipv6 unicast are supported");
3601 return CMD_WARNING;
3602 }
3603
3604 if (afi == AFI_IP) {
3605
3606 /* if we are not advertising ipv4 prefix as type-5
3607 * nothing to do
3608 */
3609 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3610 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
3611 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3612 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3613 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3614 }
3615 } else {
3616
3617 /* if we are not advertising ipv6 prefix as type-5
3618 * nothing to do
3619 */
3620 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3621 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
3622 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3623 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3624 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3625 }
3626 }
3627
3628 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3629 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3630 XFREE(MTYPE_ROUTE_MAP_NAME,
3631 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3632 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3633 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3634 }
3635
3636 return CMD_SUCCESS;
3637 }
3638
3639 /*
3640 * Display VNI information - for all or a specific VNI
3641 */
3642 DEFUN(show_bgp_l2vpn_evpn_vni,
3643 show_bgp_l2vpn_evpn_vni_cmd,
3644 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
3645 SHOW_STR
3646 BGP_STR
3647 L2VPN_HELP_STR
3648 EVPN_HELP_STR
3649 "Show VNI\n"
3650 "VNI number\n"
3651 JSON_STR)
3652 {
3653 struct bgp *bgp_evpn;
3654 vni_t vni;
3655 int idx = 0;
3656 bool uj = false;
3657 json_object *json = NULL;
3658 uint32_t num_l2vnis = 0;
3659 uint32_t num_l3vnis = 0;
3660 uint32_t num_vnis = 0;
3661 struct listnode *node = NULL;
3662 struct bgp *bgp_temp = NULL;
3663
3664 uj = use_json(argc, argv);
3665
3666 bgp_evpn = bgp_get_evpn();
3667 if (!bgp_evpn)
3668 return CMD_WARNING;
3669
3670 if (!argv_find(argv, argc, "evpn", &idx))
3671 return CMD_WARNING;
3672
3673 if (uj)
3674 json = json_object_new_object();
3675
3676 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
3677
3678 num_l2vnis = hashcount(bgp_evpn->vnihash);
3679
3680 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3681 if (bgp_temp->l3vni)
3682 num_l3vnis++;
3683 }
3684 num_vnis = num_l2vnis + num_l3vnis;
3685 if (uj) {
3686 json_object_string_add(json, "advertiseGatewayMacip",
3687 bgp_evpn->advertise_gw_macip
3688 ? "Enabled"
3689 : "Disabled");
3690 json_object_string_add(json, "advertiseAllVnis",
3691 is_evpn_enabled() ? "Enabled"
3692 : "Disabled");
3693 json_object_string_add(
3694 json, "flooding",
3695 bgp_evpn->vxlan_flood_ctrl
3696 == VXLAN_FLOOD_HEAD_END_REPL
3697 ? "Head-end replication"
3698 : "Disabled");
3699 json_object_int_add(json, "numVnis", num_vnis);
3700 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3701 json_object_int_add(json, "numL3Vnis", num_l3vnis);
3702 } else {
3703 vty_out(vty, "Advertise Gateway Macip: %s\n",
3704 bgp_evpn->advertise_gw_macip ? "Enabled"
3705 : "Disabled");
3706 vty_out(vty, "Advertise SVI Macip: %s\n",
3707 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
3708 : "Disabled");
3709 vty_out(vty, "Advertise All VNI flag: %s\n",
3710 is_evpn_enabled() ? "Enabled" : "Disabled");
3711 vty_out(vty, "BUM flooding: %s\n",
3712 bgp_evpn->vxlan_flood_ctrl
3713 == VXLAN_FLOOD_HEAD_END_REPL
3714 ? "Head-end replication"
3715 : "Disabled");
3716 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3717 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
3718 }
3719 evpn_show_all_vnis(vty, bgp_evpn, json);
3720 } else {
3721 int vni_idx = 0;
3722
3723 if (!argv_find(argv, argc, "vni", &vni_idx))
3724 return CMD_WARNING;
3725
3726 /* Display specific VNI */
3727 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
3728 evpn_show_vni(vty, bgp_evpn, vni, json);
3729 }
3730
3731 if (uj) {
3732 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3733 json, JSON_C_TO_STRING_PRETTY));
3734 json_object_free(json);
3735 }
3736
3737 return CMD_SUCCESS;
3738 }
3739
3740 /* Disaply ES */
3741 DEFUN(show_bgp_l2vpn_evpn_es,
3742 show_bgp_l2vpn_evpn_es_cmd,
3743 "show bgp l2vpn evpn es [ESI] [json]",
3744 SHOW_STR
3745 BGP_STR
3746 L2VPN_HELP_STR
3747 EVPN_HELP_STR
3748 "ethernet-Segment\n"
3749 "Ethernet-Segment Identifier\n"
3750 JSON_STR)
3751 {
3752 int idx = 0;
3753 bool uj = false;
3754 esi_t esi;
3755 json_object *json = NULL;
3756 struct bgp *bgp = NULL;
3757
3758 memset(&esi, 0, sizeof(esi));
3759 uj = use_json(argc, argv);
3760
3761 bgp = bgp_get_evpn();
3762 if (!bgp)
3763 return CMD_WARNING;
3764
3765 if (!argv_find(argv, argc, "evpn", &idx))
3766 return CMD_WARNING;
3767
3768 if ((uj && argc == ((idx + 1) + 2)) ||
3769 (!uj && argc == (idx + 1) + 1)) {
3770
3771 /* show all ESs */
3772 evpn_show_all_es(vty, bgp, json);
3773 } else {
3774
3775 /* show a specific ES */
3776
3777 /* get the ESI - ESI-ID is at argv[5] */
3778 if (!str_to_esi(argv[idx + 2]->arg, &esi)) {
3779 vty_out(vty, "%% Malformed ESI\n");
3780 return CMD_WARNING;
3781 }
3782 evpn_show_es(vty, bgp, &esi, json);
3783 }
3784
3785 if (uj) {
3786 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3787 json, JSON_C_TO_STRING_PRETTY));
3788 json_object_free(json);
3789 }
3790
3791 return CMD_SUCCESS;
3792 }
3793
3794 /*
3795 * Display EVPN neighbor summary.
3796 */
3797 DEFUN(show_bgp_l2vpn_evpn_summary,
3798 show_bgp_l2vpn_evpn_summary_cmd,
3799 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3800 SHOW_STR
3801 BGP_STR
3802 "bgp vrf\n"
3803 "vrf name\n"
3804 L2VPN_HELP_STR
3805 EVPN_HELP_STR
3806 "Summary of BGP neighbor status\n"
3807 "Show only sessions not in Established state\n"
3808 JSON_STR)
3809 {
3810 int idx_vrf = 0;
3811 bool uj = use_json(argc, argv);
3812 char *vrf = NULL;
3813 bool show_failed = false;
3814
3815 if (argv_find(argv, argc, "vrf", &idx_vrf))
3816 vrf = argv[++idx_vrf]->arg;
3817 if (argv_find(argv, argc, "failed", &idx_vrf))
3818 show_failed = true;
3819 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN,
3820 show_failed, uj);
3821 }
3822
3823 /*
3824 * Display global EVPN routing table.
3825 */
3826 DEFUN(show_bgp_l2vpn_evpn_route,
3827 show_bgp_l2vpn_evpn_route_cmd,
3828 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3829 SHOW_STR
3830 BGP_STR
3831 L2VPN_HELP_STR
3832 EVPN_HELP_STR
3833 "EVPN route information\n"
3834 "Display Detailed Information\n"
3835 "Specify Route type\n"
3836 "MAC-IP (Type-2) route\n"
3837 "Multicast (Type-3) route\n"
3838 "Ethernet Segment (type-4) route \n"
3839 "Prefix (type-5 )route\n"
3840 JSON_STR)
3841 {
3842 struct bgp *bgp;
3843 int type_idx = 0;
3844 int detail = 0;
3845 int type = 0;
3846 bool uj = false;
3847 json_object *json = NULL;
3848
3849 uj = use_json(argc, argv);
3850
3851 bgp = bgp_get_evpn();
3852 if (!bgp)
3853 return CMD_WARNING;
3854
3855 if (uj)
3856 json = json_object_new_object();
3857
3858 /* get the type */
3859 if (argv_find(argv, argc, "type", &type_idx)) {
3860 /* Specific type is requested */
3861 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3862 type = BGP_EVPN_MAC_IP_ROUTE;
3863 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3864 type = BGP_EVPN_IMET_ROUTE;
3865 else if (strncmp(argv[type_idx + 1]->arg, "e", 1) == 0)
3866 type = BGP_EVPN_ES_ROUTE;
3867 else if (strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
3868 type = BGP_EVPN_IP_PREFIX_ROUTE;
3869 else
3870 return CMD_WARNING;
3871 }
3872
3873 if (argv_find(argv, argc, "detail", &detail))
3874 detail = 1;
3875
3876 evpn_show_all_routes(vty, bgp, type, json, detail);
3877
3878 if (uj) {
3879 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3880 json, JSON_C_TO_STRING_PRETTY));
3881 json_object_free(json);
3882 }
3883 return CMD_SUCCESS;
3884 }
3885
3886 /*
3887 * Display global EVPN routing table for specific RD.
3888 */
3889 DEFUN(show_bgp_l2vpn_evpn_route_rd,
3890 show_bgp_l2vpn_evpn_route_rd_cmd,
3891 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3892 SHOW_STR
3893 BGP_STR
3894 L2VPN_HELP_STR
3895 EVPN_HELP_STR
3896 "EVPN route information\n"
3897 "Route Distinguisher\n"
3898 "ASN:XX or A.B.C.D:XX\n"
3899 "Specify Route type\n"
3900 "MAC-IP (Type-2) route\n"
3901 "Multicast (Type-3) route\n"
3902 "Ethernet Segment route\n"
3903 "Prefix route\n"
3904 JSON_STR)
3905 {
3906 struct bgp *bgp;
3907 int ret;
3908 struct prefix_rd prd;
3909 int type = 0;
3910 int rd_idx = 0;
3911 int type_idx = 0;
3912 bool uj = false;
3913 json_object *json = NULL;
3914
3915 bgp = bgp_get_evpn();
3916 if (!bgp)
3917 return CMD_WARNING;
3918
3919 /* check if we need json output */
3920 uj = use_json(argc, argv);
3921 if (uj)
3922 json = json_object_new_object();
3923
3924 /* get the RD */
3925 if (argv_find(argv, argc, "rd", &rd_idx)) {
3926 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3927
3928 if (!ret) {
3929 vty_out(vty, "%% Malformed Route Distinguisher\n");
3930 return CMD_WARNING;
3931 }
3932 }
3933
3934 /* get the type */
3935 if (argv_find(argv, argc, "type", &type_idx)) {
3936 /* Specific type is requested */
3937 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3938 type = BGP_EVPN_MAC_IP_ROUTE;
3939 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3940 type = BGP_EVPN_IMET_ROUTE;
3941 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3942 type = BGP_EVPN_IP_PREFIX_ROUTE;
3943 else
3944 return CMD_WARNING;
3945 }
3946
3947 evpn_show_route_rd(vty, bgp, &prd, type, json);
3948
3949 if (uj) {
3950 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3951 json, JSON_C_TO_STRING_PRETTY));
3952 json_object_free(json);
3953 }
3954
3955 return CMD_SUCCESS;
3956 }
3957
3958 /*
3959 * Display global EVPN routing table for specific RD and MACIP.
3960 */
3961 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3962 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
3963 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3964 SHOW_STR
3965 BGP_STR
3966 L2VPN_HELP_STR
3967 EVPN_HELP_STR
3968 "EVPN route information\n"
3969 "Route Distinguisher\n"
3970 "ASN:XX or A.B.C.D:XX\n"
3971 "MAC\n"
3972 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3973 "IP\n"
3974 "IP address (IPv4 or IPv6)\n"
3975 JSON_STR)
3976 {
3977 struct bgp *bgp;
3978 int ret;
3979 struct prefix_rd prd;
3980 struct ethaddr mac;
3981 struct ipaddr ip;
3982 int rd_idx = 0;
3983 int mac_idx = 0;
3984 int ip_idx = 0;
3985 bool uj = false;
3986 json_object *json = NULL;
3987
3988 memset(&mac, 0, sizeof(struct ethaddr));
3989 memset(&ip, 0, sizeof(struct ipaddr));
3990
3991 bgp = bgp_get_evpn();
3992 if (!bgp)
3993 return CMD_WARNING;
3994
3995 /* check if we need json output */
3996 uj = use_json(argc, argv);
3997 if (uj)
3998 json = json_object_new_object();
3999
4000 /* get the prd */
4001 if (argv_find(argv, argc, "rd", &rd_idx)) {
4002 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
4003 if (!ret) {
4004 vty_out(vty, "%% Malformed Route Distinguisher\n");
4005 return CMD_WARNING;
4006 }
4007 }
4008
4009 /* get the mac */
4010 if (argv_find(argv, argc, "mac", &mac_idx)) {
4011 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4012 vty_out(vty, "%% Malformed MAC address\n");
4013 return CMD_WARNING;
4014 }
4015 }
4016
4017 /* get the ip if specified */
4018 if (argv_find(argv, argc, "ip", &ip_idx)) {
4019 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4020 vty_out(vty, "%% Malformed IP address\n");
4021 return CMD_WARNING;
4022 }
4023 }
4024
4025 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4026
4027 if (uj) {
4028 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4029 json, JSON_C_TO_STRING_PRETTY));
4030 json_object_free(json);
4031 }
4032
4033 return CMD_SUCCESS;
4034 }
4035
4036 /* Display per ESI routing table */
4037 DEFUN(show_bgp_l2vpn_evpn_route_esi,
4038 show_bgp_l2vpn_evpn_route_esi_cmd,
4039 "show bgp l2vpn evpn route esi ESI [json]",
4040 SHOW_STR
4041 BGP_STR
4042 L2VPN_HELP_STR
4043 EVPN_HELP_STR
4044 "EVPN route information\n"
4045 "Ethernet Segment Identifier\n"
4046 "ESI ID\n"
4047 JSON_STR)
4048 {
4049 bool uj = false;
4050 esi_t esi;
4051 struct bgp *bgp = NULL;
4052 json_object *json = NULL;
4053
4054 memset(&esi, 0, sizeof(esi));
4055 bgp = bgp_get_evpn();
4056 if (!bgp)
4057 return CMD_WARNING;
4058
4059 uj = use_json(argc, argv);
4060 if (uj)
4061 json = json_object_new_object();
4062
4063 /* get the ESI - ESI-ID is at argv[6] */
4064 if (!str_to_esi(argv[6]->arg, &esi)) {
4065 vty_out(vty, "%% Malformed ESI\n");
4066 return CMD_WARNING;
4067 }
4068
4069 evpn_show_routes_esi(vty, bgp, &esi, json);
4070
4071 if (uj) {
4072 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4073 json, JSON_C_TO_STRING_PRETTY));
4074 json_object_free(json);
4075 }
4076
4077 return CMD_SUCCESS;
4078 }
4079
4080
4081 /*
4082 * Display per-VNI EVPN routing table.
4083 */
4084 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
4085 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4086 SHOW_STR
4087 BGP_STR
4088 L2VPN_HELP_STR
4089 EVPN_HELP_STR
4090 "EVPN route information\n"
4091 "VXLAN Network Identifier\n"
4092 "VNI number\n"
4093 "Specify Route type\n"
4094 "MAC-IP (Type-2) route\n"
4095 "Multicast (Type-3) route\n"
4096 "Remote VTEP\n"
4097 "Remote VTEP IP address\n"
4098 JSON_STR)
4099 {
4100 vni_t vni;
4101 struct bgp *bgp;
4102 struct in_addr vtep_ip;
4103 int type = 0;
4104 int idx = 0;
4105 bool uj = false;
4106 json_object *json = NULL;
4107
4108 bgp = bgp_get_evpn();
4109 if (!bgp)
4110 return CMD_WARNING;
4111
4112 /* check if we need json output */
4113 uj = use_json(argc, argv);
4114 if (uj)
4115 json = json_object_new_object();
4116
4117 if (!argv_find(argv, argc, "evpn", &idx))
4118 return CMD_WARNING;
4119
4120 vtep_ip.s_addr = 0;
4121
4122 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4123
4124 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
4125 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
4126 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
4127 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
4128 type = BGP_EVPN_MAC_IP_ROUTE;
4129 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
4130 type = BGP_EVPN_IMET_ROUTE;
4131 else
4132 return CMD_WARNING;
4133 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
4134 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
4135 vty_out(vty, "%% Malformed VTEP IP address\n");
4136 return CMD_WARNING;
4137 }
4138 } else
4139 return CMD_WARNING;
4140 }
4141
4142 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
4143
4144 if (uj) {
4145 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4146 json, JSON_C_TO_STRING_PRETTY));
4147 json_object_free(json);
4148 }
4149
4150 return CMD_SUCCESS;
4151 }
4152
4153 /*
4154 * Display per-VNI EVPN routing table for specific MACIP.
4155 */
4156 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
4157 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
4158 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
4159 SHOW_STR
4160 BGP_STR
4161 L2VPN_HELP_STR
4162 EVPN_HELP_STR
4163 "EVPN route information\n"
4164 "VXLAN Network Identifier\n"
4165 "VNI number\n"
4166 "MAC\n"
4167 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4168 "IP\n"
4169 "IP address (IPv4 or IPv6)\n"
4170 JSON_STR)
4171 {
4172 vni_t vni;
4173 struct bgp *bgp;
4174 struct ethaddr mac;
4175 struct ipaddr ip;
4176 int idx = 0;
4177 bool uj = false;
4178 json_object *json = NULL;
4179
4180 bgp = bgp_get_evpn();
4181 if (!bgp)
4182 return CMD_WARNING;
4183
4184 /* check if we need json output */
4185 uj = use_json(argc, argv);
4186 if (uj)
4187 json = json_object_new_object();
4188
4189 if (!argv_find(argv, argc, "evpn", &idx))
4190 return CMD_WARNING;
4191
4192 /* get the VNI */
4193 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4194
4195 /* get the mac */
4196 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
4197 vty_out(vty, "%% Malformed MAC address\n");
4198 return CMD_WARNING;
4199 }
4200
4201 /* get the ip */
4202 memset(&ip, 0, sizeof(ip));
4203 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
4204 || (uj
4205 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
4206 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
4207 vty_out(vty, "%% Malformed IP address\n");
4208 return CMD_WARNING;
4209 }
4210 }
4211
4212 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
4213
4214 if (uj) {
4215 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4216 json, JSON_C_TO_STRING_PRETTY));
4217 json_object_free(json);
4218 }
4219
4220 return CMD_SUCCESS;
4221 }
4222
4223 /*
4224 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4225 */
4226 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
4227 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
4228 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
4229 SHOW_STR
4230 BGP_STR
4231 L2VPN_HELP_STR
4232 EVPN_HELP_STR
4233 "EVPN route information\n"
4234 "VXLAN Network Identifier\n"
4235 "VNI number\n"
4236 "Multicast (Type-3) route\n"
4237 "Originating Router IP address\n"
4238 JSON_STR)
4239 {
4240 vni_t vni;
4241 struct bgp *bgp;
4242 int ret;
4243 struct in_addr orig_ip;
4244 int idx = 0;
4245 bool uj = false;
4246 json_object *json = NULL;
4247
4248 bgp = bgp_get_evpn();
4249 if (!bgp)
4250 return CMD_WARNING;
4251
4252 /* check if we need json output */
4253 uj = use_json(argc, argv);
4254 if (uj)
4255 json = json_object_new_object();
4256
4257 if (!argv_find(argv, argc, "evpn", &idx))
4258 return CMD_WARNING;
4259
4260 /* get the VNI */
4261 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4262
4263 /* get the ip */
4264 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
4265 if (!ret) {
4266 vty_out(vty, "%% Malformed Originating Router IP address\n");
4267 return CMD_WARNING;
4268 }
4269
4270 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
4271
4272 if (uj) {
4273 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4274 json, JSON_C_TO_STRING_PRETTY));
4275 json_object_free(json);
4276 }
4277
4278 return CMD_SUCCESS;
4279 }
4280
4281 /*
4282 * Display per-VNI EVPN routing table - for all VNIs.
4283 */
4284 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
4285 show_bgp_l2vpn_evpn_route_vni_all_cmd,
4286 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4287 SHOW_STR
4288 BGP_STR
4289 L2VPN_HELP_STR
4290 EVPN_HELP_STR
4291 "EVPN route information\n"
4292 "VXLAN Network Identifier\n"
4293 "All VNIs\n"
4294 "Print Detailed Output\n"
4295 "Remote VTEP\n"
4296 "Remote VTEP IP address\n"
4297 JSON_STR)
4298 {
4299 struct bgp *bgp;
4300 struct in_addr vtep_ip;
4301 int idx = 0;
4302 bool uj = false;
4303 json_object *json = NULL;
4304 /* Detail Adjust. Adjust indexes according to detail option */
4305 int da = 0;
4306
4307 bgp = bgp_get_evpn();
4308 if (!bgp)
4309 return CMD_WARNING;
4310
4311 /* check if we need json output */
4312 uj = use_json(argc, argv);
4313 if (uj)
4314 json = json_object_new_object();
4315
4316 if (!argv_find(argv, argc, "evpn", &idx))
4317 return CMD_WARNING;
4318
4319 if (argv_find(argv, argc, "detail", &da))
4320 da = 1;
4321
4322 /* vtep-ip position depends on detail option */
4323 vtep_ip.s_addr = 0;
4324 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
4325 || (uj
4326 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
4327 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
4328 vty_out(vty, "%% Malformed VTEP IP address\n");
4329 return CMD_WARNING;
4330 }
4331 }
4332
4333 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da);
4334
4335 if (uj) {
4336 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4337 json, JSON_C_TO_STRING_PRETTY));
4338 json_object_free(json);
4339 }
4340
4341 return CMD_SUCCESS;
4342 }
4343
4344 /*
4345 * Display EVPN import route-target hash table
4346 */
4347 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
4348 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
4349 "show bgp l2vpn evpn vrf-import-rt [json]",
4350 SHOW_STR
4351 BGP_STR
4352 L2VPN_HELP_STR
4353 EVPN_HELP_STR
4354 "Show vrf import route target\n"
4355 JSON_STR)
4356 {
4357 bool uj = false;
4358 struct bgp *bgp_evpn = NULL;
4359 json_object *json = NULL;
4360
4361 bgp_evpn = bgp_get_evpn();
4362 if (!bgp_evpn)
4363 return CMD_WARNING;
4364
4365 uj = use_json(argc, argv);
4366 if (uj)
4367 json = json_object_new_object();
4368
4369 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
4370
4371 if (uj) {
4372 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4373 json, JSON_C_TO_STRING_PRETTY));
4374 json_object_free(json);
4375 }
4376
4377 return CMD_SUCCESS;
4378 }
4379
4380 /*
4381 * Display EVPN import route-target hash table
4382 */
4383 DEFUN(show_bgp_l2vpn_evpn_import_rt,
4384 show_bgp_l2vpn_evpn_import_rt_cmd,
4385 "show bgp l2vpn evpn import-rt [json]",
4386 SHOW_STR
4387 BGP_STR
4388 L2VPN_HELP_STR
4389 EVPN_HELP_STR
4390 "Show import route target\n"
4391 JSON_STR)
4392 {
4393 struct bgp *bgp;
4394 bool uj = false;
4395 json_object *json = NULL;
4396
4397 bgp = bgp_get_evpn();
4398 if (!bgp)
4399 return CMD_WARNING;
4400
4401 uj = use_json(argc, argv);
4402 if (uj)
4403 json = json_object_new_object();
4404
4405 evpn_show_import_rts(vty, bgp, json);
4406
4407 if (uj) {
4408 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4409 json, JSON_C_TO_STRING_PRETTY));
4410 json_object_free(json);
4411 }
4412
4413 return CMD_SUCCESS;
4414 }
4415
4416 DEFUN(test_adv_evpn_type4_route,
4417 test_adv_evpn_type4_route_cmd,
4418 "advertise es ESI",
4419 "Advertise EVPN ES route\n"
4420 "Ethernet-segment\n"
4421 "Ethernet-Segment Identifier\n")
4422 {
4423 int ret = 0;
4424 esi_t esi;
4425 struct bgp *bgp;
4426 struct ipaddr vtep_ip;
4427
4428 bgp = bgp_get_evpn();
4429 if (!bgp) {
4430 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4431 return CMD_WARNING;
4432 }
4433
4434 if (!str_to_esi(argv[2]->arg, &esi)) {
4435 vty_out(vty, "%%Malformed ESI\n");
4436 return CMD_WARNING;
4437 }
4438
4439 vtep_ip.ipa_type = IPADDR_V4;
4440 vtep_ip.ipaddr_v4 = bgp->router_id;
4441
4442 ret = bgp_evpn_local_es_add(bgp, &esi, &vtep_ip);
4443 if (ret == -1) {
4444 vty_out(vty, "%%Failed to EVPN advertise type-4 route\n");
4445 return CMD_WARNING;
4446 }
4447 return CMD_SUCCESS;
4448 }
4449
4450 DEFUN(test_withdraw_evpn_type4_route,
4451 test_withdraw_evpn_type4_route_cmd,
4452 "withdraw es ESI",
4453 "Advertise EVPN ES route\n"
4454 "Ethernet-segment\n"
4455 "Ethernet-Segment Identifier\n")
4456 {
4457 int ret = 0;
4458 esi_t esi;
4459 struct bgp *bgp;
4460 struct ipaddr vtep_ip;
4461
4462 bgp = bgp_get_evpn();
4463 if (!bgp) {
4464 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4465 return CMD_WARNING;
4466 }
4467
4468 if (!bgp->peer_self) {
4469 vty_out(vty, "%%BGP instance doesn't have self peer\n");
4470 return CMD_WARNING;
4471 }
4472
4473 if (!str_to_esi(argv[2]->arg, &esi)) {
4474 vty_out(vty, "%%Malformed ESI\n");
4475 return CMD_WARNING;
4476 }
4477
4478 vtep_ip.ipa_type = IPADDR_V4;
4479 vtep_ip.ipaddr_v4 = bgp->router_id;
4480 ret = bgp_evpn_local_es_del(bgp, &esi, &vtep_ip);
4481 if (ret == -1) {
4482 vty_out(vty, "%%Failed to withdraw EVPN type-4 route\n");
4483 return CMD_WARNING;
4484 }
4485 return CMD_SUCCESS;
4486 }
4487
4488 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
4489 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
4490 "Show VNI\n"
4491 "VNI number\n")
4492
4493 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
4494 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4495 "Summary of BGP neighbor status\n" JSON_STR)
4496
4497 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
4498 "show bgp evpn route [detail] [type <macip|multicast>]",
4499 SHOW_STR BGP_STR EVPN_HELP_STR
4500 "EVPN route information\n"
4501 "Display Detailed Information\n"
4502 "Specify Route type\n"
4503 "MAC-IP (Type-2) route\n"
4504 "Multicast (Type-3) route\n")
4505
4506 ALIAS_HIDDEN(
4507 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
4508 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4509 SHOW_STR BGP_STR EVPN_HELP_STR
4510 "EVPN route information\n"
4511 "Route Distinguisher\n"
4512 "ASN:XX or A.B.C.D:XX\n"
4513 "Specify Route type\n"
4514 "MAC-IP (Type-2) route\n"
4515 "Multicast (Type-3) route\n")
4516
4517 ALIAS_HIDDEN(
4518 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
4519 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4520 SHOW_STR BGP_STR EVPN_HELP_STR
4521 "EVPN route information\n"
4522 "Route Distinguisher\n"
4523 "ASN:XX or A.B.C.D:XX\n"
4524 "MAC\n"
4525 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4526 "IP\n"
4527 "IP address (IPv4 or IPv6)\n")
4528
4529 ALIAS_HIDDEN(
4530 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
4531 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]",
4532 SHOW_STR BGP_STR EVPN_HELP_STR
4533 "EVPN route information\n"
4534 "VXLAN Network Identifier\n"
4535 "VNI number\n"
4536 "Specify Route type\n"
4537 "MAC-IP (Type-2) route\n"
4538 "Multicast (Type-3) route\n"
4539 "Remote VTEP\n"
4540 "Remote VTEP IP address\n")
4541
4542 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4543 show_bgp_evpn_route_vni_macip_cmd,
4544 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
4545 SHOW_STR BGP_STR EVPN_HELP_STR
4546 "EVPN route information\n"
4547 "VXLAN Network Identifier\n"
4548 "VNI number\n"
4549 "MAC\n"
4550 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4551 "IP\n"
4552 "IP address (IPv4 or IPv6)\n")
4553
4554 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4555 show_bgp_evpn_route_vni_multicast_cmd,
4556 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
4557 SHOW_STR BGP_STR EVPN_HELP_STR
4558 "EVPN route information\n"
4559 "VXLAN Network Identifier\n"
4560 "VNI number\n"
4561 "Multicast (Type-3) route\n"
4562 "Originating Router IP address\n")
4563
4564 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
4565 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4566 SHOW_STR BGP_STR EVPN_HELP_STR
4567 "EVPN route information\n"
4568 "VXLAN Network Identifier\n"
4569 "All VNIs\n"
4570 "Print Detailed Output\n"
4571 "Remote VTEP\n"
4572 "Remote VTEP IP address\n")
4573
4574 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4575 "show bgp evpn import-rt",
4576 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
4577
4578 DEFUN_NOSH (bgp_evpn_vni,
4579 bgp_evpn_vni_cmd,
4580 "vni " CMD_VNI_RANGE,
4581 "VXLAN Network Identifier\n"
4582 "VNI number\n")
4583 {
4584 vni_t vni;
4585 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4586 struct bgpevpn *vpn;
4587
4588 if (!bgp)
4589 return CMD_WARNING;
4590
4591 vni = strtoul(argv[1]->arg, NULL, 10);
4592
4593 /* Create VNI, or mark as configured. */
4594 vpn = evpn_create_update_vni(bgp, vni);
4595 if (!vpn) {
4596 vty_out(vty, "%% Failed to create VNI \n");
4597 return CMD_WARNING;
4598 }
4599
4600 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4601 return CMD_SUCCESS;
4602 }
4603
4604 DEFUN (no_bgp_evpn_vni,
4605 no_bgp_evpn_vni_cmd,
4606 "no vni " CMD_VNI_RANGE,
4607 NO_STR
4608 "VXLAN Network Identifier\n"
4609 "VNI number\n")
4610 {
4611 vni_t vni;
4612 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4613 struct bgpevpn *vpn;
4614
4615 if (!bgp)
4616 return CMD_WARNING;
4617
4618 vni = strtoul(argv[2]->arg, NULL, 10);
4619
4620 /* Check if we should disallow. */
4621 vpn = bgp_evpn_lookup_vni(bgp, vni);
4622 if (!vpn) {
4623 vty_out(vty, "%% Specified VNI does not exist\n");
4624 return CMD_WARNING;
4625 }
4626 if (!is_vni_configured(vpn)) {
4627 vty_out(vty, "%% Specified VNI is not configured\n");
4628 return CMD_WARNING;
4629 }
4630
4631 evpn_delete_vni(bgp, vpn);
4632 return CMD_SUCCESS;
4633 }
4634
4635 DEFUN_NOSH (exit_vni,
4636 exit_vni_cmd,
4637 "exit-vni",
4638 "Exit from VNI mode\n")
4639 {
4640 if (vty->node == BGP_EVPN_VNI_NODE)
4641 vty->node = BGP_EVPN_NODE;
4642 return CMD_SUCCESS;
4643 }
4644
4645 DEFUN (bgp_evpn_vrf_rd,
4646 bgp_evpn_vrf_rd_cmd,
4647 "rd ASN:NN_OR_IP-ADDRESS:NN",
4648 "Route Distinguisher\n"
4649 "ASN:XX or A.B.C.D:XX\n")
4650 {
4651 int ret;
4652 struct prefix_rd prd;
4653 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4654
4655 if (!bgp_vrf)
4656 return CMD_WARNING;
4657
4658 ret = str2prefix_rd(argv[1]->arg, &prd);
4659 if (!ret) {
4660 vty_out(vty, "%% Malformed Route Distinguisher\n");
4661 return CMD_WARNING;
4662 }
4663
4664 /* If same as existing value, there is nothing more to do. */
4665 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4666 return CMD_SUCCESS;
4667
4668 /* Configure or update the RD. */
4669 evpn_configure_vrf_rd(bgp_vrf, &prd);
4670 return CMD_SUCCESS;
4671 }
4672
4673 DEFUN (no_bgp_evpn_vrf_rd,
4674 no_bgp_evpn_vrf_rd_cmd,
4675 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4676 NO_STR
4677 "Route Distinguisher\n"
4678 "ASN:XX or A.B.C.D:XX\n")
4679 {
4680 int ret;
4681 struct prefix_rd prd;
4682 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4683
4684 if (!bgp_vrf)
4685 return CMD_WARNING;
4686
4687 ret = str2prefix_rd(argv[2]->arg, &prd);
4688 if (!ret) {
4689 vty_out(vty, "%% Malformed Route Distinguisher\n");
4690 return CMD_WARNING;
4691 }
4692
4693 /* Check if we should disallow. */
4694 if (!is_vrf_rd_configured(bgp_vrf)) {
4695 vty_out(vty, "%% RD is not configured for this VRF\n");
4696 return CMD_WARNING;
4697 }
4698
4699 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4700 vty_out(vty,
4701 "%% RD specified does not match configuration for this VRF\n");
4702 return CMD_WARNING;
4703 }
4704
4705 evpn_unconfigure_vrf_rd(bgp_vrf);
4706 return CMD_SUCCESS;
4707 }
4708
4709 DEFUN (no_bgp_evpn_vrf_rd_without_val,
4710 no_bgp_evpn_vrf_rd_without_val_cmd,
4711 "no rd",
4712 NO_STR
4713 "Route Distinguisher\n")
4714 {
4715 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4716
4717 if (!bgp_vrf)
4718 return CMD_WARNING;
4719
4720 /* Check if we should disallow. */
4721 if (!is_vrf_rd_configured(bgp_vrf)) {
4722 vty_out(vty, "%% RD is not configured for this VRF\n");
4723 return CMD_WARNING;
4724 }
4725
4726 evpn_unconfigure_vrf_rd(bgp_vrf);
4727 return CMD_SUCCESS;
4728 }
4729
4730 DEFUN (bgp_evpn_vni_rd,
4731 bgp_evpn_vni_rd_cmd,
4732 "rd ASN:NN_OR_IP-ADDRESS:NN",
4733 "Route Distinguisher\n"
4734 "ASN:XX or A.B.C.D:XX\n")
4735 {
4736 struct prefix_rd prd;
4737 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4738 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4739 int ret;
4740
4741 if (!bgp)
4742 return CMD_WARNING;
4743
4744 if (!EVPN_ENABLED(bgp)) {
4745 vty_out(vty,
4746 "This command is only supported under EVPN VRF\n");
4747 return CMD_WARNING;
4748 }
4749
4750 ret = str2prefix_rd(argv[1]->arg, &prd);
4751 if (!ret) {
4752 vty_out(vty, "%% Malformed Route Distinguisher\n");
4753 return CMD_WARNING;
4754 }
4755
4756 /* If same as existing value, there is nothing more to do. */
4757 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4758 return CMD_SUCCESS;
4759
4760 /* Configure or update the RD. */
4761 evpn_configure_rd(bgp, vpn, &prd);
4762 return CMD_SUCCESS;
4763 }
4764
4765 DEFUN (no_bgp_evpn_vni_rd,
4766 no_bgp_evpn_vni_rd_cmd,
4767 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4768 NO_STR
4769 "Route Distinguisher\n"
4770 "ASN:XX or A.B.C.D:XX\n")
4771 {
4772 struct prefix_rd prd;
4773 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4774 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4775 int ret;
4776
4777 if (!bgp)
4778 return CMD_WARNING;
4779
4780 if (!EVPN_ENABLED(bgp)) {
4781 vty_out(vty,
4782 "This command is only supported under EVPN VRF\n");
4783 return CMD_WARNING;
4784 }
4785
4786 ret = str2prefix_rd(argv[2]->arg, &prd);
4787 if (!ret) {
4788 vty_out(vty, "%% Malformed Route Distinguisher\n");
4789 return CMD_WARNING;
4790 }
4791
4792 /* Check if we should disallow. */
4793 if (!is_rd_configured(vpn)) {
4794 vty_out(vty, "%% RD is not configured for this VNI\n");
4795 return CMD_WARNING;
4796 }
4797
4798 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
4799 vty_out(vty,
4800 "%% RD specified does not match configuration for this VNI\n");
4801 return CMD_WARNING;
4802 }
4803
4804 evpn_unconfigure_rd(bgp, vpn);
4805 return CMD_SUCCESS;
4806 }
4807
4808 DEFUN (no_bgp_evpn_vni_rd_without_val,
4809 no_bgp_evpn_vni_rd_without_val_cmd,
4810 "no rd",
4811 NO_STR
4812 "Route Distinguisher\n")
4813 {
4814 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4815 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4816
4817 if (!bgp)
4818 return CMD_WARNING;
4819
4820 if (!EVPN_ENABLED(bgp)) {
4821 vty_out(vty,
4822 "This command is only supported under EVPN VRF\n");
4823 return CMD_WARNING;
4824 }
4825
4826 /* Check if we should disallow. */
4827 if (!is_rd_configured(vpn)) {
4828 vty_out(vty, "%% RD is not configured for this VNI\n");
4829 return CMD_WARNING;
4830 }
4831
4832 evpn_unconfigure_rd(bgp, vpn);
4833 return CMD_SUCCESS;
4834 }
4835
4836 /*
4837 * Loop over all extended-communities in the route-target list rtl and
4838 * return 1 if we find ecomtarget
4839 */
4840 static int bgp_evpn_rt_matches_existing(struct list *rtl,
4841 struct ecommunity *ecomtarget)
4842 {
4843 struct listnode *node, *nnode;
4844 struct ecommunity *ecom;
4845
4846 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
4847 if (ecommunity_match(ecom, ecomtarget))
4848 return 1;
4849 }
4850
4851 return 0;
4852 }
4853
4854 /* display L3VNI related info for a VRF instance */
4855 DEFUN (show_bgp_vrf_l3vni_info,
4856 show_bgp_vrf_l3vni_info_cmd,
4857 "show bgp vrf VRFNAME vni [json]",
4858 SHOW_STR
4859 BGP_STR
4860 "show bgp vrf\n"
4861 "VRF Name\n"
4862 "L3-VNI\n"
4863 JSON_STR)
4864 {
4865 char buf[ETHER_ADDR_STRLEN];
4866 char buf1[INET6_ADDRSTRLEN];
4867 int idx_vrf = 3;
4868 const char *name = NULL;
4869 struct bgp *bgp = NULL;
4870 struct listnode *node = NULL;
4871 struct bgpevpn *vpn = NULL;
4872 struct ecommunity *ecom = NULL;
4873 json_object *json = NULL;
4874 json_object *json_vnis = NULL;
4875 json_object *json_export_rts = NULL;
4876 json_object *json_import_rts = NULL;
4877 bool uj = use_json(argc, argv);
4878
4879 if (uj) {
4880 json = json_object_new_object();
4881 json_vnis = json_object_new_array();
4882 json_export_rts = json_object_new_array();
4883 json_import_rts = json_object_new_array();
4884 }
4885
4886 name = argv[idx_vrf]->arg;
4887 bgp = bgp_lookup_by_name(name);
4888 if (!bgp) {
4889 if (!uj)
4890 vty_out(vty, "BGP instance for VRF %s not found", name);
4891 else {
4892 json_object_string_add(json, "warning",
4893 "BGP instance not found");
4894 vty_out(vty, "%s\n", json_object_to_json_string(json));
4895 json_object_free(json);
4896 }
4897 return CMD_WARNING;
4898 }
4899
4900 if (!json) {
4901 vty_out(vty, "BGP VRF: %s\n", name);
4902 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
4903 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
4904 vty_out(vty, " Rmac: %s\n",
4905 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4906 vty_out(vty, " VNI Filter: %s\n",
4907 CHECK_FLAG(bgp->vrf_flags,
4908 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4909 ? "prefix-routes-only"
4910 : "none");
4911 vty_out(vty, " L2-VNI List:\n");
4912 vty_out(vty, " ");
4913 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4914 vty_out(vty, "%u ", vpn->vni);
4915 vty_out(vty, "\n");
4916 vty_out(vty, " Export-RTs:\n");
4917 vty_out(vty, " ");
4918 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4919 vty_out(vty, "%s ", ecommunity_str(ecom));
4920 vty_out(vty, "\n");
4921 vty_out(vty, " Import-RTs:\n");
4922 vty_out(vty, " ");
4923 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4924 vty_out(vty, "%s ", ecommunity_str(ecom));
4925 vty_out(vty, "\n");
4926 vty_out(vty, " RD: %s\n",
4927 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
4928 } else {
4929 json_object_string_add(json, "vrf", name);
4930 json_object_string_add(json, "local-ip",
4931 inet_ntoa(bgp->originator_ip));
4932 json_object_int_add(json, "l3vni", bgp->l3vni);
4933 json_object_string_add(
4934 json, "rmac",
4935 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4936 json_object_string_add(
4937 json, "vniFilter",
4938 CHECK_FLAG(bgp->vrf_flags,
4939 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4940 ? "prefix-routes-only"
4941 : "none");
4942 /* list of l2vnis */
4943 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4944 json_object_array_add(json_vnis,
4945 json_object_new_int(vpn->vni));
4946 json_object_object_add(json, "l2vnis", json_vnis);
4947
4948 /* export rts */
4949 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4950 json_object_array_add(
4951 json_export_rts,
4952 json_object_new_string(ecommunity_str(ecom)));
4953 json_object_object_add(json, "export-rts", json_export_rts);
4954
4955 /* import rts */
4956 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4957 json_object_array_add(
4958 json_import_rts,
4959 json_object_new_string(ecommunity_str(ecom)));
4960 json_object_object_add(json, "import-rts", json_import_rts);
4961 json_object_string_add(
4962 json, "rd",
4963 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
4964 }
4965
4966 if (uj) {
4967 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4968 json, JSON_C_TO_STRING_PRETTY));
4969 json_object_free(json);
4970 }
4971 return CMD_SUCCESS;
4972 }
4973
4974 /* import/export rt for l3vni-vrf */
4975 DEFUN (bgp_evpn_vrf_rt,
4976 bgp_evpn_vrf_rt_cmd,
4977 "route-target <both|import|export> RT",
4978 "Route Target\n"
4979 "import and export\n"
4980 "import\n"
4981 "export\n"
4982 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4983 {
4984 int rt_type;
4985 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4986 struct ecommunity *ecomadd = NULL;
4987
4988 if (!bgp)
4989 return CMD_WARNING;
4990
4991 if (!strcmp(argv[1]->arg, "import"))
4992 rt_type = RT_TYPE_IMPORT;
4993 else if (!strcmp(argv[1]->arg, "export"))
4994 rt_type = RT_TYPE_EXPORT;
4995 else if (!strcmp(argv[1]->arg, "both"))
4996 rt_type = RT_TYPE_BOTH;
4997 else {
4998 vty_out(vty, "%% Invalid Route Target type\n");
4999 return CMD_WARNING;
5000 }
5001
5002 /* Add/update the import route-target */
5003 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5004 ecomadd = ecommunity_str2com(argv[2]->arg,
5005 ECOMMUNITY_ROUTE_TARGET, 0);
5006 if (!ecomadd) {
5007 vty_out(vty, "%% Malformed Route Target list\n");
5008 return CMD_WARNING;
5009 }
5010 ecommunity_str(ecomadd);
5011
5012 /* Do nothing if we already have this import route-target */
5013 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
5014 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
5015 }
5016
5017 /* Add/update the export route-target */
5018 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5019 ecomadd = ecommunity_str2com(argv[2]->arg,
5020 ECOMMUNITY_ROUTE_TARGET, 0);
5021 if (!ecomadd) {
5022 vty_out(vty, "%% Malformed Route Target list\n");
5023 return CMD_WARNING;
5024 }
5025 ecommunity_str(ecomadd);
5026
5027 /* Do nothing if we already have this export route-target */
5028 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
5029 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
5030 }
5031
5032 return CMD_SUCCESS;
5033 }
5034
5035 DEFUN (no_bgp_evpn_vrf_rt,
5036 no_bgp_evpn_vrf_rt_cmd,
5037 "no route-target <both|import|export> RT",
5038 NO_STR
5039 "Route Target\n"
5040 "import and export\n"
5041 "import\n"
5042 "export\n"
5043 "ASN:XX or A.B.C.D:XX\n")
5044 {
5045 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5046 int rt_type, found_ecomdel;
5047 struct ecommunity *ecomdel = NULL;
5048
5049 if (!bgp)
5050 return CMD_WARNING;
5051
5052 if (!strcmp(argv[2]->arg, "import"))
5053 rt_type = RT_TYPE_IMPORT;
5054 else if (!strcmp(argv[2]->arg, "export"))
5055 rt_type = RT_TYPE_EXPORT;
5056 else if (!strcmp(argv[2]->arg, "both"))
5057 rt_type = RT_TYPE_BOTH;
5058 else {
5059 vty_out(vty, "%% Invalid Route Target type\n");
5060 return CMD_WARNING;
5061 }
5062
5063 if (rt_type == RT_TYPE_IMPORT) {
5064 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5065 vty_out(vty,
5066 "%% Import RT is not configured for this VRF\n");
5067 return CMD_WARNING;
5068 }
5069 } else if (rt_type == RT_TYPE_EXPORT) {
5070 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5071 vty_out(vty,
5072 "%% Export RT is not configured for this VRF\n");
5073 return CMD_WARNING;
5074 }
5075 } else if (rt_type == RT_TYPE_BOTH) {
5076 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
5077 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5078 vty_out(vty,
5079 "%% Import/Export RT is not configured for this VRF\n");
5080 return CMD_WARNING;
5081 }
5082 }
5083
5084 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5085 if (!ecomdel) {
5086 vty_out(vty, "%% Malformed Route Target list\n");
5087 return CMD_WARNING;
5088 }
5089 ecommunity_str(ecomdel);
5090
5091 if (rt_type == RT_TYPE_IMPORT) {
5092 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5093 ecomdel)) {
5094 vty_out(vty,
5095 "%% RT specified does not match configuration for this VRF\n");
5096 return CMD_WARNING;
5097 }
5098 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5099 } else if (rt_type == RT_TYPE_EXPORT) {
5100 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5101 ecomdel)) {
5102 vty_out(vty,
5103 "%% RT specified does not match configuration for this VRF\n");
5104 return CMD_WARNING;
5105 }
5106 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5107 } else if (rt_type == RT_TYPE_BOTH) {
5108 found_ecomdel = 0;
5109
5110 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5111 ecomdel)) {
5112 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5113 found_ecomdel = 1;
5114 }
5115
5116 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5117 ecomdel)) {
5118 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5119 found_ecomdel = 1;
5120 }
5121
5122 if (!found_ecomdel) {
5123 vty_out(vty,
5124 "%% RT specified does not match configuration for this VRF\n");
5125 return CMD_WARNING;
5126 }
5127 }
5128
5129 return CMD_SUCCESS;
5130 }
5131
5132 DEFUN (bgp_evpn_vni_rt,
5133 bgp_evpn_vni_rt_cmd,
5134 "route-target <both|import|export> RT",
5135 "Route Target\n"
5136 "import and export\n"
5137 "import\n"
5138 "export\n"
5139 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5140 {
5141 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5142 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5143 int rt_type;
5144 struct ecommunity *ecomadd = NULL;
5145
5146 if (!bgp)
5147 return CMD_WARNING;
5148
5149 if (!EVPN_ENABLED(bgp)) {
5150 vty_out(vty,
5151 "This command is only supported under EVPN VRF\n");
5152 return CMD_WARNING;
5153 }
5154
5155 if (!strcmp(argv[1]->text, "import"))
5156 rt_type = RT_TYPE_IMPORT;
5157 else if (!strcmp(argv[1]->text, "export"))
5158 rt_type = RT_TYPE_EXPORT;
5159 else if (!strcmp(argv[1]->text, "both"))
5160 rt_type = RT_TYPE_BOTH;
5161 else {
5162 vty_out(vty, "%% Invalid Route Target type\n");
5163 return CMD_WARNING;
5164 }
5165
5166 /* Add/update the import route-target */
5167 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5168 ecomadd = ecommunity_str2com(argv[2]->arg,
5169 ECOMMUNITY_ROUTE_TARGET, 0);
5170 if (!ecomadd) {
5171 vty_out(vty, "%% Malformed Route Target list\n");
5172 return CMD_WARNING;
5173 }
5174 ecommunity_str(ecomadd);
5175
5176 /* Do nothing if we already have this import route-target */
5177 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
5178 evpn_configure_import_rt(bgp, vpn, ecomadd);
5179 }
5180
5181 /* Add/update the export route-target */
5182 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5183 ecomadd = ecommunity_str2com(argv[2]->arg,
5184 ECOMMUNITY_ROUTE_TARGET, 0);
5185 if (!ecomadd) {
5186 vty_out(vty, "%% Malformed Route Target list\n");
5187 return CMD_WARNING;
5188 }
5189 ecommunity_str(ecomadd);
5190
5191 /* Do nothing if we already have this export route-target */
5192 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
5193 evpn_configure_export_rt(bgp, vpn, ecomadd);
5194 }
5195
5196 return CMD_SUCCESS;
5197 }
5198
5199 DEFUN (no_bgp_evpn_vni_rt,
5200 no_bgp_evpn_vni_rt_cmd,
5201 "no route-target <both|import|export> RT",
5202 NO_STR
5203 "Route Target\n"
5204 "import and export\n"
5205 "import\n"
5206 "export\n"
5207 "ASN:XX or A.B.C.D:XX\n")
5208 {
5209 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5210 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5211 int rt_type, found_ecomdel;
5212 struct ecommunity *ecomdel = NULL;
5213
5214 if (!bgp)
5215 return CMD_WARNING;
5216
5217 if (!EVPN_ENABLED(bgp)) {
5218 vty_out(vty,
5219 "This command is only supported under EVPN VRF\n");
5220 return CMD_WARNING;
5221 }
5222
5223 if (!strcmp(argv[2]->text, "import"))
5224 rt_type = RT_TYPE_IMPORT;
5225 else if (!strcmp(argv[2]->text, "export"))
5226 rt_type = RT_TYPE_EXPORT;
5227 else if (!strcmp(argv[2]->text, "both"))
5228 rt_type = RT_TYPE_BOTH;
5229 else {
5230 vty_out(vty, "%% Invalid Route Target type\n");
5231 return CMD_WARNING;
5232 }
5233
5234 /* The user did "no route-target import", check to see if there are any
5235 * import route-targets configured. */
5236 if (rt_type == RT_TYPE_IMPORT) {
5237 if (!is_import_rt_configured(vpn)) {
5238 vty_out(vty,
5239 "%% Import RT is not configured for this VNI\n");
5240 return CMD_WARNING;
5241 }
5242 } else if (rt_type == RT_TYPE_EXPORT) {
5243 if (!is_export_rt_configured(vpn)) {
5244 vty_out(vty,
5245 "%% Export RT is not configured for this VNI\n");
5246 return CMD_WARNING;
5247 }
5248 } else if (rt_type == RT_TYPE_BOTH) {
5249 if (!is_import_rt_configured(vpn)
5250 && !is_export_rt_configured(vpn)) {
5251 vty_out(vty,
5252 "%% Import/Export RT is not configured for this VNI\n");
5253 return CMD_WARNING;
5254 }
5255 }
5256
5257 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5258 if (!ecomdel) {
5259 vty_out(vty, "%% Malformed Route Target list\n");
5260 return CMD_WARNING;
5261 }
5262 ecommunity_str(ecomdel);
5263
5264 if (rt_type == RT_TYPE_IMPORT) {
5265 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5266 vty_out(vty,
5267 "%% RT specified does not match configuration for this VNI\n");
5268 return CMD_WARNING;
5269 }
5270 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5271 } else if (rt_type == RT_TYPE_EXPORT) {
5272 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5273 vty_out(vty,
5274 "%% RT specified does not match configuration for this VNI\n");
5275 return CMD_WARNING;
5276 }
5277 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5278 } else if (rt_type == RT_TYPE_BOTH) {
5279 found_ecomdel = 0;
5280
5281 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5282 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5283 found_ecomdel = 1;
5284 }
5285
5286 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5287 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5288 found_ecomdel = 1;
5289 }
5290
5291 if (!found_ecomdel) {
5292 vty_out(vty,
5293 "%% RT specified does not match configuration for this VNI\n");
5294 return CMD_WARNING;
5295 }
5296 }
5297
5298 return CMD_SUCCESS;
5299 }
5300
5301 DEFUN (no_bgp_evpn_vni_rt_without_val,
5302 no_bgp_evpn_vni_rt_without_val_cmd,
5303 "no route-target <import|export>",
5304 NO_STR
5305 "Route Target\n"
5306 "import\n"
5307 "export\n")
5308 {
5309 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5310 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5311 int rt_type;
5312
5313 if (!bgp)
5314 return CMD_WARNING;
5315
5316 if (!EVPN_ENABLED(bgp)) {
5317 vty_out(vty,
5318 "This command is only supported under EVPN VRF\n");
5319 return CMD_WARNING;
5320 }
5321
5322 if (!strcmp(argv[2]->text, "import")) {
5323 rt_type = RT_TYPE_IMPORT;
5324 } else if (!strcmp(argv[2]->text, "export")) {
5325 rt_type = RT_TYPE_EXPORT;
5326 } else {
5327 vty_out(vty, "%% Invalid Route Target type\n");
5328 return CMD_WARNING;
5329 }
5330
5331 /* Check if we should disallow. */
5332 if (rt_type == RT_TYPE_IMPORT) {
5333 if (!is_import_rt_configured(vpn)) {
5334 vty_out(vty,
5335 "%% Import RT is not configured for this VNI\n");
5336 return CMD_WARNING;
5337 }
5338 } else {
5339 if (!is_export_rt_configured(vpn)) {
5340 vty_out(vty,
5341 "%% Export RT is not configured for this VNI\n");
5342 return CMD_WARNING;
5343 }
5344 }
5345
5346 /* Unconfigure the RT. */
5347 if (rt_type == RT_TYPE_IMPORT)
5348 evpn_unconfigure_import_rt(bgp, vpn, NULL);
5349 else
5350 evpn_unconfigure_export_rt(bgp, vpn, NULL);
5351 return CMD_SUCCESS;
5352 }
5353
5354 static int vni_cmp(const void **a, const void **b)
5355 {
5356 const struct bgpevpn *first = *a;
5357 const struct bgpevpn *secnd = *b;
5358
5359 return secnd->vni - first->vni;
5360 }
5361
5362 /*
5363 * Output EVPN configuration information.
5364 */
5365 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
5366 safi_t safi)
5367 {
5368 char buf1[RD_ADDRSTRLEN];
5369
5370 if (bgp->vnihash) {
5371 struct list *vnilist = hash_to_list(bgp->vnihash);
5372 struct listnode *ln;
5373 struct bgpevpn *data;
5374
5375 list_sort(vnilist, vni_cmp);
5376 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
5377 write_vni_config(vty, data);
5378
5379 list_delete(&vnilist);
5380 }
5381
5382 if (bgp->advertise_all_vni)
5383 vty_out(vty, " advertise-all-vni\n");
5384
5385 if (bgp->advertise_autort_rfc8365)
5386 vty_out(vty, " autort rfc8365-compatible\n");
5387
5388 if (bgp->advertise_gw_macip)
5389 vty_out(vty, " advertise-default-gw\n");
5390
5391 if (bgp->evpn_info->advertise_svi_macip)
5392 vty_out(vty, " advertise-svi-ip\n");
5393
5394 if (!bgp->evpn_info->dup_addr_detect)
5395 vty_out(vty, " no dup-addr-detection\n");
5396
5397 if (bgp->evpn_info->dad_max_moves !=
5398 EVPN_DAD_DEFAULT_MAX_MOVES ||
5399 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
5400 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
5401 bgp->evpn_info->dad_max_moves,
5402 bgp->evpn_info->dad_time);
5403
5404 if (bgp->evpn_info->dad_freeze) {
5405 if (bgp->evpn_info->dad_freeze_time)
5406 vty_out(vty,
5407 " dup-addr-detection freeze %u\n",
5408 bgp->evpn_info->dad_freeze_time);
5409 else
5410 vty_out(vty,
5411 " dup-addr-detection freeze permanent\n");
5412 }
5413
5414 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
5415 vty_out(vty, " flooding disable\n");
5416
5417 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5418 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
5419 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
5420 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
5421 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
5422 else
5423 vty_out(vty, " advertise ipv4 unicast\n");
5424 }
5425
5426 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5427 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
5428 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
5429 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
5430 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
5431 else
5432 vty_out(vty, " advertise ipv6 unicast\n");
5433 }
5434
5435 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5436 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
5437 vty_out(vty, " default-originate ipv4\n");
5438
5439 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5440 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
5441 vty_out(vty, " default-originate ipv6\n");
5442
5443 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
5444 vty_out(vty, " rd %s\n",
5445 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
5446
5447 /* import route-target */
5448 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5449 char *ecom_str;
5450 struct listnode *node, *nnode;
5451 struct ecommunity *ecom;
5452
5453 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
5454 ecom)) {
5455 ecom_str = ecommunity_ecom2str(
5456 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5457 vty_out(vty, " route-target import %s\n", ecom_str);
5458 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5459 }
5460 }
5461
5462 /* export route-target */
5463 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5464 char *ecom_str;
5465 struct listnode *node, *nnode;
5466 struct ecommunity *ecom;
5467
5468 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
5469 ecom)) {
5470 ecom_str = ecommunity_ecom2str(
5471 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5472 vty_out(vty, " route-target export %s\n", ecom_str);
5473 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5474 }
5475 }
5476 }
5477
5478 void bgp_ethernetvpn_init(void)
5479 {
5480 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
5481 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
5482 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
5483 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
5484 install_element(VIEW_NODE,
5485 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
5486 install_element(VIEW_NODE,
5487 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
5488 install_element(
5489 VIEW_NODE,
5490 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
5491 install_element(
5492 VIEW_NODE,
5493 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
5494 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
5495 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
5496 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
5497 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
5498 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
5499 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
5500 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
5501 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
5502 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
5503 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
5504 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
5505 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
5506 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
5507 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
5508 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
5509 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
5510 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
5511 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
5512 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5513
5514 /* test commands */
5515 install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
5516 install_element(BGP_EVPN_NODE, &test_withdraw_evpn_type4_route_cmd);
5517
5518 /* "show bgp l2vpn evpn" commands. */
5519 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
5520 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
5521 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
5522 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
5523 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
5524 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
5525 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
5526 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
5527 install_element(VIEW_NODE,
5528 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
5529 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
5530 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
5531 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
5532 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
5533
5534 /* "show bgp evpn" commands. */
5535 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
5536 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
5537 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
5538 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
5539 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
5540 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
5541 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
5542 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
5543 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
5544 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
5545 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5546 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
5547
5548 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
5549 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
5550 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
5551 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
5552 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
5553 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
5554 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
5555 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
5556 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
5557 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5558 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
5559 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
5560 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5561 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
5562 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
5563 install_element(BGP_EVPN_VNI_NODE,
5564 &bgp_evpn_advertise_default_gw_vni_cmd);
5565 install_element(BGP_EVPN_VNI_NODE,
5566 &no_bgp_evpn_advertise_default_gw_vni_cmd);
5567 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5568 install_element(BGP_EVPN_VNI_NODE,
5569 &no_bgp_evpn_advertise_vni_subnet_cmd);
5570 }