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