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