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