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