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