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