]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
Merge pull request #12757 from opensourcerouting/fix/advance_versions_for_packages
[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,
3020 show_evpn_access_vlan_cmd,
3021 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3022 SHOW_STR
3023 "EVPN\n"
3024 "Access VLANs\n"
3025 "VLAN ID\n"
3026 "Detailed information\n"
3027 JSON_STR)
3028 {
3029 bool uj = !!json;
3030
3031 if (vid) {
3032 zebra_evpn_acc_vl_show_vid(vty, uj, vid);
3033 } else {
3034 if (detail)
3035 zebra_evpn_acc_vl_show_detail(vty, uj);
3036 else
3037 zebra_evpn_acc_vl_show(vty, uj);
3038 }
3039
3040 return CMD_SUCCESS;
3041 }
3042
3043 DEFUN (show_evpn_vni,
3044 show_evpn_vni_cmd,
3045 "show evpn vni [json]",
3046 SHOW_STR
3047 "EVPN\n"
3048 "VxLAN Network Identifier\n"
3049 JSON_STR)
3050 {
3051 struct zebra_vrf *zvrf;
3052 bool uj = use_json(argc, argv);
3053
3054 zvrf = zebra_vrf_get_evpn();
3055 zebra_vxlan_print_vnis(vty, zvrf, uj);
3056 return CMD_SUCCESS;
3057 }
3058
3059 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
3060 "show evpn vni detail [json]",
3061 SHOW_STR
3062 "EVPN\n"
3063 "VxLAN Network Identifier\n"
3064 "Detailed Information On Each VNI\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_detail(vty, zvrf, uj);
3072 return CMD_SUCCESS;
3073 }
3074
3075 DEFUN (show_evpn_vni_vni,
3076 show_evpn_vni_vni_cmd,
3077 "show evpn vni " CMD_VNI_RANGE "[json]",
3078 SHOW_STR
3079 "EVPN\n"
3080 "VxLAN Network Identifier\n"
3081 "VNI number\n"
3082 JSON_STR)
3083 {
3084 struct zebra_vrf *zvrf;
3085 vni_t vni;
3086 bool uj = use_json(argc, argv);
3087
3088 vni = strtoul(argv[3]->arg, NULL, 10);
3089 zvrf = zebra_vrf_get_evpn();
3090 zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
3091 return CMD_SUCCESS;
3092 }
3093
3094 DEFUN (show_evpn_rmac_vni_mac,
3095 show_evpn_rmac_vni_mac_cmd,
3096 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
3097 SHOW_STR
3098 "EVPN\n"
3099 "RMAC\n"
3100 "L3 VNI\n"
3101 "VNI number\n"
3102 "MAC\n"
3103 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3104 JSON_STR)
3105 {
3106 vni_t l3vni = 0;
3107 struct ethaddr mac;
3108 bool uj = use_json(argc, argv);
3109
3110 l3vni = strtoul(argv[4]->arg, NULL, 10);
3111 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3112 vty_out(vty, "%% Malformed MAC address\n");
3113 return CMD_WARNING;
3114 }
3115 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
3116 return CMD_SUCCESS;
3117 }
3118
3119 DEFUN (show_evpn_rmac_vni,
3120 show_evpn_rmac_vni_cmd,
3121 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
3122 SHOW_STR
3123 "EVPN\n"
3124 "RMAC\n"
3125 "L3 VNI\n"
3126 "VNI number\n"
3127 JSON_STR)
3128 {
3129 vni_t l3vni = 0;
3130 bool uj = use_json(argc, argv);
3131
3132 l3vni = strtoul(argv[4]->arg, NULL, 10);
3133 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
3134
3135 return CMD_SUCCESS;
3136 }
3137
3138 DEFUN (show_evpn_rmac_vni_all,
3139 show_evpn_rmac_vni_all_cmd,
3140 "show evpn rmac vni all [json]",
3141 SHOW_STR
3142 "EVPN\n"
3143 "RMAC addresses\n"
3144 "L3 VNI\n"
3145 "All VNIs\n"
3146 JSON_STR)
3147 {
3148 bool uj = use_json(argc, argv);
3149
3150 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
3151
3152 return CMD_SUCCESS;
3153 }
3154
3155 DEFUN (show_evpn_nh_vni_ip,
3156 show_evpn_nh_vni_ip_cmd,
3157 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
3158 SHOW_STR
3159 "EVPN\n"
3160 "Remote Vteps\n"
3161 "L3 VNI\n"
3162 "VNI number\n"
3163 "Ip address\n"
3164 "Host address (ipv4 or ipv6)\n"
3165 JSON_STR)
3166 {
3167 vni_t l3vni;
3168 struct ipaddr ip;
3169 bool uj = use_json(argc, argv);
3170
3171 l3vni = strtoul(argv[4]->arg, NULL, 10);
3172 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3173 if (!uj)
3174 vty_out(vty, "%% Malformed Neighbor address\n");
3175 return CMD_WARNING;
3176 }
3177 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
3178
3179 return CMD_SUCCESS;
3180 }
3181
3182 DEFUN (show_evpn_nh_vni,
3183 show_evpn_nh_vni_cmd,
3184 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
3185 SHOW_STR
3186 "EVPN\n"
3187 "Remote Vteps\n"
3188 "L3 VNI\n"
3189 "VNI number\n"
3190 JSON_STR)
3191 {
3192 vni_t l3vni;
3193 bool uj = use_json(argc, argv);
3194
3195 l3vni = strtoul(argv[4]->arg, NULL, 10);
3196 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
3197
3198 return CMD_SUCCESS;
3199 }
3200
3201 DEFUN (show_evpn_nh_vni_all,
3202 show_evpn_nh_vni_all_cmd,
3203 "show evpn next-hops vni all [json]",
3204 SHOW_STR
3205 "EVPN\n"
3206 "Remote VTEPs\n"
3207 "L3 VNI\n"
3208 "All VNIs\n"
3209 JSON_STR)
3210 {
3211 bool uj = use_json(argc, argv);
3212
3213 zebra_vxlan_print_nh_all_l3vni(vty, uj);
3214
3215 return CMD_SUCCESS;
3216 }
3217
3218 DEFUN (show_evpn_mac_vni,
3219 show_evpn_mac_vni_cmd,
3220 "show evpn mac vni " CMD_VNI_RANGE "[json]",
3221 SHOW_STR
3222 "EVPN\n"
3223 "MAC addresses\n"
3224 "VxLAN Network Identifier\n"
3225 "VNI number\n"
3226 JSON_STR)
3227 {
3228 struct zebra_vrf *zvrf;
3229 vni_t vni;
3230 bool uj = use_json(argc, argv);
3231
3232 vni = strtoul(argv[4]->arg, NULL, 10);
3233 zvrf = zebra_vrf_get_evpn();
3234 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, false);
3235 return CMD_SUCCESS;
3236 }
3237
3238 DEFPY (show_evpn_mac_vni_detail,
3239 show_evpn_mac_vni_detail_cmd,
3240 "show evpn mac vni " CMD_VNI_RANGE " detail [json]",
3241 SHOW_STR
3242 "EVPN\n"
3243 "MAC addresses\n"
3244 "VXLAN Network Identifier\n"
3245 "VNI number\n"
3246 "Detailed Information On Each VNI MAC\n"
3247 JSON_STR)
3248 {
3249 struct zebra_vrf *zvrf;
3250 bool uj = use_json(argc, argv);
3251
3252 zvrf = zebra_vrf_get_evpn();
3253 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj, true);
3254 return CMD_SUCCESS;
3255 }
3256
3257 DEFUN (show_evpn_mac_vni_all,
3258 show_evpn_mac_vni_all_cmd,
3259 "show evpn mac vni all [json]",
3260 SHOW_STR
3261 "EVPN\n"
3262 "MAC addresses\n"
3263 "VxLAN Network Identifier\n"
3264 "All VNIs\n"
3265 JSON_STR)
3266 {
3267 struct zebra_vrf *zvrf;
3268 bool uj = use_json(argc, argv);
3269
3270 zvrf = zebra_vrf_get_evpn();
3271 zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
3272 return CMD_SUCCESS;
3273 }
3274
3275 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
3276 "show evpn mac vni all detail [json]",
3277 SHOW_STR
3278 "EVPN\n"
3279 "MAC addresses\n"
3280 "VxLAN Network Identifier\n"
3281 "All VNIs\n"
3282 "Detailed Information On Each VNI MAC\n"
3283 JSON_STR)
3284 {
3285 struct zebra_vrf *zvrf;
3286 bool uj = use_json(argc, argv);
3287
3288 zvrf = zebra_vrf_get_evpn();
3289 zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
3290 return CMD_SUCCESS;
3291 }
3292
3293 DEFUN (show_evpn_mac_vni_all_vtep,
3294 show_evpn_mac_vni_all_vtep_cmd,
3295 "show evpn mac vni all vtep A.B.C.D [json]",
3296 SHOW_STR
3297 "EVPN\n"
3298 "MAC addresses\n"
3299 "VxLAN Network Identifier\n"
3300 "All VNIs\n"
3301 "Remote VTEP\n"
3302 "Remote VTEP IP address\n"
3303 JSON_STR)
3304 {
3305 struct zebra_vrf *zvrf;
3306 struct in_addr vtep_ip;
3307 bool uj = use_json(argc, argv);
3308
3309 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3310 if (!uj)
3311 vty_out(vty, "%% Malformed VTEP IP address\n");
3312 return CMD_WARNING;
3313 }
3314 zvrf = zebra_vrf_get_evpn();
3315 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
3316
3317 return CMD_SUCCESS;
3318 }
3319
3320
3321 DEFUN (show_evpn_mac_vni_mac,
3322 show_evpn_mac_vni_mac_cmd,
3323 "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
3324 SHOW_STR
3325 "EVPN\n"
3326 "MAC addresses\n"
3327 "VxLAN Network Identifier\n"
3328 "VNI number\n"
3329 "MAC\n"
3330 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3331 JSON_STR)
3332
3333 {
3334 struct zebra_vrf *zvrf;
3335 vni_t vni;
3336 struct ethaddr mac;
3337 bool uj = use_json(argc, argv);
3338
3339 vni = strtoul(argv[4]->arg, NULL, 10);
3340 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3341 vty_out(vty, "%% Malformed MAC address\n");
3342 return CMD_WARNING;
3343 }
3344 zvrf = zebra_vrf_get_evpn();
3345 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
3346 return CMD_SUCCESS;
3347 }
3348
3349 DEFUN (show_evpn_mac_vni_vtep,
3350 show_evpn_mac_vni_vtep_cmd,
3351 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
3352 SHOW_STR
3353 "EVPN\n"
3354 "MAC addresses\n"
3355 "VxLAN Network Identifier\n"
3356 "VNI number\n"
3357 "Remote VTEP\n"
3358 "Remote VTEP IP address\n"
3359 JSON_STR)
3360 {
3361 struct zebra_vrf *zvrf;
3362 vni_t vni;
3363 struct in_addr vtep_ip;
3364 bool uj = use_json(argc, argv);
3365
3366 vni = strtoul(argv[4]->arg, NULL, 10);
3367 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3368 if (!uj)
3369 vty_out(vty, "%% Malformed VTEP IP address\n");
3370 return CMD_WARNING;
3371 }
3372
3373 zvrf = zebra_vrf_get_evpn();
3374 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3375 return CMD_SUCCESS;
3376 }
3377
3378 DEFPY (show_evpn_mac_vni_all_dad,
3379 show_evpn_mac_vni_all_dad_cmd,
3380 "show evpn mac vni all duplicate [json]",
3381 SHOW_STR
3382 "EVPN\n"
3383 "MAC addresses\n"
3384 "VxLAN Network Identifier\n"
3385 "All VNIs\n"
3386 "Duplicate address list\n"
3387 JSON_STR)
3388 {
3389 struct zebra_vrf *zvrf;
3390 bool uj = use_json(argc, argv);
3391
3392 zvrf = zebra_vrf_get_evpn();
3393 zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
3394 return CMD_SUCCESS;
3395 }
3396
3397
3398 DEFPY (show_evpn_mac_vni_dad,
3399 show_evpn_mac_vni_dad_cmd,
3400 "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
3401 SHOW_STR
3402 "EVPN\n"
3403 "MAC addresses\n"
3404 "VxLAN Network Identifier\n"
3405 "VNI number\n"
3406 "Duplicate address list\n"
3407 JSON_STR)
3408 {
3409 struct zebra_vrf *zvrf;
3410 bool uj = use_json(argc, argv);
3411
3412 zvrf = zebra_vrf_get_evpn();
3413
3414 zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
3415
3416 return CMD_SUCCESS;
3417 }
3418
3419 DEFPY (show_evpn_neigh_vni_dad,
3420 show_evpn_neigh_vni_dad_cmd,
3421 "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
3422 SHOW_STR
3423 "EVPN\n"
3424 "ARP and ND cache\n"
3425 "VxLAN Network Identifier\n"
3426 "VNI number\n"
3427 "Duplicate address list\n"
3428 JSON_STR)
3429 {
3430 struct zebra_vrf *zvrf;
3431 bool uj = use_json(argc, argv);
3432
3433 zvrf = zebra_vrf_get_evpn();
3434 zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
3435 return CMD_SUCCESS;
3436 }
3437
3438 DEFPY (show_evpn_neigh_vni_all_dad,
3439 show_evpn_neigh_vni_all_dad_cmd,
3440 "show evpn arp-cache vni all duplicate [json]",
3441 SHOW_STR
3442 "EVPN\n"
3443 "ARP and ND cache\n"
3444 "VxLAN Network Identifier\n"
3445 "All VNIs\n"
3446 "Duplicate address list\n"
3447 JSON_STR)
3448 {
3449 struct zebra_vrf *zvrf;
3450 bool uj = use_json(argc, argv);
3451
3452 zvrf = zebra_vrf_get_evpn();
3453 zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
3454 return CMD_SUCCESS;
3455 }
3456
3457
3458 DEFUN (show_evpn_neigh_vni,
3459 show_evpn_neigh_vni_cmd,
3460 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
3461 SHOW_STR
3462 "EVPN\n"
3463 "ARP and ND cache\n"
3464 "VxLAN Network Identifier\n"
3465 "VNI number\n"
3466 JSON_STR)
3467 {
3468 struct zebra_vrf *zvrf;
3469 vni_t vni;
3470 bool uj = use_json(argc, argv);
3471
3472 vni = strtoul(argv[4]->arg, NULL, 10);
3473 zvrf = zebra_vrf_get_evpn();
3474 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
3475 return CMD_SUCCESS;
3476 }
3477
3478 DEFUN (show_evpn_neigh_vni_all,
3479 show_evpn_neigh_vni_all_cmd,
3480 "show evpn arp-cache vni all [json]",
3481 SHOW_STR
3482 "EVPN\n"
3483 "ARP and ND cache\n"
3484 "VxLAN Network Identifier\n"
3485 "All VNIs\n"
3486 JSON_STR)
3487 {
3488 struct zebra_vrf *zvrf;
3489 bool uj = use_json(argc, argv);
3490
3491 zvrf = zebra_vrf_get_evpn();
3492 zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
3493 return CMD_SUCCESS;
3494 }
3495
3496 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
3497 "show evpn arp-cache vni all detail [json]",
3498 SHOW_STR
3499 "EVPN\n"
3500 "ARP and ND cache\n"
3501 "VxLAN Network Identifier\n"
3502 "All VNIs\n"
3503 "Neighbor details for all vnis in detail\n" JSON_STR)
3504 {
3505 struct zebra_vrf *zvrf;
3506 bool uj = use_json(argc, argv);
3507
3508 zvrf = zebra_vrf_get_evpn();
3509 zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
3510 return CMD_SUCCESS;
3511 }
3512
3513 DEFUN (show_evpn_neigh_vni_neigh,
3514 show_evpn_neigh_vni_neigh_cmd,
3515 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
3516 SHOW_STR
3517 "EVPN\n"
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3520 "VNI number\n"
3521 "Neighbor\n"
3522 "Neighbor address (IPv4 or IPv6 address)\n"
3523 JSON_STR)
3524 {
3525 struct zebra_vrf *zvrf;
3526 vni_t vni;
3527 struct ipaddr ip;
3528 bool uj = use_json(argc, argv);
3529
3530 vni = strtoul(argv[4]->arg, NULL, 10);
3531 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3532 if (!uj)
3533 vty_out(vty, "%% Malformed Neighbor address\n");
3534 return CMD_WARNING;
3535 }
3536 zvrf = zebra_vrf_get_evpn();
3537 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
3538 return CMD_SUCCESS;
3539 }
3540
3541 DEFUN (show_evpn_neigh_vni_vtep,
3542 show_evpn_neigh_vni_vtep_cmd,
3543 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
3544 SHOW_STR
3545 "EVPN\n"
3546 "ARP and ND cache\n"
3547 "VxLAN Network Identifier\n"
3548 "VNI number\n"
3549 "Remote VTEP\n"
3550 "Remote VTEP IP address\n"
3551 JSON_STR)
3552 {
3553 struct zebra_vrf *zvrf;
3554 vni_t vni;
3555 struct in_addr vtep_ip;
3556 bool uj = use_json(argc, argv);
3557
3558 vni = strtoul(argv[4]->arg, NULL, 10);
3559 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3560 if (!uj)
3561 vty_out(vty, "%% Malformed VTEP IP address\n");
3562 return CMD_WARNING;
3563 }
3564
3565 zvrf = zebra_vrf_get_evpn();
3566 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3567 return CMD_SUCCESS;
3568 }
3569
3570 /* policy routing contexts */
3571 DEFUN (show_pbr_ipset,
3572 show_pbr_ipset_cmd,
3573 "show pbr ipset [WORD]",
3574 SHOW_STR
3575 "Policy-Based Routing\n"
3576 "IPset Context information\n"
3577 "IPset Name information\n")
3578 {
3579 int idx = 0;
3580 int found = 0;
3581 found = argv_find(argv, argc, "WORD", &idx);
3582 if (!found)
3583 zebra_pbr_show_ipset_list(vty, NULL);
3584 else
3585 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
3586 return CMD_SUCCESS;
3587 }
3588
3589 /* policy routing contexts */
3590 DEFUN (show_pbr_iptable,
3591 show_pbr_iptable_cmd,
3592 "show pbr iptable [WORD]",
3593 SHOW_STR
3594 "Policy-Based Routing\n"
3595 "IPtable Context information\n"
3596 "IPtable Name information\n")
3597 {
3598 int idx = 0;
3599 int found = 0;
3600
3601 found = argv_find(argv, argc, "WORD", &idx);
3602 if (!found)
3603 zebra_pbr_show_iptable(vty, NULL);
3604 else
3605 zebra_pbr_show_iptable(vty, argv[idx]->arg);
3606 return CMD_SUCCESS;
3607 }
3608
3609 /* policy routing contexts */
3610 DEFPY (show_pbr_rule,
3611 show_pbr_rule_cmd,
3612 "show pbr rule",
3613 SHOW_STR
3614 "Policy-Based Routing\n"
3615 "Rule\n")
3616 {
3617 zebra_pbr_show_rule(vty);
3618 return CMD_SUCCESS;
3619 }
3620
3621 DEFPY (pbr_nexthop_resolve,
3622 pbr_nexthop_resolve_cmd,
3623 "[no$no] pbr nexthop-resolve",
3624 NO_STR
3625 "Policy Based Routing\n"
3626 "Resolve nexthop for dataplane programming\n")
3627 {
3628 zebra_pbr_expand_action_update(!no);
3629 return CMD_SUCCESS;
3630 }
3631
3632 DEFPY (clear_evpn_dup_addr,
3633 clear_evpn_dup_addr_cmd,
3634 "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>]>",
3635 CLEAR_STR
3636 "EVPN\n"
3637 "Duplicate address \n"
3638 "VxLAN Network Identifier\n"
3639 "VNI number\n"
3640 "All VNIs\n"
3641 "MAC\n"
3642 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3643 "IP\n"
3644 "IPv4 address\n"
3645 "IPv6 address\n")
3646 {
3647 struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
3648 int ret = CMD_SUCCESS;
3649 struct list *input;
3650 struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
3651 *yang_dup_mac = NULL;
3652
3653 input = list_new();
3654
3655 if (!vni_str) {
3656 yang_dup = yang_data_new(
3657 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3658 "all-case");
3659 } else {
3660 yang_dup = yang_data_new_uint32(
3661 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3662 vni);
3663 if (!is_zero_mac(&mac->eth_addr)) {
3664 yang_dup_mac = yang_data_new_mac(
3665 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3666 &mac->eth_addr);
3667 if (yang_dup_mac)
3668 listnode_add(input, yang_dup_mac);
3669 } else if (ip) {
3670 if (sockunion_family(ip) == AF_INET) {
3671 host_ip.ipa_type = IPADDR_V4;
3672 host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
3673 } else {
3674 host_ip.ipa_type = IPADDR_V6;
3675 memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
3676 sizeof(struct in6_addr));
3677 }
3678
3679 yang_dup_ip = yang_data_new_ip(
3680 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3681 &host_ip);
3682
3683 if (yang_dup_ip)
3684 listnode_add(input, yang_dup_ip);
3685 }
3686 }
3687
3688 if (yang_dup) {
3689 listnode_add(input, yang_dup);
3690 ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input,
3691 NULL);
3692 }
3693
3694 list_delete(&input);
3695
3696 return ret;
3697 }
3698
3699 DEFPY_HIDDEN (evpn_accept_bgp_seq,
3700 evpn_accept_bgp_seq_cmd,
3701 "evpn accept-bgp-seq",
3702 "EVPN\n"
3703 "Accept all sequence numbers from BGP\n")
3704 {
3705 zebra_vxlan_set_accept_bgp_seq(true);
3706 return CMD_SUCCESS;
3707 }
3708
3709 DEFPY_HIDDEN (no_evpn_accept_bgp_seq,
3710 no_evpn_accept_bgp_seq_cmd,
3711 "no evpn accept-bgp-seq",
3712 NO_STR
3713 "EVPN\n"
3714 "Accept all sequence numbers from BGP\n")
3715 {
3716 zebra_vxlan_set_accept_bgp_seq(false);
3717 return CMD_SUCCESS;
3718 }
3719
3720 /* Static ip route configuration write function. */
3721 static int zebra_ip_config(struct vty *vty)
3722 {
3723 int write = 0;
3724
3725 write += zebra_import_table_config(vty, VRF_DEFAULT);
3726
3727 return write;
3728 }
3729
3730 DEFUN (ip_zebra_import_table_distance,
3731 ip_zebra_import_table_distance_cmd,
3732 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3733 IP_STR
3734 "import routes from non-main kernel table\n"
3735 "kernel routing table id\n"
3736 "Distance for imported routes\n"
3737 "Default distance value\n"
3738 "route-map for filtering\n"
3739 "route-map name\n")
3740 {
3741 uint32_t table_id = 0;
3742
3743 table_id = strtoul(argv[2]->arg, NULL, 10);
3744 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3745 char *rmap =
3746 strmatch(argv[argc - 2]->text, "route-map")
3747 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3748 : NULL;
3749 int ret;
3750
3751 if (argc == 7 || (argc == 5 && !rmap))
3752 distance = strtoul(argv[4]->arg, NULL, 10);
3753
3754 if (!is_zebra_valid_kernel_table(table_id)) {
3755 vty_out(vty,
3756 "Invalid routing table ID, %d. Must be in range 1-252\n",
3757 table_id);
3758 if (rmap)
3759 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3760 return CMD_WARNING;
3761 }
3762
3763 if (is_zebra_main_routing_table(table_id)) {
3764 vty_out(vty,
3765 "Invalid routing table ID, %d. Must be non-default table\n",
3766 table_id);
3767 if (rmap)
3768 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3769 return CMD_WARNING;
3770 }
3771
3772 ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
3773 distance, rmap, 1);
3774 if (rmap)
3775 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3776
3777 return ret;
3778 }
3779
3780 DEFUN_HIDDEN (zebra_packet_process,
3781 zebra_packet_process_cmd,
3782 "zebra zapi-packets (1-10000)",
3783 ZEBRA_STR
3784 "Zapi Protocol\n"
3785 "Number of packets to process before relinquishing thread\n")
3786 {
3787 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3788
3789 atomic_store_explicit(&zrouter.packets_to_process, packets,
3790 memory_order_relaxed);
3791
3792 return CMD_SUCCESS;
3793 }
3794
3795 DEFUN_HIDDEN (no_zebra_packet_process,
3796 no_zebra_packet_process_cmd,
3797 "no zebra zapi-packets [(1-10000)]",
3798 NO_STR
3799 ZEBRA_STR
3800 "Zapi Protocol\n"
3801 "Number of packets to process before relinquishing thread\n")
3802 {
3803 atomic_store_explicit(&zrouter.packets_to_process,
3804 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3805 memory_order_relaxed);
3806
3807 return CMD_SUCCESS;
3808 }
3809
3810 DEFUN_HIDDEN (zebra_workqueue_timer,
3811 zebra_workqueue_timer_cmd,
3812 "zebra work-queue (0-10000)",
3813 ZEBRA_STR
3814 "Work Queue\n"
3815 "Time in milliseconds\n")
3816 {
3817 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3818 zrouter.ribq->spec.hold = timer;
3819
3820 return CMD_SUCCESS;
3821 }
3822
3823 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3824 no_zebra_workqueue_timer_cmd,
3825 "no zebra work-queue [(0-10000)]",
3826 NO_STR
3827 ZEBRA_STR
3828 "Work Queue\n"
3829 "Time in milliseconds\n")
3830 {
3831 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3832
3833 return CMD_SUCCESS;
3834 }
3835
3836 DEFUN (no_ip_zebra_import_table,
3837 no_ip_zebra_import_table_cmd,
3838 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3839 NO_STR
3840 IP_STR
3841 "import routes from non-main kernel table\n"
3842 "kernel routing table id\n"
3843 "Distance for imported routes\n"
3844 "Default distance value\n"
3845 "route-map for filtering\n"
3846 "route-map name\n")
3847 {
3848 uint32_t table_id = 0;
3849 table_id = strtoul(argv[3]->arg, NULL, 10);
3850
3851 if (!is_zebra_valid_kernel_table(table_id)) {
3852 vty_out(vty,
3853 "Invalid routing table ID. Must be in range 1-252\n");
3854 return CMD_WARNING;
3855 }
3856
3857 if (is_zebra_main_routing_table(table_id)) {
3858 vty_out(vty,
3859 "Invalid routing table ID, %d. Must be non-default table\n",
3860 table_id);
3861 return CMD_WARNING;
3862 }
3863
3864 if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3865 return CMD_SUCCESS;
3866
3867 return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3868 }
3869
3870 DEFPY (zebra_nexthop_group_keep,
3871 zebra_nexthop_group_keep_cmd,
3872 "[no] zebra nexthop-group keep (1-3600)",
3873 NO_STR
3874 ZEBRA_STR
3875 "Nexthop-Group\n"
3876 "How long to keep\n"
3877 "Time in seconds from 1-3600\n")
3878 {
3879 if (no)
3880 zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
3881 else
3882 zrouter.nhg_keep = keep;
3883
3884 return CMD_SUCCESS;
3885 }
3886
3887 static int config_write_protocol(struct vty *vty)
3888 {
3889 if (zrouter.allow_delete)
3890 vty_out(vty, "allow-external-route-update\n");
3891
3892 if (zrouter.nhg_keep != ZEBRA_DEFAULT_NHG_KEEP_TIMER)
3893 vty_out(vty, "zebra nexthop-group keep %u\n", zrouter.nhg_keep);
3894
3895 if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3896 vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3897
3898 if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3899 vty_out(vty, "zebra zapi-packets %u\n",
3900 zrouter.packets_to_process);
3901
3902 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3903
3904 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3905 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3906 ipv4_multicast_mode == MCAST_URIB_ONLY
3907 ? "urib-only"
3908 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3909 ? "mrib-only"
3910 : ipv4_multicast_mode
3911 == MCAST_MIX_MRIB_FIRST
3912 ? "mrib-then-urib"
3913 : ipv4_multicast_mode
3914 == MCAST_MIX_DISTANCE
3915 ? "lower-distance"
3916 : "longer-prefix");
3917
3918 /* Include dataplane info */
3919 dplane_config_write_helper(vty);
3920
3921 zebra_evpn_mh_config_write(vty);
3922
3923 zebra_pbr_config_write(vty);
3924
3925 if (!zebra_vxlan_get_accept_bgp_seq())
3926 vty_out(vty, "no evpn accept-bgp-seq\n");
3927
3928 /* Include nexthop-group config */
3929 if (!zebra_nhg_kernel_nexthops_enabled())
3930 vty_out(vty, "no zebra nexthop kernel enable\n");
3931
3932 if (zebra_nhg_proto_nexthops_only())
3933 vty_out(vty, "zebra nexthop proto only\n");
3934
3935 if (!zebra_nhg_recursive_use_backups())
3936 vty_out(vty, "no zebra nexthop resolve-via-backup\n");
3937
3938 if (rnh_get_hide_backups())
3939 vty_out(vty, "ip nht hide-backup-events\n");
3940
3941 #ifdef HAVE_NETLINK
3942 /* Include netlink info */
3943 netlink_config_write_helper(vty);
3944 #endif /* HAVE_NETLINK */
3945
3946 return 1;
3947 }
3948
3949 DEFUN (show_zebra,
3950 show_zebra_cmd,
3951 "show zebra",
3952 SHOW_STR
3953 ZEBRA_STR)
3954 {
3955 struct vrf *vrf;
3956 struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3957 char *out;
3958
3959 ttable_rowseps(table, 0, BOTTOM, true, '-');
3960 ttable_add_row(table, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3961 ttable_add_row(table, "ECMP Maximum|%d", zrouter.multipath_num);
3962 ttable_add_row(table, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3963 ttable_add_row(table, "v6 Forwarding|%s",
3964 ipforward_ipv6() ? "On" : "Off");
3965 ttable_add_row(table, "MPLS|%s", mpls_enabled ? "On" : "Off");
3966 ttable_add_row(table, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3967 ttable_add_row(table, "Kernel socket buffer size|%d", rcvbufsize);
3968
3969
3970 #ifdef GNU_LINUX
3971 if (!vrf_is_backend_netns())
3972 ttable_add_row(table, "VRF|l3mdev Available");
3973 else
3974 ttable_add_row(table, "VRF|Namespaces");
3975 #else
3976 ttable_add_row(table, "VRF|Not Available");
3977 #endif
3978
3979 ttable_add_row(table, "ASIC offload|%s",
3980 zrouter.asic_offloaded ? "Used" : "Unavailable");
3981
3982 /*
3983 * Do not display this unless someone is actually using it
3984 *
3985 * Why this distinction? I think this is effectively dead code
3986 * and should not be exposed. Maybe someone proves me wrong.
3987 */
3988 if (zrouter.asic_notification_nexthop_control)
3989 ttable_add_row(table, "ASIC offload and nexthop control|Used");
3990
3991 ttable_add_row(table, "RA|%s",
3992 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
3993 ttable_add_row(table, "RFC 5549|%s",
3994 rtadv_get_interfaces_configured_from_bgp()
3995 ? "BGP is using"
3996 : "BGP is not using");
3997
3998 ttable_add_row(table, "Kernel NHG|%s",
3999 zrouter.supports_nhgs ? "Available" : "Unavailable");
4000
4001 ttable_add_row(table, "Allow Non FRR route deletion|%s",
4002 zrouter.allow_delete ? "Yes" : "No");
4003 ttable_add_row(table, "v4 All LinkDown Routes|%s",
4004 zrouter.all_linkdownv4 ? "On" : "Off");
4005 ttable_add_row(table, "v4 Default LinkDown Routes|%s",
4006 zrouter.default_linkdownv4 ? "On" : "Off");
4007 ttable_add_row(table, "v6 All LinkDown Routes|%s",
4008 zrouter.all_linkdownv6 ? "On" : "Off");
4009 ttable_add_row(table, "v6 Default LinkDown Routes|%s",
4010 zrouter.default_linkdownv6 ? "On" : "Off");
4011
4012 ttable_add_row(table, "v4 All MC Forwarding|%s",
4013 zrouter.all_mc_forwardingv4 ? "On" : "Off");
4014 ttable_add_row(table, "v4 Default MC Forwarding|%s",
4015 zrouter.default_mc_forwardingv4 ? "On" : "Off");
4016 ttable_add_row(table, "v6 All MC Forwarding|%s",
4017 zrouter.all_mc_forwardingv6 ? "On" : "Off");
4018 ttable_add_row(table, "v6 Default MC Forwarding|%s",
4019 zrouter.default_mc_forwardingv6 ? "On" : "Off");
4020
4021 out = ttable_dump(table, "\n");
4022 vty_out(vty, "%s\n", out);
4023 XFREE(MTYPE_TMP, out);
4024
4025 ttable_del(table);
4026 vty_out(vty,
4027 " Route Route Neighbor LSP LSP\n");
4028 vty_out(vty,
4029 "VRF Installs Removals Updates Installs Removals\n");
4030
4031 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4032 struct zebra_vrf *zvrf = vrf->info;
4033
4034 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64" %10" PRIu64 " %10" PRIu64 "\n",
4035 vrf->name, zvrf->installs, zvrf->removals,
4036 zvrf->neigh_updates, zvrf->lsp_installs,
4037 zvrf->lsp_removals);
4038 }
4039
4040 return CMD_SUCCESS;
4041 }
4042
4043 DEFUN (ip_forwarding,
4044 ip_forwarding_cmd,
4045 "ip forwarding",
4046 IP_STR
4047 "Turn on IP forwarding\n")
4048 {
4049 int ret;
4050
4051 ret = ipforward();
4052 if (ret == 0)
4053 ret = ipforward_on();
4054
4055 if (ret == 0) {
4056 vty_out(vty, "Can't turn on IP forwarding\n");
4057 return CMD_WARNING_CONFIG_FAILED;
4058 }
4059
4060 return CMD_SUCCESS;
4061 }
4062
4063 DEFUN (no_ip_forwarding,
4064 no_ip_forwarding_cmd,
4065 "no ip forwarding",
4066 NO_STR
4067 IP_STR
4068 "Turn off IP forwarding\n")
4069 {
4070 int ret;
4071
4072 ret = ipforward();
4073 if (ret != 0)
4074 ret = ipforward_off();
4075
4076 if (ret != 0) {
4077 vty_out(vty, "Can't turn off IP forwarding\n");
4078 return CMD_WARNING_CONFIG_FAILED;
4079 }
4080
4081 return CMD_SUCCESS;
4082 }
4083
4084 /* Only display ip forwarding is enabled or not. */
4085 DEFUN (show_ip_forwarding,
4086 show_ip_forwarding_cmd,
4087 "show ip forwarding",
4088 SHOW_STR
4089 IP_STR
4090 "IP forwarding status\n")
4091 {
4092 int ret;
4093
4094 ret = ipforward();
4095
4096 if (ret == 0)
4097 vty_out(vty, "IP forwarding is off\n");
4098 else
4099 vty_out(vty, "IP forwarding is on\n");
4100 return CMD_SUCCESS;
4101 }
4102
4103 /* Only display ipv6 forwarding is enabled or not. */
4104 DEFUN (show_ipv6_forwarding,
4105 show_ipv6_forwarding_cmd,
4106 "show ipv6 forwarding",
4107 SHOW_STR
4108 "IPv6 information\n"
4109 "Forwarding status\n")
4110 {
4111 int ret;
4112
4113 ret = ipforward_ipv6();
4114
4115 switch (ret) {
4116 case -1:
4117 vty_out(vty, "ipv6 forwarding is unknown\n");
4118 break;
4119 case 0:
4120 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4121 break;
4122 case 1:
4123 vty_out(vty, "ipv6 forwarding is %s\n", "on");
4124 break;
4125 default:
4126 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4127 break;
4128 }
4129 return CMD_SUCCESS;
4130 }
4131
4132 DEFUN (ipv6_forwarding,
4133 ipv6_forwarding_cmd,
4134 "ipv6 forwarding",
4135 IPV6_STR
4136 "Turn on IPv6 forwarding\n")
4137 {
4138 int ret;
4139
4140 ret = ipforward_ipv6();
4141 if (ret == 0)
4142 ret = ipforward_ipv6_on();
4143
4144 if (ret == 0) {
4145 vty_out(vty, "Can't turn on IPv6 forwarding\n");
4146 return CMD_WARNING_CONFIG_FAILED;
4147 }
4148
4149 return CMD_SUCCESS;
4150 }
4151
4152 DEFUN (no_ipv6_forwarding,
4153 no_ipv6_forwarding_cmd,
4154 "no ipv6 forwarding",
4155 NO_STR
4156 IPV6_STR
4157 "Turn off IPv6 forwarding\n")
4158 {
4159 int ret;
4160
4161 ret = ipforward_ipv6();
4162 if (ret != 0)
4163 ret = ipforward_ipv6_off();
4164
4165 if (ret != 0) {
4166 vty_out(vty, "Can't turn off IPv6 forwarding\n");
4167 return CMD_WARNING_CONFIG_FAILED;
4168 }
4169
4170 return CMD_SUCCESS;
4171 }
4172
4173 /* Display dataplane info */
4174 DEFUN (show_dataplane,
4175 show_dataplane_cmd,
4176 "show zebra dplane [detailed]",
4177 SHOW_STR
4178 ZEBRA_STR
4179 "Zebra dataplane information\n"
4180 "Detailed output\n")
4181 {
4182 int idx = 0;
4183 bool detailed = false;
4184
4185 if (argv_find(argv, argc, "detailed", &idx))
4186 detailed = true;
4187
4188 return dplane_show_helper(vty, detailed);
4189 }
4190
4191 /* Display dataplane providers info */
4192 DEFUN (show_dataplane_providers,
4193 show_dataplane_providers_cmd,
4194 "show zebra dplane providers [detailed]",
4195 SHOW_STR
4196 ZEBRA_STR
4197 "Zebra dataplane information\n"
4198 "Zebra dataplane provider information\n"
4199 "Detailed output\n")
4200 {
4201 int idx = 0;
4202 bool detailed = false;
4203
4204 if (argv_find(argv, argc, "detailed", &idx))
4205 detailed = true;
4206
4207 return dplane_show_provs_helper(vty, detailed);
4208 }
4209
4210 /* Configure dataplane incoming queue limit */
4211 DEFUN (zebra_dplane_queue_limit,
4212 zebra_dplane_queue_limit_cmd,
4213 "zebra dplane limit (0-10000)",
4214 ZEBRA_STR
4215 "Zebra dataplane\n"
4216 "Limit incoming queued updates\n"
4217 "Number of queued updates\n")
4218 {
4219 uint32_t limit = 0;
4220
4221 limit = strtoul(argv[3]->arg, NULL, 10);
4222
4223 dplane_set_in_queue_limit(limit, true);
4224
4225 return CMD_SUCCESS;
4226 }
4227
4228 /* Reset dataplane queue limit to default value */
4229 DEFUN (no_zebra_dplane_queue_limit,
4230 no_zebra_dplane_queue_limit_cmd,
4231 "no zebra dplane limit [(0-10000)]",
4232 NO_STR
4233 ZEBRA_STR
4234 "Zebra dataplane\n"
4235 "Limit incoming queued updates\n"
4236 "Number of queued updates\n")
4237 {
4238 dplane_set_in_queue_limit(0, false);
4239
4240 return CMD_SUCCESS;
4241 }
4242
4243 DEFUN (zebra_show_routing_tables_summary,
4244 zebra_show_routing_tables_summary_cmd,
4245 "show zebra router table summary",
4246 SHOW_STR
4247 ZEBRA_STR
4248 "The Zebra Router Information\n"
4249 "Table Information about this Zebra Router\n"
4250 "Summary Information\n")
4251 {
4252 zebra_router_show_table_summary(vty);
4253
4254 return CMD_SUCCESS;
4255 }
4256
4257 /* Table configuration write function. */
4258 static int config_write_table(struct vty *vty)
4259 {
4260 return 0;
4261 }
4262
4263 /* IPForwarding configuration write function. */
4264 static int config_write_forwarding(struct vty *vty)
4265 {
4266 if (!ipforward())
4267 vty_out(vty, "no ip forwarding\n");
4268 if (!ipforward_ipv6())
4269 vty_out(vty, "no ipv6 forwarding\n");
4270 vty_out(vty, "!\n");
4271 return 0;
4272 }
4273
4274 DEFUN_HIDDEN (show_frr,
4275 show_frr_cmd,
4276 "show frr",
4277 SHOW_STR
4278 "FRR\n")
4279 {
4280 vty_out(vty, "........ .. . .. . ..... ...77:................................................\n");
4281 vty_out(vty, ".............................7777:..............................................\n");
4282 vty_out(vty, ".............................777777,............................................\n");
4283 vty_out(vty, "... .........................77777777,..........................................\n");
4284 vty_out(vty, "............................=7777777777:........................................\n");
4285 vty_out(vty, "........................:7777777777777777,......................................\n");
4286 vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
4287 vty_out(vty, "...................I7777777777+.................................................\n");
4288 vty_out(vty, "................,777777777?............ .......................................\n");
4289 vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
4290 vty_out(vty, ".............77777777~........=7777777777.......................................\n");
4291 vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
4292 vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
4293 vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
4294 vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4295 vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4296 vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4297 vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4298 vty_out(vty, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4299 vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4300 vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4301 vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4302 vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4303 vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4304 vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4305 vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4306 vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4307 vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4308 vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4309 vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4310 vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4311 vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4312 vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
4313 vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4314 vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4315 vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4316 vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4317 vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4318 vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4319 vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4320 vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
4321 vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
4322 vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
4323 vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
4324 vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
4325 vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
4326 vty_out(vty, ".......................=77777777777777777............777777I....................\n");
4327 vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
4328 vty_out(vty, "............................~777777777777..............+777777..................\n");
4329 vty_out(vty, "................................~77777777...............=777777.................\n");
4330 vty_out(vty, ".....................................:=?I................~777777................\n");
4331 vty_out(vty, "..........................................................:777777,..............\n");
4332 vty_out(vty, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4333
4334 return CMD_SUCCESS;
4335 }
4336
4337 #ifdef HAVE_NETLINK
4338 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf,
4339 zebra_kernel_netlink_batch_tx_buf_cmd,
4340 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4341 ZEBRA_STR
4342 "Zebra kernel interface\n"
4343 "Set Netlink parameters\n"
4344 "Set batch buffer size and send threshold\n"
4345 "Size of the buffer\n"
4346 "Send threshold\n")
4347 {
4348 uint32_t bufsize = 0, threshold = 0;
4349
4350 bufsize = strtoul(argv[4]->arg, NULL, 10);
4351 threshold = strtoul(argv[5]->arg, NULL, 10);
4352
4353 netlink_set_batch_buffer_size(bufsize, threshold, true);
4354
4355 return CMD_SUCCESS;
4356 }
4357
4358 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf,
4359 no_zebra_kernel_netlink_batch_tx_buf_cmd,
4360 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4361 NO_STR ZEBRA_STR
4362 "Zebra kernel interface\n"
4363 "Set Netlink parameters\n"
4364 "Set batch buffer size and send threshold\n"
4365 "Size of the buffer\n"
4366 "Send threshold\n")
4367 {
4368 netlink_set_batch_buffer_size(0, 0, false);
4369
4370 return CMD_SUCCESS;
4371 }
4372
4373 DEFPY (zebra_protodown_bit,
4374 zebra_protodown_bit_cmd,
4375 "zebra protodown reason-bit (0-31)$bit",
4376 ZEBRA_STR
4377 "Protodown Configuration\n"
4378 "Reason Bit used in the kernel for application\n"
4379 "Reason Bit range\n")
4380 {
4381 if_netlink_set_frr_protodown_r_bit(bit);
4382 return CMD_SUCCESS;
4383 }
4384
4385 DEFPY (no_zebra_protodown_bit,
4386 no_zebra_protodown_bit_cmd,
4387 "no zebra protodown reason-bit [(0-31)$bit]",
4388 NO_STR
4389 ZEBRA_STR
4390 "Protodown Configuration\n"
4391 "Reason Bit used in the kernel for setting protodown\n"
4392 "Reason Bit Range\n")
4393 {
4394 if_netlink_unset_frr_protodown_r_bit();
4395 return CMD_SUCCESS;
4396 }
4397
4398 #endif /* HAVE_NETLINK */
4399
4400 DEFUN(ip_table_range, ip_table_range_cmd,
4401 "[no] ip table range (1-4294967295) (1-4294967295)",
4402 NO_STR IP_STR
4403 "table configuration\n"
4404 "Configure table range\n"
4405 "Start Routing Table\n"
4406 "End Routing Table\n")
4407 {
4408 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
4409
4410 if (!zvrf)
4411 return CMD_WARNING;
4412
4413 if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) {
4414 vty_out(vty,
4415 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4416 return CMD_WARNING;
4417 }
4418
4419 if (strmatch(argv[0]->text, "no"))
4420 return table_manager_range(vty, false, zvrf, NULL, NULL);
4421
4422 return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg);
4423 }
4424
4425 #ifdef HAVE_SCRIPTING
4426
4427 DEFUN(zebra_on_rib_process_script, zebra_on_rib_process_script_cmd,
4428 "zebra on-rib-process script SCRIPT",
4429 ZEBRA_STR
4430 "on_rib_process_dplane_results hook call\n"
4431 "Set a script\n"
4432 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4433 {
4434
4435 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
4436 argv[3]->arg)
4437 == 0) {
4438 vty_out(vty, "Successfully added script %s for hook call %s\n",
4439 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4440 } else {
4441 vty_out(vty, "Failed to add script %s for hook call %s\n",
4442 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4443 }
4444 return CMD_SUCCESS;
4445 }
4446
4447 #endif /* HAVE_SCRIPTING */
4448
4449 /* IP node for static routes. */
4450 static int zebra_ip_config(struct vty *vty);
4451 static struct cmd_node ip_node = {
4452 .name = "static ip",
4453 .node = IP_NODE,
4454 .prompt = "",
4455 .config_write = zebra_ip_config,
4456 };
4457 static int config_write_protocol(struct vty *vty);
4458 static struct cmd_node protocol_node = {
4459 .name = "protocol",
4460 .node = PROTOCOL_NODE,
4461 .prompt = "",
4462 .config_write = config_write_protocol,
4463 };
4464 /* table node for routing tables. */
4465 static int config_write_table(struct vty *vty);
4466 static struct cmd_node table_node = {
4467 .name = "table",
4468 .node = TABLE_NODE,
4469 .prompt = "",
4470 .config_write = config_write_table,
4471 };
4472 static int config_write_forwarding(struct vty *vty);
4473 static struct cmd_node forwarding_node = {
4474 .name = "forwarding",
4475 .node = FORWARDING_NODE,
4476 .prompt = "",
4477 .config_write = config_write_forwarding,
4478 };
4479
4480 /* Route VTY. */
4481 void zebra_vty_init(void)
4482 {
4483 /* Install configuration write function. */
4484 install_node(&table_node);
4485 install_node(&forwarding_node);
4486
4487 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
4488 install_element(CONFIG_NODE, &ip_forwarding_cmd);
4489 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
4490 install_element(ENABLE_NODE, &show_zebra_cmd);
4491
4492 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
4493 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
4494 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
4495
4496 /* Route-map */
4497 zebra_route_map_init();
4498
4499 install_node(&ip_node);
4500 install_node(&protocol_node);
4501
4502 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
4503 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
4504
4505 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
4506 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
4507
4508 install_element(CONFIG_NODE, &zebra_nexthop_group_keep_cmd);
4509 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
4510 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
4511 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
4512 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
4513 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
4514 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
4515 install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
4516 install_element(CONFIG_NODE, &proto_nexthop_group_only_cmd);
4517 install_element(CONFIG_NODE, &backup_nexthop_recursive_use_enable_cmd);
4518
4519 install_element(VIEW_NODE, &show_nexthop_group_cmd);
4520 install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
4521
4522 install_element(VIEW_NODE, &show_vrf_cmd);
4523 install_element(VIEW_NODE, &show_vrf_vni_cmd);
4524 install_element(VIEW_NODE, &show_route_cmd);
4525 install_element(VIEW_NODE, &show_ro_cmd);
4526 install_element(VIEW_NODE, &show_route_detail_cmd);
4527 install_element(VIEW_NODE, &show_route_summary_cmd);
4528 install_element(VIEW_NODE, &show_ip_nht_cmd);
4529
4530 install_element(VIEW_NODE, &show_ip_rpf_cmd);
4531 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
4532
4533 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
4534 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
4535 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
4536 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
4537 install_element(VRF_NODE, &ip_nht_default_route_cmd);
4538 install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
4539 install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
4540 install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
4541 install_element(CONFIG_NODE, &rnh_hide_backups_cmd);
4542
4543 install_element(VIEW_NODE, &show_frr_cmd);
4544 install_element(VIEW_NODE, &show_evpn_global_cmd);
4545 install_element(VIEW_NODE, &show_evpn_vni_cmd);
4546 install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
4547 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
4548 install_element(VIEW_NODE, &show_evpn_l2_nh_cmd);
4549 install_element(VIEW_NODE, &show_evpn_es_cmd);
4550 install_element(VIEW_NODE, &show_evpn_es_evi_cmd);
4551 install_element(VIEW_NODE, &show_evpn_access_vlan_cmd);
4552 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
4553 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
4554 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
4555 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
4556 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
4557 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
4558 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
4559 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
4560 install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
4561 install_element(VIEW_NODE, &show_evpn_mac_vni_detail_cmd);
4562 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
4563 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
4564 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
4565 install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
4566 install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
4567 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
4568 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
4569 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
4570 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
4571 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
4572 install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
4573 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
4574 install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
4575 install_element(CONFIG_NODE, &evpn_accept_bgp_seq_cmd);
4576 install_element(CONFIG_NODE, &no_evpn_accept_bgp_seq_cmd);
4577
4578 install_element(VIEW_NODE, &show_neigh_cmd);
4579
4580 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
4581 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
4582 install_element(VIEW_NODE, &show_pbr_rule_cmd);
4583 install_element(CONFIG_NODE, &pbr_nexthop_resolve_cmd);
4584 install_element(VIEW_NODE, &show_route_zebra_dump_cmd);
4585
4586 install_element(CONFIG_NODE, &evpn_mh_mac_holdtime_cmd);
4587 install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd);
4588 install_element(CONFIG_NODE, &evpn_mh_startup_delay_cmd);
4589 install_element(CONFIG_NODE, &evpn_mh_redirect_off_cmd);
4590 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
4591 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
4592 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
4593 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
4594
4595 install_element(VIEW_NODE, &show_dataplane_cmd);
4596 install_element(VIEW_NODE, &show_dataplane_providers_cmd);
4597 install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
4598 install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
4599
4600 install_element(CONFIG_NODE, &ip_table_range_cmd);
4601 install_element(VRF_NODE, &ip_table_range_cmd);
4602
4603 #ifdef HAVE_NETLINK
4604 install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd);
4605 install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
4606 install_element(CONFIG_NODE, &zebra_protodown_bit_cmd);
4607 install_element(CONFIG_NODE, &no_zebra_protodown_bit_cmd);
4608 #endif /* HAVE_NETLINK */
4609
4610 #ifdef HAVE_SCRIPTING
4611 install_element(CONFIG_NODE, &zebra_on_rib_process_script_cmd);
4612 #endif /* HAVE_SCRIPTING */
4613
4614 install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
4615 }