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