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