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