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