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