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