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