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