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