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