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