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