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