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