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