]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
Merge pull request #12195 from anlancs/fix/ospfd-missing-max-metric
[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 #ifndef VTYSH_EXTRACT_PL
3340 #include "bgpd/bgp_evpn_vty_clippy.c"
3341 #endif
3342
3343 DEFPY(bgp_evpn_flood_control,
3344 bgp_evpn_flood_control_cmd,
3345 "[no$no] flooding <disable$disable|head-end-replication$her>",
3346 NO_STR
3347 "Specify handling for BUM packets\n"
3348 "Do not flood any BUM packets\n"
3349 "Flood BUM packets using head-end replication\n")
3350 {
3351 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3352 enum vxlan_flood_control flood_ctrl;
3353
3354 if (!bgp)
3355 return CMD_WARNING;
3356
3357 if (disable && !no)
3358 flood_ctrl = VXLAN_FLOOD_DISABLED;
3359 else if (her || no)
3360 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3361 else
3362 return CMD_WARNING;
3363
3364 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3365 return CMD_SUCCESS;
3366
3367 bgp->vxlan_flood_ctrl = flood_ctrl;
3368 bgp_evpn_flood_control_change(bgp);
3369
3370 return CMD_SUCCESS;
3371 }
3372
3373 DEFUN (bgp_evpn_advertise_default_gw_vni,
3374 bgp_evpn_advertise_default_gw_vni_cmd,
3375 "advertise-default-gw",
3376 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3377 {
3378 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3379 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3380
3381 if (!bgp)
3382 return CMD_WARNING;
3383
3384 evpn_set_advertise_default_gw(bgp, vpn);
3385
3386 return CMD_SUCCESS;
3387 }
3388
3389 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3390 no_bgp_evpn_advertise_default_gw_vni_cmd,
3391 "no advertise-default-gw",
3392 NO_STR
3393 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3394 {
3395 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3396 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3397
3398 if (!bgp)
3399 return CMD_WARNING;
3400
3401 evpn_unset_advertise_default_gw(bgp, vpn);
3402
3403 return CMD_SUCCESS;
3404 }
3405
3406
3407 DEFUN (bgp_evpn_advertise_default_gw,
3408 bgp_evpn_advertise_default_gw_cmd,
3409 "advertise-default-gw",
3410 "Advertise All default g/w mac-ip routes in EVPN\n")
3411 {
3412 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3413
3414 if (!bgp)
3415 return CMD_WARNING;
3416
3417 if (!EVPN_ENABLED(bgp)) {
3418 vty_out(vty,
3419 "This command is only supported under the EVPN VRF\n");
3420 return CMD_WARNING;
3421 }
3422
3423 evpn_set_advertise_default_gw(bgp, NULL);
3424
3425 return CMD_SUCCESS;
3426 }
3427
3428 DEFUN (no_bgp_evpn_advertise_default_gw,
3429 no_bgp_evpn_advertise_default_gw_cmd,
3430 "no advertise-default-gw",
3431 NO_STR
3432 "Withdraw All default g/w mac-ip routes from EVPN\n")
3433 {
3434 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3435
3436 if (!bgp)
3437 return CMD_WARNING;
3438
3439 evpn_unset_advertise_default_gw(bgp, NULL);
3440
3441 return CMD_SUCCESS;
3442 }
3443
3444 DEFUN (bgp_evpn_advertise_all_vni,
3445 bgp_evpn_advertise_all_vni_cmd,
3446 "advertise-all-vni",
3447 "Advertise All local VNIs\n")
3448 {
3449 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3450 struct bgp *bgp_evpn = NULL;
3451
3452 if (!bgp)
3453 return CMD_WARNING;
3454
3455 bgp_evpn = bgp_get_evpn();
3456 if (bgp_evpn && bgp_evpn != bgp) {
3457 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3458 bgp_evpn->name_pretty);
3459 return CMD_WARNING_CONFIG_FAILED;
3460 }
3461
3462 evpn_set_advertise_all_vni(bgp);
3463 return CMD_SUCCESS;
3464 }
3465
3466 DEFUN (no_bgp_evpn_advertise_all_vni,
3467 no_bgp_evpn_advertise_all_vni_cmd,
3468 "no advertise-all-vni",
3469 NO_STR
3470 "Advertise All local VNIs\n")
3471 {
3472 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3473
3474 if (!bgp)
3475 return CMD_WARNING;
3476 evpn_unset_advertise_all_vni(bgp);
3477 return CMD_SUCCESS;
3478 }
3479
3480 DEFUN (bgp_evpn_advertise_autort_rfc8365,
3481 bgp_evpn_advertise_autort_rfc8365_cmd,
3482 "autort rfc8365-compatible",
3483 "Auto-derivation of RT\n"
3484 "Auto-derivation of RT using RFC8365\n")
3485 {
3486 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3487
3488 if (!bgp)
3489 return CMD_WARNING;
3490 evpn_set_advertise_autort_rfc8365(bgp);
3491 return CMD_SUCCESS;
3492 }
3493
3494 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3495 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3496 "no autort rfc8365-compatible",
3497 NO_STR
3498 "Auto-derivation of RT\n"
3499 "Auto-derivation of RT using RFC8365\n")
3500 {
3501 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3502
3503 if (!bgp)
3504 return CMD_WARNING;
3505 evpn_unset_advertise_autort_rfc8365(bgp);
3506 return CMD_SUCCESS;
3507 }
3508
3509 DEFUN (bgp_evpn_default_originate,
3510 bgp_evpn_default_originate_cmd,
3511 "default-originate <ipv4 | ipv6>",
3512 "originate a default route\n"
3513 "ipv4 address family\n"
3514 "ipv6 address family\n")
3515 {
3516 afi_t afi = 0;
3517 int idx_afi = 0;
3518 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3519
3520 if (!bgp_vrf)
3521 return CMD_WARNING;
3522 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3523 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3524 return CMD_SUCCESS;
3525 }
3526
3527 DEFUN (no_bgp_evpn_default_originate,
3528 no_bgp_evpn_default_originate_cmd,
3529 "no default-originate <ipv4 | ipv6>",
3530 NO_STR
3531 "withdraw a default route\n"
3532 "ipv4 address family\n"
3533 "ipv6 address family\n")
3534 {
3535 afi_t afi = 0;
3536 int idx_afi = 0;
3537 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3538
3539 if (!bgp_vrf)
3540 return CMD_WARNING;
3541 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3542 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3543 return CMD_SUCCESS;
3544 }
3545
3546 DEFPY (dup_addr_detection,
3547 dup_addr_detection_cmd,
3548 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3549 "Duplicate address detection\n"
3550 "Max allowed moves before address detected as duplicate\n"
3551 "Num of max allowed moves (2-1000) default 5\n"
3552 "Duplicate address detection time\n"
3553 "Time in seconds (2-1800) default 180\n")
3554 {
3555 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3556
3557 if (!bgp_vrf)
3558 return CMD_WARNING;
3559
3560 if (!EVPN_ENABLED(bgp_vrf)) {
3561 vty_out(vty,
3562 "This command is only supported under the EVPN VRF\n");
3563 return CMD_WARNING;
3564 }
3565
3566 bgp_vrf->evpn_info->dup_addr_detect = true;
3567
3568 if (time_val)
3569 bgp_vrf->evpn_info->dad_time = time_val;
3570 if (max_moves_val)
3571 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3572
3573 bgp_zebra_dup_addr_detection(bgp_vrf);
3574
3575 return CMD_SUCCESS;
3576 }
3577
3578 DEFPY (dup_addr_detection_auto_recovery,
3579 dup_addr_detection_auto_recovery_cmd,
3580 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3581 "Duplicate address detection\n"
3582 "Duplicate address detection freeze\n"
3583 "Duplicate address detection permanent freeze\n"
3584 "Duplicate address detection freeze time (30-3600)\n")
3585 {
3586 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3587 uint32_t freeze_time = freeze_time_val;
3588
3589 if (!bgp_vrf)
3590 return CMD_WARNING;
3591
3592 if (!EVPN_ENABLED(bgp_vrf)) {
3593 vty_out(vty,
3594 "This command is only supported under the EVPN VRF\n");
3595 return CMD_WARNING;
3596 }
3597
3598 bgp_vrf->evpn_info->dup_addr_detect = true;
3599 bgp_vrf->evpn_info->dad_freeze = true;
3600 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3601
3602 bgp_zebra_dup_addr_detection(bgp_vrf);
3603
3604 return CMD_SUCCESS;
3605 }
3606
3607 DEFPY (no_dup_addr_detection,
3608 no_dup_addr_detection_cmd,
3609 "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>]",
3610 NO_STR
3611 "Duplicate address detection\n"
3612 "Max allowed moves before address detected as duplicate\n"
3613 "Num of max allowed moves (2-1000) default 5\n"
3614 "Duplicate address detection time\n"
3615 "Time in seconds (2-1800) default 180\n"
3616 "Duplicate address detection freeze\n"
3617 "Duplicate address detection permanent freeze\n"
3618 "Duplicate address detection freeze time (30-3600)\n")
3619 {
3620 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3621 uint32_t max_moves = (uint32_t)max_moves_val;
3622 uint32_t freeze_time = (uint32_t)freeze_time_val;
3623
3624 if (!bgp_vrf)
3625 return CMD_WARNING;
3626
3627 if (!EVPN_ENABLED(bgp_vrf)) {
3628 vty_out(vty,
3629 "This command is only supported under the EVPN VRF\n");
3630 return CMD_WARNING;
3631 }
3632
3633 if (argc == 2) {
3634 if (!bgp_vrf->evpn_info->dup_addr_detect)
3635 return CMD_SUCCESS;
3636 /* Reset all parameters to default. */
3637 bgp_vrf->evpn_info->dup_addr_detect = false;
3638 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3639 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3640 bgp_vrf->evpn_info->dad_freeze = false;
3641 bgp_vrf->evpn_info->dad_freeze_time = 0;
3642 } else {
3643 if (max_moves) {
3644 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3645 vty_out(vty,
3646 "%% Value does not match with config\n");
3647 return CMD_SUCCESS;
3648 }
3649 bgp_vrf->evpn_info->dad_max_moves =
3650 EVPN_DAD_DEFAULT_MAX_MOVES;
3651 }
3652
3653 if (time_val) {
3654 if (bgp_vrf->evpn_info->dad_time != time_val) {
3655 vty_out(vty,
3656 "%% Value does not match with config\n");
3657 return CMD_SUCCESS;
3658 }
3659 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3660 }
3661
3662 if (freeze_time) {
3663 if (bgp_vrf->evpn_info->dad_freeze_time
3664 != freeze_time) {
3665 vty_out(vty,
3666 "%% Value does not match with config\n");
3667 return CMD_SUCCESS;
3668 }
3669 bgp_vrf->evpn_info->dad_freeze_time = 0;
3670 bgp_vrf->evpn_info->dad_freeze = false;
3671 }
3672
3673 if (permanent_val) {
3674 if (bgp_vrf->evpn_info->dad_freeze_time) {
3675 vty_out(vty,
3676 "%% Value does not match with config\n");
3677 return CMD_SUCCESS;
3678 }
3679 bgp_vrf->evpn_info->dad_freeze = false;
3680 }
3681 }
3682
3683 bgp_zebra_dup_addr_detection(bgp_vrf);
3684
3685 return CMD_SUCCESS;
3686 }
3687
3688 DEFPY(bgp_evpn_advertise_svi_ip,
3689 bgp_evpn_advertise_svi_ip_cmd,
3690 "[no$no] advertise-svi-ip",
3691 NO_STR
3692 "Advertise svi mac-ip routes in EVPN\n")
3693 {
3694 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3695
3696 if (!bgp)
3697 return CMD_WARNING;
3698
3699 if (no)
3700 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3701 else {
3702 if (!EVPN_ENABLED(bgp)) {
3703 vty_out(vty,
3704 "This command is only supported under EVPN VRF\n");
3705 return CMD_WARNING;
3706 }
3707 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3708 }
3709
3710 return CMD_SUCCESS;
3711 }
3712
3713 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3714 bgp_evpn_advertise_svi_ip_vni_cmd,
3715 "[no$no] advertise-svi-ip",
3716 NO_STR
3717 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3718 {
3719 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3720 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3721
3722 if (!bgp)
3723 return CMD_WARNING;
3724
3725 if (no)
3726 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3727 else
3728 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3729
3730 return CMD_SUCCESS;
3731 }
3732
3733 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3734 bgp_evpn_advertise_vni_subnet_cmd,
3735 "advertise-subnet",
3736 "Advertise the subnet corresponding to VNI\n")
3737 {
3738 struct bgp *bgp_vrf = NULL;
3739 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3740 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3741
3742 if (!bgp)
3743 return CMD_WARNING;
3744
3745 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3746 if (!bgp_vrf)
3747 return CMD_WARNING;
3748
3749 evpn_set_advertise_subnet(bgp, vpn);
3750 return CMD_SUCCESS;
3751 }
3752
3753 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3754 no_bgp_evpn_advertise_vni_subnet_cmd,
3755 "no advertise-subnet",
3756 NO_STR
3757 "Advertise All local VNIs\n")
3758 {
3759 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3760 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3761
3762 if (!bgp)
3763 return CMD_WARNING;
3764
3765 evpn_unset_advertise_subnet(bgp, vpn);
3766 return CMD_SUCCESS;
3767 }
3768
3769 DEFUN (bgp_evpn_advertise_type5,
3770 bgp_evpn_advertise_type5_cmd,
3771 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
3772 "Advertise prefix routes\n"
3773 BGP_AFI_HELP_STR
3774 BGP_SAFI_HELP_STR
3775 "advertise gateway IP overlay index\n"
3776 "route-map for filtering specific routes\n"
3777 "Name of the route map\n")
3778 {
3779 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3780 int idx_afi = 0;
3781 int idx_safi = 0;
3782 int idx_rmap = 0;
3783 afi_t afi = 0;
3784 safi_t safi = 0;
3785 int ret = 0;
3786 int rmap_changed = 0;
3787 enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3788 int idx_oly = 0;
3789 bool adv_flag_changed = false;
3790
3791 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3792 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3793 argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3794
3795 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3796 if (ret) {
3797 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3798 rmap_changed = 1;
3799 else if (strcmp(argv[idx_rmap + 1]->arg,
3800 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3801 != 0)
3802 rmap_changed = 1;
3803 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3804 rmap_changed = 1;
3805 }
3806
3807 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3808 vty_out(vty,
3809 "%% Only ipv4 or ipv6 address families are supported\n");
3810 return CMD_WARNING;
3811 }
3812
3813 if (safi != SAFI_UNICAST) {
3814 vty_out(vty,
3815 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3816 return CMD_WARNING;
3817 }
3818
3819 if ((oly != OVERLAY_INDEX_TYPE_NONE)
3820 && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
3821 vty_out(vty, "%% Unknown overlay-index type specified\n");
3822 return CMD_WARNING;
3823 }
3824
3825 if (afi == AFI_IP) {
3826 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3827 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
3828 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3829 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
3830
3831 /*
3832 * this is the case for first time ever configuration
3833 * adv ipv4 unicast is enabled for the first time.
3834 * So no need to reset any flag
3835 */
3836 if (oly == OVERLAY_INDEX_TYPE_NONE)
3837 SET_FLAG(
3838 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3839 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
3840 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
3841 SET_FLAG(
3842 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3843 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
3844 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
3845 && (!CHECK_FLAG(
3846 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3847 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
3848
3849 /*
3850 * This is modify case from gateway-ip
3851 * to no overlay index
3852 */
3853 adv_flag_changed = true;
3854 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3855 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
3856 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3857 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
3858 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
3859 && (!CHECK_FLAG(
3860 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3861 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
3862
3863 /*
3864 * This is modify case from no overlay index
3865 * to gateway-ip
3866 */
3867 adv_flag_changed = true;
3868 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3869 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
3870 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3871 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
3872 } else {
3873
3874 /*
3875 * Command is issued with the same option
3876 * (no overlay index or gateway-ip) which was
3877 * already configured. So nothing to do.
3878 * However, route-map may have been modified.
3879 * check if route-map has been modified.
3880 * If not, return an error
3881 */
3882 if (!rmap_changed)
3883 return CMD_WARNING;
3884 }
3885 } else {
3886 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3887 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
3888 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3889 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
3890
3891 /*
3892 * this is the case for first time ever configuration
3893 * adv ipv6 unicast is enabled for the first time.
3894 * So no need to reset any flag
3895 */
3896 if (oly == OVERLAY_INDEX_TYPE_NONE)
3897 SET_FLAG(
3898 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3899 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
3900 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
3901 SET_FLAG(
3902 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3903 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
3904 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
3905 && (!CHECK_FLAG(
3906 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3907 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
3908
3909 /*
3910 * This is modify case from gateway-ip
3911 * to no overlay index
3912 */
3913 adv_flag_changed = true;
3914 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3915 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
3916 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3917 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
3918 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
3919 && (!CHECK_FLAG(
3920 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3921 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
3922
3923 /*
3924 * This is modify case from no overlay index
3925 * to gateway-ip
3926 */
3927 adv_flag_changed = true;
3928 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3929 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
3930 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3931 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
3932 } else {
3933
3934 /*
3935 * Command is issued with the same option
3936 * (no overlay index or gateway-ip) which was
3937 * already configured. So nothing to do.
3938 * However, route-map may have been modified.
3939 * check if route-map has been modified.
3940 * If not, return an error
3941 */
3942 if (!rmap_changed)
3943 return CMD_WARNING;
3944 }
3945 }
3946
3947 if ((rmap_changed) || (adv_flag_changed)) {
3948
3949 /* If either of these are changed, then FRR needs to
3950 * withdraw already advertised type5 routes.
3951 */
3952 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3953 if (rmap_changed) {
3954 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3955 XFREE(MTYPE_ROUTE_MAP_NAME,
3956 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3957 route_map_counter_decrement(
3958 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3959 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3960 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3961 }
3962 }
3963 }
3964
3965 /* set the route-map for advertise command */
3966 if (ret && argv[idx_rmap + 1]->arg) {
3967 bgp_vrf->adv_cmd_rmap[afi][safi].name =
3968 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
3969 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3970 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3971 route_map_counter_increment(
3972 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3973 }
3974
3975 /* advertise type-5 routes */
3976 if (advertise_type5_routes(bgp_vrf, afi))
3977 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
3978 return CMD_SUCCESS;
3979 }
3980
3981 DEFUN (no_bgp_evpn_advertise_type5,
3982 no_bgp_evpn_advertise_type5_cmd,
3983 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
3984 NO_STR
3985 "Advertise prefix routes\n"
3986 BGP_AFI_HELP_STR
3987 BGP_SAFI_HELP_STR
3988 "route-map for filtering specific routes\n"
3989 "Name of the route map\n")
3990 {
3991 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3992 int idx_afi = 0;
3993 int idx_safi = 0;
3994 afi_t afi = 0;
3995 safi_t safi = 0;
3996
3997 if (!bgp_vrf)
3998 return CMD_WARNING;
3999
4000 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4001 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4002
4003 if (!(afi == AFI_IP || afi == AFI_IP6)) {
4004 vty_out(vty,
4005 "%% Only ipv4 or ipv6 address families are supported\n");
4006 return CMD_WARNING;
4007 }
4008
4009 if (safi != SAFI_UNICAST) {
4010 vty_out(vty,
4011 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4012 return CMD_WARNING;
4013 }
4014
4015 if (afi == AFI_IP) {
4016
4017 /* if we are not advertising ipv4 prefix as type-5
4018 * nothing to do
4019 */
4020 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4021 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4022 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4023 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4024 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4025 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4027 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4028 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4029 }
4030 } else {
4031
4032 /* if we are not advertising ipv6 prefix as type-5
4033 * nothing to do
4034 */
4035 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4036 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4037 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4038 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
4039 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4040 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4041 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4042 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4043 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4044 }
4045 }
4046
4047 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4048 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4049 XFREE(MTYPE_ROUTE_MAP_NAME,
4050 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4051 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4052 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4053 }
4054
4055 return CMD_SUCCESS;
4056 }
4057
4058 DEFPY (bgp_evpn_use_es_l3nhg,
4059 bgp_evpn_use_es_l3nhg_cmd,
4060 "[no$no] use-es-l3nhg",
4061 NO_STR
4062 "use L3 nexthop group for host routes with ES destination\n")
4063 {
4064 bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4065 return CMD_SUCCESS;
4066 }
4067
4068 DEFPY (bgp_evpn_ead_evi_rx_disable,
4069 bgp_evpn_ead_evi_rx_disable_cmd,
4070 "[no$no] disable-ead-evi-rx",
4071 NO_STR
4072 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4073 {
4074 bool ead_evi_rx = no? true :false;
4075
4076 if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4077 bgp_mh_info->ead_evi_rx = ead_evi_rx;
4078 bgp_evpn_switch_ead_evi_rx();
4079 }
4080 return CMD_SUCCESS;
4081 }
4082
4083 DEFPY (bgp_evpn_ead_evi_tx_disable,
4084 bgp_evpn_ead_evi_tx_disable_cmd,
4085 "[no$no] disable-ead-evi-tx",
4086 NO_STR
4087 "Don't advertise EAD-EVI for local ESs\n")
4088 {
4089 bgp_mh_info->ead_evi_tx = no? true :false;
4090 return CMD_SUCCESS;
4091 }
4092
4093 DEFPY (bgp_evpn_enable_resolve_overlay_index,
4094 bgp_evpn_enable_resolve_overlay_index_cmd,
4095 "[no$no] enable-resolve-overlay-index",
4096 NO_STR
4097 "Enable Recursive Resolution of type-5 route overlay index\n")
4098 {
4099 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4100
4101 if (bgp != bgp_get_evpn()) {
4102 vty_out(vty, "This command is only supported under EVPN VRF\n");
4103 return CMD_WARNING;
4104 }
4105
4106 bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4107 return CMD_SUCCESS;
4108 }
4109
4110 DEFPY (bgp_evpn_advertise_pip_ip_mac,
4111 bgp_evpn_advertise_pip_ip_mac_cmd,
4112 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4113 NO_STR
4114 "evpn system primary IP\n"
4115 IP_STR
4116 "ip address\n"
4117 MAC_STR MAC_STR MAC_STR)
4118 {
4119 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4120 struct bgp *bgp_evpn = NULL;
4121
4122 if (EVPN_ENABLED(bgp_vrf)) {
4123 vty_out(vty,
4124 "This command is supported under L3VNI BGP EVPN VRF\n");
4125 return CMD_WARNING_CONFIG_FAILED;
4126 }
4127 bgp_evpn = bgp_get_evpn();
4128
4129 if (!no) {
4130 /* pip is already enabled */
4131 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4132 return CMD_SUCCESS;
4133
4134 bgp_vrf->evpn_info->advertise_pip = true;
4135 if (ip.s_addr != INADDR_ANY) {
4136 /* Already configured with same IP */
4137 if (IPV4_ADDR_SAME(&ip,
4138 &bgp_vrf->evpn_info->pip_ip_static))
4139 return CMD_SUCCESS;
4140
4141 bgp_vrf->evpn_info->pip_ip_static = ip;
4142 bgp_vrf->evpn_info->pip_ip = ip;
4143 } else {
4144 bgp_vrf->evpn_info->pip_ip_static.s_addr
4145 = INADDR_ANY;
4146 /* default instance router-id assignemt */
4147 if (bgp_evpn)
4148 bgp_vrf->evpn_info->pip_ip =
4149 bgp_evpn->router_id;
4150 }
4151 /* parse sys mac */
4152 if (!is_zero_mac(&mac->eth_addr)) {
4153 /* Already configured with same MAC */
4154 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4155 &mac->eth_addr, ETH_ALEN) == 0)
4156 return CMD_SUCCESS;
4157
4158 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4159 &mac->eth_addr, ETH_ALEN);
4160 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4161 &bgp_vrf->evpn_info->pip_rmac_static,
4162 ETH_ALEN);
4163 } else {
4164 /* Copy zebra sys mac */
4165 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4166 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4167 &bgp_vrf->evpn_info->pip_rmac_zebra,
4168 ETH_ALEN);
4169 }
4170 } else {
4171 if (argc == 2) {
4172 if (!bgp_vrf->evpn_info->advertise_pip)
4173 return CMD_SUCCESS;
4174 /* Disable PIP feature */
4175 bgp_vrf->evpn_info->advertise_pip = false;
4176 /* copy anycast mac */
4177 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4178 &bgp_vrf->rmac, ETH_ALEN);
4179 } else {
4180 /* remove MAC-IP option retain PIP knob. */
4181 if ((ip.s_addr != INADDR_ANY) &&
4182 !IPV4_ADDR_SAME(&ip,
4183 &bgp_vrf->evpn_info->pip_ip_static)) {
4184 vty_out(vty,
4185 "%% BGP EVPN PIP IP does not match\n");
4186 return CMD_WARNING_CONFIG_FAILED;
4187 }
4188
4189 if (!is_zero_mac(&mac->eth_addr) &&
4190 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4191 &mac->eth_addr, ETH_ALEN) != 0) {
4192 vty_out(vty,
4193 "%% BGP EVPN PIP MAC does not match\n");
4194 return CMD_WARNING_CONFIG_FAILED;
4195 }
4196 /* pip_rmac can carry vrr_rmac reset only if it matches
4197 * with static value.
4198 */
4199 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4200 &bgp_vrf->evpn_info->pip_rmac_static,
4201 ETH_ALEN) == 0) {
4202 /* Copy zebra sys mac */
4203 if (!is_zero_mac(
4204 &bgp_vrf->evpn_info->pip_rmac_zebra))
4205 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4206 &bgp_vrf->evpn_info->pip_rmac_zebra,
4207 ETH_ALEN);
4208 else {
4209 /* copy anycast mac */
4210 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4211 &bgp_vrf->rmac, ETH_ALEN);
4212 }
4213 }
4214 }
4215 /* reset user configured sys MAC */
4216 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4217 /* reset user configured sys IP */
4218 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4219 /* Assign default PIP IP (bgp instance router-id) */
4220 if (bgp_evpn)
4221 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4222 else
4223 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4224 }
4225
4226 if (is_evpn_enabled()) {
4227 struct listnode *node = NULL;
4228 struct bgpevpn *vpn = NULL;
4229
4230 /*
4231 * At this point if bgp_evpn is NULL and evpn is enabled
4232 * something stupid has gone wrong
4233 */
4234 assert(bgp_evpn);
4235
4236 update_advertise_vrf_routes(bgp_vrf);
4237
4238 /* Update (svi) type-2 routes */
4239 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4240 if (!bgp_evpn_is_svi_macip_enabled(vpn))
4241 continue;
4242 update_routes_for_vni(bgp_evpn, vpn);
4243 }
4244 }
4245
4246 return CMD_SUCCESS;
4247 }
4248
4249 /*
4250 * Display VNI information - for all or a specific VNI
4251 */
4252 DEFUN(show_bgp_l2vpn_evpn_vni,
4253 show_bgp_l2vpn_evpn_vni_cmd,
4254 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
4255 SHOW_STR
4256 BGP_STR
4257 L2VPN_HELP_STR
4258 EVPN_HELP_STR
4259 "Show VNI\n"
4260 "VNI number\n"
4261 JSON_STR)
4262 {
4263 struct bgp *bgp_evpn;
4264 vni_t vni;
4265 int idx = 0;
4266 bool uj = false;
4267 json_object *json = NULL;
4268 uint32_t num_l2vnis = 0;
4269 uint32_t num_l3vnis = 0;
4270 uint32_t num_vnis = 0;
4271 struct listnode *node = NULL;
4272 struct bgp *bgp_temp = NULL;
4273
4274 uj = use_json(argc, argv);
4275
4276 bgp_evpn = bgp_get_evpn();
4277 if (!bgp_evpn)
4278 return CMD_WARNING;
4279
4280 if (!argv_find(argv, argc, "evpn", &idx))
4281 return CMD_WARNING;
4282
4283 if (uj)
4284 json = json_object_new_object();
4285
4286 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4287
4288 num_l2vnis = hashcount(bgp_evpn->vnihash);
4289
4290 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4291 if (bgp_temp->l3vni)
4292 num_l3vnis++;
4293 }
4294 num_vnis = num_l2vnis + num_l3vnis;
4295 if (uj) {
4296 json_object_string_add(json, "advertiseGatewayMacip",
4297 bgp_evpn->advertise_gw_macip
4298 ? "Enabled"
4299 : "Disabled");
4300 json_object_string_add(json, "advertiseSviMacIp",
4301 bgp_evpn->evpn_info->advertise_svi_macip
4302 ? "Enabled" : "Disabled");
4303 json_object_string_add(json, "advertiseAllVnis",
4304 is_evpn_enabled() ? "Enabled"
4305 : "Disabled");
4306 json_object_string_add(
4307 json, "flooding",
4308 bgp_evpn->vxlan_flood_ctrl ==
4309 VXLAN_FLOOD_HEAD_END_REPL
4310 ? "Head-end replication"
4311 : "Disabled");
4312 json_object_string_add(
4313 json, "vxlanFlooding",
4314 bgp_evpn->vxlan_flood_ctrl ==
4315 VXLAN_FLOOD_HEAD_END_REPL
4316 ? "Enabled"
4317 : "Disabled");
4318 json_object_int_add(json, "numVnis", num_vnis);
4319 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4320 json_object_int_add(json, "numL3Vnis", num_l3vnis);
4321 } else {
4322 vty_out(vty, "Advertise Gateway Macip: %s\n",
4323 bgp_evpn->advertise_gw_macip ? "Enabled"
4324 : "Disabled");
4325 vty_out(vty, "Advertise SVI Macip: %s\n",
4326 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
4327 : "Disabled");
4328 vty_out(vty, "Advertise All VNI flag: %s\n",
4329 is_evpn_enabled() ? "Enabled" : "Disabled");
4330 vty_out(vty, "BUM flooding: %s\n",
4331 bgp_evpn->vxlan_flood_ctrl ==
4332 VXLAN_FLOOD_HEAD_END_REPL
4333 ? "Head-end replication"
4334 : "Disabled");
4335 vty_out(vty, "VXLAN flooding: %s\n",
4336 bgp_evpn->vxlan_flood_ctrl ==
4337 VXLAN_FLOOD_HEAD_END_REPL
4338 ? "Enabled"
4339 : "Disabled");
4340 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4341 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
4342 }
4343 evpn_show_all_vnis(vty, bgp_evpn, json);
4344 } else {
4345 int vni_idx = 0;
4346
4347 if (!argv_find(argv, argc, "vni", &vni_idx))
4348 return CMD_WARNING;
4349
4350 /* Display specific VNI */
4351 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4352 evpn_show_vni(vty, bgp_evpn, vni, json);
4353 }
4354
4355 if (uj)
4356 vty_json(vty, json);
4357
4358 return CMD_SUCCESS;
4359 }
4360
4361 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4362 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4363 "show bgp l2vpn evpn vni remote-ip-hash",
4364 SHOW_STR
4365 BGP_STR
4366 L2VPN_HELP_STR
4367 EVPN_HELP_STR
4368 "Show VNI\n"
4369 "Remote IP hash\n")
4370 {
4371 struct bgp *bgp_evpn;
4372 int idx = 0;
4373
4374 bgp_evpn = bgp_get_evpn();
4375 if (!bgp_evpn)
4376 return CMD_WARNING;
4377
4378 if (!argv_find(argv, argc, "evpn", &idx))
4379 return CMD_WARNING;
4380
4381 hash_iterate(bgp_evpn->vnihash,
4382 (void (*)(struct hash_bucket *,
4383 void *))bgp_evpn_show_remote_ip_hash,
4384 vty);
4385
4386 return CMD_SUCCESS;
4387 }
4388
4389 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4390 show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4391 "show bgp l2vpn evpn vni-svi-hash",
4392 SHOW_STR
4393 BGP_STR
4394 L2VPN_HELP_STR
4395 EVPN_HELP_STR
4396 "Show vni-svi-hash\n")
4397 {
4398 struct bgp *bgp_evpn;
4399 int idx = 0;
4400
4401 bgp_evpn = bgp_get_evpn();
4402 if (!bgp_evpn)
4403 return CMD_WARNING;
4404
4405 if (!argv_find(argv, argc, "evpn", &idx))
4406 return CMD_WARNING;
4407
4408 hash_iterate(bgp_evpn->vni_svi_hash,
4409 (void (*)(struct hash_bucket *,
4410 void *))bgp_evpn_show_vni_svi_hash,
4411 vty);
4412
4413 return CMD_SUCCESS;
4414 }
4415
4416 DEFPY(show_bgp_l2vpn_evpn_es_evi,
4417 show_bgp_l2vpn_evpn_es_evi_cmd,
4418 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4419 SHOW_STR
4420 BGP_STR
4421 L2VPN_HELP_STR
4422 EVPN_HELP_STR
4423 "ES per EVI\n"
4424 "VxLAN Network Identifier\n"
4425 "VNI\n"
4426 JSON_STR
4427 "Detailed information\n")
4428 {
4429 if (vni)
4430 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4431 else
4432 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4433
4434 return CMD_SUCCESS;
4435 }
4436
4437 DEFPY(show_bgp_l2vpn_evpn_es,
4438 show_bgp_l2vpn_evpn_es_cmd,
4439 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4440 SHOW_STR
4441 BGP_STR
4442 L2VPN_HELP_STR
4443 EVPN_HELP_STR
4444 "Ethernet Segment\n"
4445 "ES ID\n"
4446 "Detailed information\n"
4447 JSON_STR)
4448 {
4449 esi_t esi;
4450
4451 if (esi_str) {
4452 if (!str_to_esi(esi_str, &esi)) {
4453 vty_out(vty, "%% Malformed ESI\n");
4454 return CMD_WARNING;
4455 }
4456 bgp_evpn_es_show_esi(vty, &esi, uj);
4457 } else {
4458
4459 bgp_evpn_es_show(vty, uj, !!detail);
4460 }
4461
4462 return CMD_SUCCESS;
4463 }
4464
4465 DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4466 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4467 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4468 "Ethernet Segment\n"
4469 "ES ID\n" JSON_STR)
4470 {
4471 esi_t esi;
4472
4473 if (esi_str) {
4474 if (!str_to_esi(esi_str, &esi)) {
4475 vty_out(vty, "%% Malformed ESI\n");
4476 return CMD_WARNING;
4477 }
4478 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4479 } else {
4480
4481 bgp_evpn_es_vrf_show(vty, uj, NULL);
4482 }
4483
4484 return CMD_SUCCESS;
4485 }
4486
4487 DEFPY(show_bgp_l2vpn_evpn_nh,
4488 show_bgp_l2vpn_evpn_nh_cmd,
4489 "show bgp l2vpn evpn next-hops [json$uj]",
4490 SHOW_STR
4491 BGP_STR
4492 L2VPN_HELP_STR
4493 EVPN_HELP_STR
4494 "Nexthops\n"
4495 JSON_STR)
4496 {
4497 bgp_evpn_nh_show(vty, uj);
4498
4499 return CMD_SUCCESS;
4500 }
4501
4502 /*
4503 * Display EVPN neighbor summary.
4504 */
4505 DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
4506 "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]",
4507 SHOW_STR BGP_STR
4508 "bgp vrf\n"
4509 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4510 "Summary of BGP neighbor status\n"
4511 "Show only sessions in Established state\n"
4512 "Show only sessions not in Established state\n"
4513 "Show only the specified neighbor session\n"
4514 "Neighbor to display information about\n"
4515 "Neighbor to display information about\n"
4516 "Neighbor on BGP configured interface\n"
4517 "Show only the specified remote AS sessions\n"
4518 "AS number\n"
4519 "Internal (iBGP) AS sessions\n"
4520 "External (eBGP) AS sessions\n"
4521 "Shorten the information on BGP instances\n"
4522 "Increase table width for longer output\n" JSON_STR)
4523 {
4524 int idx_vrf = 0;
4525 int idx = 0;
4526 char *vrf = NULL;
4527 char *neighbor = NULL;
4528 as_t as = 0; /* 0 means AS filter not set */
4529 int as_type = AS_UNSPECIFIED;
4530 uint16_t show_flags = 0;
4531
4532 if (argv_find(argv, argc, "vrf", &idx_vrf))
4533 vrf = argv[++idx_vrf]->arg;
4534
4535 if (argv_find(argv, argc, "failed", &idx))
4536 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4537
4538 if (argv_find(argv, argc, "established", &idx))
4539 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4540
4541
4542 if (argv_find(argv, argc, "neighbor", &idx))
4543 neighbor = argv[idx + 1]->arg;
4544
4545 if (argv_find(argv, argc, "remote-as", &idx)) {
4546 if (argv[idx + 1]->arg[0] == 'i')
4547 as_type = AS_INTERNAL;
4548 else if (argv[idx + 1]->arg[0] == 'e')
4549 as_type = AS_EXTERNAL;
4550 else
4551 as = (as_t)atoi(argv[idx + 1]->arg);
4552 }
4553
4554 if (argv_find(argv, argc, "terse", &idx))
4555 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4556
4557 if (argv_find(argv, argc, "wide", &idx))
4558 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4559
4560 if (use_json(argc, argv))
4561 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4562
4563 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4564 as_type, as, show_flags);
4565 }
4566
4567 int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
4568 {
4569 int type_idx = 0;
4570
4571 if (argv_find(argv, argc, "type", &type_idx)) {
4572 /* Specific type is requested */
4573 if ((strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
4574 || (strmatch(argv[type_idx + 1]->arg, "2")))
4575 *type = BGP_EVPN_MAC_IP_ROUTE;
4576 else if ((strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
4577 || (strmatch(argv[type_idx + 1]->arg, "3")))
4578 *type = BGP_EVPN_IMET_ROUTE;
4579 else if ((strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
4580 || (strmatch(argv[type_idx + 1]->arg, "4")))
4581 *type = BGP_EVPN_ES_ROUTE;
4582 else if ((strncmp(argv[type_idx + 1]->arg, "ea", 2) == 0)
4583 || (strmatch(argv[type_idx + 1]->arg, "1")))
4584 *type = BGP_EVPN_AD_ROUTE;
4585 else if ((strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
4586 || (strmatch(argv[type_idx + 1]->arg, "5")))
4587 *type = BGP_EVPN_IP_PREFIX_ROUTE;
4588 else
4589 return -1;
4590 }
4591
4592 return 0;
4593 }
4594
4595 /*
4596 * Display global EVPN routing table.
4597 */
4598 DEFUN(show_bgp_l2vpn_evpn_route,
4599 show_bgp_l2vpn_evpn_route_cmd,
4600 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
4601 SHOW_STR
4602 BGP_STR
4603 L2VPN_HELP_STR
4604 EVPN_HELP_STR
4605 EVPN_RT_HELP_STR
4606 "Display Detailed Information\n"
4607 EVPN_TYPE_HELP_STR
4608 EVPN_TYPE_ALL_LIST_HELP_STR
4609 JSON_STR)
4610 {
4611 struct bgp *bgp;
4612 int detail = 0;
4613 int type = 0;
4614 bool uj = false;
4615 json_object *json = NULL;
4616
4617 uj = use_json(argc, argv);
4618
4619 bgp = bgp_get_evpn();
4620 if (!bgp)
4621 return CMD_WARNING;
4622
4623 if (uj)
4624 json = json_object_new_object();
4625
4626 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4627 return CMD_WARNING;
4628
4629 if (argv_find(argv, argc, "detail", &detail))
4630 detail = 1;
4631
4632 evpn_show_all_routes(vty, bgp, type, json, detail);
4633
4634 if (uj)
4635 vty_json(vty, json);
4636 return CMD_SUCCESS;
4637 }
4638
4639 /*
4640 * Display global EVPN routing table for specific RD.
4641 */
4642 DEFUN(show_bgp_l2vpn_evpn_route_rd,
4643 show_bgp_l2vpn_evpn_route_rd_cmd,
4644 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
4645 SHOW_STR
4646 BGP_STR
4647 L2VPN_HELP_STR
4648 EVPN_HELP_STR
4649 EVPN_RT_HELP_STR
4650 EVPN_RT_DIST_HELP_STR
4651 EVPN_ASN_IP_HELP_STR
4652 "All VPN Route Distinguishers\n"
4653 EVPN_TYPE_HELP_STR
4654 EVPN_TYPE_ALL_LIST_HELP_STR
4655 JSON_STR)
4656 {
4657 struct bgp *bgp;
4658 int ret = 0;
4659 struct prefix_rd prd;
4660 int type = 0;
4661 bool uj = false;
4662 json_object *json = NULL;
4663 int idx_ext_community = 0;
4664 int rd_all = 0;
4665
4666 bgp = bgp_get_evpn();
4667 if (!bgp)
4668 return CMD_WARNING;
4669
4670 /* check if we need json output */
4671 uj = use_json(argc, argv);
4672 if (uj)
4673 json = json_object_new_object();
4674
4675 if (!argv_find(argv, argc, "all", &rd_all)) {
4676 /* get the RD */
4677 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4678 &idx_ext_community)) {
4679 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4680 if (!ret) {
4681 vty_out(vty,
4682 "%% Malformed Route Distinguisher\n");
4683 return CMD_WARNING;
4684 }
4685 }
4686 }
4687
4688 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4689 return CMD_WARNING;
4690
4691 if (rd_all)
4692 evpn_show_all_routes(vty, bgp, type, json, 1);
4693 else
4694 evpn_show_route_rd(vty, bgp, &prd, type, json);
4695
4696 if (uj)
4697 vty_json(vty, json);
4698
4699 return CMD_SUCCESS;
4700 }
4701
4702 /*
4703 * Display global EVPN routing table for specific RD and MACIP.
4704 */
4705 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4706 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
4707 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4708 SHOW_STR
4709 BGP_STR
4710 L2VPN_HELP_STR
4711 EVPN_HELP_STR
4712 EVPN_RT_HELP_STR
4713 EVPN_RT_DIST_HELP_STR
4714 EVPN_ASN_IP_HELP_STR
4715 "All VPN Route Distinguishers\n"
4716 "MAC\n"
4717 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4718 "IP\n"
4719 "IP address (IPv4 or IPv6)\n"
4720 JSON_STR)
4721 {
4722 struct bgp *bgp;
4723 int ret = 0;
4724 struct prefix_rd prd;
4725 struct ethaddr mac;
4726 struct ipaddr ip;
4727 int idx_ext_community = 0;
4728 int mac_idx = 0;
4729 int ip_idx = 0;
4730 bool uj = false;
4731 json_object *json = NULL;
4732 int rd_all = 0;
4733
4734 memset(&mac, 0, sizeof(struct ethaddr));
4735 memset(&ip, 0, sizeof(struct ipaddr));
4736
4737 bgp = bgp_get_evpn();
4738 if (!bgp)
4739 return CMD_WARNING;
4740
4741 /* check if we need json output */
4742 uj = use_json(argc, argv);
4743 if (uj)
4744 json = json_object_new_object();
4745
4746 /* get the prd */
4747 if (!argv_find(argv, argc, "all", &rd_all)) {
4748 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4749 &idx_ext_community)) {
4750 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4751 if (!ret) {
4752 vty_out(vty,
4753 "%% Malformed Route Distinguisher\n");
4754 return CMD_WARNING;
4755 }
4756 }
4757 }
4758
4759 /* get the mac */
4760 if (argv_find(argv, argc, "mac", &mac_idx)) {
4761 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4762 vty_out(vty, "%% Malformed MAC address\n");
4763 return CMD_WARNING;
4764 }
4765 }
4766
4767 /* get the ip if specified */
4768 if (argv_find(argv, argc, "ip", &ip_idx)) {
4769 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4770 vty_out(vty, "%% Malformed IP address\n");
4771 return CMD_WARNING;
4772 }
4773 }
4774
4775 if (rd_all)
4776 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4777 else
4778 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4779
4780 if (uj)
4781 vty_json(vty, json);
4782
4783 return CMD_SUCCESS;
4784 }
4785
4786 /* Display per ESI routing table */
4787 DEFUN(show_bgp_l2vpn_evpn_route_esi,
4788 show_bgp_l2vpn_evpn_route_esi_cmd,
4789 "show bgp l2vpn evpn route esi ESI [json]",
4790 SHOW_STR
4791 BGP_STR
4792 L2VPN_HELP_STR
4793 EVPN_HELP_STR
4794 EVPN_RT_HELP_STR
4795 "Ethernet Segment Identifier\n"
4796 "ESI ID\n"
4797 JSON_STR)
4798 {
4799 bool uj = false;
4800 esi_t esi;
4801 struct bgp *bgp = NULL;
4802 json_object *json = NULL;
4803
4804 memset(&esi, 0, sizeof(esi));
4805 bgp = bgp_get_evpn();
4806 if (!bgp)
4807 return CMD_WARNING;
4808
4809 uj = use_json(argc, argv);
4810 if (uj)
4811 json = json_object_new_object();
4812
4813 /* get the ESI - ESI-ID is at argv[6] */
4814 if (!str_to_esi(argv[6]->arg, &esi)) {
4815 vty_out(vty, "%% Malformed ESI\n");
4816 return CMD_WARNING;
4817 }
4818
4819 evpn_show_routes_esi(vty, bgp, &esi, json);
4820
4821 if (uj)
4822 vty_json(vty, json);
4823
4824 return CMD_SUCCESS;
4825 }
4826
4827
4828 /*
4829 * Display per-VNI EVPN routing table.
4830 */
4831 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
4832 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4833 SHOW_STR
4834 BGP_STR
4835 L2VPN_HELP_STR
4836 EVPN_HELP_STR
4837 EVPN_RT_HELP_STR
4838 "VXLAN Network Identifier\n"
4839 "VNI number\n"
4840 EVPN_TYPE_HELP_STR
4841 EVPN_TYPE_1_HELP_STR
4842 EVPN_TYPE_1_HELP_STR
4843 EVPN_TYPE_2_HELP_STR
4844 EVPN_TYPE_2_HELP_STR
4845 EVPN_TYPE_3_HELP_STR
4846 EVPN_TYPE_3_HELP_STR
4847 "Remote VTEP\n"
4848 "Remote VTEP IP address\n"
4849 JSON_STR)
4850 {
4851 vni_t vni;
4852 struct bgp *bgp;
4853 struct in_addr vtep_ip;
4854 int type = 0;
4855 int idx = 0;
4856 int vtep_idx = 0;
4857 bool uj = false;
4858 json_object *json = NULL;
4859
4860 bgp = bgp_get_evpn();
4861 if (!bgp)
4862 return CMD_WARNING;
4863
4864 /* check if we need json output */
4865 uj = use_json(argc, argv);
4866 if (uj)
4867 json = json_object_new_object();
4868
4869 if (!argv_find(argv, argc, "evpn", &idx))
4870 return CMD_WARNING;
4871
4872 vtep_ip.s_addr = 0;
4873
4874 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4875
4876 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4877 return CMD_WARNING;
4878
4879 if (argv_find(argv, argc, "vtep", &vtep_idx)) {
4880 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
4881 vty_out(vty, "%% Malformed VTEP IP address\n");
4882 return CMD_WARNING;
4883 }
4884 }
4885
4886 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
4887
4888 if (uj)
4889 vty_json(vty, json);
4890
4891 return CMD_SUCCESS;
4892 }
4893
4894 /*
4895 * Display per-VNI EVPN routing table for specific MACIP.
4896 */
4897 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
4898 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
4899 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
4900 SHOW_STR
4901 BGP_STR
4902 L2VPN_HELP_STR
4903 EVPN_HELP_STR
4904 EVPN_RT_HELP_STR
4905 "VXLAN Network Identifier\n"
4906 "VNI number\n"
4907 "MAC\n"
4908 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4909 "IP\n"
4910 "IP address (IPv4 or IPv6)\n"
4911 JSON_STR)
4912 {
4913 vni_t vni;
4914 struct bgp *bgp;
4915 struct ethaddr mac;
4916 struct ipaddr ip;
4917 int idx = 0;
4918 bool uj = false;
4919 json_object *json = NULL;
4920
4921 bgp = bgp_get_evpn();
4922 if (!bgp)
4923 return CMD_WARNING;
4924
4925 /* check if we need json output */
4926 uj = use_json(argc, argv);
4927 if (uj)
4928 json = json_object_new_object();
4929
4930 if (!argv_find(argv, argc, "evpn", &idx))
4931 return CMD_WARNING;
4932
4933 /* get the VNI */
4934 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4935
4936 /* get the mac */
4937 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
4938 vty_out(vty, "%% Malformed MAC address\n");
4939 return CMD_WARNING;
4940 }
4941
4942 /* get the ip */
4943 memset(&ip, 0, sizeof(ip));
4944 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
4945 || (uj
4946 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
4947 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
4948 vty_out(vty, "%% Malformed IP address\n");
4949 return CMD_WARNING;
4950 }
4951 }
4952
4953 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
4954
4955 if (uj)
4956 vty_json(vty, json);
4957
4958 return CMD_SUCCESS;
4959 }
4960
4961 /*
4962 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4963 */
4964 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
4965 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
4966 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
4967 SHOW_STR
4968 BGP_STR
4969 L2VPN_HELP_STR
4970 EVPN_HELP_STR
4971 EVPN_RT_HELP_STR
4972 "VXLAN Network Identifier\n"
4973 "VNI number\n"
4974 EVPN_TYPE_3_HELP_STR
4975 "Originating Router IP address\n"
4976 JSON_STR)
4977 {
4978 vni_t vni;
4979 struct bgp *bgp;
4980 int ret;
4981 struct in_addr orig_ip;
4982 int idx = 0;
4983 bool uj = false;
4984 json_object *json = NULL;
4985
4986 bgp = bgp_get_evpn();
4987 if (!bgp)
4988 return CMD_WARNING;
4989
4990 /* check if we need json output */
4991 uj = use_json(argc, argv);
4992 if (uj)
4993 json = json_object_new_object();
4994
4995 if (!argv_find(argv, argc, "evpn", &idx))
4996 return CMD_WARNING;
4997
4998 /* get the VNI */
4999 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5000
5001 /* get the ip */
5002 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
5003 if (!ret) {
5004 vty_out(vty, "%% Malformed Originating Router IP address\n");
5005 return CMD_WARNING;
5006 }
5007
5008 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5009
5010 if (uj)
5011 vty_json(vty, json);
5012
5013 return CMD_SUCCESS;
5014 }
5015
5016 /*
5017 * Display per-VNI EVPN routing table - for all VNIs.
5018 */
5019 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5020 show_bgp_l2vpn_evpn_route_vni_all_cmd,
5021 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5022 SHOW_STR
5023 BGP_STR
5024 L2VPN_HELP_STR
5025 EVPN_HELP_STR
5026 EVPN_RT_HELP_STR
5027 "VXLAN Network Identifier\n"
5028 "All VNIs\n"
5029 "Print Detailed Output\n"
5030 "Remote VTEP\n"
5031 "Remote VTEP IP address\n"
5032 JSON_STR)
5033 {
5034 struct bgp *bgp;
5035 struct in_addr vtep_ip;
5036 int idx = 0;
5037 bool uj = false;
5038 json_object *json = NULL;
5039 /* Detail Adjust. Adjust indexes according to detail option */
5040 int da = 0;
5041
5042 bgp = bgp_get_evpn();
5043 if (!bgp)
5044 return CMD_WARNING;
5045
5046 /* check if we need json output */
5047 uj = use_json(argc, argv);
5048 if (uj)
5049 json = json_object_new_object();
5050
5051 if (!argv_find(argv, argc, "evpn", &idx))
5052 return CMD_WARNING;
5053
5054 if (argv_find(argv, argc, "detail", &da))
5055 da = 1;
5056
5057 /* vtep-ip position depends on detail option */
5058 vtep_ip.s_addr = 0;
5059 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5060 || (uj
5061 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5062 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
5063 vty_out(vty, "%% Malformed VTEP IP address\n");
5064 return CMD_WARNING;
5065 }
5066 }
5067
5068 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da);
5069
5070 if (uj)
5071 vty_json(vty, json);
5072
5073 return CMD_SUCCESS;
5074 }
5075
5076 DEFPY_HIDDEN(
5077 show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5078 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5079 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5080 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5081 "EVPN route information\n"
5082 "MAC IP routes in the EVI tables linked to the ES\n"
5083 "ES ID\n"
5084 "Detailed information\n" JSON_STR)
5085 {
5086 esi_t esi;
5087 esi_t *esi_p;
5088 json_object *json = NULL;
5089
5090 if (esi_str) {
5091 if (!str_to_esi(esi_str, &esi)) {
5092 vty_out(vty, "%% Malformed ESI\n");
5093 return CMD_WARNING;
5094 }
5095 esi_p = &esi;
5096 } else {
5097 esi_p = NULL;
5098 }
5099
5100 if (uj)
5101 json = json_object_new_object();
5102 bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
5103 if (uj)
5104 vty_json(vty, json);
5105
5106 return CMD_SUCCESS;
5107 }
5108
5109 DEFPY_HIDDEN(
5110 show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5111 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5112 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5113 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5114 "EVPN route information\n"
5115 "MAC IP routes in the global table linked to the ES\n"
5116 "ES ID\n"
5117 "Detailed information\n" JSON_STR)
5118 {
5119 esi_t esi;
5120 esi_t *esi_p;
5121 json_object *json = NULL;
5122
5123 if (esi_str) {
5124 if (!str_to_esi(esi_str, &esi)) {
5125 vty_out(vty, "%% Malformed ESI\n");
5126 return CMD_WARNING;
5127 }
5128 esi_p = &esi;
5129 } else {
5130 esi_p = NULL;
5131 }
5132
5133 if (uj)
5134 json = json_object_new_object();
5135 bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
5136 if (uj)
5137 vty_json(vty, json);
5138
5139 return CMD_SUCCESS;
5140 }
5141
5142 /*
5143 * Display EVPN import route-target hash table
5144 */
5145 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5146 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5147 "show bgp l2vpn evpn vrf-import-rt [json]",
5148 SHOW_STR
5149 BGP_STR
5150 L2VPN_HELP_STR
5151 EVPN_HELP_STR
5152 "Show vrf import route target\n"
5153 JSON_STR)
5154 {
5155 bool uj = false;
5156 struct bgp *bgp_evpn = NULL;
5157 json_object *json = NULL;
5158
5159 bgp_evpn = bgp_get_evpn();
5160 if (!bgp_evpn)
5161 return CMD_WARNING;
5162
5163 uj = use_json(argc, argv);
5164 if (uj)
5165 json = json_object_new_object();
5166
5167 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
5168
5169 if (uj)
5170 vty_json(vty, json);
5171
5172 return CMD_SUCCESS;
5173 }
5174
5175 /*
5176 * Display EVPN import route-target hash table
5177 */
5178 DEFUN(show_bgp_l2vpn_evpn_import_rt,
5179 show_bgp_l2vpn_evpn_import_rt_cmd,
5180 "show bgp l2vpn evpn import-rt [json]",
5181 SHOW_STR
5182 BGP_STR
5183 L2VPN_HELP_STR
5184 EVPN_HELP_STR
5185 "Show import route target\n"
5186 JSON_STR)
5187 {
5188 struct bgp *bgp;
5189 bool uj = false;
5190 json_object *json = NULL;
5191
5192 bgp = bgp_get_evpn();
5193 if (!bgp)
5194 return CMD_WARNING;
5195
5196 uj = use_json(argc, argv);
5197 if (uj)
5198 json = json_object_new_object();
5199
5200 evpn_show_import_rts(vty, bgp, json);
5201
5202 if (uj)
5203 vty_json(vty, json);
5204
5205 return CMD_SUCCESS;
5206 }
5207
5208 DEFPY_HIDDEN(test_es_add,
5209 test_es_add_cmd,
5210 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5211 NO_STR
5212 "Test\n"
5213 "Ethernet-segment\n"
5214 "Ethernet-Segment Identifier\n"
5215 "ES link state\n"
5216 "up|down\n"
5217 )
5218 {
5219 int ret = 0;
5220 esi_t esi;
5221 struct bgp *bgp;
5222 struct in_addr vtep_ip;
5223 bool oper_up;
5224
5225 bgp = bgp_get_evpn();
5226 if (!bgp) {
5227 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5228 return CMD_WARNING;
5229 }
5230
5231 if (!str_to_esi(esi_str, &esi)) {
5232 vty_out(vty, "%% Malformed ESI\n");
5233 return CMD_WARNING;
5234 }
5235
5236 if (no) {
5237 ret = bgp_evpn_local_es_del(bgp, &esi);
5238 if (ret == -1) {
5239 vty_out(vty, "%% Failed to delete ES\n");
5240 return CMD_WARNING;
5241 }
5242 } else {
5243 if (state_str && !strcmp(state_str, "up"))
5244 oper_up = true;
5245 else
5246 oper_up = false;
5247 vtep_ip = bgp->router_id;
5248
5249 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
5250 EVPN_MH_DF_PREF_MIN, false);
5251 if (ret == -1) {
5252 vty_out(vty, "%% Failed to add ES\n");
5253 return CMD_WARNING;
5254 }
5255 }
5256 return CMD_SUCCESS;
5257 }
5258
5259 DEFPY_HIDDEN(test_es_vni_add,
5260 test_es_vni_add_cmd,
5261 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5262 NO_STR
5263 "Test\n"
5264 "Ethernet-segment\n"
5265 "Ethernet-Segment Identifier\n"
5266 "VNI\n"
5267 "1-16777215\n"
5268 )
5269 {
5270 int ret = 0;
5271 esi_t esi;
5272 struct bgp *bgp;
5273
5274 bgp = bgp_get_evpn();
5275 if (!bgp) {
5276 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5277 return CMD_WARNING;
5278 }
5279
5280 if (!str_to_esi(esi_str, &esi)) {
5281 vty_out(vty, "%% Malformed ESI\n");
5282 return CMD_WARNING;
5283 }
5284
5285 if (no) {
5286 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5287 if (ret == -1) {
5288 vty_out(vty, "%% Failed to deref ES VNI\n");
5289 return CMD_WARNING;
5290 }
5291 } else {
5292 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5293 if (ret == -1) {
5294 vty_out(vty, "%% Failed to ref ES VNI\n");
5295 return CMD_WARNING;
5296 }
5297 }
5298 return CMD_SUCCESS;
5299 }
5300
5301 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
5302 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5303 "Show VNI\n"
5304 "VNI number\n")
5305
5306 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5307 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5308 "Summary of BGP neighbor status\n" JSON_STR)
5309
5310 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
5311 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5312 SHOW_STR BGP_STR EVPN_HELP_STR
5313 EVPN_RT_HELP_STR
5314 "Display Detailed Information\n"
5315 EVPN_TYPE_HELP_STR
5316 EVPN_TYPE_2_HELP_STR
5317 EVPN_TYPE_2_HELP_STR
5318 EVPN_TYPE_3_HELP_STR
5319 EVPN_TYPE_3_HELP_STR)
5320
5321 ALIAS_HIDDEN(
5322 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
5323 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5324 SHOW_STR BGP_STR EVPN_HELP_STR
5325 EVPN_RT_HELP_STR
5326 EVPN_RT_DIST_HELP_STR
5327 EVPN_ASN_IP_HELP_STR
5328 EVPN_TYPE_HELP_STR
5329 EVPN_TYPE_2_HELP_STR
5330 EVPN_TYPE_2_HELP_STR
5331 EVPN_TYPE_3_HELP_STR
5332 EVPN_TYPE_3_HELP_STR)
5333
5334 ALIAS_HIDDEN(
5335 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
5336 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5337 SHOW_STR BGP_STR EVPN_HELP_STR
5338 EVPN_RT_HELP_STR
5339 EVPN_RT_DIST_HELP_STR
5340 EVPN_ASN_IP_HELP_STR
5341 "MAC\n"
5342 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5343 "IP\n"
5344 "IP address (IPv4 or IPv6)\n")
5345
5346 ALIAS_HIDDEN(
5347 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
5348 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5349 SHOW_STR BGP_STR EVPN_HELP_STR
5350 EVPN_RT_HELP_STR
5351 "VXLAN Network Identifier\n"
5352 "VNI number\n"
5353 EVPN_TYPE_HELP_STR
5354 EVPN_TYPE_2_HELP_STR
5355 EVPN_TYPE_2_HELP_STR
5356 EVPN_TYPE_3_HELP_STR
5357 EVPN_TYPE_3_HELP_STR
5358 "Remote VTEP\n"
5359 "Remote VTEP IP address\n")
5360
5361 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
5362 show_bgp_evpn_route_vni_macip_cmd,
5363 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
5364 SHOW_STR BGP_STR EVPN_HELP_STR
5365 EVPN_RT_HELP_STR
5366 "VXLAN Network Identifier\n"
5367 "VNI number\n"
5368 "MAC\n"
5369 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5370 "IP\n"
5371 "IP address (IPv4 or IPv6)\n")
5372
5373 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
5374 show_bgp_evpn_route_vni_multicast_cmd,
5375 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
5376 SHOW_STR BGP_STR EVPN_HELP_STR
5377 EVPN_RT_HELP_STR
5378 "VXLAN Network Identifier\n"
5379 "VNI number\n"
5380 EVPN_TYPE_3_HELP_STR
5381 "Originating Router IP address\n")
5382
5383 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
5384 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5385 SHOW_STR BGP_STR EVPN_HELP_STR
5386 EVPN_RT_HELP_STR
5387 "VXLAN Network Identifier\n"
5388 "All VNIs\n"
5389 "Print Detailed Output\n"
5390 "Remote VTEP\n"
5391 "Remote VTEP IP address\n")
5392
5393 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
5394 "show bgp evpn import-rt",
5395 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
5396
5397 DEFUN_NOSH (bgp_evpn_vni,
5398 bgp_evpn_vni_cmd,
5399 "vni " CMD_VNI_RANGE,
5400 "VXLAN Network Identifier\n"
5401 "VNI number\n")
5402 {
5403 vni_t vni;
5404 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5405 struct bgpevpn *vpn;
5406
5407 if (!bgp)
5408 return CMD_WARNING;
5409
5410 vni = strtoul(argv[1]->arg, NULL, 10);
5411
5412 /* Create VNI, or mark as configured. */
5413 vpn = evpn_create_update_vni(bgp, vni);
5414 if (!vpn) {
5415 vty_out(vty, "%% Failed to create VNI \n");
5416 return CMD_WARNING;
5417 }
5418
5419 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
5420 return CMD_SUCCESS;
5421 }
5422
5423 DEFUN (no_bgp_evpn_vni,
5424 no_bgp_evpn_vni_cmd,
5425 "no vni " CMD_VNI_RANGE,
5426 NO_STR
5427 "VXLAN Network Identifier\n"
5428 "VNI number\n")
5429 {
5430 vni_t vni;
5431 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5432 struct bgpevpn *vpn;
5433
5434 if (!bgp)
5435 return CMD_WARNING;
5436
5437 vni = strtoul(argv[2]->arg, NULL, 10);
5438
5439 /* Check if we should disallow. */
5440 vpn = bgp_evpn_lookup_vni(bgp, vni);
5441 if (!vpn) {
5442 vty_out(vty, "%% Specified VNI does not exist\n");
5443 return CMD_WARNING;
5444 }
5445 if (!is_vni_configured(vpn)) {
5446 vty_out(vty, "%% Specified VNI is not configured\n");
5447 return CMD_WARNING;
5448 }
5449
5450 evpn_delete_vni(bgp, vpn);
5451 return CMD_SUCCESS;
5452 }
5453
5454 DEFUN_NOSH (exit_vni,
5455 exit_vni_cmd,
5456 "exit-vni",
5457 "Exit from VNI mode\n")
5458 {
5459 if (vty->node == BGP_EVPN_VNI_NODE)
5460 vty->node = BGP_EVPN_NODE;
5461 return CMD_SUCCESS;
5462 }
5463
5464 DEFUN (bgp_evpn_vrf_rd,
5465 bgp_evpn_vrf_rd_cmd,
5466 "rd ASN:NN_OR_IP-ADDRESS:NN",
5467 EVPN_RT_DIST_HELP_STR
5468 EVPN_ASN_IP_HELP_STR)
5469 {
5470 int ret;
5471 struct prefix_rd prd;
5472 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
5473
5474 if (!bgp_vrf)
5475 return CMD_WARNING;
5476
5477 ret = str2prefix_rd(argv[1]->arg, &prd);
5478 if (!ret) {
5479 vty_out(vty, "%% Malformed Route Distinguisher\n");
5480 return CMD_WARNING;
5481 }
5482
5483 /* If same as existing value, there is nothing more to do. */
5484 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
5485 return CMD_SUCCESS;
5486
5487 /* Configure or update the RD. */
5488 evpn_configure_vrf_rd(bgp_vrf, &prd);
5489 return CMD_SUCCESS;
5490 }
5491
5492 DEFUN (no_bgp_evpn_vrf_rd,
5493 no_bgp_evpn_vrf_rd_cmd,
5494 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5495 NO_STR
5496 EVPN_RT_DIST_HELP_STR
5497 EVPN_ASN_IP_HELP_STR)
5498 {
5499 int ret;
5500 struct prefix_rd prd;
5501 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
5502
5503 if (!bgp_vrf)
5504 return CMD_WARNING;
5505
5506 ret = str2prefix_rd(argv[2]->arg, &prd);
5507 if (!ret) {
5508 vty_out(vty, "%% Malformed Route Distinguisher\n");
5509 return CMD_WARNING;
5510 }
5511
5512 /* Check if we should disallow. */
5513 if (!is_vrf_rd_configured(bgp_vrf)) {
5514 vty_out(vty, "%% RD is not configured for this VRF\n");
5515 return CMD_WARNING;
5516 }
5517
5518 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
5519 vty_out(vty,
5520 "%% RD specified does not match configuration for this VRF\n");
5521 return CMD_WARNING;
5522 }
5523
5524 evpn_unconfigure_vrf_rd(bgp_vrf);
5525 return CMD_SUCCESS;
5526 }
5527
5528 DEFUN (no_bgp_evpn_vrf_rd_without_val,
5529 no_bgp_evpn_vrf_rd_without_val_cmd,
5530 "no rd",
5531 NO_STR
5532 EVPN_RT_DIST_HELP_STR)
5533 {
5534 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
5535
5536 if (!bgp_vrf)
5537 return CMD_WARNING;
5538
5539 /* Check if we should disallow. */
5540 if (!is_vrf_rd_configured(bgp_vrf)) {
5541 vty_out(vty, "%% RD is not configured for this VRF\n");
5542 return CMD_WARNING;
5543 }
5544
5545 evpn_unconfigure_vrf_rd(bgp_vrf);
5546 return CMD_SUCCESS;
5547 }
5548
5549 DEFUN (bgp_evpn_vni_rd,
5550 bgp_evpn_vni_rd_cmd,
5551 "rd ASN:NN_OR_IP-ADDRESS:NN",
5552 EVPN_RT_DIST_HELP_STR
5553 EVPN_ASN_IP_HELP_STR)
5554 {
5555 struct prefix_rd prd;
5556 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5557 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5558 int ret;
5559
5560 if (!bgp)
5561 return CMD_WARNING;
5562
5563 if (!EVPN_ENABLED(bgp)) {
5564 vty_out(vty,
5565 "This command is only supported under EVPN VRF\n");
5566 return CMD_WARNING;
5567 }
5568
5569 ret = str2prefix_rd(argv[1]->arg, &prd);
5570 if (!ret) {
5571 vty_out(vty, "%% Malformed Route Distinguisher\n");
5572 return CMD_WARNING;
5573 }
5574
5575 /* If same as existing value, there is nothing more to do. */
5576 if (bgp_evpn_rd_matches_existing(vpn, &prd))
5577 return CMD_SUCCESS;
5578
5579 /* Configure or update the RD. */
5580 evpn_configure_rd(bgp, vpn, &prd);
5581 return CMD_SUCCESS;
5582 }
5583
5584 DEFUN (no_bgp_evpn_vni_rd,
5585 no_bgp_evpn_vni_rd_cmd,
5586 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5587 NO_STR
5588 EVPN_RT_DIST_HELP_STR
5589 EVPN_ASN_IP_HELP_STR)
5590 {
5591 struct prefix_rd prd;
5592 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5593 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5594 int ret;
5595
5596 if (!bgp)
5597 return CMD_WARNING;
5598
5599 if (!EVPN_ENABLED(bgp)) {
5600 vty_out(vty,
5601 "This command is only supported under EVPN VRF\n");
5602 return CMD_WARNING;
5603 }
5604
5605 ret = str2prefix_rd(argv[2]->arg, &prd);
5606 if (!ret) {
5607 vty_out(vty, "%% Malformed Route Distinguisher\n");
5608 return CMD_WARNING;
5609 }
5610
5611 /* Check if we should disallow. */
5612 if (!is_rd_configured(vpn)) {
5613 vty_out(vty, "%% RD is not configured for this VNI\n");
5614 return CMD_WARNING;
5615 }
5616
5617 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
5618 vty_out(vty,
5619 "%% RD specified does not match configuration for this VNI\n");
5620 return CMD_WARNING;
5621 }
5622
5623 evpn_unconfigure_rd(bgp, vpn);
5624 return CMD_SUCCESS;
5625 }
5626
5627 DEFUN (no_bgp_evpn_vni_rd_without_val,
5628 no_bgp_evpn_vni_rd_without_val_cmd,
5629 "no rd",
5630 NO_STR
5631 EVPN_RT_DIST_HELP_STR)
5632 {
5633 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5634 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5635
5636 if (!bgp)
5637 return CMD_WARNING;
5638
5639 if (!EVPN_ENABLED(bgp)) {
5640 vty_out(vty,
5641 "This command is only supported under EVPN VRF\n");
5642 return CMD_WARNING;
5643 }
5644
5645 /* Check if we should disallow. */
5646 if (!is_rd_configured(vpn)) {
5647 vty_out(vty, "%% RD is not configured for this VNI\n");
5648 return CMD_WARNING;
5649 }
5650
5651 evpn_unconfigure_rd(bgp, vpn);
5652 return CMD_SUCCESS;
5653 }
5654
5655 /*
5656 * Loop over all extended-communities in the route-target list rtl and
5657 * return 1 if we find ecomtarget
5658 */
5659 static bool bgp_evpn_rt_matches_existing(struct list *rtl,
5660 struct ecommunity *ecomtarget)
5661 {
5662 struct listnode *node;
5663 struct ecommunity *ecom;
5664
5665 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
5666 if (ecommunity_match(ecom, ecomtarget))
5667 return true;
5668 }
5669
5670 return false;
5671 }
5672
5673 /*
5674 * L3 RT version of above.
5675 */
5676 static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
5677 struct ecommunity *ecomtarget)
5678 {
5679 struct listnode *node;
5680 struct vrf_route_target *l3rt;
5681
5682 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
5683 if (ecommunity_match(l3rt->ecom, ecomtarget))
5684 return true;
5685 }
5686
5687 return false;
5688 }
5689
5690 /* display L3VNI related info for a VRF instance */
5691 DEFUN (show_bgp_vrf_l3vni_info,
5692 show_bgp_vrf_l3vni_info_cmd,
5693 "show bgp vrf VRFNAME vni [json]",
5694 SHOW_STR
5695 BGP_STR
5696 "show bgp vrf\n"
5697 "VRF Name\n"
5698 "L3-VNI\n"
5699 JSON_STR)
5700 {
5701 char buf[ETHER_ADDR_STRLEN];
5702 int idx_vrf = 3;
5703 const char *name = NULL;
5704 struct bgp *bgp = NULL;
5705 struct listnode *node = NULL;
5706 struct bgpevpn *vpn = NULL;
5707 struct vrf_route_target *l3rt;
5708 json_object *json = NULL;
5709 json_object *json_vnis = NULL;
5710 json_object *json_export_rts = NULL;
5711 json_object *json_import_rts = NULL;
5712 bool uj = use_json(argc, argv);
5713
5714 if (uj) {
5715 json = json_object_new_object();
5716 json_vnis = json_object_new_array();
5717 json_export_rts = json_object_new_array();
5718 json_import_rts = json_object_new_array();
5719 }
5720
5721 name = argv[idx_vrf]->arg;
5722 bgp = bgp_lookup_by_name(name);
5723 if (strmatch(name, VRF_DEFAULT_NAME))
5724 bgp = bgp_get_default();
5725
5726 if (!bgp) {
5727 if (!uj)
5728 vty_out(vty, "BGP instance for VRF %s not found\n",
5729 name);
5730 else {
5731 json_object_string_add(json, "warning",
5732 "BGP instance not found");
5733 vty_out(vty, "%s\n", json_object_to_json_string(json));
5734 json_object_free(json);
5735 }
5736 return CMD_WARNING;
5737 }
5738
5739 if (!json) {
5740 vty_out(vty, "BGP VRF: %s\n", name);
5741 vty_out(vty, " Local-Ip: %pI4\n", &bgp->originator_ip);
5742 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
5743 vty_out(vty, " Rmac: %s\n",
5744 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
5745 vty_out(vty, " VNI Filter: %s\n",
5746 CHECK_FLAG(bgp->vrf_flags,
5747 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
5748 ? "prefix-routes-only"
5749 : "none");
5750 vty_out(vty, " L2-VNI List:\n");
5751 vty_out(vty, " ");
5752 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
5753 vty_out(vty, "%u ", vpn->vni);
5754 vty_out(vty, "\n");
5755 vty_out(vty, " Export-RTs:\n");
5756 vty_out(vty, " ");
5757 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
5758 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
5759 vty_out(vty, "\n");
5760 vty_out(vty, " Import-RTs:\n");
5761 vty_out(vty, " ");
5762 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
5763 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
5764 vty_out(vty, "\n");
5765 vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd);
5766 } else {
5767 json_object_string_add(json, "vrf", name);
5768 json_object_string_addf(json, "local-ip", "%pI4",
5769 &bgp->originator_ip);
5770 json_object_int_add(json, "l3vni", bgp->l3vni);
5771 json_object_string_add(
5772 json, "rmac",
5773 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
5774 json_object_string_add(
5775 json, "vniFilter",
5776 CHECK_FLAG(bgp->vrf_flags,
5777 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
5778 ? "prefix-routes-only"
5779 : "none");
5780 /* list of l2vnis */
5781 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
5782 json_object_array_add(json_vnis,
5783 json_object_new_int(vpn->vni));
5784 json_object_object_add(json, "l2vnis", json_vnis);
5785
5786 /* export rts */
5787 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
5788 json_object_array_add(
5789 json_export_rts,
5790 json_object_new_string(
5791 ecommunity_str(l3rt->ecom)));
5792 json_object_object_add(json, "export-rts", json_export_rts);
5793
5794 /* import rts */
5795 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
5796 json_object_array_add(
5797 json_import_rts,
5798 json_object_new_string(
5799 ecommunity_str(l3rt->ecom)));
5800 json_object_object_add(json, "import-rts", json_import_rts);
5801 json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
5802 }
5803
5804 if (uj)
5805 vty_json(vty, json);
5806 return CMD_SUCCESS;
5807 }
5808
5809 static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
5810 bool is_wildcard)
5811 {
5812 /* Do nothing if we already have this route-target */
5813 if (is_import) {
5814 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
5815 ecom))
5816 bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
5817 is_wildcard);
5818 else
5819 return -1;
5820 } else {
5821 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
5822 ecom))
5823 bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
5824 else
5825 return -1;
5826 }
5827
5828 return 0;
5829 }
5830
5831 static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
5832 {
5833 /* Verify we already have this route-target */
5834 if (is_import) {
5835 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
5836 ecom))
5837 return -1;
5838
5839 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
5840 } else {
5841 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
5842 ecom))
5843 return -1;
5844
5845 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
5846 }
5847
5848 return 0;
5849 }
5850
5851 static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
5852 struct cmd_token **argv, int rt_idx, bool is_add,
5853 bool is_import)
5854 {
5855 int ret = CMD_SUCCESS;
5856 bool is_wildcard = false;
5857 struct ecommunity *ecom = NULL;
5858
5859 for (int i = rt_idx; i < argc; i++) {
5860 is_wildcard = false;
5861
5862 /*
5863 * Special handling for wildcard '*' here.
5864 *
5865 * Let's just convert it to 0 here so we dont have to modify
5866 * the ecommunity parser.
5867 */
5868 if ((argv[i]->arg)[0] == '*') {
5869 (argv[i]->arg)[0] = '0';
5870 is_wildcard = true;
5871 }
5872
5873 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
5874 0);
5875
5876 /* Put it back as was */
5877 if (is_wildcard)
5878 (argv[i]->arg)[0] = '*';
5879
5880 if (!ecom) {
5881 vty_out(vty, "%% Malformed Route Target list\n");
5882 ret = CMD_WARNING;
5883 continue;
5884 }
5885
5886 ecommunity_str(ecom);
5887
5888 if (is_add) {
5889 if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
5890 vty_out(vty,
5891 "%% RT specified already configured for this VRF: %s\n",
5892 argv[i]->arg);
5893 ecommunity_free(&ecom);
5894 ret = CMD_WARNING;
5895 }
5896
5897 } else {
5898 if (del_rt(bgp, ecom, is_import) != 0) {
5899 vty_out(vty,
5900 "%% RT specified does not match configuration for this VRF: %s\n",
5901 argv[i]->arg);
5902 ret = CMD_WARNING;
5903 }
5904
5905 ecommunity_free(&ecom);
5906 }
5907 }
5908
5909 return ret;
5910 }
5911
5912 /* import/export rt for l3vni-vrf */
5913 DEFUN (bgp_evpn_vrf_rt,
5914 bgp_evpn_vrf_rt_cmd,
5915 "route-target <both|import|export> RTLIST...",
5916 "Route Target\n"
5917 "import and export\n"
5918 "import\n"
5919 "export\n"
5920 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
5921 {
5922 int ret = CMD_SUCCESS;
5923 int tmp_ret = CMD_SUCCESS;
5924 int rt_type;
5925 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5926
5927 if (!bgp)
5928 return CMD_WARNING_CONFIG_FAILED;
5929
5930 if (!strcmp(argv[1]->arg, "import"))
5931 rt_type = RT_TYPE_IMPORT;
5932 else if (!strcmp(argv[1]->arg, "export"))
5933 rt_type = RT_TYPE_EXPORT;
5934 else if (!strcmp(argv[1]->arg, "both"))
5935 rt_type = RT_TYPE_BOTH;
5936 else {
5937 vty_out(vty, "%% Invalid Route Target type\n");
5938 return CMD_WARNING_CONFIG_FAILED;
5939 }
5940
5941 if (strmatch(argv[2]->arg, "auto")) {
5942 vty_out(vty, "%% `auto` cannot be configured via list\n");
5943 return CMD_WARNING_CONFIG_FAILED;
5944 }
5945
5946 if (rt_type != RT_TYPE_IMPORT) {
5947 for (int i = 2; i < argc; i++) {
5948 if ((argv[i]->arg)[0] == '*') {
5949 vty_out(vty,
5950 "%% Wildcard '*' only applicable for import\n");
5951 return CMD_WARNING_CONFIG_FAILED;
5952 }
5953 }
5954 }
5955
5956 /* Add/update the import route-target */
5957 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
5958 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
5959
5960 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
5961 ret = tmp_ret;
5962
5963 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
5964 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
5965
5966 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
5967 ret = tmp_ret;
5968
5969 return ret;
5970 }
5971
5972 DEFPY (bgp_evpn_vrf_rt_auto,
5973 bgp_evpn_vrf_rt_auto_cmd,
5974 "route-target <both|import|export>$type auto",
5975 "Route Target\n"
5976 "import and export\n"
5977 "import\n"
5978 "export\n"
5979 "Automatically derive route target\n")
5980 {
5981 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5982 int rt_type;
5983
5984 if (!bgp)
5985 return CMD_WARNING_CONFIG_FAILED;
5986
5987 if (strmatch(type, "import"))
5988 rt_type = RT_TYPE_IMPORT;
5989 else if (strmatch(type, "export"))
5990 rt_type = RT_TYPE_EXPORT;
5991 else if (strmatch(type, "both"))
5992 rt_type = RT_TYPE_BOTH;
5993 else {
5994 vty_out(vty, "%% Invalid Route Target type\n");
5995 return CMD_WARNING_CONFIG_FAILED;
5996 }
5997
5998 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
5999 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6000
6001 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6002 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6003
6004 return CMD_SUCCESS;
6005 }
6006
6007 DEFUN (no_bgp_evpn_vrf_rt,
6008 no_bgp_evpn_vrf_rt_cmd,
6009 "no route-target <both|import|export> RTLIST...",
6010 NO_STR
6011 "Route Target\n"
6012 "import and export\n"
6013 "import\n"
6014 "export\n"
6015 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6016 {
6017 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6018 int ret = CMD_SUCCESS;
6019 int tmp_ret = CMD_SUCCESS;
6020 int rt_type;
6021
6022 if (!bgp)
6023 return CMD_WARNING_CONFIG_FAILED;
6024
6025 if (!strcmp(argv[2]->arg, "import"))
6026 rt_type = RT_TYPE_IMPORT;
6027 else if (!strcmp(argv[2]->arg, "export"))
6028 rt_type = RT_TYPE_EXPORT;
6029 else if (!strcmp(argv[2]->arg, "both"))
6030 rt_type = RT_TYPE_BOTH;
6031 else {
6032 vty_out(vty, "%% Invalid Route Target type\n");
6033 return CMD_WARNING_CONFIG_FAILED;
6034 }
6035
6036 if (!strcmp(argv[3]->arg, "auto")) {
6037 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6038 return CMD_WARNING_CONFIG_FAILED;
6039 }
6040
6041 if (rt_type == RT_TYPE_IMPORT) {
6042 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6043 vty_out(vty,
6044 "%% Import RT is not configured for this VRF\n");
6045 return CMD_WARNING_CONFIG_FAILED;
6046 }
6047 } else if (rt_type == RT_TYPE_EXPORT) {
6048 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6049 vty_out(vty,
6050 "%% Export RT is not configured for this VRF\n");
6051 return CMD_WARNING_CONFIG_FAILED;
6052 }
6053 } else if (rt_type == RT_TYPE_BOTH) {
6054 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6055 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6056 vty_out(vty,
6057 "%% Import/Export RT is not configured for this VRF\n");
6058 return CMD_WARNING_CONFIG_FAILED;
6059 }
6060 }
6061
6062 if (rt_type != RT_TYPE_IMPORT) {
6063 for (int i = 3; i < argc; i++) {
6064 if ((argv[i]->arg)[0] == '*') {
6065 vty_out(vty,
6066 "%% Wildcard '*' only applicable for import\n");
6067 return CMD_WARNING_CONFIG_FAILED;
6068 }
6069 }
6070 }
6071
6072 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6073 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
6074
6075 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6076 ret = tmp_ret;
6077
6078 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6079 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
6080
6081 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6082 ret = tmp_ret;
6083
6084 return ret;
6085 }
6086
6087 DEFPY (no_bgp_evpn_vrf_rt_auto,
6088 no_bgp_evpn_vrf_rt_auto_cmd,
6089 "no route-target <both|import|export>$type auto",
6090 NO_STR
6091 "Route Target\n"
6092 "import and export\n"
6093 "import\n"
6094 "export\n"
6095 "Automatically derive route target\n")
6096 {
6097 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6098 int rt_type;
6099
6100 if (!bgp)
6101 return CMD_WARNING_CONFIG_FAILED;
6102
6103 if (strmatch(type, "import"))
6104 rt_type = RT_TYPE_IMPORT;
6105 else if (strmatch(type, "export"))
6106 rt_type = RT_TYPE_EXPORT;
6107 else if (strmatch(type, "both"))
6108 rt_type = RT_TYPE_BOTH;
6109 else {
6110 vty_out(vty, "%% Invalid Route Target type\n");
6111 return CMD_WARNING_CONFIG_FAILED;
6112 }
6113
6114 if (rt_type == RT_TYPE_IMPORT) {
6115 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
6116 vty_out(vty,
6117 "%% Import AUTO RT is not configured for this VRF\n");
6118 return CMD_WARNING_CONFIG_FAILED;
6119 }
6120 } else if (rt_type == RT_TYPE_EXPORT) {
6121 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6122 vty_out(vty,
6123 "%% Export AUTO RT is not configured for this VRF\n");
6124 return CMD_WARNING_CONFIG_FAILED;
6125 }
6126 } else if (rt_type == RT_TYPE_BOTH) {
6127 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6128 !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6129 vty_out(vty,
6130 "%% Import/Export AUTO RT is not configured for this VRF\n");
6131 return CMD_WARNING_CONFIG_FAILED;
6132 }
6133 }
6134
6135 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6136 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6137
6138 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6139 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6140
6141 return CMD_SUCCESS;
6142 }
6143
6144 DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6145 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6146 NO_STR
6147 "EAD ES fragment config\n"
6148 "EVIs per-fragment\n"
6149 "limit\n")
6150 {
6151 bgp_mh_info->evi_per_es_frag =
6152 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6153
6154 return CMD_SUCCESS;
6155 }
6156
6157 DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6158 "ead-es-route-target export RT",
6159 "EAD ES Route Target\n"
6160 "export\n"
6161 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6162 {
6163 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6164 struct ecommunity *ecomadd = NULL;
6165
6166 if (!bgp)
6167 return CMD_WARNING;
6168
6169 if (!EVPN_ENABLED(bgp)) {
6170 vty_out(vty, "This command is only supported under EVPN VRF\n");
6171 return CMD_WARNING;
6172 }
6173
6174 /* Add/update the export route-target */
6175 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6176 if (!ecomadd) {
6177 vty_out(vty, "%% Malformed Route Target list\n");
6178 return CMD_WARNING;
6179 }
6180 ecommunity_str(ecomadd);
6181
6182 /* Do nothing if we already have this export route-target */
6183 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6184 ecomadd))
6185 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6186
6187 return CMD_SUCCESS;
6188 }
6189
6190 DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6191 "no ead-es-route-target export RT",
6192 NO_STR
6193 "EAD ES Route Target\n"
6194 "export\n" EVPN_ASN_IP_HELP_STR)
6195 {
6196 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6197 struct ecommunity *ecomdel = NULL;
6198
6199 if (!bgp)
6200 return CMD_WARNING;
6201
6202 if (!EVPN_ENABLED(bgp)) {
6203 vty_out(vty, "This command is only supported under EVPN VRF\n");
6204 return CMD_WARNING;
6205 }
6206
6207 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6208 if (!ecomdel) {
6209 vty_out(vty, "%% Malformed Route Target list\n");
6210 return CMD_WARNING;
6211 }
6212 ecommunity_str(ecomdel);
6213
6214 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6215 ecomdel)) {
6216 ecommunity_free(&ecomdel);
6217 vty_out(vty,
6218 "%% RT specified does not match EAD-ES RT configuration\n");
6219 return CMD_WARNING;
6220 }
6221 bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6222
6223 return CMD_SUCCESS;
6224 }
6225
6226 DEFUN (bgp_evpn_vni_rt,
6227 bgp_evpn_vni_rt_cmd,
6228 "route-target <both|import|export> RT",
6229 "Route Target\n"
6230 "import and export\n"
6231 "import\n"
6232 "export\n"
6233 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6234 {
6235 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6236 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6237 int rt_type;
6238 struct ecommunity *ecomadd = NULL;
6239
6240 if (!bgp)
6241 return CMD_WARNING;
6242
6243 if (!EVPN_ENABLED(bgp)) {
6244 vty_out(vty,
6245 "This command is only supported under EVPN VRF\n");
6246 return CMD_WARNING;
6247 }
6248
6249 if (!strcmp(argv[1]->text, "import"))
6250 rt_type = RT_TYPE_IMPORT;
6251 else if (!strcmp(argv[1]->text, "export"))
6252 rt_type = RT_TYPE_EXPORT;
6253 else if (!strcmp(argv[1]->text, "both"))
6254 rt_type = RT_TYPE_BOTH;
6255 else {
6256 vty_out(vty, "%% Invalid Route Target type\n");
6257 return CMD_WARNING;
6258 }
6259
6260 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6261 if (!ecomadd) {
6262 vty_out(vty, "%% Malformed Route Target list\n");
6263 return CMD_WARNING;
6264 }
6265 ecommunity_str(ecomadd);
6266
6267 /* Add/update the import route-target */
6268 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
6269 /* Do nothing if we already have this import route-target */
6270 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6271 evpn_configure_import_rt(bgp, vpn, ecomadd);
6272 }
6273
6274 /* Add/update the export route-target */
6275 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
6276 /* Do nothing if we already have this export route-target */
6277 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6278 evpn_configure_export_rt(bgp, vpn, ecomadd);
6279 }
6280
6281 return CMD_SUCCESS;
6282 }
6283
6284 DEFUN (no_bgp_evpn_vni_rt,
6285 no_bgp_evpn_vni_rt_cmd,
6286 "no route-target <both|import|export> RT",
6287 NO_STR
6288 "Route Target\n"
6289 "import and export\n"
6290 "import\n"
6291 "export\n"
6292 EVPN_ASN_IP_HELP_STR)
6293 {
6294 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6295 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6296 int rt_type, found_ecomdel;
6297 struct ecommunity *ecomdel = NULL;
6298
6299 if (!bgp)
6300 return CMD_WARNING;
6301
6302 if (!EVPN_ENABLED(bgp)) {
6303 vty_out(vty,
6304 "This command is only supported under EVPN VRF\n");
6305 return CMD_WARNING;
6306 }
6307
6308 if (!strcmp(argv[2]->text, "import"))
6309 rt_type = RT_TYPE_IMPORT;
6310 else if (!strcmp(argv[2]->text, "export"))
6311 rt_type = RT_TYPE_EXPORT;
6312 else if (!strcmp(argv[2]->text, "both"))
6313 rt_type = RT_TYPE_BOTH;
6314 else {
6315 vty_out(vty, "%% Invalid Route Target type\n");
6316 return CMD_WARNING;
6317 }
6318
6319 /* The user did "no route-target import", check to see if there are any
6320 * import route-targets configured. */
6321 if (rt_type == RT_TYPE_IMPORT) {
6322 if (!is_import_rt_configured(vpn)) {
6323 vty_out(vty,
6324 "%% Import RT is not configured for this VNI\n");
6325 return CMD_WARNING;
6326 }
6327 } else if (rt_type == RT_TYPE_EXPORT) {
6328 if (!is_export_rt_configured(vpn)) {
6329 vty_out(vty,
6330 "%% Export RT is not configured for this VNI\n");
6331 return CMD_WARNING;
6332 }
6333 } else if (rt_type == RT_TYPE_BOTH) {
6334 if (!is_import_rt_configured(vpn)
6335 && !is_export_rt_configured(vpn)) {
6336 vty_out(vty,
6337 "%% Import/Export RT is not configured for this VNI\n");
6338 return CMD_WARNING;
6339 }
6340 }
6341
6342 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6343 if (!ecomdel) {
6344 vty_out(vty, "%% Malformed Route Target list\n");
6345 return CMD_WARNING;
6346 }
6347 ecommunity_str(ecomdel);
6348
6349 if (rt_type == RT_TYPE_IMPORT) {
6350 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
6351 ecommunity_free(&ecomdel);
6352 vty_out(vty,
6353 "%% RT specified does not match configuration for this VNI\n");
6354 return CMD_WARNING;
6355 }
6356 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
6357 } else if (rt_type == RT_TYPE_EXPORT) {
6358 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
6359 ecommunity_free(&ecomdel);
6360 vty_out(vty,
6361 "%% RT specified does not match configuration for this VNI\n");
6362 return CMD_WARNING;
6363 }
6364 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
6365 } else if (rt_type == RT_TYPE_BOTH) {
6366 found_ecomdel = 0;
6367
6368 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
6369 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
6370 found_ecomdel = 1;
6371 }
6372
6373 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
6374 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
6375 found_ecomdel = 1;
6376 }
6377
6378 if (!found_ecomdel) {
6379 ecommunity_free(&ecomdel);
6380 vty_out(vty,
6381 "%% RT specified does not match configuration for this VNI\n");
6382 return CMD_WARNING;
6383 }
6384 }
6385
6386 return CMD_SUCCESS;
6387 }
6388
6389 DEFUN (no_bgp_evpn_vni_rt_without_val,
6390 no_bgp_evpn_vni_rt_without_val_cmd,
6391 "no route-target <import|export>",
6392 NO_STR
6393 "Route Target\n"
6394 "import\n"
6395 "export\n")
6396 {
6397 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6398 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6399 int rt_type;
6400
6401 if (!bgp)
6402 return CMD_WARNING;
6403
6404 if (!EVPN_ENABLED(bgp)) {
6405 vty_out(vty,
6406 "This command is only supported under EVPN VRF\n");
6407 return CMD_WARNING;
6408 }
6409
6410 if (!strcmp(argv[2]->text, "import")) {
6411 rt_type = RT_TYPE_IMPORT;
6412 } else if (!strcmp(argv[2]->text, "export")) {
6413 rt_type = RT_TYPE_EXPORT;
6414 } else {
6415 vty_out(vty, "%% Invalid Route Target type\n");
6416 return CMD_WARNING;
6417 }
6418
6419 /* Check if we should disallow. */
6420 if (rt_type == RT_TYPE_IMPORT) {
6421 if (!is_import_rt_configured(vpn)) {
6422 vty_out(vty,
6423 "%% Import RT is not configured for this VNI\n");
6424 return CMD_WARNING;
6425 }
6426 } else {
6427 if (!is_export_rt_configured(vpn)) {
6428 vty_out(vty,
6429 "%% Export RT is not configured for this VNI\n");
6430 return CMD_WARNING;
6431 }
6432 }
6433
6434 /* Unconfigure the RT. */
6435 if (rt_type == RT_TYPE_IMPORT)
6436 evpn_unconfigure_import_rt(bgp, vpn, NULL);
6437 else
6438 evpn_unconfigure_export_rt(bgp, vpn, NULL);
6439 return CMD_SUCCESS;
6440 }
6441
6442 static int vni_cmp(const void **a, const void **b)
6443 {
6444 const struct bgpevpn *first = *a;
6445 const struct bgpevpn *secnd = *b;
6446
6447 return secnd->vni - first->vni;
6448 }
6449
6450 /*
6451 * Output EVPN configuration information.
6452 */
6453 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
6454 safi_t safi)
6455 {
6456 char buf2[INET6_ADDRSTRLEN];
6457
6458 if (bgp->advertise_all_vni)
6459 vty_out(vty, " advertise-all-vni\n");
6460
6461 if (hashcount(bgp->vnihash)) {
6462 struct list *vnilist = hash_to_list(bgp->vnihash);
6463 struct listnode *ln;
6464 struct bgpevpn *data;
6465
6466 list_sort(vnilist, vni_cmp);
6467 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
6468 write_vni_config(vty, data);
6469
6470 list_delete(&vnilist);
6471 }
6472
6473 if (bgp->advertise_autort_rfc8365)
6474 vty_out(vty, " autort rfc8365-compatible\n");
6475
6476 if (bgp->advertise_gw_macip)
6477 vty_out(vty, " advertise-default-gw\n");
6478
6479 if (bgp->evpn_info->advertise_svi_macip)
6480 vty_out(vty, " advertise-svi-ip\n");
6481
6482 if (bgp->resolve_overlay_index)
6483 vty_out(vty, " enable-resolve-overlay-index\n");
6484
6485 if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
6486 vty_out(vty, " ead-es-frag evi-limit %u\n",
6487 bgp_mh_info->evi_per_es_frag);
6488
6489 if (bgp_mh_info->host_routes_use_l3nhg !=
6490 BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
6491 if (bgp_mh_info->host_routes_use_l3nhg)
6492 vty_out(vty, " use-es-l3nhg\n");
6493 else
6494 vty_out(vty, " no use-es-l3nhg\n");
6495 }
6496
6497 if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
6498 if (bgp_mh_info->ead_evi_rx)
6499 vty_out(vty, " no disable-ead-evi-rx\n");
6500 else
6501 vty_out(vty, " disable-ead-evi-rx\n");
6502 }
6503
6504 if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
6505 if (bgp_mh_info->ead_evi_tx)
6506 vty_out(vty, " no disable-ead-evi-tx\n");
6507 else
6508 vty_out(vty, " disable-ead-evi-tx\n");
6509 }
6510
6511 if (!bgp->evpn_info->dup_addr_detect)
6512 vty_out(vty, " no dup-addr-detection\n");
6513
6514 if (bgp->evpn_info->dad_max_moves !=
6515 EVPN_DAD_DEFAULT_MAX_MOVES ||
6516 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
6517 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
6518 bgp->evpn_info->dad_max_moves,
6519 bgp->evpn_info->dad_time);
6520
6521 if (bgp->evpn_info->dad_freeze) {
6522 if (bgp->evpn_info->dad_freeze_time)
6523 vty_out(vty,
6524 " dup-addr-detection freeze %u\n",
6525 bgp->evpn_info->dad_freeze_time);
6526 else
6527 vty_out(vty,
6528 " dup-addr-detection freeze permanent\n");
6529 }
6530
6531 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
6532 vty_out(vty, " flooding disable\n");
6533
6534 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6535 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
6536 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
6537 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
6538 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
6539 else
6540 vty_out(vty,
6541 " advertise ipv4 unicast\n");
6542 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6543 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
6544 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
6545 vty_out(vty,
6546 " advertise ipv4 unicast gateway-ip route-map %s\n",
6547 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
6548 else
6549 vty_out(vty, " advertise ipv4 unicast gateway-ip\n");
6550 }
6551
6552 /* EAD ES export route-target */
6553 if (listcount(bgp_mh_info->ead_es_export_rtl)) {
6554 struct ecommunity *ecom;
6555 char *ecom_str;
6556 struct listnode *node;
6557
6558 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
6559 ecom)) {
6560
6561 ecom_str = ecommunity_ecom2str(
6562 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
6563 vty_out(vty, " ead-es-route-target export %s\n",
6564 ecom_str);
6565 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
6566 }
6567 }
6568
6569 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6570 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
6571 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
6572 vty_out(vty,
6573 " advertise ipv6 unicast route-map %s\n",
6574 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
6575 else
6576 vty_out(vty,
6577 " advertise ipv6 unicast\n");
6578 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6579 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
6580 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
6581 vty_out(vty,
6582 " advertise ipv6 unicast gateway-ip route-map %s\n",
6583 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
6584 else
6585 vty_out(vty, " advertise ipv6 unicast gateway-ip\n");
6586 }
6587
6588 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6589 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
6590 vty_out(vty, " default-originate ipv4\n");
6591
6592 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
6593 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
6594 vty_out(vty, " default-originate ipv6\n");
6595
6596 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
6597 if (!bgp->evpn_info->advertise_pip)
6598 vty_out(vty, " no advertise-pip\n");
6599 if (bgp->evpn_info->advertise_pip) {
6600 if (bgp->evpn_info->pip_ip_static.s_addr
6601 != INADDR_ANY) {
6602 vty_out(vty, " advertise-pip ip %s",
6603 inet_ntop(AF_INET,
6604 &bgp->evpn_info->pip_ip_static,
6605 buf2, INET_ADDRSTRLEN));
6606 if (!is_zero_mac(&(
6607 bgp->evpn_info->pip_rmac_static))) {
6608 char buf[ETHER_ADDR_STRLEN];
6609
6610 vty_out(vty, " mac %s",
6611 prefix_mac2str(
6612 &bgp->evpn_info
6613 ->pip_rmac,
6614 buf, sizeof(buf)));
6615 }
6616 vty_out(vty, "\n");
6617 }
6618 }
6619 }
6620 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
6621 vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
6622
6623 /* import route-target */
6624 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6625 char *ecom_str;
6626 struct listnode *node, *nnode;
6627 struct vrf_route_target *l3rt;
6628
6629 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
6630 l3rt)) {
6631
6632 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
6633 continue;
6634
6635 ecom_str = ecommunity_ecom2str(
6636 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
6637
6638 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
6639 char *vni_str = NULL;
6640
6641 vni_str = strchr(ecom_str, ':');
6642
6643 if (!vni_str)
6644 continue; /* This should never happen */
6645
6646 /* Move pointer to vni */
6647 vni_str += 1;
6648
6649 vty_out(vty, " route-target import *:%s\n",
6650 vni_str);
6651
6652 } else
6653 vty_out(vty, " route-target import %s\n",
6654 ecom_str);
6655
6656 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
6657 }
6658 }
6659
6660 /* import route-target auto */
6661 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
6662 vty_out(vty, " route-target import auto\n");
6663
6664 /* export route-target */
6665 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6666 char *ecom_str;
6667 struct listnode *node, *nnode;
6668 struct vrf_route_target *l3rt;
6669
6670 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
6671 l3rt)) {
6672
6673 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
6674 continue;
6675
6676 ecom_str = ecommunity_ecom2str(
6677 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
6678 vty_out(vty, " route-target export %s\n", ecom_str);
6679 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
6680 }
6681 }
6682
6683 /* export route-target auto */
6684 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
6685 vty_out(vty, " route-target export auto\n");
6686 }
6687
6688 void bgp_ethernetvpn_init(void)
6689 {
6690 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
6691 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
6692 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
6693 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
6694 install_element(VIEW_NODE,
6695 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
6696 install_element(VIEW_NODE,
6697 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
6698 install_element(
6699 VIEW_NODE,
6700 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
6701 install_element(
6702 VIEW_NODE,
6703 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
6704 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
6705 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
6706 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
6707 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
6708 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
6709 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
6710 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
6711 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
6712 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
6713 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
6714 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
6715 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
6716 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
6717 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
6718 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
6719 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
6720 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
6721 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
6722 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
6723 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
6724 install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
6725 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
6726 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
6727 install_element(BGP_EVPN_NODE,
6728 &bgp_evpn_enable_resolve_overlay_index_cmd);
6729
6730 /* test commands */
6731 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
6732 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
6733
6734 /* "show bgp l2vpn evpn" commands. */
6735 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
6736 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
6737 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
6738 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
6739 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
6740 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
6741 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
6742 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
6743 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
6744 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
6745 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
6746 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
6747 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
6748 install_element(VIEW_NODE,
6749 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
6750 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
6751 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
6752 install_element(VIEW_NODE,
6753 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
6754 install_element(VIEW_NODE,
6755 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
6756 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
6757 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
6758
6759 /* "show bgp evpn" commands. */
6760 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
6761 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
6762 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
6763 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
6764 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
6765 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
6766 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
6767 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
6768 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
6769 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
6770 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
6771 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
6772
6773 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
6774 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
6775 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
6776 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
6777 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
6778 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
6779 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
6780 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
6781 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
6782 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
6783 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
6784 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
6785 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
6786 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
6787 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
6788 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
6789 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
6790 install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
6791 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
6792 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
6793 install_element(BGP_EVPN_VNI_NODE,
6794 &bgp_evpn_advertise_default_gw_vni_cmd);
6795 install_element(BGP_EVPN_VNI_NODE,
6796 &no_bgp_evpn_advertise_default_gw_vni_cmd);
6797 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
6798 install_element(BGP_EVPN_VNI_NODE,
6799 &no_bgp_evpn_advertise_vni_subnet_cmd);
6800 }