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