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