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