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