]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
zebra: multiple vlan aware bridge data structure and related changes
[mirror_frr.git] / zebra / zebra_vty.c
1 /* Zebra VTY functions
2 * Copyright (C) 2002 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra 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 * GNU Zebra 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
23 #include "memory.h"
24 #include "if.h"
25 #include "prefix.h"
26 #include "command.h"
27 #include "table.h"
28 #include "rib.h"
29 #include "nexthop.h"
30 #include "vrf.h"
31 #include "linklist.h"
32 #include "mpls.h"
33 #include "routemap.h"
34 #include "srcdest_table.h"
35 #include "vxlan.h"
36 #include "termtable.h"
37
38 #include "zebra/zebra_router.h"
39 #include "zebra/zserv.h"
40 #include "zebra/zebra_vrf.h"
41 #include "zebra/zebra_mpls.h"
42 #include "zebra/zebra_rnh.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/zebra_routemap.h"
45 #include "lib/json.h"
46 #include "lib/route_opaque.h"
47 #include "zebra/zebra_vxlan.h"
48 #include "zebra/zebra_evpn_mh.h"
49 #include "zebra/zebra_vty_clippy.c"
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_pbr.h"
55 #include "zebra/zebra_nhg.h"
56 #include "zebra/zebra_evpn_mh.h"
57 #include "zebra/interface.h"
58 #include "northbound_cli.h"
59 #include "zebra/zebra_nb.h"
60 #include "zebra/kernel_netlink.h"
61 #include "zebra/if_netlink.h"
62 #include "zebra/table_manager.h"
63 #include "zebra/zebra_script.h"
64 #include "zebra/rtadv.h"
65 #include "zebra/zebra_neigh.h"
66
67 /* context to manage dumps in multiple tables or vrfs */
68 struct route_show_ctx {
69 bool multi; /* dump multiple tables or vrf */
70 bool header_done; /* common header already displayed */
71 };
72
73 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
74 safi_t safi, bool use_fib, bool use_json,
75 route_tag_t tag,
76 const struct prefix *longer_prefix_p,
77 bool supernets_only, int type,
78 unsigned short ospf_instance_id, uint32_t tableid,
79 bool show_ng, struct route_show_ctx *ctx);
80 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
81 int mcast, bool use_fib, bool show_ng);
82 static void vty_show_ip_route_summary(struct vty *vty,
83 struct route_table *table, bool use_json);
84 static void vty_show_ip_route_summary_prefix(struct vty *vty,
85 struct route_table *table,
86 bool use_json);
87 /* Helper api to format a nexthop in the 'detailed' output path. */
88 static void show_nexthop_detail_helper(struct vty *vty,
89 const struct route_entry *re,
90 const struct nexthop *nexthop,
91 bool is_backup);
92
93 static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table);
94 static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
95 struct route_entry *re, unsigned int num);
96
97 DEFUN (ip_multicast_mode,
98 ip_multicast_mode_cmd,
99 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
100 IP_STR
101 "Multicast options\n"
102 "RPF lookup behavior\n"
103 "Lookup in unicast RIB only\n"
104 "Lookup in multicast RIB only\n"
105 "Try multicast RIB first, fall back to unicast RIB\n"
106 "Lookup both, use entry with lower distance\n"
107 "Lookup both, use entry with longer prefix\n")
108 {
109 char *mode = argv[3]->text;
110
111 if (strmatch(mode, "urib-only"))
112 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
113 else if (strmatch(mode, "mrib-only"))
114 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
115 else if (strmatch(mode, "mrib-then-urib"))
116 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
117 else if (strmatch(mode, "lower-distance"))
118 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
119 else if (strmatch(mode, "longer-prefix"))
120 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
121 else {
122 vty_out(vty, "Invalid mode specified\n");
123 return CMD_WARNING_CONFIG_FAILED;
124 }
125
126 return CMD_SUCCESS;
127 }
128
129 DEFUN (no_ip_multicast_mode,
130 no_ip_multicast_mode_cmd,
131 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
132 NO_STR
133 IP_STR
134 "Multicast options\n"
135 "RPF lookup behavior\n"
136 "Lookup in unicast RIB only\n"
137 "Lookup in multicast RIB only\n"
138 "Try multicast RIB first, fall back to unicast RIB\n"
139 "Lookup both, use entry with lower distance\n"
140 "Lookup both, use entry with longer prefix\n")
141 {
142 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
143 return CMD_SUCCESS;
144 }
145
146
147 DEFUN (show_ip_rpf,
148 show_ip_rpf_cmd,
149 "show ip rpf [json]",
150 SHOW_STR
151 IP_STR
152 "Display RPF information for multicast source\n"
153 JSON_STR)
154 {
155 bool uj = use_json(argc, argv);
156 struct route_show_ctx ctx = {
157 .multi = false,
158 };
159
160 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
161 false, uj, 0, NULL, false, 0, 0, 0, false,
162 &ctx);
163 }
164
165 DEFUN (show_ip_rpf_addr,
166 show_ip_rpf_addr_cmd,
167 "show ip rpf A.B.C.D",
168 SHOW_STR
169 IP_STR
170 "Display RPF information for multicast source\n"
171 "IP multicast source address (e.g. 10.0.0.0)\n")
172 {
173 int idx_ipv4 = 3;
174 struct in_addr addr;
175 struct route_node *rn;
176 struct route_entry *re;
177 int ret;
178
179 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
180 if (ret == 0) {
181 vty_out(vty, "%% Malformed address\n");
182 return CMD_WARNING;
183 }
184
185 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
186
187 if (re)
188 vty_show_ip_route_detail(vty, rn, 1, false, false);
189 else
190 vty_out(vty, "%% No match for RPF lookup\n");
191
192 return CMD_SUCCESS;
193 }
194
195 static char re_status_output_char(const struct route_entry *re,
196 const struct nexthop *nhop,
197 bool is_fib)
198 {
199 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
200 bool star_p = false;
201
202 if (nhop &&
203 !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
204 !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) {
205 /* More-specific test for 'fib' output */
206 if (is_fib) {
207 star_p = !!CHECK_FLAG(nhop->flags,
208 NEXTHOP_FLAG_FIB);
209 } else
210 star_p = true;
211 }
212
213 if (zrouter.asic_offloaded &&
214 CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
215 return 'q';
216
217 if (zrouter.asic_offloaded
218 && CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED))
219 return 't';
220
221 if (zrouter.asic_offloaded
222 && CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
223 return 'o';
224
225 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OUTOFSYNC))
226 return 'd';
227
228 if (star_p)
229 return '*';
230 else
231 return ' ';
232 }
233
234 if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED)) {
235 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
236 return 'q';
237
238 return 'r';
239 }
240
241 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
242 return 'q';
243
244 return ' ';
245 }
246
247 /*
248 * Show backup nexthop info, in the 'detailed' output path
249 */
250 static void show_nh_backup_helper(struct vty *vty,
251 const struct route_entry *re,
252 const struct nexthop *nexthop)
253 {
254 const struct nexthop *start, *backup, *temp;
255 int i, idx;
256
257 /* Double-check that there _is_ a backup */
258 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
259 re->nhe->backup_info == NULL || re->nhe->backup_info->nhe == NULL ||
260 re->nhe->backup_info->nhe->nhg.nexthop == NULL)
261 return;
262
263 /* Locate the backup nexthop(s) */
264 start = re->nhe->backup_info->nhe->nhg.nexthop;
265 for (i = 0; i < nexthop->backup_num; i++) {
266 /* Format the backup(s) (indented) */
267 backup = start;
268 for (idx = 0; idx < nexthop->backup_idx[i]; idx++) {
269 backup = backup->next;
270 if (backup == NULL)
271 break;
272 }
273
274 /* It's possible for backups to be recursive too,
275 * so walk the recursive resolution list if present.
276 */
277 temp = backup;
278 while (backup) {
279 vty_out(vty, " ");
280 show_nexthop_detail_helper(vty, re, backup,
281 true /*backup*/);
282 vty_out(vty, "\n");
283
284 if (backup->resolved && temp == backup)
285 backup = backup->resolved;
286 else
287 backup = nexthop_next(backup);
288
289 if (backup == temp->next)
290 break;
291 }
292 }
293
294 }
295
296 /*
297 * Helper api to format output for a nexthop, used in the 'detailed'
298 * output path.
299 */
300 static void show_nexthop_detail_helper(struct vty *vty,
301 const struct route_entry *re,
302 const struct nexthop *nexthop,
303 bool is_backup)
304 {
305 char addrstr[32];
306 char buf[MPLS_LABEL_STRLEN];
307 int i;
308
309 if (is_backup)
310 vty_out(vty, " b%s",
311 nexthop->rparent ? " " : "");
312 else
313 vty_out(vty, " %c%s",
314 re_status_output_char(re, nexthop, false),
315 nexthop->rparent ? " " : "");
316
317 switch (nexthop->type) {
318 case NEXTHOP_TYPE_IPV4:
319 case NEXTHOP_TYPE_IPV4_IFINDEX:
320 vty_out(vty, " %pI4",
321 &nexthop->gate.ipv4);
322 if (nexthop->ifindex)
323 vty_out(vty, ", via %s",
324 ifindex2ifname(
325 nexthop->ifindex,
326 nexthop->vrf_id));
327 break;
328 case NEXTHOP_TYPE_IPV6:
329 case NEXTHOP_TYPE_IPV6_IFINDEX:
330 vty_out(vty, " %s",
331 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
332 buf, sizeof(buf)));
333 if (nexthop->ifindex)
334 vty_out(vty, ", via %s",
335 ifindex2ifname(
336 nexthop->ifindex,
337 nexthop->vrf_id));
338 break;
339
340 case NEXTHOP_TYPE_IFINDEX:
341 vty_out(vty, " directly connected, %s",
342 ifindex2ifname(nexthop->ifindex,
343 nexthop->vrf_id));
344 break;
345 case NEXTHOP_TYPE_BLACKHOLE:
346 vty_out(vty, " unreachable");
347 switch (nexthop->bh_type) {
348 case BLACKHOLE_REJECT:
349 vty_out(vty, " (ICMP unreachable)");
350 break;
351 case BLACKHOLE_ADMINPROHIB:
352 vty_out(vty,
353 " (ICMP admin-prohibited)");
354 break;
355 case BLACKHOLE_NULL:
356 vty_out(vty, " (blackhole)");
357 break;
358 case BLACKHOLE_UNSPEC:
359 break;
360 }
361 break;
362 }
363
364 if (re->vrf_id != nexthop->vrf_id) {
365 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
366
367 vty_out(vty, "(vrf %s)", VRF_LOGNAME(vrf));
368 }
369
370 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
371 vty_out(vty, " (duplicate nexthop removed)");
372
373 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
374 vty_out(vty, " inactive");
375
376 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
377 vty_out(vty, " onlink");
378
379 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
380 vty_out(vty, " linkdown");
381
382 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
383 vty_out(vty, " (recursive)");
384
385 /* Source specified? */
386 switch (nexthop->type) {
387 case NEXTHOP_TYPE_IPV4:
388 case NEXTHOP_TYPE_IPV4_IFINDEX:
389 if (nexthop->src.ipv4.s_addr) {
390 if (inet_ntop(AF_INET, &nexthop->src.ipv4,
391 addrstr, sizeof(addrstr)))
392 vty_out(vty, ", src %s",
393 addrstr);
394 }
395 break;
396
397 case NEXTHOP_TYPE_IPV6:
398 case NEXTHOP_TYPE_IPV6_IFINDEX:
399 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
400 &in6addr_any)) {
401 if (inet_ntop(AF_INET6, &nexthop->src.ipv6,
402 addrstr, sizeof(addrstr)))
403 vty_out(vty, ", src %s",
404 addrstr);
405 }
406 break;
407
408 case NEXTHOP_TYPE_IFINDEX:
409 case NEXTHOP_TYPE_BLACKHOLE:
410 break;
411 }
412
413 if (re->nexthop_mtu)
414 vty_out(vty, ", mtu %u", re->nexthop_mtu);
415
416 /* Label information */
417 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
418 vty_out(vty, ", label %s",
419 mpls_label2str(nexthop->nh_label->num_labels,
420 nexthop->nh_label->label, buf,
421 sizeof(buf), 1 /*pretty*/));
422 }
423
424 if (nexthop->weight)
425 vty_out(vty, ", weight %u", nexthop->weight);
426
427 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
428 vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
429
430 for (i = 1; i < nexthop->backup_num; i++)
431 vty_out(vty, ",%d", nexthop->backup_idx[i]);
432 }
433 }
434
435 static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
436 struct json_object *json)
437 {
438 struct bgp_zebra_opaque bzo = {};
439 struct ospf_zebra_opaque ozo = {};
440
441 if (!re->opaque)
442 return;
443
444 switch (re->type) {
445 case ZEBRA_ROUTE_SHARP:
446 if (json)
447 json_object_string_add(json, "opaque",
448 (char *)re->opaque->data);
449 else
450 vty_out(vty, " Opaque Data: %s",
451 (char *)re->opaque->data);
452 break;
453
454 case ZEBRA_ROUTE_BGP:
455 memcpy(&bzo, re->opaque->data, re->opaque->length);
456
457 if (json) {
458 json_object_string_add(json, "asPath", bzo.aspath);
459 json_object_string_add(json, "communities",
460 bzo.community);
461 json_object_string_add(json, "largeCommunities",
462 bzo.lcommunity);
463 json_object_string_add(json, "selectionReason",
464 bzo.selection_reason);
465 } else {
466 vty_out(vty, " AS-Path : %s\n", bzo.aspath);
467
468 if (bzo.community[0] != '\0')
469 vty_out(vty, " Communities : %s\n",
470 bzo.community);
471
472 if (bzo.lcommunity[0] != '\0')
473 vty_out(vty, " Large-Communities: %s\n",
474 bzo.lcommunity);
475
476 vty_out(vty, " Selection reason : %s\n",
477 bzo.selection_reason);
478 }
479 break;
480 case ZEBRA_ROUTE_OSPF:
481 case ZEBRA_ROUTE_OSPF6:
482 memcpy(&ozo, re->opaque->data, re->opaque->length);
483
484 if (json) {
485 json_object_string_add(json, "ospfPathType",
486 ozo.path_type);
487 if (ozo.area_id[0] != '\0')
488 json_object_string_add(json, "ospfAreaId",
489 ozo.area_id);
490 if (ozo.tag[0] != '\0')
491 json_object_string_add(json, "ospfTag",
492 ozo.tag);
493 } else {
494 vty_out(vty, " OSPF path type : %s\n",
495 ozo.path_type);
496 if (ozo.area_id[0] != '\0')
497 vty_out(vty, " OSPF area ID : %s\n",
498 ozo.area_id);
499 if (ozo.tag[0] != '\0')
500 vty_out(vty, " OSPF tag : %s\n",
501 ozo.tag);
502 }
503 break;
504 default:
505 break;
506 }
507 }
508
509 static void uptime2str(time_t uptime, char *buf, size_t bufsize)
510 {
511 time_t cur;
512
513 cur = monotime(NULL);
514 cur -= uptime;
515
516 frrtime_to_interval(cur, buf, bufsize);
517 }
518
519 /* New RIB. Detailed information for IPv4 route. */
520 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
521 int mcast, bool use_fib, bool show_ng)
522 {
523 struct route_entry *re;
524 struct nexthop *nexthop;
525 char buf[SRCDEST2STR_BUFFER];
526 struct zebra_vrf *zvrf;
527 rib_dest_t *dest;
528
529 dest = rib_dest_from_rnode(rn);
530
531 RNODE_FOREACH_RE (rn, re) {
532 /*
533 * If re not selected for forwarding, skip re
534 * for "show ip/ipv6 fib <prefix>"
535 */
536 if (use_fib && re != dest->selected_fib)
537 continue;
538
539 const char *mcast_info = "";
540 if (mcast) {
541 struct rib_table_info *info =
542 srcdest_rnode_table_info(rn);
543 mcast_info = (info->safi == SAFI_MULTICAST)
544 ? " using Multicast RIB"
545 : " using Unicast RIB";
546 }
547
548 vty_out(vty, "Routing entry for %s%s\n",
549 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
550 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
551 if (re->instance)
552 vty_out(vty, "[%d]", re->instance);
553 vty_out(vty, "\"");
554 vty_out(vty, ", distance %u, metric %u", re->distance,
555 re->metric);
556 if (re->tag) {
557 vty_out(vty, ", tag %u", re->tag);
558 #if defined(SUPPORT_REALMS)
559 if (re->tag > 0 && re->tag <= 255)
560 vty_out(vty, "(realm)");
561 #endif
562 }
563 if (re->mtu)
564 vty_out(vty, ", mtu %u", re->mtu);
565 if (re->vrf_id != VRF_DEFAULT) {
566 zvrf = vrf_info_lookup(re->vrf_id);
567 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
568 }
569 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
570 vty_out(vty, ", best");
571 vty_out(vty, "\n");
572
573 uptime2str(re->uptime, buf, sizeof(buf));
574
575 vty_out(vty, " Last update %s ago\n", buf);
576
577 if (show_ng) {
578 vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id);
579 if (re->nhe_installed_id != 0
580 && re->nhe_id != re->nhe_installed_id)
581 vty_out(vty,
582 " Installed Nexthop Group ID: %u\n",
583 re->nhe_installed_id);
584 }
585
586 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
587 /* Use helper to format each nexthop */
588 show_nexthop_detail_helper(vty, re, nexthop,
589 false /*not backup*/);
590 vty_out(vty, "\n");
591
592 /* Include backup(s), if present */
593 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP))
594 show_nh_backup_helper(vty, re, nexthop);
595 }
596 zebra_show_ip_route_opaque(vty, re, NULL);
597
598 vty_out(vty, "\n");
599 }
600 }
601
602 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
603 struct route_entry *re, json_object *json,
604 bool is_fib, bool show_ng)
605 {
606 const struct nexthop *nexthop;
607 int len = 0;
608 char buf[SRCDEST2STR_BUFFER];
609 json_object *json_nexthops = NULL;
610 json_object *json_nexthop = NULL;
611 json_object *json_route = NULL;
612 const rib_dest_t *dest = rib_dest_from_rnode(rn);
613 const struct nexthop_group *nhg;
614 char up_str[MONOTIME_STRLEN];
615 bool first_p = true;
616 bool nhg_from_backup = false;
617
618 uptime2str(re->uptime, up_str, sizeof(up_str));
619
620 /* If showing fib information, use the fib view of the
621 * nexthops.
622 */
623 if (is_fib)
624 nhg = rib_get_fib_nhg(re);
625 else
626 nhg = &(re->nhe->nhg);
627
628 if (json) {
629 json_route = json_object_new_object();
630 json_nexthops = json_object_new_array();
631
632 json_object_string_add(json_route, "prefix",
633 srcdest_rnode2str(rn, buf, sizeof(buf)));
634 json_object_int_add(json_route, "prefixLen", rn->p.prefixlen);
635 json_object_string_add(json_route, "protocol",
636 zebra_route_string(re->type));
637
638 if (re->instance)
639 json_object_int_add(json_route, "instance",
640 re->instance);
641
642 json_object_int_add(json_route, "vrfId", re->vrf_id);
643 json_object_string_add(json_route, "vrfName",
644 vrf_id_to_name(re->vrf_id));
645
646 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
647 json_object_boolean_true_add(json_route, "selected");
648
649 if (dest->selected_fib == re)
650 json_object_boolean_true_add(json_route,
651 "destSelected");
652
653 json_object_int_add(json_route, "distance",
654 re->distance);
655 json_object_int_add(json_route, "metric", re->metric);
656
657 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
658 json_object_boolean_true_add(json_route, "installed");
659
660 if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
661 json_object_boolean_true_add(json_route, "failed");
662
663 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
664 json_object_boolean_true_add(json_route, "queued");
665
666 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED))
667 json_object_boolean_true_add(json_route, "trapped");
668
669 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
670 json_object_boolean_true_add(json_route, "offloaded");
671
672 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
673 json_object_boolean_false_add(json_route, "offloaded");
674
675 if (re->tag)
676 json_object_int_add(json_route, "tag", re->tag);
677
678 if (re->table)
679 json_object_int_add(json_route, "table", re->table);
680
681 json_object_int_add(json_route, "internalStatus",
682 re->status);
683 json_object_int_add(json_route, "internalFlags",
684 re->flags);
685 json_object_int_add(json_route, "internalNextHopNum",
686 nexthop_group_nexthop_num(&(re->nhe->nhg)));
687 json_object_int_add(json_route, "internalNextHopActiveNum",
688 nexthop_group_active_nexthop_num(
689 &(re->nhe->nhg)));
690 json_object_int_add(json_route, "nexthopGroupId", re->nhe_id);
691
692 if (re->nhe_installed_id != 0)
693 json_object_int_add(json_route,
694 "installedNexthopGroupId",
695 re->nhe_installed_id);
696
697 json_object_string_add(json_route, "uptime", up_str);
698
699 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
700 json_nexthop = json_object_new_object();
701 show_nexthop_json_helper(json_nexthop,
702 nexthop, re);
703
704 json_object_array_add(json_nexthops,
705 json_nexthop);
706 }
707
708 json_object_object_add(json_route, "nexthops", json_nexthops);
709
710 /* If there are backup nexthops, include them */
711 if (is_fib)
712 nhg = rib_get_fib_backup_nhg(re);
713 else
714 nhg = zebra_nhg_get_backup_nhg(re->nhe);
715
716 if (nhg && nhg->nexthop) {
717 json_nexthops = json_object_new_array();
718
719 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
720 json_nexthop = json_object_new_object();
721
722 show_nexthop_json_helper(json_nexthop,
723 nexthop, re);
724 json_object_array_add(json_nexthops,
725 json_nexthop);
726 }
727
728 json_object_object_add(json_route, "backupNexthops",
729 json_nexthops);
730 }
731 zebra_show_ip_route_opaque(NULL, re, json_route);
732
733 json_object_array_add(json, json_route);
734 return;
735 }
736
737 /* Prefix information, and first nexthop. If we're showing 'fib',
738 * and there are no installed primary nexthops, see if there are any
739 * backup nexthops and start with those.
740 */
741 if (is_fib && nhg->nexthop == NULL) {
742 nhg = rib_get_fib_backup_nhg(re);
743 nhg_from_backup = true;
744 }
745
746 len = vty_out(vty, "%c", zebra_route_char(re->type));
747 if (re->instance)
748 len += vty_out(vty, "[%d]", re->instance);
749 if (nhg_from_backup && nhg->nexthop) {
750 len += vty_out(
751 vty, "%cb%c %s",
752 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
753 re_status_output_char(re, nhg->nexthop, is_fib),
754 srcdest_rnode2str(rn, buf, sizeof(buf)));
755 } else {
756 len += vty_out(
757 vty, "%c%c %s",
758 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
759 re_status_output_char(re, nhg->nexthop, is_fib),
760 srcdest_rnode2str(rn, buf, sizeof(buf)));
761 }
762
763 /* Distance and metric display. */
764 if (((re->type == ZEBRA_ROUTE_CONNECT) &&
765 (re->distance || re->metric)) ||
766 (re->type != ZEBRA_ROUTE_CONNECT))
767 len += vty_out(vty, " [%u/%u]", re->distance,
768 re->metric);
769
770 if (show_ng)
771 len += vty_out(vty, " (%u)", re->nhe_id);
772
773 /* Nexthop information. */
774 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
775 if (first_p) {
776 first_p = false;
777 } else if (nhg_from_backup) {
778 vty_out(vty, " b%c%*c",
779 re_status_output_char(re, nexthop, is_fib),
780 len - 3 + (2 * nexthop_level(nexthop)), ' ');
781 } else {
782 vty_out(vty, " %c%*c",
783 re_status_output_char(re, nexthop, is_fib),
784 len - 3 + (2 * nexthop_level(nexthop)), ' ');
785 }
786
787 show_route_nexthop_helper(vty, re, nexthop);
788 vty_out(vty, ", %s\n", up_str);
789 }
790
791 /* If we only had backup nexthops, we're done */
792 if (nhg_from_backup)
793 return;
794
795 /* Check for backup nexthop info if present */
796 if (is_fib)
797 nhg = rib_get_fib_backup_nhg(re);
798 else
799 nhg = zebra_nhg_get_backup_nhg(re->nhe);
800
801 if (nhg == NULL)
802 return;
803
804 /* Print backup info */
805 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
806 bool star_p = false;
807
808 if (is_fib)
809 star_p = CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
810
811 /* TODO -- it'd be nice to be able to include
812 * the entire list of backups, *and* include the
813 * real installation state.
814 */
815 vty_out(vty, " b%c %*c",
816 (star_p ? '*' : ' '),
817 len - 3 + (2 * nexthop_level(nexthop)), ' ');
818 show_route_nexthop_helper(vty, re, nexthop);
819 vty_out(vty, "\n");
820 }
821
822 }
823
824 static void vty_show_ip_route_detail_json(struct vty *vty,
825 struct route_node *rn, bool use_fib)
826 {
827 json_object *json = NULL;
828 json_object *json_prefix = NULL;
829 struct route_entry *re;
830 char buf[BUFSIZ];
831 rib_dest_t *dest;
832
833 dest = rib_dest_from_rnode(rn);
834
835 json = json_object_new_object();
836 json_prefix = json_object_new_array();
837
838 RNODE_FOREACH_RE (rn, re) {
839 /*
840 * If re not selected for forwarding, skip re
841 * for "show ip/ipv6 fib <prefix> json"
842 */
843 if (use_fib && re != dest->selected_fib)
844 continue;
845 vty_show_ip_route(vty, rn, re, json_prefix, use_fib, false);
846 }
847
848 prefix2str(&rn->p, buf, sizeof(buf));
849 json_object_object_add(json, buf, json_prefix);
850 vty_json(vty, json);
851 }
852
853 static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
854 struct route_table *table, afi_t afi,
855 bool use_fib, route_tag_t tag,
856 const struct prefix *longer_prefix_p,
857 bool supernets_only, int type,
858 unsigned short ospf_instance_id, bool use_json,
859 uint32_t tableid, bool show_ng,
860 struct route_show_ctx *ctx)
861 {
862 struct route_node *rn;
863 struct route_entry *re;
864 int first = 1;
865 rib_dest_t *dest;
866 json_object *json = NULL;
867 json_object *json_prefix = NULL;
868 uint32_t addr;
869 char buf[BUFSIZ];
870
871 /*
872 * ctx->multi indicates if we are dumping multiple tables or vrfs.
873 * if set:
874 * => display the common header at most once
875 * => add newline at each call except first
876 * => always display the VRF and table
877 * else:
878 * => display the common header if at least one entry is found
879 * => display the VRF and table if specific
880 */
881
882 if (use_json)
883 json = json_object_new_object();
884
885 /* Show all routes. */
886 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
887 dest = rib_dest_from_rnode(rn);
888
889 RNODE_FOREACH_RE (rn, re) {
890 if (use_fib && re != dest->selected_fib)
891 continue;
892
893 if (tag && re->tag != tag)
894 continue;
895
896 if (longer_prefix_p
897 && !prefix_match(longer_prefix_p, &rn->p))
898 continue;
899
900 /* This can only be true when the afi is IPv4 */
901 if (supernets_only) {
902 addr = ntohl(rn->p.u.prefix4.s_addr);
903
904 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
905 continue;
906
907 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
908 continue;
909
910 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
911 continue;
912 }
913
914 if (type && re->type != type)
915 continue;
916
917 if (ospf_instance_id
918 && (re->type != ZEBRA_ROUTE_OSPF
919 || re->instance != ospf_instance_id))
920 continue;
921
922 if (use_json) {
923 if (!json_prefix)
924 json_prefix = json_object_new_array();
925 } else if (first) {
926 if (!ctx->header_done) {
927 if (afi == AFI_IP)
928 vty_out(vty,
929 SHOW_ROUTE_V4_HEADER);
930 else
931 vty_out(vty,
932 SHOW_ROUTE_V6_HEADER);
933 }
934 if (ctx->multi && ctx->header_done)
935 vty_out(vty, "\n");
936 if (ctx->multi || zvrf_id(zvrf) != VRF_DEFAULT
937 || tableid) {
938 if (!tableid)
939 vty_out(vty, "VRF %s:\n",
940 zvrf_name(zvrf));
941 else
942 vty_out(vty,
943 "VRF %s table %u:\n",
944 zvrf_name(zvrf),
945 tableid);
946 }
947 ctx->header_done = true;
948 first = 0;
949 }
950
951 vty_show_ip_route(vty, rn, re, json_prefix, use_fib,
952 show_ng);
953 }
954
955 if (json_prefix) {
956 prefix2str(&rn->p, buf, sizeof(buf));
957 json_object_object_add(json, buf, json_prefix);
958 json_prefix = NULL;
959 }
960 }
961
962 if (use_json)
963 vty_json(vty, json);
964 }
965
966 static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
967 afi_t afi, bool use_fib, bool use_json,
968 route_tag_t tag,
969 const struct prefix *longer_prefix_p,
970 bool supernets_only, int type,
971 unsigned short ospf_instance_id, bool show_ng,
972 struct route_show_ctx *ctx)
973 {
974 struct zebra_router_table *zrt;
975 struct rib_table_info *info;
976
977 RB_FOREACH (zrt, zebra_router_table_head,
978 &zrouter.tables) {
979 info = route_table_get_info(zrt->table);
980
981 if (zvrf != info->zvrf)
982 continue;
983 if (zrt->afi != afi ||
984 zrt->safi != SAFI_UNICAST)
985 continue;
986
987 do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
988 use_fib, use_json, tag, longer_prefix_p,
989 supernets_only, type, ospf_instance_id,
990 zrt->tableid, show_ng, ctx);
991 }
992 }
993
994 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
995 safi_t safi, bool use_fib, bool use_json,
996 route_tag_t tag,
997 const struct prefix *longer_prefix_p,
998 bool supernets_only, int type,
999 unsigned short ospf_instance_id, uint32_t tableid,
1000 bool show_ng, struct route_show_ctx *ctx)
1001 {
1002 struct route_table *table;
1003 struct zebra_vrf *zvrf = NULL;
1004
1005 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
1006 if (use_json)
1007 vty_out(vty, "{}\n");
1008 else
1009 vty_out(vty, "vrf %s not defined\n", vrf_name);
1010 return CMD_SUCCESS;
1011 }
1012
1013 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
1014 if (use_json)
1015 vty_out(vty, "{}\n");
1016 else
1017 vty_out(vty, "vrf %s inactive\n", vrf_name);
1018 return CMD_SUCCESS;
1019 }
1020
1021 if (tableid)
1022 table = zebra_router_find_table(zvrf, tableid, afi, SAFI_UNICAST);
1023 else
1024 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
1025 if (!table) {
1026 if (use_json)
1027 vty_out(vty, "{}\n");
1028 return CMD_SUCCESS;
1029 }
1030
1031 do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
1032 longer_prefix_p, supernets_only, type,
1033 ospf_instance_id, use_json, tableid, show_ng, ctx);
1034
1035 return CMD_SUCCESS;
1036 }
1037
1038 DEFPY (show_ip_nht,
1039 show_ip_nht_cmd,
1040 "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
1041 SHOW_STR
1042 IP_STR
1043 IP6_STR
1044 "IP nexthop tracking table\n"
1045 "IP import check tracking table\n"
1046 "IPv4 Address\n"
1047 "IPv6 Address\n"
1048 VRF_CMD_HELP_STR
1049 "IPv4 Address\n"
1050 "IPv6 Address\n"
1051 VRF_ALL_CMD_HELP_STR
1052 "Show Multicast (MRIB) NHT state\n"
1053 JSON_STR)
1054 {
1055 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1056 vrf_id_t vrf_id = VRF_DEFAULT;
1057 struct prefix prefix, *p = NULL;
1058 safi_t safi = mrib ? SAFI_MULTICAST : SAFI_UNICAST;
1059 bool uj = use_json(argc, argv);
1060 json_object *json = NULL;
1061 json_object *json_vrf = NULL;
1062 json_object *json_nexthop = NULL;
1063
1064 if (uj)
1065 json = json_object_new_object();
1066
1067 if (vrf_all) {
1068 struct vrf *vrf;
1069 struct zebra_vrf *zvrf;
1070
1071 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1072 if ((zvrf = vrf->info) != NULL) {
1073 if (uj) {
1074 json_vrf = json_object_new_object();
1075 json_nexthop = json_object_new_object();
1076 json_object_object_add(json,
1077 zvrf_name(zvrf),
1078 json_vrf);
1079 json_object_object_add(json_vrf,
1080 (afi == AFI_IP)
1081 ? "ipv4"
1082 : "ipv6",
1083 json_nexthop);
1084 } else {
1085 vty_out(vty, "\nVRF %s:\n",
1086 zvrf_name(zvrf));
1087 }
1088 zebra_print_rnh_table(zvrf_id(zvrf), afi, safi,
1089 vty, NULL, json_nexthop);
1090 }
1091 }
1092
1093 if (uj)
1094 vty_json(vty, json);
1095
1096 return CMD_SUCCESS;
1097 }
1098 if (vrf_name)
1099 VRF_GET_ID(vrf_id, vrf_name, false);
1100
1101 memset(&prefix, 0, sizeof(prefix));
1102 if (addr) {
1103 p = sockunion2hostprefix(addr, &prefix);
1104 if (!p) {
1105 if (uj)
1106 json_object_free(json);
1107 return CMD_WARNING;
1108 }
1109 }
1110
1111 if (uj) {
1112 json_vrf = json_object_new_object();
1113 json_nexthop = json_object_new_object();
1114 if (vrf_name)
1115 json_object_object_add(json, vrf_name, json_vrf);
1116 else
1117 json_object_object_add(json, "default", json_vrf);
1118
1119 json_object_object_add(json_vrf,
1120 (afi == AFI_IP) ? "ipv4" : "ipv6",
1121 json_nexthop);
1122 }
1123
1124 zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop);
1125
1126 if (uj)
1127 vty_json(vty, json);
1128
1129 return CMD_SUCCESS;
1130 }
1131
1132 DEFUN (ip_nht_default_route,
1133 ip_nht_default_route_cmd,
1134 "ip nht resolve-via-default",
1135 IP_STR
1136 "Filter Next Hop tracking route resolution\n"
1137 "Resolve via default route\n")
1138 {
1139 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1140
1141 if (!zvrf)
1142 return CMD_WARNING;
1143
1144 if (zvrf->zebra_rnh_ip_default_route)
1145 return CMD_SUCCESS;
1146
1147 zvrf->zebra_rnh_ip_default_route = true;
1148
1149 zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
1150 return CMD_SUCCESS;
1151 }
1152
1153 static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
1154 json_object *json_nhe_hdr)
1155 {
1156 struct nexthop *nexthop = NULL;
1157 struct nhg_connected *rb_node_dep = NULL;
1158 struct nexthop_group *backup_nhg;
1159 char up_str[MONOTIME_STRLEN];
1160 char time_left[MONOTIME_STRLEN];
1161 json_object *json_dependants = NULL;
1162 json_object *json_depends = NULL;
1163 json_object *json_nexthop_array = NULL;
1164 json_object *json_nexthops = NULL;
1165 json_object *json = NULL;
1166 json_object *json_backup_nexthop_array = NULL;
1167 json_object *json_backup_nexthops = NULL;
1168
1169
1170 uptime2str(nhe->uptime, up_str, sizeof(up_str));
1171
1172 if (json_nhe_hdr)
1173 json = json_object_new_object();
1174
1175 if (json) {
1176 json_object_string_add(json, "type",
1177 zebra_route_string(nhe->type));
1178 json_object_int_add(json, "refCount", nhe->refcnt);
1179 if (thread_is_scheduled(nhe->timer))
1180 json_object_string_add(
1181 json, "timeToDeletion",
1182 thread_timer_to_hhmmss(time_left,
1183 sizeof(time_left),
1184 nhe->timer));
1185 json_object_string_add(json, "uptime", up_str);
1186 json_object_string_add(json, "vrf",
1187 vrf_id_to_name(nhe->vrf_id));
1188
1189 } else {
1190 vty_out(vty, "ID: %u (%s)\n", nhe->id,
1191 zebra_route_string(nhe->type));
1192 vty_out(vty, " RefCnt: %u", nhe->refcnt);
1193 if (thread_is_scheduled(nhe->timer))
1194 vty_out(vty, " Time to Deletion: %s",
1195 thread_timer_to_hhmmss(time_left,
1196 sizeof(time_left),
1197 nhe->timer));
1198 vty_out(vty, "\n");
1199
1200 vty_out(vty, " Uptime: %s\n", up_str);
1201 vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
1202 }
1203
1204 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
1205 if (json)
1206 json_object_boolean_true_add(json, "valid");
1207 else
1208 vty_out(vty, " Valid");
1209
1210 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) {
1211 if (json)
1212 json_object_boolean_true_add(json, "installed");
1213 else
1214 vty_out(vty, ", Installed");
1215 }
1216 if (!json)
1217 vty_out(vty, "\n");
1218 }
1219 if (nhe->ifp) {
1220 if (json)
1221 json_object_int_add(json, "interfaceIndex",
1222 nhe->ifp->ifindex);
1223 else
1224 vty_out(vty, " Interface Index: %d\n",
1225 nhe->ifp->ifindex);
1226 }
1227
1228 if (!zebra_nhg_depends_is_empty(nhe)) {
1229 if (json)
1230 json_depends = json_object_new_array();
1231 else
1232 vty_out(vty, " Depends:");
1233 frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
1234 if (json_depends)
1235 json_object_array_add(
1236 json_depends,
1237 json_object_new_int(
1238 rb_node_dep->nhe->id));
1239 else
1240 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1241 }
1242 if (!json_depends)
1243 vty_out(vty, "\n");
1244 else
1245 json_object_object_add(json, "depends", json_depends);
1246 }
1247
1248 /* Output nexthops */
1249 if (json)
1250 json_nexthop_array = json_object_new_array();
1251
1252
1253 for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
1254 if (json_nexthop_array) {
1255 json_nexthops = json_object_new_object();
1256 show_nexthop_json_helper(json_nexthops, nexthop, NULL);
1257 } else {
1258 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1259 vty_out(vty, " ");
1260 else
1261 /* Make recursive nexthops a bit more clear */
1262 vty_out(vty, " ");
1263 show_route_nexthop_helper(vty, NULL, nexthop);
1264 }
1265
1266 if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) {
1267 if (CHECK_FLAG(nexthop->flags,
1268 NEXTHOP_FLAG_HAS_BACKUP)) {
1269 if (json)
1270 json_object_int_add(
1271 json_nexthops, "backup",
1272 nexthop->backup_idx[0]);
1273 else
1274 vty_out(vty, " [backup %d]",
1275 nexthop->backup_idx[0]);
1276 }
1277
1278 if (!json)
1279 vty_out(vty, "\n");
1280 else
1281 json_object_array_add(json_nexthop_array,
1282 json_nexthops);
1283
1284 continue;
1285 }
1286
1287 if (!json) {
1288 /* TODO -- print more useful backup info */
1289 if (CHECK_FLAG(nexthop->flags,
1290 NEXTHOP_FLAG_HAS_BACKUP)) {
1291 int i;
1292
1293 vty_out(vty, "[backup");
1294 for (i = 0; i < nexthop->backup_num; i++)
1295 vty_out(vty, " %d",
1296 nexthop->backup_idx[i]);
1297 vty_out(vty, "]");
1298 }
1299 vty_out(vty, "\n");
1300 } else {
1301 json_object_array_add(json_nexthop_array,
1302 json_nexthops);
1303 }
1304 }
1305
1306 if (json)
1307 json_object_object_add(json, "nexthops", json_nexthop_array);
1308
1309 /* Output backup nexthops (if any) */
1310 backup_nhg = zebra_nhg_get_backup_nhg(nhe);
1311 if (backup_nhg) {
1312 if (json)
1313 json_backup_nexthop_array = json_object_new_array();
1314 else
1315 vty_out(vty, " Backups:\n");
1316
1317 for (ALL_NEXTHOPS_PTR(backup_nhg, nexthop)) {
1318 if (json_backup_nexthop_array) {
1319 json_backup_nexthops = json_object_new_object();
1320 show_nexthop_json_helper(json_backup_nexthops,
1321 nexthop, NULL);
1322 json_object_array_add(json_backup_nexthop_array,
1323 json_backup_nexthops);
1324 } else {
1325
1326 if (!CHECK_FLAG(nexthop->flags,
1327 NEXTHOP_FLAG_RECURSIVE))
1328 vty_out(vty, " ");
1329 else
1330 /* Make recursive nexthops a bit more
1331 * clear
1332 */
1333 vty_out(vty, " ");
1334 show_route_nexthop_helper(vty, NULL, nexthop);
1335 vty_out(vty, "\n");
1336 }
1337 }
1338
1339 if (json)
1340 json_object_object_add(json, "backupNexthops",
1341 json_backup_nexthop_array);
1342 }
1343
1344 if (!zebra_nhg_dependents_is_empty(nhe)) {
1345 if (json)
1346 json_dependants = json_object_new_array();
1347 else
1348 vty_out(vty, " Dependents:");
1349 frr_each(nhg_connected_tree, &nhe->nhg_dependents,
1350 rb_node_dep) {
1351 if (json)
1352 json_object_array_add(
1353 json_dependants,
1354 json_object_new_int(
1355 rb_node_dep->nhe->id));
1356 else
1357 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1358 }
1359 if (json)
1360 json_object_object_add(json, "dependents",
1361 json_dependants);
1362 else
1363 vty_out(vty, "\n");
1364 }
1365
1366 if (nhe->nhg.nhgr.buckets) {
1367 if (json) {
1368 json_object_int_add(json, "buckets",
1369 nhe->nhg.nhgr.buckets);
1370 json_object_int_add(json, "idleTimer",
1371 nhe->nhg.nhgr.idle_timer);
1372 json_object_int_add(json, "unbalancedTimer",
1373 nhe->nhg.nhgr.unbalanced_timer);
1374 json_object_int_add(json, "unbalancedTime",
1375 nhe->nhg.nhgr.unbalanced_time);
1376 } else {
1377 vty_out(vty,
1378 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1379 "\n",
1380 nhe->nhg.nhgr.buckets, nhe->nhg.nhgr.idle_timer,
1381 nhe->nhg.nhgr.unbalanced_timer,
1382 nhe->nhg.nhgr.unbalanced_time);
1383 }
1384 }
1385
1386 if (json_nhe_hdr)
1387 json_object_object_addf(json_nhe_hdr, json, "%u", nhe->id);
1388 }
1389
1390 static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id,
1391 json_object *json)
1392 {
1393 struct nhg_hash_entry *nhe = NULL;
1394
1395 nhe = zebra_nhg_lookup_id(id);
1396
1397 if (nhe)
1398 show_nexthop_group_out(vty, nhe, json);
1399 else {
1400 if (json)
1401 vty_json(vty, json);
1402 else
1403 vty_out(vty, "Nexthop Group ID: %u does not exist\n",
1404 id);
1405 return CMD_WARNING;
1406 }
1407
1408 if (json)
1409 vty_json(vty, json);
1410
1411 return CMD_SUCCESS;
1412 }
1413
1414 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1415
1416 struct nhe_show_context {
1417 struct vty *vty;
1418 vrf_id_t vrf_id;
1419 afi_t afi;
1420 int type;
1421 json_object *json;
1422 };
1423
1424 static int nhe_show_walker(struct hash_bucket *bucket, void *arg)
1425 {
1426 struct nhe_show_context *ctx = arg;
1427 struct nhg_hash_entry *nhe;
1428
1429 nhe = bucket->data; /* We won't be offered NULL buckets */
1430
1431 if (ctx->afi && nhe->afi != ctx->afi)
1432 goto done;
1433
1434 if (ctx->vrf_id && nhe->vrf_id != ctx->vrf_id)
1435 goto done;
1436
1437 if (ctx->type && nhe->type != ctx->type)
1438 goto done;
1439
1440 show_nexthop_group_out(ctx->vty, nhe, ctx->json);
1441
1442 done:
1443 return HASHWALK_CONTINUE;
1444 }
1445
1446 static void show_nexthop_group_cmd_helper(struct vty *vty,
1447 struct zebra_vrf *zvrf, afi_t afi,
1448 int type, json_object *json)
1449 {
1450 struct nhe_show_context ctx;
1451
1452 ctx.vty = vty;
1453 ctx.afi = afi;
1454 ctx.vrf_id = zvrf->vrf->vrf_id;
1455 ctx.type = type;
1456 ctx.json = json;
1457
1458 hash_walk(zrouter.nhgs_id, nhe_show_walker, &ctx);
1459 }
1460
1461 static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
1462 {
1463 struct zebra_if *zebra_if = NULL;
1464 struct nhg_connected *rb_node_dep = NULL;
1465
1466 zebra_if = ifp->info;
1467
1468 if (!if_nhg_dependents_is_empty(ifp)) {
1469 vty_out(vty, "Interface %s:\n", ifp->name);
1470
1471 frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
1472 rb_node_dep) {
1473 vty_out(vty, " ");
1474 show_nexthop_group_out(vty, rb_node_dep->nhe, NULL);
1475 }
1476 }
1477 }
1478
1479 DEFPY (show_interface_nexthop_group,
1480 show_interface_nexthop_group_cmd,
1481 "show interface [IFNAME$if_name] nexthop-group",
1482 SHOW_STR
1483 "Interface status and configuration\n"
1484 "Interface name\n"
1485 "Show Nexthop Groups\n")
1486 {
1487 struct vrf *vrf = NULL;
1488 struct interface *ifp = NULL;
1489 bool found = false;
1490
1491 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1492 if (if_name) {
1493 ifp = if_lookup_by_name(if_name, vrf->vrf_id);
1494 if (ifp) {
1495 if_nexthop_group_dump_vty(vty, ifp);
1496 found = true;
1497 }
1498 } else {
1499 FOR_ALL_INTERFACES (vrf, ifp)
1500 if_nexthop_group_dump_vty(vty, ifp);
1501 found = true;
1502 }
1503 }
1504
1505 if (!found) {
1506 vty_out(vty, "%% Can't find interface %s\n", if_name);
1507 return CMD_WARNING;
1508 }
1509
1510 return CMD_SUCCESS;
1511 }
1512
1513 DEFPY(show_nexthop_group,
1514 show_nexthop_group_cmd,
1515 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]",
1516 SHOW_STR
1517 "Show Nexthop Groups\n"
1518 "RIB information\n"
1519 "Nexthop Group ID\n"
1520 "Show Singleton Nexthop-Groups\n"
1521 IP_STR
1522 IP6_STR
1523 "Kernel (not installed via the zebra RIB)\n"
1524 "Zebra (implicitly created by zebra)\n"
1525 "Border Gateway Protocol (BGP)\n"
1526 "Super Happy Advanced Routing Protocol (SHARP)\n"
1527 VRF_FULL_CMD_HELP_STR
1528 JSON_STR)
1529 {
1530
1531 struct zebra_vrf *zvrf = NULL;
1532 afi_t afi = AFI_UNSPEC;
1533 int type = 0;
1534 bool uj = use_json(argc, argv);
1535 json_object *json = NULL;
1536 json_object *json_vrf = NULL;
1537
1538 if (uj)
1539 json = json_object_new_object();
1540
1541 if (id)
1542 return show_nexthop_group_id_cmd_helper(vty, id, json);
1543
1544 if (v4)
1545 afi = AFI_IP;
1546 else if (v6)
1547 afi = AFI_IP6;
1548
1549 if (type_str) {
1550 type = proto_redistnum((afi ? afi : AFI_IP), type_str);
1551 if (type < 0) {
1552 /* assume zebra */
1553 type = ZEBRA_ROUTE_NHG;
1554 }
1555 }
1556
1557 if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1558 if (uj)
1559 vty_json(vty, json);
1560 else
1561 vty_out(vty,
1562 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1563 return CMD_WARNING;
1564 }
1565
1566 if (vrf_all) {
1567 struct vrf *vrf;
1568
1569 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1570 struct zebra_vrf *zvrf;
1571
1572 zvrf = vrf->info;
1573 if (!zvrf)
1574 continue;
1575 if (uj)
1576 json_vrf = json_object_new_object();
1577 else
1578 vty_out(vty, "VRF: %s\n", vrf->name);
1579
1580 show_nexthop_group_cmd_helper(vty, zvrf, afi, type,
1581 json_vrf);
1582 if (uj)
1583 json_object_object_add(json, vrf->name,
1584 json_vrf);
1585 }
1586
1587 if (uj)
1588 vty_json(vty, json);
1589
1590 return CMD_SUCCESS;
1591 }
1592
1593 if (vrf_name)
1594 zvrf = zebra_vrf_lookup_by_name(vrf_name);
1595 else
1596 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1597
1598 if (!zvrf) {
1599 if (uj)
1600 vty_json(vty, json);
1601 else
1602 vty_out(vty, "%% VRF '%s' specified does not exist\n",
1603 vrf_name);
1604 return CMD_WARNING;
1605 }
1606
1607 show_nexthop_group_cmd_helper(vty, zvrf, afi, type, json);
1608
1609 if (uj)
1610 vty_json(vty, json);
1611
1612 return CMD_SUCCESS;
1613 }
1614
1615 DEFPY_HIDDEN(nexthop_group_use_enable,
1616 nexthop_group_use_enable_cmd,
1617 "[no] zebra nexthop kernel enable",
1618 NO_STR
1619 ZEBRA_STR
1620 "Nexthop configuration \n"
1621 "Configure use of kernel nexthops\n"
1622 "Enable kernel nexthops\n")
1623 {
1624 zebra_nhg_enable_kernel_nexthops(!no);
1625 return CMD_SUCCESS;
1626 }
1627
1628 DEFPY_HIDDEN(proto_nexthop_group_only, proto_nexthop_group_only_cmd,
1629 "[no] zebra nexthop proto only",
1630 NO_STR ZEBRA_STR
1631 "Nexthop configuration\n"
1632 "Configure exclusive use of proto nexthops\n"
1633 "Only use proto nexthops\n")
1634 {
1635 zebra_nhg_set_proto_nexthops_only(!no);
1636 return CMD_SUCCESS;
1637 }
1638
1639 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable,
1640 backup_nexthop_recursive_use_enable_cmd,
1641 "[no] zebra nexthop resolve-via-backup",
1642 NO_STR
1643 ZEBRA_STR
1644 "Nexthop configuration \n"
1645 "Configure use of backup nexthops in recursive resolution\n")
1646 {
1647 zebra_nhg_set_recursive_use_backups(!no);
1648 return CMD_SUCCESS;
1649 }
1650
1651 DEFUN (no_ip_nht_default_route,
1652 no_ip_nht_default_route_cmd,
1653 "no ip nht resolve-via-default",
1654 NO_STR
1655 IP_STR
1656 "Filter Next Hop tracking route resolution\n"
1657 "Resolve via default route\n")
1658 {
1659 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1660
1661 if (!zvrf)
1662 return CMD_WARNING;
1663
1664 if (!zvrf->zebra_rnh_ip_default_route)
1665 return CMD_SUCCESS;
1666
1667 zvrf->zebra_rnh_ip_default_route = false;
1668 zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
1669 return CMD_SUCCESS;
1670 }
1671
1672 DEFUN (ipv6_nht_default_route,
1673 ipv6_nht_default_route_cmd,
1674 "ipv6 nht resolve-via-default",
1675 IP6_STR
1676 "Filter Next Hop tracking route resolution\n"
1677 "Resolve via default route\n")
1678 {
1679 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1680
1681 if (!zvrf)
1682 return CMD_WARNING;
1683
1684 if (zvrf->zebra_rnh_ipv6_default_route)
1685 return CMD_SUCCESS;
1686
1687 zvrf->zebra_rnh_ipv6_default_route = true;
1688 zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
1689 return CMD_SUCCESS;
1690 }
1691
1692 DEFUN (no_ipv6_nht_default_route,
1693 no_ipv6_nht_default_route_cmd,
1694 "no ipv6 nht resolve-via-default",
1695 NO_STR
1696 IP6_STR
1697 "Filter Next Hop tracking route resolution\n"
1698 "Resolve via default route\n")
1699 {
1700 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1701
1702 if (!zvrf)
1703 return CMD_WARNING;
1704
1705 if (!zvrf->zebra_rnh_ipv6_default_route)
1706 return CMD_SUCCESS;
1707
1708 zvrf->zebra_rnh_ipv6_default_route = false;
1709 zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
1710 return CMD_SUCCESS;
1711 }
1712
1713 DEFPY_HIDDEN(rnh_hide_backups, rnh_hide_backups_cmd,
1714 "[no] ip nht hide-backup-events",
1715 NO_STR
1716 IP_STR
1717 "Nexthop-tracking configuration\n"
1718 "Hide notification about backup nexthops\n")
1719 {
1720 rnh_set_hide_backups(!no);
1721 return CMD_SUCCESS;
1722 }
1723
1724 DEFPY (show_route,
1725 show_route_cmd,
1726 "show\
1727 <\
1728 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1729 [vrf <NAME$vrf_name|all$vrf_all>]\
1730 [{\
1731 tag (1-4294967295)\
1732 |A.B.C.D/M$prefix longer-prefixes\
1733 |supernets-only$supernets_only\
1734 }]\
1735 [<\
1736 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1737 |ospf$type_str (1-65535)$ospf_instance_id\
1738 >]\
1739 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1740 [vrf <NAME$vrf_name|all$vrf_all>]\
1741 [{\
1742 tag (1-4294967295)\
1743 |X:X::X:X/M$prefix longer-prefixes\
1744 }]\
1745 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1746 >\
1747 [<json$json|nexthop-group$ng>]",
1748 SHOW_STR
1749 IP_STR
1750 "IP forwarding table\n"
1751 "IP routing table\n"
1752 "Table to display\n"
1753 "The table number to display\n"
1754 "All tables\n"
1755 VRF_FULL_CMD_HELP_STR
1756 "Show only routes with tag\n"
1757 "Tag value\n"
1758 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1759 "Show route matching the specified Network/Mask pair only\n"
1760 "Show supernet entries only\n"
1761 FRR_IP_REDIST_HELP_STR_ZEBRA
1762 "Open Shortest Path First (OSPFv2)\n"
1763 "Instance ID\n"
1764 IPV6_STR
1765 "IP forwarding table\n"
1766 "IP routing table\n"
1767 "Table to display\n"
1768 "The table number to display\n"
1769 "All tables\n"
1770 VRF_FULL_CMD_HELP_STR
1771 "Show only routes with tag\n"
1772 "Tag value\n"
1773 "IPv6 prefix\n"
1774 "Show route matching the specified Network/Mask pair only\n"
1775 FRR_IP6_REDIST_HELP_STR_ZEBRA
1776 JSON_STR
1777 "Nexthop Group Information\n")
1778 {
1779 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1780 struct vrf *vrf;
1781 int type = 0;
1782 struct zebra_vrf *zvrf;
1783 struct route_show_ctx ctx = {
1784 .multi = vrf_all || table_all,
1785 };
1786
1787 if (!vrf_is_backend_netns()) {
1788 if ((vrf_all || vrf_name) && (table || table_all)) {
1789 if (!!json)
1790 vty_out(vty, "{}\n");
1791 else {
1792 vty_out(vty, "Linux vrf backend already points to table id\n");
1793 vty_out(vty, "Either remove table parameter or vrf parameter\n");
1794 }
1795 return CMD_SUCCESS;
1796 }
1797 }
1798 if (type_str) {
1799 type = proto_redistnum(afi, type_str);
1800 if (type < 0) {
1801 vty_out(vty, "Unknown route type\n");
1802 return CMD_WARNING;
1803 }
1804 }
1805
1806 if (vrf_all) {
1807 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1808 if ((zvrf = vrf->info) == NULL
1809 || (zvrf->table[afi][SAFI_UNICAST] == NULL))
1810 continue;
1811
1812 if (table_all)
1813 do_show_ip_route_all(
1814 vty, zvrf, afi, !!fib, !!json, tag,
1815 prefix_str ? prefix : NULL,
1816 !!supernets_only, type,
1817 ospf_instance_id, !!ng, &ctx);
1818 else
1819 do_show_ip_route(
1820 vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
1821 !!fib, !!json, tag,
1822 prefix_str ? prefix : NULL,
1823 !!supernets_only, type,
1824 ospf_instance_id, table, !!ng, &ctx);
1825 }
1826 } else {
1827 vrf_id_t vrf_id = VRF_DEFAULT;
1828
1829 if (vrf_name)
1830 VRF_GET_ID(vrf_id, vrf_name, !!json);
1831 vrf = vrf_lookup_by_id(vrf_id);
1832 if (!vrf)
1833 return CMD_SUCCESS;
1834
1835 zvrf = vrf->info;
1836 if (!zvrf)
1837 return CMD_SUCCESS;
1838
1839 if (table_all)
1840 do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
1841 prefix_str ? prefix : NULL,
1842 !!supernets_only, type,
1843 ospf_instance_id, !!ng, &ctx);
1844 else
1845 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
1846 !!fib, !!json, tag,
1847 prefix_str ? prefix : NULL,
1848 !!supernets_only, type,
1849 ospf_instance_id, table, !!ng, &ctx);
1850 }
1851
1852 return CMD_SUCCESS;
1853 }
1854
1855 ALIAS_HIDDEN (show_route,
1856 show_ro_cmd,
1857 "show <ip$ipv4|ipv6$ipv6> ro",
1858 SHOW_STR
1859 IP_STR
1860 IPV6_STR
1861 "IP routing table\n");
1862
1863
1864 DEFPY (show_route_detail,
1865 show_route_detail_cmd,
1866 "show\
1867 <\
1868 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1869 <\
1870 A.B.C.D$address\
1871 |A.B.C.D/M$prefix\
1872 >\
1873 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1874 <\
1875 X:X::X:X$address\
1876 |X:X::X:X/M$prefix\
1877 >\
1878 >\
1879 [json$json] [nexthop-group$ng]",
1880 SHOW_STR
1881 IP_STR
1882 "IP forwarding table\n"
1883 "IP routing table\n"
1884 VRF_FULL_CMD_HELP_STR
1885 "Network in the IP routing table to display\n"
1886 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1887 IP6_STR
1888 "IPv6 forwarding table\n"
1889 "IPv6 routing table\n"
1890 VRF_FULL_CMD_HELP_STR
1891 "IPv6 Address\n"
1892 "IPv6 prefix\n"
1893 JSON_STR
1894 "Nexthop Group Information\n")
1895 {
1896 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1897 struct route_table *table;
1898 struct prefix p;
1899 struct route_node *rn;
1900 bool use_fib = !!fib;
1901 rib_dest_t *dest;
1902 bool network_found = false;
1903 bool show_ng = !!ng;
1904
1905 if (address_str)
1906 prefix_str = address_str;
1907 if (str2prefix(prefix_str, &p) < 0) {
1908 vty_out(vty, "%% Malformed address\n");
1909 return CMD_WARNING;
1910 }
1911
1912 if (vrf_all) {
1913 struct vrf *vrf;
1914 struct zebra_vrf *zvrf;
1915
1916 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1917 if ((zvrf = vrf->info) == NULL
1918 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1919 continue;
1920
1921 rn = route_node_match(table, &p);
1922 if (!rn)
1923 continue;
1924 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1925 route_unlock_node(rn);
1926 continue;
1927 }
1928
1929 dest = rib_dest_from_rnode(rn);
1930 if (use_fib && !dest->selected_fib) {
1931 route_unlock_node(rn);
1932 continue;
1933 }
1934
1935 network_found = true;
1936 if (json)
1937 vty_show_ip_route_detail_json(vty, rn, use_fib);
1938 else
1939 vty_show_ip_route_detail(vty, rn, 0, use_fib,
1940 show_ng);
1941
1942 route_unlock_node(rn);
1943 }
1944
1945 if (!network_found) {
1946 if (json)
1947 vty_out(vty, "{}\n");
1948 else {
1949 if (use_fib)
1950 vty_out(vty,
1951 "%% Network not in FIB\n");
1952 else
1953 vty_out(vty,
1954 "%% Network not in RIB\n");
1955 }
1956 return CMD_WARNING;
1957 }
1958 } else {
1959 vrf_id_t vrf_id = VRF_DEFAULT;
1960
1961 if (vrf_name)
1962 VRF_GET_ID(vrf_id, vrf_name, false);
1963
1964 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1965 if (!table)
1966 return CMD_SUCCESS;
1967
1968 rn = route_node_match(table, &p);
1969 if (rn)
1970 dest = rib_dest_from_rnode(rn);
1971
1972 if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
1973 (use_fib && dest && !dest->selected_fib)) {
1974 if (json)
1975 vty_out(vty, "{}\n");
1976 else {
1977 if (use_fib)
1978 vty_out(vty,
1979 "%% Network not in FIB\n");
1980 else
1981 vty_out(vty,
1982 "%% Network not in table\n");
1983 }
1984 if (rn)
1985 route_unlock_node(rn);
1986 return CMD_WARNING;
1987 }
1988
1989 if (json)
1990 vty_show_ip_route_detail_json(vty, rn, use_fib);
1991 else
1992 vty_show_ip_route_detail(vty, rn, 0, use_fib, show_ng);
1993
1994 route_unlock_node(rn);
1995 }
1996
1997 return CMD_SUCCESS;
1998 }
1999
2000 DEFPY (show_route_summary,
2001 show_route_summary_cmd,
2002 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2003 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2004 SHOW_STR
2005 IP_STR
2006 IP6_STR
2007 "IP routing table\n"
2008 VRF_FULL_CMD_HELP_STR
2009 "Summary of all routes\n"
2010 "Table to display summary for\n"
2011 "The table number\n"
2012 "Prefix routes\n"
2013 JSON_STR)
2014 {
2015 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2016 struct route_table *table;
2017 bool uj = use_json(argc, argv);
2018
2019 if (vrf_all) {
2020 struct vrf *vrf;
2021 struct zebra_vrf *zvrf;
2022
2023 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2024 if ((zvrf = vrf->info) == NULL)
2025 continue;
2026
2027 if (table_id == 0)
2028 table = zebra_vrf_table(afi, SAFI_UNICAST,
2029 zvrf->vrf->vrf_id);
2030 else
2031 table = zebra_vrf_lookup_table_with_table_id(
2032 afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
2033 table_id);
2034
2035 if (!table)
2036 continue;
2037
2038 if (prefix)
2039 vty_show_ip_route_summary_prefix(vty, table,
2040 uj);
2041 else
2042 vty_show_ip_route_summary(vty, table, uj);
2043 }
2044 } else {
2045 vrf_id_t vrf_id = VRF_DEFAULT;
2046
2047 if (vrf_name)
2048 VRF_GET_ID(vrf_id, vrf_name, false);
2049
2050 if (table_id == 0)
2051 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2052 else
2053 table = zebra_vrf_lookup_table_with_table_id(
2054 afi, SAFI_UNICAST, vrf_id, table_id);
2055 if (!table)
2056 return CMD_SUCCESS;
2057
2058 if (prefix)
2059 vty_show_ip_route_summary_prefix(vty, table, uj);
2060 else
2061 vty_show_ip_route_summary(vty, table, uj);
2062 }
2063
2064 return CMD_SUCCESS;
2065 }
2066
2067 DEFUN_HIDDEN (show_route_zebra_dump,
2068 show_route_zebra_dump_cmd,
2069 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2070 SHOW_STR
2071 IP_STR
2072 IP6_STR
2073 "Zebra daemon\n"
2074 "Routing table\n"
2075 "All information\n"
2076 VRF_CMD_HELP_STR)
2077 {
2078 afi_t afi = AFI_IP;
2079 struct route_table *table;
2080 const char *vrf_name = NULL;
2081 int idx = 0;
2082
2083 afi = strmatch(argv[1]->text, "ipv6") ? AFI_IP6 : AFI_IP;
2084
2085 if (argv_find(argv, argc, "vrf", &idx))
2086 vrf_name = argv[++idx]->arg;
2087
2088 if (!vrf_name) {
2089 struct vrf *vrf;
2090 struct zebra_vrf *zvrf;
2091
2092 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2093 zvrf = vrf->info;
2094 if ((zvrf == NULL)
2095 || (zvrf->table[afi][SAFI_UNICAST] == NULL))
2096 continue;
2097
2098 table = zvrf->table[afi][SAFI_UNICAST];
2099 show_ip_route_dump_vty(vty, table);
2100 }
2101 } else {
2102 vrf_id_t vrf_id = VRF_DEFAULT;
2103
2104 VRF_GET_ID(vrf_id, vrf_name, true);
2105
2106 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2107 if (!table)
2108 return CMD_SUCCESS;
2109
2110 show_ip_route_dump_vty(vty, table);
2111 }
2112
2113 return CMD_SUCCESS;
2114 }
2115
2116 static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
2117 struct route_entry *re, unsigned int num)
2118 {
2119
2120 char buf[SRCDEST2STR_BUFFER];
2121
2122 vty_out(vty, " Nexthop %u:\n", num);
2123 vty_out(vty, " type: %u\n", nexthop->type);
2124 vty_out(vty, " flags: %u\n", nexthop->flags);
2125 switch (nexthop->type) {
2126 case NEXTHOP_TYPE_IPV4:
2127 case NEXTHOP_TYPE_IPV4_IFINDEX:
2128 vty_out(vty, " ip address: %s\n",
2129 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
2130 sizeof(buf)));
2131 vty_out(vty, " afi: ipv4\n");
2132
2133 if (nexthop->ifindex) {
2134 vty_out(vty, " interface index: %d\n",
2135 nexthop->ifindex);
2136 vty_out(vty, " interface name: %s\n",
2137 ifindex2ifname(nexthop->ifindex,
2138 nexthop->vrf_id));
2139 }
2140
2141 if (nexthop->src.ipv4.s_addr
2142 && (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
2143 sizeof(buf))))
2144 vty_out(vty, " source: %s\n", buf);
2145 break;
2146 case NEXTHOP_TYPE_IPV6:
2147 case NEXTHOP_TYPE_IPV6_IFINDEX:
2148 vty_out(vty, " ip: %s\n",
2149 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
2150 sizeof(buf)));
2151 vty_out(vty, " afi: ipv6\n");
2152
2153 if (nexthop->ifindex) {
2154 vty_out(vty, " interface index: %d\n",
2155 nexthop->ifindex);
2156 vty_out(vty, " interface name: %s\n",
2157 ifindex2ifname(nexthop->ifindex,
2158 nexthop->vrf_id));
2159 }
2160
2161 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
2162 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
2163 sizeof(buf)))
2164 vty_out(vty, " source: %s\n", buf);
2165 }
2166 break;
2167 case NEXTHOP_TYPE_IFINDEX:
2168 vty_out(vty,
2169 " Nexthop is an interface (directly connected).\n");
2170 vty_out(vty, " interface index: %d\n", nexthop->ifindex);
2171 vty_out(vty, " interface name: %s\n",
2172 ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
2173 break;
2174 case NEXTHOP_TYPE_BLACKHOLE:
2175 vty_out(vty, " Nexthop type is blackhole.\n");
2176
2177 switch (nexthop->bh_type) {
2178 case BLACKHOLE_REJECT:
2179 vty_out(vty, " Blackhole type: reject\n");
2180 break;
2181 case BLACKHOLE_ADMINPROHIB:
2182 vty_out(vty,
2183 " Blackhole type: admin-prohibited\n");
2184 break;
2185 case BLACKHOLE_NULL:
2186 vty_out(vty, " Blackhole type: NULL0\n");
2187 break;
2188 case BLACKHOLE_UNSPEC:
2189 break;
2190 }
2191 break;
2192 }
2193 }
2194
2195 static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
2196 {
2197 struct route_node *rn;
2198 struct route_entry *re;
2199 char buf[SRCDEST2STR_BUFFER];
2200 char time[20];
2201 time_t uptime;
2202 struct tm tm;
2203 struct timeval tv;
2204 struct nexthop *nexthop = NULL;
2205 int nexthop_num = 0;
2206
2207 vty_out(vty, "\nIPv4/IPv6 Routing table dump\n");
2208 vty_out(vty, "----------------------------\n");
2209
2210 for (rn = route_top(table); rn; rn = route_next(rn)) {
2211 RNODE_FOREACH_RE (rn, re) {
2212 vty_out(vty, "Route: %s\n",
2213 srcdest_rnode2str(rn, buf, sizeof(buf)));
2214 vty_out(vty, " protocol: %s\n",
2215 zebra_route_string(re->type));
2216 vty_out(vty, " instance: %u\n", re->instance);
2217 vty_out(vty, " VRF ID: %u\n", re->vrf_id);
2218 vty_out(vty, " VRF name: %s\n",
2219 vrf_id_to_name(re->vrf_id));
2220 vty_out(vty, " flags: %u\n", re->flags);
2221
2222 if (re->type != ZEBRA_ROUTE_CONNECT) {
2223 vty_out(vty, " distance: %u\n", re->distance);
2224 vty_out(vty, " metric: %u\n", re->metric);
2225 }
2226
2227 vty_out(vty, " tag: %u\n", re->tag);
2228
2229 uptime = monotime(&tv);
2230 uptime -= re->uptime;
2231 gmtime_r(&uptime, &tm);
2232
2233 if (uptime < ONE_DAY_SECOND)
2234 snprintf(time, sizeof(time), "%02d:%02d:%02d",
2235 tm.tm_hour, tm.tm_min, tm.tm_sec);
2236 else if (uptime < ONE_WEEK_SECOND)
2237 snprintf(time, sizeof(time), "%dd%02dh%02dm",
2238 tm.tm_yday, tm.tm_hour, tm.tm_min);
2239 else
2240 snprintf(time, sizeof(time), "%02dw%dd%02dh",
2241 tm.tm_yday / 7,
2242 tm.tm_yday - ((tm.tm_yday / 7) * 7),
2243 tm.tm_hour);
2244
2245 vty_out(vty, " status: %u\n", re->status);
2246 vty_out(vty, " nexthop_num: %u\n",
2247 nexthop_group_nexthop_num(&(re->nhe->nhg)));
2248 vty_out(vty, " nexthop_active_num: %u\n",
2249 nexthop_group_active_nexthop_num(
2250 &(re->nhe->nhg)));
2251 vty_out(vty, " table: %u\n", re->table);
2252 vty_out(vty, " uptime: %s\n", time);
2253
2254 for (ALL_NEXTHOPS_PTR(&(re->nhe->nhg), nexthop)) {
2255 nexthop_num++;
2256 show_ip_route_nht_dump(vty, nexthop, re,
2257 nexthop_num);
2258 }
2259
2260 nexthop_num = 0;
2261 vty_out(vty, "\n");
2262 }
2263 }
2264 }
2265
2266 static void vty_show_ip_route_summary(struct vty *vty,
2267 struct route_table *table, bool use_json)
2268 {
2269 struct route_node *rn;
2270 struct route_entry *re;
2271 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2272 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2273 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2274 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2275 uint32_t offload_cnt[ZEBRA_ROUTE_TOTAL + 1];
2276 uint32_t trap_cnt[ZEBRA_ROUTE_TOTAL + 1];
2277 uint32_t i;
2278 uint32_t is_ibgp;
2279 json_object *json_route_summary = NULL;
2280 json_object *json_route_routes = NULL;
2281
2282 memset(&rib_cnt, 0, sizeof(rib_cnt));
2283 memset(&fib_cnt, 0, sizeof(fib_cnt));
2284 memset(&offload_cnt, 0, sizeof(offload_cnt));
2285 memset(&trap_cnt, 0, sizeof(trap_cnt));
2286
2287 if (use_json) {
2288 json_route_summary = json_object_new_object();
2289 json_route_routes = json_object_new_array();
2290 json_object_object_add(json_route_summary, "routes",
2291 json_route_routes);
2292 }
2293
2294 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2295 RNODE_FOREACH_RE (rn, re) {
2296 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
2297 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
2298
2299 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2300 if (is_ibgp)
2301 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2302 else
2303 rib_cnt[re->type]++;
2304
2305 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
2306 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2307
2308 if (is_ibgp)
2309 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2310 else
2311 fib_cnt[re->type]++;
2312 }
2313
2314 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) {
2315 if (is_ibgp)
2316 trap_cnt[ZEBRA_ROUTE_IBGP]++;
2317 else
2318 trap_cnt[re->type]++;
2319 }
2320
2321 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) {
2322 if (is_ibgp)
2323 offload_cnt[ZEBRA_ROUTE_IBGP]++;
2324 else
2325 offload_cnt[re->type]++;
2326 }
2327 }
2328
2329 if (!use_json)
2330 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2331 "Routes", "FIB",
2332 zvrf_name(((struct rib_table_info *)
2333 route_table_get_info(table))
2334 ->zvrf));
2335
2336 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2337 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
2338 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
2339 if (i == ZEBRA_ROUTE_BGP) {
2340 if (use_json) {
2341 json_object *json_route_ebgp =
2342 json_object_new_object();
2343
2344 json_object_int_add(
2345 json_route_ebgp, "fib",
2346 fib_cnt[ZEBRA_ROUTE_BGP]);
2347 json_object_int_add(
2348 json_route_ebgp, "rib",
2349 rib_cnt[ZEBRA_ROUTE_BGP]);
2350 json_object_int_add(
2351 json_route_ebgp, "fibOffLoaded",
2352 offload_cnt[ZEBRA_ROUTE_BGP]);
2353 json_object_int_add(
2354 json_route_ebgp, "fibTrapped",
2355 trap_cnt[ZEBRA_ROUTE_BGP]);
2356
2357 json_object_string_add(json_route_ebgp,
2358 "type", "ebgp");
2359 json_object_array_add(json_route_routes,
2360 json_route_ebgp);
2361
2362 json_object *json_route_ibgp =
2363 json_object_new_object();
2364
2365 json_object_int_add(
2366 json_route_ibgp, "fib",
2367 fib_cnt[ZEBRA_ROUTE_IBGP]);
2368 json_object_int_add(
2369 json_route_ibgp, "rib",
2370 rib_cnt[ZEBRA_ROUTE_IBGP]);
2371 json_object_int_add(
2372 json_route_ibgp, "fibOffLoaded",
2373 offload_cnt[ZEBRA_ROUTE_IBGP]);
2374 json_object_int_add(
2375 json_route_ibgp, "fibTrapped",
2376 trap_cnt[ZEBRA_ROUTE_IBGP]);
2377 json_object_string_add(json_route_ibgp,
2378 "type", "ibgp");
2379 json_object_array_add(json_route_routes,
2380 json_route_ibgp);
2381 } else {
2382 vty_out(vty, "%-20s %-20d %-20d \n",
2383 "ebgp",
2384 rib_cnt[ZEBRA_ROUTE_BGP],
2385 fib_cnt[ZEBRA_ROUTE_BGP]);
2386 vty_out(vty, "%-20s %-20d %-20d \n",
2387 "ibgp",
2388 rib_cnt[ZEBRA_ROUTE_IBGP],
2389 fib_cnt[ZEBRA_ROUTE_IBGP]);
2390 }
2391 } else {
2392 if (use_json) {
2393 json_object *json_route_type =
2394 json_object_new_object();
2395
2396 json_object_int_add(json_route_type,
2397 "fib", fib_cnt[i]);
2398 json_object_int_add(json_route_type,
2399 "rib", rib_cnt[i]);
2400
2401 json_object_int_add(json_route_type,
2402 "fibOffLoaded",
2403 offload_cnt[i]);
2404 json_object_int_add(json_route_type,
2405 "fibTrapped",
2406 trap_cnt[i]);
2407 json_object_string_add(
2408 json_route_type, "type",
2409 zebra_route_string(i));
2410 json_object_array_add(json_route_routes,
2411 json_route_type);
2412 } else
2413 vty_out(vty, "%-20s %-20d %-20d \n",
2414 zebra_route_string(i),
2415 rib_cnt[i], fib_cnt[i]);
2416 }
2417 }
2418 }
2419
2420 if (use_json) {
2421 json_object_int_add(json_route_summary, "routesTotal",
2422 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2423 json_object_int_add(json_route_summary, "routesTotalFib",
2424 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2425
2426 vty_json(vty, json_route_summary);
2427 } else {
2428 vty_out(vty, "------\n");
2429 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2430 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2431 vty_out(vty, "\n");
2432 }
2433 }
2434
2435 /*
2436 * Implementation of the ip route summary prefix command.
2437 *
2438 * This command prints the primary prefixes that have been installed by various
2439 * protocols on the box.
2440 *
2441 */
2442 static void vty_show_ip_route_summary_prefix(struct vty *vty,
2443 struct route_table *table,
2444 bool use_json)
2445 {
2446 struct route_node *rn;
2447 struct route_entry *re;
2448 struct nexthop *nexthop;
2449 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2450 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2451 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2452 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2453 uint32_t i;
2454 int cnt;
2455 json_object *json_route_summary = NULL;
2456 json_object *json_route_routes = NULL;
2457
2458 memset(&rib_cnt, 0, sizeof(rib_cnt));
2459 memset(&fib_cnt, 0, sizeof(fib_cnt));
2460
2461 if (use_json) {
2462 json_route_summary = json_object_new_object();
2463 json_route_routes = json_object_new_array();
2464 json_object_object_add(json_route_summary, "prefixRoutes",
2465 json_route_routes);
2466 }
2467
2468 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2469 RNODE_FOREACH_RE (rn, re) {
2470
2471 /*
2472 * In case of ECMP, count only once.
2473 */
2474 cnt = 0;
2475 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
2476 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2477 fib_cnt[re->type]++;
2478 }
2479 for (nexthop = re->nhe->nhg.nexthop; (!cnt && nexthop);
2480 nexthop = nexthop->next) {
2481 cnt++;
2482 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2483 rib_cnt[re->type]++;
2484 if (re->type == ZEBRA_ROUTE_BGP
2485 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
2486 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2487 if (CHECK_FLAG(re->status,
2488 ROUTE_ENTRY_INSTALLED))
2489 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2490 }
2491 }
2492 }
2493
2494 if (!use_json)
2495 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2496 "Prefix Routes", "FIB",
2497 zvrf_name(((struct rib_table_info *)
2498 route_table_get_info(table))
2499 ->zvrf));
2500
2501 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2502 if (rib_cnt[i] > 0) {
2503 if (i == ZEBRA_ROUTE_BGP) {
2504 if (use_json) {
2505 json_object *json_route_ebgp =
2506 json_object_new_object();
2507
2508 json_object_int_add(
2509 json_route_ebgp, "fib",
2510 fib_cnt[ZEBRA_ROUTE_BGP]
2511 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2512 json_object_int_add(
2513 json_route_ebgp, "rib",
2514 rib_cnt[ZEBRA_ROUTE_BGP]
2515 - rib_cnt[ZEBRA_ROUTE_IBGP]);
2516 json_object_string_add(json_route_ebgp,
2517 "type", "ebgp");
2518 json_object_array_add(json_route_routes,
2519 json_route_ebgp);
2520
2521 json_object *json_route_ibgp =
2522 json_object_new_object();
2523
2524 json_object_int_add(
2525 json_route_ibgp, "fib",
2526 fib_cnt[ZEBRA_ROUTE_IBGP]);
2527 json_object_int_add(
2528 json_route_ibgp, "rib",
2529 rib_cnt[ZEBRA_ROUTE_IBGP]);
2530 json_object_string_add(json_route_ibgp,
2531 "type", "ibgp");
2532 json_object_array_add(json_route_routes,
2533 json_route_ibgp);
2534 } else {
2535 vty_out(vty, "%-20s %-20d %-20d \n",
2536 "ebgp",
2537 rib_cnt[ZEBRA_ROUTE_BGP]
2538 - rib_cnt[ZEBRA_ROUTE_IBGP],
2539 fib_cnt[ZEBRA_ROUTE_BGP]
2540 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2541 vty_out(vty, "%-20s %-20d %-20d \n",
2542 "ibgp",
2543 rib_cnt[ZEBRA_ROUTE_IBGP],
2544 fib_cnt[ZEBRA_ROUTE_IBGP]);
2545 }
2546 } else {
2547 if (use_json) {
2548 json_object *json_route_type =
2549 json_object_new_object();
2550
2551 json_object_int_add(json_route_type,
2552 "fib", fib_cnt[i]);
2553 json_object_int_add(json_route_type,
2554 "rib", rib_cnt[i]);
2555 json_object_string_add(
2556 json_route_type, "type",
2557 zebra_route_string(i));
2558 json_object_array_add(json_route_routes,
2559 json_route_type);
2560 } else
2561 vty_out(vty, "%-20s %-20d %-20d \n",
2562 zebra_route_string(i),
2563 rib_cnt[i], fib_cnt[i]);
2564 }
2565 }
2566 }
2567
2568 if (use_json) {
2569 json_object_int_add(json_route_summary, "prefixRoutesTotal",
2570 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2571 json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
2572 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2573
2574 vty_json(vty, json_route_summary);
2575 } else {
2576 vty_out(vty, "------\n");
2577 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2578 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2579 vty_out(vty, "\n");
2580 }
2581 }
2582
2583 DEFUN (allow_external_route_update,
2584 allow_external_route_update_cmd,
2585 "allow-external-route-update",
2586 "Allow FRR routes to be overwritten by external processes\n")
2587 {
2588 zrouter.allow_delete = true;
2589
2590 return CMD_SUCCESS;
2591 }
2592
2593 DEFUN (no_allow_external_route_update,
2594 no_allow_external_route_update_cmd,
2595 "no allow-external-route-update",
2596 NO_STR
2597 "Allow FRR routes to be overwritten by external processes\n")
2598 {
2599 zrouter.allow_delete = false;
2600
2601 return CMD_SUCCESS;
2602 }
2603
2604 /* show vrf */
2605 DEFUN (show_vrf,
2606 show_vrf_cmd,
2607 "show vrf",
2608 SHOW_STR
2609 "VRF\n")
2610 {
2611 struct vrf *vrf;
2612 struct zebra_vrf *zvrf;
2613
2614 if (vrf_is_backend_netns())
2615 vty_out(vty, "netns-based vrfs\n");
2616
2617 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2618 if (!(zvrf = vrf->info))
2619 continue;
2620 if (zvrf_id(zvrf) == VRF_DEFAULT)
2621 continue;
2622
2623 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2624 if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2625 vty_out(vty, "inactive");
2626 else if (zvrf_ns_name(zvrf))
2627 vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2628 zvrf_ns_name(zvrf));
2629 else
2630 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2631 zvrf->table_id);
2632 if (vrf_is_user_cfged(vrf))
2633 vty_out(vty, " (configured)");
2634 vty_out(vty, "\n");
2635 }
2636
2637 return CMD_SUCCESS;
2638 }
2639
2640 DEFPY (evpn_mh_mac_holdtime,
2641 evpn_mh_mac_holdtime_cmd,
2642 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2643 NO_STR
2644 "EVPN\n"
2645 "Multihoming\n"
2646 "MAC hold time\n"
2647 "Duration in seconds\n")
2648 {
2649 return zebra_evpn_mh_mac_holdtime_update(vty, duration,
2650 no ? true : false);
2651 }
2652
2653 DEFPY (evpn_mh_neigh_holdtime,
2654 evpn_mh_neigh_holdtime_cmd,
2655 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2656 NO_STR
2657 "EVPN\n"
2658 "Multihoming\n"
2659 "Neighbor entry hold time\n"
2660 "Duration in seconds\n")
2661 {
2662
2663 return zebra_evpn_mh_neigh_holdtime_update(vty, duration,
2664 no ? true : false);
2665 }
2666
2667 DEFPY (evpn_mh_startup_delay,
2668 evpn_mh_startup_delay_cmd,
2669 "[no] evpn mh startup-delay(0-3600)$duration",
2670 NO_STR
2671 "EVPN\n"
2672 "Multihoming\n"
2673 "Startup delay\n"
2674 "duration in seconds\n")
2675 {
2676
2677 return zebra_evpn_mh_startup_delay_update(vty, duration,
2678 no ? true : false);
2679 }
2680
2681 DEFPY(evpn_mh_redirect_off, evpn_mh_redirect_off_cmd,
2682 "[no$no] evpn mh redirect-off",
2683 NO_STR
2684 "EVPN\n"
2685 "Multihoming\n"
2686 "ES bond redirect for fast-failover off\n")
2687 {
2688 bool redirect_off;
2689
2690 redirect_off = no ? false : true;
2691
2692 return zebra_evpn_mh_redirect_off(vty, redirect_off);
2693 }
2694
2695 DEFUN (default_vrf_vni_mapping,
2696 default_vrf_vni_mapping_cmd,
2697 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2698 "VNI corresponding to the DEFAULT VRF\n"
2699 "VNI-ID\n"
2700 "Prefix routes only \n")
2701 {
2702 char xpath[XPATH_MAXLEN];
2703 struct zebra_vrf *zvrf = NULL;
2704 int filter = 0;
2705
2706 zvrf = vrf_info_lookup(VRF_DEFAULT);
2707 if (!zvrf)
2708 return CMD_WARNING;
2709
2710 if (argc == 3)
2711 filter = 1;
2712
2713 snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
2714 VRF_DEFAULT_NAME);
2715 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
2716
2717 snprintf(xpath, sizeof(xpath),
2718 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
2719 VRF_DEFAULT_NAME);
2720 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[1]->arg);
2721
2722 if (filter) {
2723 snprintf(xpath, sizeof(xpath),
2724 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
2725 VRF_DEFAULT_NAME);
2726 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "true");
2727 }
2728
2729 return nb_cli_apply_changes(vty, NULL);
2730 }
2731
2732 DEFUN (no_default_vrf_vni_mapping,
2733 no_default_vrf_vni_mapping_cmd,
2734 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2735 NO_STR
2736 "VNI corresponding to DEFAULT VRF\n"
2737 "VNI-ID\n"
2738 "Prefix routes only \n")
2739 {
2740 char xpath[XPATH_MAXLEN];
2741 int filter = 0;
2742 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2743 struct zebra_vrf *zvrf = NULL;
2744
2745 zvrf = vrf_info_lookup(VRF_DEFAULT);
2746 if (!zvrf)
2747 return CMD_WARNING;
2748
2749 if (argc == 4)
2750 filter = 1;
2751
2752 if (zvrf->l3vni != vni) {
2753 vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
2754 zvrf->vrf->name);
2755 return CMD_WARNING;
2756 }
2757
2758 snprintf(xpath, sizeof(xpath),
2759 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
2760 VRF_DEFAULT_NAME);
2761 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, argv[2]->arg);
2762
2763 if (filter) {
2764 snprintf(xpath, sizeof(xpath),
2765 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
2766 VRF_DEFAULT_NAME);
2767 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, "true");
2768 }
2769
2770 snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
2771 VRF_DEFAULT_NAME);
2772 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
2773
2774 return nb_cli_apply_changes(vty, NULL);
2775 }
2776
2777 DEFUN (vrf_vni_mapping,
2778 vrf_vni_mapping_cmd,
2779 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2780 "VNI corresponding to tenant VRF\n"
2781 "VNI-ID\n"
2782 "prefix-routes-only\n")
2783 {
2784 int filter = 0;
2785
2786 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
2787
2788 assert(vrf);
2789 assert(zvrf);
2790
2791 if (argc == 3)
2792 filter = 1;
2793
2794 nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_CREATE, NULL);
2795 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY,
2796 argv[1]->arg);
2797
2798 if (filter)
2799 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2800 NB_OP_MODIFY, "true");
2801
2802 return nb_cli_apply_changes(vty, NULL);
2803 }
2804
2805 DEFUN (no_vrf_vni_mapping,
2806 no_vrf_vni_mapping_cmd,
2807 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2808 NO_STR
2809 "VNI corresponding to tenant VRF\n"
2810 "VNI-ID\n"
2811 "prefix-routes-only\n")
2812 {
2813 int filter = 0;
2814
2815 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
2816 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2817
2818 assert(vrf);
2819 assert(zvrf);
2820
2821 if (argc == 4)
2822 filter = 1;
2823
2824 if (zvrf->l3vni != vni) {
2825 vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
2826 zvrf->vrf->name);
2827 return CMD_WARNING;
2828 }
2829
2830 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY,
2831 argv[2]->arg);
2832
2833 if (filter)
2834 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2835 NB_OP_DESTROY, "true");
2836
2837 nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_DESTROY, NULL);
2838
2839 return nb_cli_apply_changes(vty, NULL);
2840 }
2841
2842 /* show vrf */
2843 DEFPY (show_vrf_vni,
2844 show_vrf_vni_cmd,
2845 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2846 SHOW_STR
2847 VRF_FULL_CMD_HELP_STR
2848 "VNI\n"
2849 JSON_STR)
2850 {
2851 struct vrf *vrf;
2852 struct zebra_vrf *zvrf;
2853 json_object *json = NULL;
2854 json_object *json_vrfs = NULL;
2855 bool uj = use_json(argc, argv);
2856 bool use_vrf = false;
2857
2858 if (uj)
2859 json = json_object_new_object();
2860
2861 /* show vrf vni used to display across all vrfs
2862 * This is enhanced to support only for specific
2863 * vrf based output.
2864 */
2865 if (vrf_all || !vrf_name) {
2866 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2867 zvrf = vrf->info;
2868 if (!zvrf)
2869 continue;
2870
2871 use_vrf = true;
2872 break;
2873 }
2874 if (use_vrf) {
2875 if (!uj)
2876 vty_out(vty,
2877 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2878 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2879 "State", "Rmac");
2880 else
2881 json_vrfs = json_object_new_array();
2882 } else {
2883 if (uj)
2884 vty_json(vty, json);
2885 else
2886 vty_out(vty, "%% VRF does not exist\n");
2887
2888 return CMD_WARNING;
2889 }
2890 }
2891
2892 if (use_vrf) {
2893 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2894 zvrf = vrf->info;
2895 if (!zvrf)
2896 continue;
2897
2898 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2899 }
2900 } else if (vrf_name) {
2901 zvrf = zebra_vrf_lookup_by_name(vrf_name);
2902 if (!zvrf) {
2903 if (uj)
2904 vty_json(vty, json);
2905 else
2906 vty_out(vty,
2907 "%% VRF '%s' specified does not exist\n",
2908 vrf_name);
2909
2910 return CMD_WARNING;
2911 }
2912
2913 if (!uj)
2914 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2915 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2916 "Rmac");
2917 else
2918 json_vrfs = json_object_new_array();
2919
2920 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2921 }
2922
2923 if (uj) {
2924 json_object_object_add(json, "vrfs", json_vrfs);
2925 vty_json(vty, json);
2926 }
2927
2928 return CMD_SUCCESS;
2929 }
2930
2931 DEFUN (show_evpn_global,
2932 show_evpn_global_cmd,
2933 "show evpn [json]",
2934 SHOW_STR
2935 "EVPN\n"
2936 JSON_STR)
2937 {
2938 bool uj = use_json(argc, argv);
2939
2940 zebra_vxlan_print_evpn(vty, uj);
2941 return CMD_SUCCESS;
2942 }
2943
2944 DEFPY(show_evpn_neigh, show_neigh_cmd, "show ip neigh",
2945 SHOW_STR IP_STR "neighbors\n")
2946
2947 {
2948 zebra_neigh_show(vty);
2949
2950 return CMD_SUCCESS;
2951 }
2952
2953 DEFPY(show_evpn_l2_nh,
2954 show_evpn_l2_nh_cmd,
2955 "show evpn l2-nh [json$json]",
2956 SHOW_STR
2957 "EVPN\n"
2958 "Layer2 nexthops\n"
2959 JSON_STR)
2960 {
2961 bool uj = !!json;
2962
2963 zebra_evpn_l2_nh_show(vty, uj);
2964
2965 return CMD_SUCCESS;
2966 }
2967
2968 DEFPY(show_evpn_es,
2969 show_evpn_es_cmd,
2970 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2971 SHOW_STR
2972 "EVPN\n"
2973 "Ethernet Segment\n"
2974 "ES ID\n"
2975 "Detailed information\n"
2976 JSON_STR)
2977 {
2978 esi_t esi;
2979 bool uj = !!json;
2980
2981 if (esi_str) {
2982 if (!str_to_esi(esi_str, &esi)) {
2983 vty_out(vty, "%% Malformed ESI\n");
2984 return CMD_WARNING;
2985 }
2986 zebra_evpn_es_show_esi(vty, uj, &esi);
2987 } else {
2988 if (detail)
2989 zebra_evpn_es_show_detail(vty, uj);
2990 else
2991 zebra_evpn_es_show(vty, uj);
2992 }
2993
2994 return CMD_SUCCESS;
2995 }
2996
2997 DEFPY(show_evpn_es_evi,
2998 show_evpn_es_evi_cmd,
2999 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3000 SHOW_STR
3001 "EVPN\n"
3002 "Ethernet Segment per EVI\n"
3003 "VxLAN Network Identifier\n"
3004 "VNI\n"
3005 "Detailed information\n"
3006 JSON_STR)
3007 {
3008 bool uj = !!json;
3009 bool ud = !!detail;
3010
3011 if (vni)
3012 zebra_evpn_es_evi_show_vni(vty, uj, vni, ud);
3013 else
3014 zebra_evpn_es_evi_show(vty, uj, ud);
3015
3016 return CMD_SUCCESS;
3017 }
3018
3019 DEFPY(show_evpn_access_vlan, show_evpn_access_vlan_cmd,
3020 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3021 SHOW_STR
3022 "EVPN\n"
3023 "Access VLANs\n"
3024 "VLAN ID\n"
3025 "Detailed information\n" JSON_STR)
3026 {
3027 bool uj = !!json;
3028
3029 if (if_name && vid) {
3030 bool found = false;
3031 struct vrf *vrf;
3032 struct interface *ifp;
3033
3034 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3035 if (if_name) {
3036 ifp = if_lookup_by_name(if_name, vrf->vrf_id);
3037 if (ifp) {
3038 zebra_evpn_acc_vl_show_vid(vty, uj, vid,
3039 ifp);
3040 found = true;
3041 break;
3042 }
3043 }
3044 }
3045 if (!found) {
3046 vty_out(vty, "%% Can't find interface %s\n", if_name);
3047 return CMD_WARNING;
3048 }
3049 } else {
3050 if (detail)
3051 zebra_evpn_acc_vl_show_detail(vty, uj);
3052 else
3053 zebra_evpn_acc_vl_show(vty, uj);
3054 }
3055
3056 return CMD_SUCCESS;
3057 }
3058
3059 DEFUN (show_evpn_vni,
3060 show_evpn_vni_cmd,
3061 "show evpn vni [json]",
3062 SHOW_STR
3063 "EVPN\n"
3064 "VxLAN Network Identifier\n"
3065 JSON_STR)
3066 {
3067 struct zebra_vrf *zvrf;
3068 bool uj = use_json(argc, argv);
3069
3070 zvrf = zebra_vrf_get_evpn();
3071 zebra_vxlan_print_vnis(vty, zvrf, uj);
3072 return CMD_SUCCESS;
3073 }
3074
3075 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
3076 "show evpn vni detail [json]",
3077 SHOW_STR
3078 "EVPN\n"
3079 "VxLAN Network Identifier\n"
3080 "Detailed Information On Each VNI\n"
3081 JSON_STR)
3082 {
3083 struct zebra_vrf *zvrf;
3084 bool uj = use_json(argc, argv);
3085
3086 zvrf = zebra_vrf_get_evpn();
3087 zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
3088 return CMD_SUCCESS;
3089 }
3090
3091 DEFUN (show_evpn_vni_vni,
3092 show_evpn_vni_vni_cmd,
3093 "show evpn vni " CMD_VNI_RANGE "[json]",
3094 SHOW_STR
3095 "EVPN\n"
3096 "VxLAN Network Identifier\n"
3097 "VNI number\n"
3098 JSON_STR)
3099 {
3100 struct zebra_vrf *zvrf;
3101 vni_t vni;
3102 bool uj = use_json(argc, argv);
3103
3104 vni = strtoul(argv[3]->arg, NULL, 10);
3105 zvrf = zebra_vrf_get_evpn();
3106 zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
3107 return CMD_SUCCESS;
3108 }
3109
3110 DEFUN (show_evpn_rmac_vni_mac,
3111 show_evpn_rmac_vni_mac_cmd,
3112 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
3113 SHOW_STR
3114 "EVPN\n"
3115 "RMAC\n"
3116 "L3 VNI\n"
3117 "VNI number\n"
3118 "MAC\n"
3119 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3120 JSON_STR)
3121 {
3122 vni_t l3vni = 0;
3123 struct ethaddr mac;
3124 bool uj = use_json(argc, argv);
3125
3126 l3vni = strtoul(argv[4]->arg, NULL, 10);
3127 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3128 vty_out(vty, "%% Malformed MAC address\n");
3129 return CMD_WARNING;
3130 }
3131 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
3132 return CMD_SUCCESS;
3133 }
3134
3135 DEFUN (show_evpn_rmac_vni,
3136 show_evpn_rmac_vni_cmd,
3137 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
3138 SHOW_STR
3139 "EVPN\n"
3140 "RMAC\n"
3141 "L3 VNI\n"
3142 "VNI number\n"
3143 JSON_STR)
3144 {
3145 vni_t l3vni = 0;
3146 bool uj = use_json(argc, argv);
3147
3148 l3vni = strtoul(argv[4]->arg, NULL, 10);
3149 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
3150
3151 return CMD_SUCCESS;
3152 }
3153
3154 DEFUN (show_evpn_rmac_vni_all,
3155 show_evpn_rmac_vni_all_cmd,
3156 "show evpn rmac vni all [json]",
3157 SHOW_STR
3158 "EVPN\n"
3159 "RMAC addresses\n"
3160 "L3 VNI\n"
3161 "All VNIs\n"
3162 JSON_STR)
3163 {
3164 bool uj = use_json(argc, argv);
3165
3166 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
3167
3168 return CMD_SUCCESS;
3169 }
3170
3171 DEFUN (show_evpn_nh_vni_ip,
3172 show_evpn_nh_vni_ip_cmd,
3173 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
3174 SHOW_STR
3175 "EVPN\n"
3176 "Remote Vteps\n"
3177 "L3 VNI\n"
3178 "VNI number\n"
3179 "Ip address\n"
3180 "Host address (ipv4 or ipv6)\n"
3181 JSON_STR)
3182 {
3183 vni_t l3vni;
3184 struct ipaddr ip;
3185 bool uj = use_json(argc, argv);
3186
3187 l3vni = strtoul(argv[4]->arg, NULL, 10);
3188 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3189 if (!uj)
3190 vty_out(vty, "%% Malformed Neighbor address\n");
3191 return CMD_WARNING;
3192 }
3193 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
3194
3195 return CMD_SUCCESS;
3196 }
3197
3198 DEFUN (show_evpn_nh_vni,
3199 show_evpn_nh_vni_cmd,
3200 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
3201 SHOW_STR
3202 "EVPN\n"
3203 "Remote Vteps\n"
3204 "L3 VNI\n"
3205 "VNI number\n"
3206 JSON_STR)
3207 {
3208 vni_t l3vni;
3209 bool uj = use_json(argc, argv);
3210
3211 l3vni = strtoul(argv[4]->arg, NULL, 10);
3212 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
3213
3214 return CMD_SUCCESS;
3215 }
3216
3217 DEFUN (show_evpn_nh_vni_all,
3218 show_evpn_nh_vni_all_cmd,
3219 "show evpn next-hops vni all [json]",
3220 SHOW_STR
3221 "EVPN\n"
3222 "Remote VTEPs\n"
3223 "L3 VNI\n"
3224 "All VNIs\n"
3225 JSON_STR)
3226 {
3227 bool uj = use_json(argc, argv);
3228
3229 zebra_vxlan_print_nh_all_l3vni(vty, uj);
3230
3231 return CMD_SUCCESS;
3232 }
3233
3234 DEFUN (show_evpn_mac_vni,
3235 show_evpn_mac_vni_cmd,
3236 "show evpn mac vni " CMD_VNI_RANGE "[json]",
3237 SHOW_STR
3238 "EVPN\n"
3239 "MAC addresses\n"
3240 "VxLAN Network Identifier\n"
3241 "VNI number\n"
3242 JSON_STR)
3243 {
3244 struct zebra_vrf *zvrf;
3245 vni_t vni;
3246 bool uj = use_json(argc, argv);
3247
3248 vni = strtoul(argv[4]->arg, NULL, 10);
3249 zvrf = zebra_vrf_get_evpn();
3250 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, false);
3251 return CMD_SUCCESS;
3252 }
3253
3254 DEFPY (show_evpn_mac_vni_detail,
3255 show_evpn_mac_vni_detail_cmd,
3256 "show evpn mac vni " CMD_VNI_RANGE " detail [json]",
3257 SHOW_STR
3258 "EVPN\n"
3259 "MAC addresses\n"
3260 "VXLAN Network Identifier\n"
3261 "VNI number\n"
3262 "Detailed Information On Each VNI MAC\n"
3263 JSON_STR)
3264 {
3265 struct zebra_vrf *zvrf;
3266 bool uj = use_json(argc, argv);
3267
3268 zvrf = zebra_vrf_get_evpn();
3269 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, true);
3270 return CMD_SUCCESS;
3271 }
3272
3273 DEFUN (show_evpn_mac_vni_all,
3274 show_evpn_mac_vni_all_cmd,
3275 "show evpn mac vni all [json]",
3276 SHOW_STR
3277 "EVPN\n"
3278 "MAC addresses\n"
3279 "VxLAN Network Identifier\n"
3280 "All VNIs\n"
3281 JSON_STR)
3282 {
3283 struct zebra_vrf *zvrf;
3284 bool uj = use_json(argc, argv);
3285
3286 zvrf = zebra_vrf_get_evpn();
3287 zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
3288 return CMD_SUCCESS;
3289 }
3290
3291 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
3292 "show evpn mac vni all detail [json]",
3293 SHOW_STR
3294 "EVPN\n"
3295 "MAC addresses\n"
3296 "VxLAN Network Identifier\n"
3297 "All VNIs\n"
3298 "Detailed Information On Each VNI MAC\n"
3299 JSON_STR)
3300 {
3301 struct zebra_vrf *zvrf;
3302 bool uj = use_json(argc, argv);
3303
3304 zvrf = zebra_vrf_get_evpn();
3305 zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
3306 return CMD_SUCCESS;
3307 }
3308
3309 DEFUN (show_evpn_mac_vni_all_vtep,
3310 show_evpn_mac_vni_all_vtep_cmd,
3311 "show evpn mac vni all vtep A.B.C.D [json]",
3312 SHOW_STR
3313 "EVPN\n"
3314 "MAC addresses\n"
3315 "VxLAN Network Identifier\n"
3316 "All VNIs\n"
3317 "Remote VTEP\n"
3318 "Remote VTEP IP address\n"
3319 JSON_STR)
3320 {
3321 struct zebra_vrf *zvrf;
3322 struct in_addr vtep_ip;
3323 bool uj = use_json(argc, argv);
3324
3325 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3326 if (!uj)
3327 vty_out(vty, "%% Malformed VTEP IP address\n");
3328 return CMD_WARNING;
3329 }
3330 zvrf = zebra_vrf_get_evpn();
3331 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
3332
3333 return CMD_SUCCESS;
3334 }
3335
3336
3337 DEFUN (show_evpn_mac_vni_mac,
3338 show_evpn_mac_vni_mac_cmd,
3339 "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
3340 SHOW_STR
3341 "EVPN\n"
3342 "MAC addresses\n"
3343 "VxLAN Network Identifier\n"
3344 "VNI number\n"
3345 "MAC\n"
3346 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3347 JSON_STR)
3348
3349 {
3350 struct zebra_vrf *zvrf;
3351 vni_t vni;
3352 struct ethaddr mac;
3353 bool uj = use_json(argc, argv);
3354
3355 vni = strtoul(argv[4]->arg, NULL, 10);
3356 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3357 vty_out(vty, "%% Malformed MAC address\n");
3358 return CMD_WARNING;
3359 }
3360 zvrf = zebra_vrf_get_evpn();
3361 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
3362 return CMD_SUCCESS;
3363 }
3364
3365 DEFUN (show_evpn_mac_vni_vtep,
3366 show_evpn_mac_vni_vtep_cmd,
3367 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
3368 SHOW_STR
3369 "EVPN\n"
3370 "MAC addresses\n"
3371 "VxLAN Network Identifier\n"
3372 "VNI number\n"
3373 "Remote VTEP\n"
3374 "Remote VTEP IP address\n"
3375 JSON_STR)
3376 {
3377 struct zebra_vrf *zvrf;
3378 vni_t vni;
3379 struct in_addr vtep_ip;
3380 bool uj = use_json(argc, argv);
3381
3382 vni = strtoul(argv[4]->arg, NULL, 10);
3383 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3384 if (!uj)
3385 vty_out(vty, "%% Malformed VTEP IP address\n");
3386 return CMD_WARNING;
3387 }
3388
3389 zvrf = zebra_vrf_get_evpn();
3390 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3391 return CMD_SUCCESS;
3392 }
3393
3394 DEFPY (show_evpn_mac_vni_all_dad,
3395 show_evpn_mac_vni_all_dad_cmd,
3396 "show evpn mac vni all duplicate [json]",
3397 SHOW_STR
3398 "EVPN\n"
3399 "MAC addresses\n"
3400 "VxLAN Network Identifier\n"
3401 "All VNIs\n"
3402 "Duplicate address list\n"
3403 JSON_STR)
3404 {
3405 struct zebra_vrf *zvrf;
3406 bool uj = use_json(argc, argv);
3407
3408 zvrf = zebra_vrf_get_evpn();
3409 zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
3410 return CMD_SUCCESS;
3411 }
3412
3413
3414 DEFPY (show_evpn_mac_vni_dad,
3415 show_evpn_mac_vni_dad_cmd,
3416 "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
3417 SHOW_STR
3418 "EVPN\n"
3419 "MAC addresses\n"
3420 "VxLAN Network Identifier\n"
3421 "VNI number\n"
3422 "Duplicate address list\n"
3423 JSON_STR)
3424 {
3425 struct zebra_vrf *zvrf;
3426 bool uj = use_json(argc, argv);
3427
3428 zvrf = zebra_vrf_get_evpn();
3429
3430 zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
3431
3432 return CMD_SUCCESS;
3433 }
3434
3435 DEFPY (show_evpn_neigh_vni_dad,
3436 show_evpn_neigh_vni_dad_cmd,
3437 "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
3438 SHOW_STR
3439 "EVPN\n"
3440 "ARP and ND cache\n"
3441 "VxLAN Network Identifier\n"
3442 "VNI number\n"
3443 "Duplicate address list\n"
3444 JSON_STR)
3445 {
3446 struct zebra_vrf *zvrf;
3447 bool uj = use_json(argc, argv);
3448
3449 zvrf = zebra_vrf_get_evpn();
3450 zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
3451 return CMD_SUCCESS;
3452 }
3453
3454 DEFPY (show_evpn_neigh_vni_all_dad,
3455 show_evpn_neigh_vni_all_dad_cmd,
3456 "show evpn arp-cache vni all duplicate [json]",
3457 SHOW_STR
3458 "EVPN\n"
3459 "ARP and ND cache\n"
3460 "VxLAN Network Identifier\n"
3461 "All VNIs\n"
3462 "Duplicate address list\n"
3463 JSON_STR)
3464 {
3465 struct zebra_vrf *zvrf;
3466 bool uj = use_json(argc, argv);
3467
3468 zvrf = zebra_vrf_get_evpn();
3469 zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
3470 return CMD_SUCCESS;
3471 }
3472
3473
3474 DEFUN (show_evpn_neigh_vni,
3475 show_evpn_neigh_vni_cmd,
3476 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
3477 SHOW_STR
3478 "EVPN\n"
3479 "ARP and ND cache\n"
3480 "VxLAN Network Identifier\n"
3481 "VNI number\n"
3482 JSON_STR)
3483 {
3484 struct zebra_vrf *zvrf;
3485 vni_t vni;
3486 bool uj = use_json(argc, argv);
3487
3488 vni = strtoul(argv[4]->arg, NULL, 10);
3489 zvrf = zebra_vrf_get_evpn();
3490 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
3491 return CMD_SUCCESS;
3492 }
3493
3494 DEFUN (show_evpn_neigh_vni_all,
3495 show_evpn_neigh_vni_all_cmd,
3496 "show evpn arp-cache vni all [json]",
3497 SHOW_STR
3498 "EVPN\n"
3499 "ARP and ND cache\n"
3500 "VxLAN Network Identifier\n"
3501 "All VNIs\n"
3502 JSON_STR)
3503 {
3504 struct zebra_vrf *zvrf;
3505 bool uj = use_json(argc, argv);
3506
3507 zvrf = zebra_vrf_get_evpn();
3508 zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
3509 return CMD_SUCCESS;
3510 }
3511
3512 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
3513 "show evpn arp-cache vni all detail [json]",
3514 SHOW_STR
3515 "EVPN\n"
3516 "ARP and ND cache\n"
3517 "VxLAN Network Identifier\n"
3518 "All VNIs\n"
3519 "Neighbor details for all vnis in detail\n" JSON_STR)
3520 {
3521 struct zebra_vrf *zvrf;
3522 bool uj = use_json(argc, argv);
3523
3524 zvrf = zebra_vrf_get_evpn();
3525 zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
3526 return CMD_SUCCESS;
3527 }
3528
3529 DEFUN (show_evpn_neigh_vni_neigh,
3530 show_evpn_neigh_vni_neigh_cmd,
3531 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
3532 SHOW_STR
3533 "EVPN\n"
3534 "ARP and ND cache\n"
3535 "VxLAN Network Identifier\n"
3536 "VNI number\n"
3537 "Neighbor\n"
3538 "Neighbor address (IPv4 or IPv6 address)\n"
3539 JSON_STR)
3540 {
3541 struct zebra_vrf *zvrf;
3542 vni_t vni;
3543 struct ipaddr ip;
3544 bool uj = use_json(argc, argv);
3545
3546 vni = strtoul(argv[4]->arg, NULL, 10);
3547 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3548 if (!uj)
3549 vty_out(vty, "%% Malformed Neighbor address\n");
3550 return CMD_WARNING;
3551 }
3552 zvrf = zebra_vrf_get_evpn();
3553 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
3554 return CMD_SUCCESS;
3555 }
3556
3557 DEFUN (show_evpn_neigh_vni_vtep,
3558 show_evpn_neigh_vni_vtep_cmd,
3559 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
3560 SHOW_STR
3561 "EVPN\n"
3562 "ARP and ND cache\n"
3563 "VxLAN Network Identifier\n"
3564 "VNI number\n"
3565 "Remote VTEP\n"
3566 "Remote VTEP IP address\n"
3567 JSON_STR)
3568 {
3569 struct zebra_vrf *zvrf;
3570 vni_t vni;
3571 struct in_addr vtep_ip;
3572 bool uj = use_json(argc, argv);
3573
3574 vni = strtoul(argv[4]->arg, NULL, 10);
3575 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3576 if (!uj)
3577 vty_out(vty, "%% Malformed VTEP IP address\n");
3578 return CMD_WARNING;
3579 }
3580
3581 zvrf = zebra_vrf_get_evpn();
3582 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3583 return CMD_SUCCESS;
3584 }
3585
3586 /* policy routing contexts */
3587 DEFUN (show_pbr_ipset,
3588 show_pbr_ipset_cmd,
3589 "show pbr ipset [WORD]",
3590 SHOW_STR
3591 "Policy-Based Routing\n"
3592 "IPset Context information\n"
3593 "IPset Name information\n")
3594 {
3595 int idx = 0;
3596 int found = 0;
3597 found = argv_find(argv, argc, "WORD", &idx);
3598 if (!found)
3599 zebra_pbr_show_ipset_list(vty, NULL);
3600 else
3601 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
3602 return CMD_SUCCESS;
3603 }
3604
3605 /* policy routing contexts */
3606 DEFUN (show_pbr_iptable,
3607 show_pbr_iptable_cmd,
3608 "show pbr iptable [WORD]",
3609 SHOW_STR
3610 "Policy-Based Routing\n"
3611 "IPtable Context information\n"
3612 "IPtable Name information\n")
3613 {
3614 int idx = 0;
3615 int found = 0;
3616
3617 found = argv_find(argv, argc, "WORD", &idx);
3618 if (!found)
3619 zebra_pbr_show_iptable(vty, NULL);
3620 else
3621 zebra_pbr_show_iptable(vty, argv[idx]->arg);
3622 return CMD_SUCCESS;
3623 }
3624
3625 /* policy routing contexts */
3626 DEFPY (show_pbr_rule,
3627 show_pbr_rule_cmd,
3628 "show pbr rule",
3629 SHOW_STR
3630 "Policy-Based Routing\n"
3631 "Rule\n")
3632 {
3633 zebra_pbr_show_rule(vty);
3634 return CMD_SUCCESS;
3635 }
3636
3637 DEFPY (pbr_nexthop_resolve,
3638 pbr_nexthop_resolve_cmd,
3639 "[no$no] pbr nexthop-resolve",
3640 NO_STR
3641 "Policy Based Routing\n"
3642 "Resolve nexthop for dataplane programming\n")
3643 {
3644 zebra_pbr_expand_action_update(!no);
3645 return CMD_SUCCESS;
3646 }
3647
3648 DEFPY (clear_evpn_dup_addr,
3649 clear_evpn_dup_addr_cmd,
3650 "clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni [mac X:X:X:X:X:X | ip <A.B.C.D|X:X::X:X>]>",
3651 CLEAR_STR
3652 "EVPN\n"
3653 "Duplicate address \n"
3654 "VxLAN Network Identifier\n"
3655 "VNI number\n"
3656 "All VNIs\n"
3657 "MAC\n"
3658 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3659 "IP\n"
3660 "IPv4 address\n"
3661 "IPv6 address\n")
3662 {
3663 struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
3664 int ret = CMD_SUCCESS;
3665 struct list *input;
3666 struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
3667 *yang_dup_mac = NULL;
3668
3669 input = list_new();
3670
3671 if (!vni_str) {
3672 yang_dup = yang_data_new(
3673 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3674 "all-case");
3675 } else {
3676 yang_dup = yang_data_new_uint32(
3677 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3678 vni);
3679 if (!is_zero_mac(&mac->eth_addr)) {
3680 yang_dup_mac = yang_data_new_mac(
3681 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3682 &mac->eth_addr);
3683 if (yang_dup_mac)
3684 listnode_add(input, yang_dup_mac);
3685 } else if (ip) {
3686 if (sockunion_family(ip) == AF_INET) {
3687 host_ip.ipa_type = IPADDR_V4;
3688 host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
3689 } else {
3690 host_ip.ipa_type = IPADDR_V6;
3691 memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
3692 sizeof(struct in6_addr));
3693 }
3694
3695 yang_dup_ip = yang_data_new_ip(
3696 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3697 &host_ip);
3698
3699 if (yang_dup_ip)
3700 listnode_add(input, yang_dup_ip);
3701 }
3702 }
3703
3704 if (yang_dup) {
3705 listnode_add(input, yang_dup);
3706 ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input,
3707 NULL);
3708 }
3709
3710 list_delete(&input);
3711
3712 return ret;
3713 }
3714
3715 DEFPY_HIDDEN (evpn_accept_bgp_seq,
3716 evpn_accept_bgp_seq_cmd,
3717 "evpn accept-bgp-seq",
3718 "EVPN\n"
3719 "Accept all sequence numbers from BGP\n")
3720 {
3721 zebra_vxlan_set_accept_bgp_seq(true);
3722 return CMD_SUCCESS;
3723 }
3724
3725 DEFPY_HIDDEN (no_evpn_accept_bgp_seq,
3726 no_evpn_accept_bgp_seq_cmd,
3727 "no evpn accept-bgp-seq",
3728 NO_STR
3729 "EVPN\n"
3730 "Accept all sequence numbers from BGP\n")
3731 {
3732 zebra_vxlan_set_accept_bgp_seq(false);
3733 return CMD_SUCCESS;
3734 }
3735
3736 /* Static ip route configuration write function. */
3737 static int zebra_ip_config(struct vty *vty)
3738 {
3739 int write = 0;
3740
3741 write += zebra_import_table_config(vty, VRF_DEFAULT);
3742
3743 return write;
3744 }
3745
3746 DEFUN (ip_zebra_import_table_distance,
3747 ip_zebra_import_table_distance_cmd,
3748 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3749 IP_STR
3750 "import routes from non-main kernel table\n"
3751 "kernel routing table id\n"
3752 "Distance for imported routes\n"
3753 "Default distance value\n"
3754 "route-map for filtering\n"
3755 "route-map name\n")
3756 {
3757 uint32_t table_id = 0;
3758
3759 table_id = strtoul(argv[2]->arg, NULL, 10);
3760 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3761 char *rmap =
3762 strmatch(argv[argc - 2]->text, "route-map")
3763 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3764 : NULL;
3765 int ret;
3766
3767 if (argc == 7 || (argc == 5 && !rmap))
3768 distance = strtoul(argv[4]->arg, NULL, 10);
3769
3770 if (!is_zebra_valid_kernel_table(table_id)) {
3771 vty_out(vty,
3772 "Invalid routing table ID, %d. Must be in range 1-252\n",
3773 table_id);
3774 if (rmap)
3775 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3776 return CMD_WARNING;
3777 }
3778
3779 if (is_zebra_main_routing_table(table_id)) {
3780 vty_out(vty,
3781 "Invalid routing table ID, %d. Must be non-default table\n",
3782 table_id);
3783 if (rmap)
3784 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3785 return CMD_WARNING;
3786 }
3787
3788 ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
3789 distance, rmap, 1);
3790 if (rmap)
3791 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3792
3793 return ret;
3794 }
3795
3796 DEFUN_HIDDEN (zebra_packet_process,
3797 zebra_packet_process_cmd,
3798 "zebra zapi-packets (1-10000)",
3799 ZEBRA_STR
3800 "Zapi Protocol\n"
3801 "Number of packets to process before relinquishing thread\n")
3802 {
3803 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3804
3805 atomic_store_explicit(&zrouter.packets_to_process, packets,
3806 memory_order_relaxed);
3807
3808 return CMD_SUCCESS;
3809 }
3810
3811 DEFUN_HIDDEN (no_zebra_packet_process,
3812 no_zebra_packet_process_cmd,
3813 "no zebra zapi-packets [(1-10000)]",
3814 NO_STR
3815 ZEBRA_STR
3816 "Zapi Protocol\n"
3817 "Number of packets to process before relinquishing thread\n")
3818 {
3819 atomic_store_explicit(&zrouter.packets_to_process,
3820 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3821 memory_order_relaxed);
3822
3823 return CMD_SUCCESS;
3824 }
3825
3826 DEFUN_HIDDEN (zebra_workqueue_timer,
3827 zebra_workqueue_timer_cmd,
3828 "zebra work-queue (0-10000)",
3829 ZEBRA_STR
3830 "Work Queue\n"
3831 "Time in milliseconds\n")
3832 {
3833 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3834 zrouter.ribq->spec.hold = timer;
3835
3836 return CMD_SUCCESS;
3837 }
3838
3839 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3840 no_zebra_workqueue_timer_cmd,
3841 "no zebra work-queue [(0-10000)]",
3842 NO_STR
3843 ZEBRA_STR
3844 "Work Queue\n"
3845 "Time in milliseconds\n")
3846 {
3847 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3848
3849 return CMD_SUCCESS;
3850 }
3851
3852 DEFUN (no_ip_zebra_import_table,
3853 no_ip_zebra_import_table_cmd,
3854 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3855 NO_STR
3856 IP_STR
3857 "import routes from non-main kernel table\n"
3858 "kernel routing table id\n"
3859 "Distance for imported routes\n"
3860 "Default distance value\n"
3861 "route-map for filtering\n"
3862 "route-map name\n")
3863 {
3864 uint32_t table_id = 0;
3865 table_id = strtoul(argv[3]->arg, NULL, 10);
3866
3867 if (!is_zebra_valid_kernel_table(table_id)) {
3868 vty_out(vty,
3869 "Invalid routing table ID. Must be in range 1-252\n");
3870 return CMD_WARNING;
3871 }
3872
3873 if (is_zebra_main_routing_table(table_id)) {
3874 vty_out(vty,
3875 "Invalid routing table ID, %d. Must be non-default table\n",
3876 table_id);
3877 return CMD_WARNING;
3878 }
3879
3880 if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3881 return CMD_SUCCESS;
3882
3883 return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3884 }
3885
3886 DEFPY (zebra_nexthop_group_keep,
3887 zebra_nexthop_group_keep_cmd,
3888 "[no] zebra nexthop-group keep (1-3600)",
3889 NO_STR
3890 ZEBRA_STR
3891 "Nexthop-Group\n"
3892 "How long to keep\n"
3893 "Time in seconds from 1-3600\n")
3894 {
3895 if (no)
3896 zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
3897 else
3898 zrouter.nhg_keep = keep;
3899
3900 return CMD_SUCCESS;
3901 }
3902
3903 static int config_write_protocol(struct vty *vty)
3904 {
3905 if (zrouter.allow_delete)
3906 vty_out(vty, "allow-external-route-update\n");
3907
3908 if (zrouter.nhg_keep != ZEBRA_DEFAULT_NHG_KEEP_TIMER)
3909 vty_out(vty, "zebra nexthop-group keep %u\n", zrouter.nhg_keep);
3910
3911 if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3912 vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3913
3914 if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3915 vty_out(vty, "zebra zapi-packets %u\n",
3916 zrouter.packets_to_process);
3917
3918 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3919
3920 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3921 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3922 ipv4_multicast_mode == MCAST_URIB_ONLY
3923 ? "urib-only"
3924 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3925 ? "mrib-only"
3926 : ipv4_multicast_mode
3927 == MCAST_MIX_MRIB_FIRST
3928 ? "mrib-then-urib"
3929 : ipv4_multicast_mode
3930 == MCAST_MIX_DISTANCE
3931 ? "lower-distance"
3932 : "longer-prefix");
3933
3934 /* Include dataplane info */
3935 dplane_config_write_helper(vty);
3936
3937 zebra_evpn_mh_config_write(vty);
3938
3939 zebra_pbr_config_write(vty);
3940
3941 if (!zebra_vxlan_get_accept_bgp_seq())
3942 vty_out(vty, "no evpn accept-bgp-seq\n");
3943
3944 /* Include nexthop-group config */
3945 if (!zebra_nhg_kernel_nexthops_enabled())
3946 vty_out(vty, "no zebra nexthop kernel enable\n");
3947
3948 if (zebra_nhg_proto_nexthops_only())
3949 vty_out(vty, "zebra nexthop proto only\n");
3950
3951 if (!zebra_nhg_recursive_use_backups())
3952 vty_out(vty, "no zebra nexthop resolve-via-backup\n");
3953
3954 if (rnh_get_hide_backups())
3955 vty_out(vty, "ip nht hide-backup-events\n");
3956
3957 #ifdef HAVE_NETLINK
3958 /* Include netlink info */
3959 netlink_config_write_helper(vty);
3960 #endif /* HAVE_NETLINK */
3961
3962 return 1;
3963 }
3964
3965 DEFUN (show_zebra,
3966 show_zebra_cmd,
3967 "show zebra",
3968 SHOW_STR
3969 ZEBRA_STR)
3970 {
3971 struct vrf *vrf;
3972 struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3973 char *out;
3974
3975 ttable_rowseps(table, 0, BOTTOM, true, '-');
3976 ttable_add_row(table, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3977 ttable_add_row(table, "ECMP Maximum|%d", zrouter.multipath_num);
3978 ttable_add_row(table, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3979 ttable_add_row(table, "v6 Forwarding|%s",
3980 ipforward_ipv6() ? "On" : "Off");
3981 ttable_add_row(table, "MPLS|%s", mpls_enabled ? "On" : "Off");
3982 ttable_add_row(table, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3983 ttable_add_row(table, "Kernel socket buffer size|%d", rcvbufsize);
3984
3985
3986 #ifdef GNU_LINUX
3987 if (!vrf_is_backend_netns())
3988 ttable_add_row(table, "VRF|l3mdev Available");
3989 else
3990 ttable_add_row(table, "VRF|Namespaces");
3991 #else
3992 ttable_add_row(table, "VRF|Not Available");
3993 #endif
3994
3995 ttable_add_row(table, "ASIC offload|%s",
3996 zrouter.asic_offloaded ? "Used" : "Unavailable");
3997
3998 /*
3999 * Do not display this unless someone is actually using it
4000 *
4001 * Why this distinction? I think this is effectively dead code
4002 * and should not be exposed. Maybe someone proves me wrong.
4003 */
4004 if (zrouter.asic_notification_nexthop_control)
4005 ttable_add_row(table, "ASIC offload and nexthop control|Used");
4006
4007 ttable_add_row(table, "RA|%s",
4008 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4009 ttable_add_row(table, "RFC 5549|%s",
4010 rtadv_get_interfaces_configured_from_bgp()
4011 ? "BGP is using"
4012 : "BGP is not using");
4013
4014 ttable_add_row(table, "Kernel NHG|%s",
4015 zrouter.supports_nhgs ? "Available" : "Unavailable");
4016
4017 ttable_add_row(table, "Allow Non FRR route deletion|%s",
4018 zrouter.allow_delete ? "Yes" : "No");
4019 ttable_add_row(table, "v4 All LinkDown Routes|%s",
4020 zrouter.all_linkdownv4 ? "On" : "Off");
4021 ttable_add_row(table, "v4 Default LinkDown Routes|%s",
4022 zrouter.default_linkdownv4 ? "On" : "Off");
4023 ttable_add_row(table, "v6 All LinkDown Routes|%s",
4024 zrouter.all_linkdownv6 ? "On" : "Off");
4025 ttable_add_row(table, "v6 Default LinkDown Routes|%s",
4026 zrouter.default_linkdownv6 ? "On" : "Off");
4027
4028 ttable_add_row(table, "v4 All MC Forwarding|%s",
4029 zrouter.all_mc_forwardingv4 ? "On" : "Off");
4030 ttable_add_row(table, "v4 Default MC Forwarding|%s",
4031 zrouter.default_mc_forwardingv4 ? "On" : "Off");
4032 ttable_add_row(table, "v6 All MC Forwarding|%s",
4033 zrouter.all_mc_forwardingv6 ? "On" : "Off");
4034 ttable_add_row(table, "v6 Default MC Forwarding|%s",
4035 zrouter.default_mc_forwardingv6 ? "On" : "Off");
4036
4037 out = ttable_dump(table, "\n");
4038 vty_out(vty, "%s\n", out);
4039 XFREE(MTYPE_TMP, out);
4040
4041 ttable_del(table);
4042 vty_out(vty,
4043 " Route Route Neighbor LSP LSP\n");
4044 vty_out(vty,
4045 "VRF Installs Removals Updates Installs Removals\n");
4046
4047 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4048 struct zebra_vrf *zvrf = vrf->info;
4049
4050 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64" %10" PRIu64 " %10" PRIu64 "\n",
4051 vrf->name, zvrf->installs, zvrf->removals,
4052 zvrf->neigh_updates, zvrf->lsp_installs,
4053 zvrf->lsp_removals);
4054 }
4055
4056 return CMD_SUCCESS;
4057 }
4058
4059 DEFUN (ip_forwarding,
4060 ip_forwarding_cmd,
4061 "ip forwarding",
4062 IP_STR
4063 "Turn on IP forwarding\n")
4064 {
4065 int ret;
4066
4067 ret = ipforward();
4068 if (ret == 0)
4069 ret = ipforward_on();
4070
4071 if (ret == 0) {
4072 vty_out(vty, "Can't turn on IP forwarding\n");
4073 return CMD_WARNING_CONFIG_FAILED;
4074 }
4075
4076 return CMD_SUCCESS;
4077 }
4078
4079 DEFUN (no_ip_forwarding,
4080 no_ip_forwarding_cmd,
4081 "no ip forwarding",
4082 NO_STR
4083 IP_STR
4084 "Turn off IP forwarding\n")
4085 {
4086 int ret;
4087
4088 ret = ipforward();
4089 if (ret != 0)
4090 ret = ipforward_off();
4091
4092 if (ret != 0) {
4093 vty_out(vty, "Can't turn off IP forwarding\n");
4094 return CMD_WARNING_CONFIG_FAILED;
4095 }
4096
4097 return CMD_SUCCESS;
4098 }
4099
4100 /* Only display ip forwarding is enabled or not. */
4101 DEFUN (show_ip_forwarding,
4102 show_ip_forwarding_cmd,
4103 "show ip forwarding",
4104 SHOW_STR
4105 IP_STR
4106 "IP forwarding status\n")
4107 {
4108 int ret;
4109
4110 ret = ipforward();
4111
4112 if (ret == 0)
4113 vty_out(vty, "IP forwarding is off\n");
4114 else
4115 vty_out(vty, "IP forwarding is on\n");
4116 return CMD_SUCCESS;
4117 }
4118
4119 /* Only display ipv6 forwarding is enabled or not. */
4120 DEFUN (show_ipv6_forwarding,
4121 show_ipv6_forwarding_cmd,
4122 "show ipv6 forwarding",
4123 SHOW_STR
4124 "IPv6 information\n"
4125 "Forwarding status\n")
4126 {
4127 int ret;
4128
4129 ret = ipforward_ipv6();
4130
4131 switch (ret) {
4132 case -1:
4133 vty_out(vty, "ipv6 forwarding is unknown\n");
4134 break;
4135 case 0:
4136 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4137 break;
4138 case 1:
4139 vty_out(vty, "ipv6 forwarding is %s\n", "on");
4140 break;
4141 default:
4142 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4143 break;
4144 }
4145 return CMD_SUCCESS;
4146 }
4147
4148 DEFUN (ipv6_forwarding,
4149 ipv6_forwarding_cmd,
4150 "ipv6 forwarding",
4151 IPV6_STR
4152 "Turn on IPv6 forwarding\n")
4153 {
4154 int ret;
4155
4156 ret = ipforward_ipv6();
4157 if (ret == 0)
4158 ret = ipforward_ipv6_on();
4159
4160 if (ret == 0) {
4161 vty_out(vty, "Can't turn on IPv6 forwarding\n");
4162 return CMD_WARNING_CONFIG_FAILED;
4163 }
4164
4165 return CMD_SUCCESS;
4166 }
4167
4168 DEFUN (no_ipv6_forwarding,
4169 no_ipv6_forwarding_cmd,
4170 "no ipv6 forwarding",
4171 NO_STR
4172 IPV6_STR
4173 "Turn off IPv6 forwarding\n")
4174 {
4175 int ret;
4176
4177 ret = ipforward_ipv6();
4178 if (ret != 0)
4179 ret = ipforward_ipv6_off();
4180
4181 if (ret != 0) {
4182 vty_out(vty, "Can't turn off IPv6 forwarding\n");
4183 return CMD_WARNING_CONFIG_FAILED;
4184 }
4185
4186 return CMD_SUCCESS;
4187 }
4188
4189 /* Display dataplane info */
4190 DEFUN (show_dataplane,
4191 show_dataplane_cmd,
4192 "show zebra dplane [detailed]",
4193 SHOW_STR
4194 ZEBRA_STR
4195 "Zebra dataplane information\n"
4196 "Detailed output\n")
4197 {
4198 int idx = 0;
4199 bool detailed = false;
4200
4201 if (argv_find(argv, argc, "detailed", &idx))
4202 detailed = true;
4203
4204 return dplane_show_helper(vty, detailed);
4205 }
4206
4207 /* Display dataplane providers info */
4208 DEFUN (show_dataplane_providers,
4209 show_dataplane_providers_cmd,
4210 "show zebra dplane providers [detailed]",
4211 SHOW_STR
4212 ZEBRA_STR
4213 "Zebra dataplane information\n"
4214 "Zebra dataplane provider information\n"
4215 "Detailed output\n")
4216 {
4217 int idx = 0;
4218 bool detailed = false;
4219
4220 if (argv_find(argv, argc, "detailed", &idx))
4221 detailed = true;
4222
4223 return dplane_show_provs_helper(vty, detailed);
4224 }
4225
4226 /* Configure dataplane incoming queue limit */
4227 DEFUN (zebra_dplane_queue_limit,
4228 zebra_dplane_queue_limit_cmd,
4229 "zebra dplane limit (0-10000)",
4230 ZEBRA_STR
4231 "Zebra dataplane\n"
4232 "Limit incoming queued updates\n"
4233 "Number of queued updates\n")
4234 {
4235 uint32_t limit = 0;
4236
4237 limit = strtoul(argv[3]->arg, NULL, 10);
4238
4239 dplane_set_in_queue_limit(limit, true);
4240
4241 return CMD_SUCCESS;
4242 }
4243
4244 /* Reset dataplane queue limit to default value */
4245 DEFUN (no_zebra_dplane_queue_limit,
4246 no_zebra_dplane_queue_limit_cmd,
4247 "no zebra dplane limit [(0-10000)]",
4248 NO_STR
4249 ZEBRA_STR
4250 "Zebra dataplane\n"
4251 "Limit incoming queued updates\n"
4252 "Number of queued updates\n")
4253 {
4254 dplane_set_in_queue_limit(0, false);
4255
4256 return CMD_SUCCESS;
4257 }
4258
4259 DEFUN (zebra_show_routing_tables_summary,
4260 zebra_show_routing_tables_summary_cmd,
4261 "show zebra router table summary",
4262 SHOW_STR
4263 ZEBRA_STR
4264 "The Zebra Router Information\n"
4265 "Table Information about this Zebra Router\n"
4266 "Summary Information\n")
4267 {
4268 zebra_router_show_table_summary(vty);
4269
4270 return CMD_SUCCESS;
4271 }
4272
4273 /* Table configuration write function. */
4274 static int config_write_table(struct vty *vty)
4275 {
4276 return 0;
4277 }
4278
4279 /* IPForwarding configuration write function. */
4280 static int config_write_forwarding(struct vty *vty)
4281 {
4282 if (!ipforward())
4283 vty_out(vty, "no ip forwarding\n");
4284 if (!ipforward_ipv6())
4285 vty_out(vty, "no ipv6 forwarding\n");
4286 vty_out(vty, "!\n");
4287 return 0;
4288 }
4289
4290 DEFUN_HIDDEN (show_frr,
4291 show_frr_cmd,
4292 "show frr",
4293 SHOW_STR
4294 "FRR\n")
4295 {
4296 vty_out(vty, "........ .. . .. . ..... ...77:................................................\n");
4297 vty_out(vty, ".............................7777:..............................................\n");
4298 vty_out(vty, ".............................777777,............................................\n");
4299 vty_out(vty, "... .........................77777777,..........................................\n");
4300 vty_out(vty, "............................=7777777777:........................................\n");
4301 vty_out(vty, "........................:7777777777777777,......................................\n");
4302 vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
4303 vty_out(vty, "...................I7777777777+.................................................\n");
4304 vty_out(vty, "................,777777777?............ .......................................\n");
4305 vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
4306 vty_out(vty, ".............77777777~........=7777777777.......................................\n");
4307 vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
4308 vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
4309 vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
4310 vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4311 vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4312 vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4313 vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4314 vty_out(vty, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4315 vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4316 vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4317 vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4318 vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4319 vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4320 vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4321 vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4322 vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4323 vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4324 vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4325 vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4326 vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4327 vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4328 vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
4329 vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4330 vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4331 vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4332 vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4333 vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4334 vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4335 vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4336 vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
4337 vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
4338 vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
4339 vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
4340 vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
4341 vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
4342 vty_out(vty, ".......................=77777777777777777............777777I....................\n");
4343 vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
4344 vty_out(vty, "............................~777777777777..............+777777..................\n");
4345 vty_out(vty, "................................~77777777...............=777777.................\n");
4346 vty_out(vty, ".....................................:=?I................~777777................\n");
4347 vty_out(vty, "..........................................................:777777,..............\n");
4348 vty_out(vty, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4349
4350 return CMD_SUCCESS;
4351 }
4352
4353 #ifdef HAVE_NETLINK
4354 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf,
4355 zebra_kernel_netlink_batch_tx_buf_cmd,
4356 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4357 ZEBRA_STR
4358 "Zebra kernel interface\n"
4359 "Set Netlink parameters\n"
4360 "Set batch buffer size and send threshold\n"
4361 "Size of the buffer\n"
4362 "Send threshold\n")
4363 {
4364 uint32_t bufsize = 0, threshold = 0;
4365
4366 bufsize = strtoul(argv[4]->arg, NULL, 10);
4367 threshold = strtoul(argv[5]->arg, NULL, 10);
4368
4369 netlink_set_batch_buffer_size(bufsize, threshold, true);
4370
4371 return CMD_SUCCESS;
4372 }
4373
4374 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf,
4375 no_zebra_kernel_netlink_batch_tx_buf_cmd,
4376 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4377 NO_STR ZEBRA_STR
4378 "Zebra kernel interface\n"
4379 "Set Netlink parameters\n"
4380 "Set batch buffer size and send threshold\n"
4381 "Size of the buffer\n"
4382 "Send threshold\n")
4383 {
4384 netlink_set_batch_buffer_size(0, 0, false);
4385
4386 return CMD_SUCCESS;
4387 }
4388
4389 DEFPY (zebra_protodown_bit,
4390 zebra_protodown_bit_cmd,
4391 "zebra protodown reason-bit (0-31)$bit",
4392 ZEBRA_STR
4393 "Protodown Configuration\n"
4394 "Reason Bit used in the kernel for application\n"
4395 "Reason Bit range\n")
4396 {
4397 if_netlink_set_frr_protodown_r_bit(bit);
4398 return CMD_SUCCESS;
4399 }
4400
4401 DEFPY (no_zebra_protodown_bit,
4402 no_zebra_protodown_bit_cmd,
4403 "no zebra protodown reason-bit [(0-31)$bit]",
4404 NO_STR
4405 ZEBRA_STR
4406 "Protodown Configuration\n"
4407 "Reason Bit used in the kernel for setting protodown\n"
4408 "Reason Bit Range\n")
4409 {
4410 if_netlink_unset_frr_protodown_r_bit();
4411 return CMD_SUCCESS;
4412 }
4413
4414 #endif /* HAVE_NETLINK */
4415
4416 DEFUN(ip_table_range, ip_table_range_cmd,
4417 "[no] ip table range (1-4294967295) (1-4294967295)",
4418 NO_STR IP_STR
4419 "table configuration\n"
4420 "Configure table range\n"
4421 "Start Routing Table\n"
4422 "End Routing Table\n")
4423 {
4424 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
4425
4426 if (!zvrf)
4427 return CMD_WARNING;
4428
4429 if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) {
4430 vty_out(vty,
4431 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4432 return CMD_WARNING;
4433 }
4434
4435 if (strmatch(argv[0]->text, "no"))
4436 return table_manager_range(vty, false, zvrf, NULL, NULL);
4437
4438 return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg);
4439 }
4440
4441 #ifdef HAVE_SCRIPTING
4442
4443 DEFUN(zebra_on_rib_process_script, zebra_on_rib_process_script_cmd,
4444 "zebra on-rib-process script SCRIPT",
4445 ZEBRA_STR
4446 "on_rib_process_dplane_results hook call\n"
4447 "Set a script\n"
4448 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4449 {
4450
4451 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
4452 argv[3]->arg)
4453 == 0) {
4454 vty_out(vty, "Successfully added script %s for hook call %s\n",
4455 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4456 } else {
4457 vty_out(vty, "Failed to add script %s for hook call %s\n",
4458 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4459 }
4460 return CMD_SUCCESS;
4461 }
4462
4463 #endif /* HAVE_SCRIPTING */
4464
4465 /* IP node for static routes. */
4466 static int zebra_ip_config(struct vty *vty);
4467 static struct cmd_node ip_node = {
4468 .name = "static ip",
4469 .node = IP_NODE,
4470 .prompt = "",
4471 .config_write = zebra_ip_config,
4472 };
4473 static int config_write_protocol(struct vty *vty);
4474 static struct cmd_node protocol_node = {
4475 .name = "protocol",
4476 .node = PROTOCOL_NODE,
4477 .prompt = "",
4478 .config_write = config_write_protocol,
4479 };
4480 /* table node for routing tables. */
4481 static int config_write_table(struct vty *vty);
4482 static struct cmd_node table_node = {
4483 .name = "table",
4484 .node = TABLE_NODE,
4485 .prompt = "",
4486 .config_write = config_write_table,
4487 };
4488 static int config_write_forwarding(struct vty *vty);
4489 static struct cmd_node forwarding_node = {
4490 .name = "forwarding",
4491 .node = FORWARDING_NODE,
4492 .prompt = "",
4493 .config_write = config_write_forwarding,
4494 };
4495
4496 /* Route VTY. */
4497 void zebra_vty_init(void)
4498 {
4499 /* Install configuration write function. */
4500 install_node(&table_node);
4501 install_node(&forwarding_node);
4502
4503 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
4504 install_element(CONFIG_NODE, &ip_forwarding_cmd);
4505 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
4506 install_element(ENABLE_NODE, &show_zebra_cmd);
4507
4508 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
4509 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
4510 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
4511
4512 /* Route-map */
4513 zebra_route_map_init();
4514
4515 install_node(&ip_node);
4516 install_node(&protocol_node);
4517
4518 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
4519 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
4520
4521 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
4522 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
4523
4524 install_element(CONFIG_NODE, &zebra_nexthop_group_keep_cmd);
4525 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
4526 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
4527 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
4528 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
4529 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
4530 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
4531 install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
4532 install_element(CONFIG_NODE, &proto_nexthop_group_only_cmd);
4533 install_element(CONFIG_NODE, &backup_nexthop_recursive_use_enable_cmd);
4534
4535 install_element(VIEW_NODE, &show_nexthop_group_cmd);
4536 install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
4537
4538 install_element(VIEW_NODE, &show_vrf_cmd);
4539 install_element(VIEW_NODE, &show_vrf_vni_cmd);
4540 install_element(VIEW_NODE, &show_route_cmd);
4541 install_element(VIEW_NODE, &show_ro_cmd);
4542 install_element(VIEW_NODE, &show_route_detail_cmd);
4543 install_element(VIEW_NODE, &show_route_summary_cmd);
4544 install_element(VIEW_NODE, &show_ip_nht_cmd);
4545
4546 install_element(VIEW_NODE, &show_ip_rpf_cmd);
4547 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
4548
4549 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
4550 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
4551 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
4552 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
4553 install_element(VRF_NODE, &ip_nht_default_route_cmd);
4554 install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
4555 install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
4556 install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
4557 install_element(CONFIG_NODE, &rnh_hide_backups_cmd);
4558
4559 install_element(VIEW_NODE, &show_frr_cmd);
4560 install_element(VIEW_NODE, &show_evpn_global_cmd);
4561 install_element(VIEW_NODE, &show_evpn_vni_cmd);
4562 install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
4563 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
4564 install_element(VIEW_NODE, &show_evpn_l2_nh_cmd);
4565 install_element(VIEW_NODE, &show_evpn_es_cmd);
4566 install_element(VIEW_NODE, &show_evpn_es_evi_cmd);
4567 install_element(VIEW_NODE, &show_evpn_access_vlan_cmd);
4568 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
4569 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
4570 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
4571 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
4572 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
4573 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
4574 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
4575 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
4576 install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
4577 install_element(VIEW_NODE, &show_evpn_mac_vni_detail_cmd);
4578 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
4579 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
4580 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
4581 install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
4582 install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
4583 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
4584 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
4585 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
4586 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
4587 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
4588 install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
4589 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
4590 install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
4591 install_element(CONFIG_NODE, &evpn_accept_bgp_seq_cmd);
4592 install_element(CONFIG_NODE, &no_evpn_accept_bgp_seq_cmd);
4593
4594 install_element(VIEW_NODE, &show_neigh_cmd);
4595
4596 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
4597 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
4598 install_element(VIEW_NODE, &show_pbr_rule_cmd);
4599 install_element(CONFIG_NODE, &pbr_nexthop_resolve_cmd);
4600 install_element(VIEW_NODE, &show_route_zebra_dump_cmd);
4601
4602 install_element(CONFIG_NODE, &evpn_mh_mac_holdtime_cmd);
4603 install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd);
4604 install_element(CONFIG_NODE, &evpn_mh_startup_delay_cmd);
4605 install_element(CONFIG_NODE, &evpn_mh_redirect_off_cmd);
4606 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
4607 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
4608 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
4609 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
4610
4611 install_element(VIEW_NODE, &show_dataplane_cmd);
4612 install_element(VIEW_NODE, &show_dataplane_providers_cmd);
4613 install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
4614 install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
4615
4616 install_element(CONFIG_NODE, &ip_table_range_cmd);
4617 install_element(VRF_NODE, &ip_table_range_cmd);
4618
4619 #ifdef HAVE_NETLINK
4620 install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd);
4621 install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
4622 install_element(CONFIG_NODE, &zebra_protodown_bit_cmd);
4623 install_element(CONFIG_NODE, &no_zebra_protodown_bit_cmd);
4624 #endif /* HAVE_NETLINK */
4625
4626 #ifdef HAVE_SCRIPTING
4627 install_element(CONFIG_NODE, &zebra_on_rib_process_script_cmd);
4628 #endif /* HAVE_SCRIPTING */
4629
4630 install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
4631 }