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