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