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