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