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