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