]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
Merge pull request #5789 from donaldsharp/bgp_ebgp_reason
[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 "zebra_memory.h"
25 #include "if.h"
26 #include "prefix.h"
27 #include "command.h"
28 #include "table.h"
29 #include "rib.h"
30 #include "nexthop.h"
31 #include "vrf.h"
32 #include "linklist.h"
33 #include "mpls.h"
34 #include "routemap.h"
35 #include "srcdest_table.h"
36 #include "vxlan.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 "zebra/zebra_vxlan.h"
47 #ifndef VTYSH_EXTRACT_PL
48 #include "zebra/zebra_vty_clippy.c"
49 #endif
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/interface.h"
57
58 extern int allow_delete;
59
60 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
61 safi_t safi, bool use_fib, bool use_json,
62 route_tag_t tag,
63 const struct prefix *longer_prefix_p,
64 bool supernets_only, int type,
65 unsigned short ospf_instance_id);
66 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
67 int mcast, bool use_fib, bool show_ng);
68 static void vty_show_ip_route_summary(struct vty *vty,
69 struct route_table *table, bool use_json);
70 static void vty_show_ip_route_summary_prefix(struct vty *vty,
71 struct route_table *table,
72 bool use_json);
73
74 DEFUN (ip_multicast_mode,
75 ip_multicast_mode_cmd,
76 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
77 IP_STR
78 "Multicast options\n"
79 "RPF lookup behavior\n"
80 "Lookup in unicast RIB only\n"
81 "Lookup in multicast RIB only\n"
82 "Try multicast RIB first, fall back to unicast RIB\n"
83 "Lookup both, use entry with lower distance\n"
84 "Lookup both, use entry with longer prefix\n")
85 {
86 char *mode = argv[3]->text;
87
88 if (strmatch(mode, "urib-only"))
89 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
90 else if (strmatch(mode, "mrib-only"))
91 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
92 else if (strmatch(mode, "mrib-then-urib"))
93 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
94 else if (strmatch(mode, "lower-distance"))
95 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
96 else if (strmatch(mode, "longer-prefix"))
97 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
98 else {
99 vty_out(vty, "Invalid mode specified\n");
100 return CMD_WARNING_CONFIG_FAILED;
101 }
102
103 return CMD_SUCCESS;
104 }
105
106 DEFUN (no_ip_multicast_mode,
107 no_ip_multicast_mode_cmd,
108 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
109 NO_STR
110 IP_STR
111 "Multicast options\n"
112 "RPF lookup behavior\n"
113 "Lookup in unicast RIB only\n"
114 "Lookup in multicast RIB only\n"
115 "Try multicast RIB first, fall back to unicast RIB\n"
116 "Lookup both, use entry with lower distance\n"
117 "Lookup both, use entry with longer prefix\n")
118 {
119 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
120 return CMD_SUCCESS;
121 }
122
123
124 DEFUN (show_ip_rpf,
125 show_ip_rpf_cmd,
126 "show ip rpf [json]",
127 SHOW_STR
128 IP_STR
129 "Display RPF information for multicast source\n"
130 JSON_STR)
131 {
132 bool uj = use_json(argc, argv);
133 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
134 false, uj, 0, NULL, false, 0, 0);
135 }
136
137 DEFUN (show_ip_rpf_addr,
138 show_ip_rpf_addr_cmd,
139 "show ip rpf A.B.C.D",
140 SHOW_STR
141 IP_STR
142 "Display RPF information for multicast source\n"
143 "IP multicast source address (e.g. 10.0.0.0)\n")
144 {
145 int idx_ipv4 = 3;
146 struct in_addr addr;
147 struct route_node *rn;
148 struct route_entry *re;
149 int ret;
150
151 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
152 if (ret == 0) {
153 vty_out(vty, "%% Malformed address\n");
154 return CMD_WARNING;
155 }
156
157 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
158
159 if (re)
160 vty_show_ip_route_detail(vty, rn, 1, false, false);
161 else
162 vty_out(vty, "%% No match for RPF lookup\n");
163
164 return CMD_SUCCESS;
165 }
166
167 static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
168 {
169 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
170 if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
171 !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
172 return '*';
173 else
174 return ' ';
175 }
176
177 if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED)) {
178 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
179 return 'q';
180
181 return 'r';
182 }
183
184 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
185 return 'q';
186
187 return ' ';
188 }
189
190 /* New RIB. Detailed information for IPv4 route. */
191 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
192 int mcast, bool use_fib, bool show_ng)
193 {
194 struct route_entry *re;
195 struct nexthop *nexthop;
196 char buf[SRCDEST2STR_BUFFER];
197 struct zebra_vrf *zvrf;
198 rib_dest_t *dest;
199
200 dest = rib_dest_from_rnode(rn);
201
202 RNODE_FOREACH_RE (rn, re) {
203 /*
204 * If re not selected for forwarding, skip re
205 * for "show ip/ipv6 fib <prefix>"
206 */
207 if (use_fib && re != dest->selected_fib)
208 continue;
209
210 const char *mcast_info = "";
211 if (mcast) {
212 rib_table_info_t *info = srcdest_rnode_table_info(rn);
213 mcast_info = (info->safi == SAFI_MULTICAST)
214 ? " using Multicast RIB"
215 : " using Unicast RIB";
216 }
217
218 vty_out(vty, "Routing entry for %s%s\n",
219 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
220 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
221 if (re->instance)
222 vty_out(vty, "[%d]", re->instance);
223 vty_out(vty, "\"");
224 vty_out(vty, ", distance %u, metric %u", re->distance,
225 re->metric);
226 if (re->tag) {
227 vty_out(vty, ", tag %u", re->tag);
228 #if defined(SUPPORT_REALMS)
229 if (re->tag > 0 && re->tag <= 255)
230 vty_out(vty, "(realm)");
231 #endif
232 }
233 if (re->mtu)
234 vty_out(vty, ", mtu %u", re->mtu);
235 if (re->vrf_id != VRF_DEFAULT) {
236 zvrf = vrf_info_lookup(re->vrf_id);
237 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
238 }
239 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
240 vty_out(vty, ", best");
241 vty_out(vty, "\n");
242
243 time_t uptime;
244 struct tm *tm;
245
246 uptime = monotime(NULL);
247 uptime -= re->uptime;
248 tm = gmtime(&uptime);
249
250 vty_out(vty, " Last update ");
251
252 if (uptime < ONE_DAY_SECOND)
253 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
254 tm->tm_sec);
255 else if (uptime < ONE_WEEK_SECOND)
256 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
257 tm->tm_min);
258 else
259 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
260 tm->tm_yday - ((tm->tm_yday / 7) * 7),
261 tm->tm_hour);
262 vty_out(vty, " ago\n");
263
264 if (show_ng)
265 vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id);
266
267 for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
268 char addrstr[32];
269
270 vty_out(vty, " %c%s",
271 re_status_output_char(re, nexthop),
272 nexthop->rparent ? " " : "");
273
274 switch (nexthop->type) {
275 case NEXTHOP_TYPE_IPV4:
276 case NEXTHOP_TYPE_IPV4_IFINDEX:
277 vty_out(vty, " %s",
278 inet_ntoa(nexthop->gate.ipv4));
279 if (nexthop->ifindex)
280 vty_out(vty, ", via %s",
281 ifindex2ifname(
282 nexthop->ifindex,
283 nexthop->vrf_id));
284 break;
285 case NEXTHOP_TYPE_IPV6:
286 case NEXTHOP_TYPE_IPV6_IFINDEX:
287 vty_out(vty, " %s",
288 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
289 buf, sizeof buf));
290 if (nexthop->ifindex)
291 vty_out(vty, ", via %s",
292 ifindex2ifname(
293 nexthop->ifindex,
294 nexthop->vrf_id));
295 break;
296 case NEXTHOP_TYPE_IFINDEX:
297 vty_out(vty, " directly connected, %s",
298 ifindex2ifname(nexthop->ifindex,
299 nexthop->vrf_id));
300 break;
301 case NEXTHOP_TYPE_BLACKHOLE:
302 vty_out(vty, " unreachable");
303 switch (nexthop->bh_type) {
304 case BLACKHOLE_REJECT:
305 vty_out(vty, " (ICMP unreachable)");
306 break;
307 case BLACKHOLE_ADMINPROHIB:
308 vty_out(vty,
309 " (ICMP admin-prohibited)");
310 break;
311 case BLACKHOLE_NULL:
312 vty_out(vty, " (blackhole)");
313 break;
314 case BLACKHOLE_UNSPEC:
315 break;
316 }
317 break;
318 default:
319 break;
320 }
321
322 if ((re->vrf_id != nexthop->vrf_id)
323 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
324 struct vrf *vrf =
325 vrf_lookup_by_id(nexthop->vrf_id);
326
327 if (vrf)
328 vty_out(vty, "(vrf %s)", vrf->name);
329 else
330 vty_out(vty, "(vrf UNKNOWN)");
331 }
332
333 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
334 vty_out(vty, " (duplicate nexthop removed)");
335
336 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
337 vty_out(vty, " inactive");
338
339 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
340 vty_out(vty, " onlink");
341
342 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
343 vty_out(vty, " (recursive)");
344
345 switch (nexthop->type) {
346 case NEXTHOP_TYPE_IPV4:
347 case NEXTHOP_TYPE_IPV4_IFINDEX:
348 if (nexthop->src.ipv4.s_addr) {
349 if (inet_ntop(AF_INET,
350 &nexthop->src.ipv4,
351 addrstr, sizeof addrstr))
352 vty_out(vty, ", src %s",
353 addrstr);
354 }
355 break;
356 case NEXTHOP_TYPE_IPV6:
357 case NEXTHOP_TYPE_IPV6_IFINDEX:
358 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
359 &in6addr_any)) {
360 if (inet_ntop(AF_INET6,
361 &nexthop->src.ipv6,
362 addrstr, sizeof addrstr))
363 vty_out(vty, ", src %s",
364 addrstr);
365 }
366 break;
367 default:
368 break;
369 }
370
371 if (re->nexthop_mtu)
372 vty_out(vty, ", mtu %u", re->nexthop_mtu);
373
374 /* Label information */
375 if (nexthop->nh_label
376 && nexthop->nh_label->num_labels) {
377 vty_out(vty, ", label %s",
378 mpls_label2str(
379 nexthop->nh_label->num_labels,
380 nexthop->nh_label->label, buf,
381 sizeof buf, 1));
382 }
383
384 if (nexthop->weight)
385 vty_out(vty, ", weight %u", nexthop->weight);
386
387 vty_out(vty, "\n");
388 }
389 vty_out(vty, "\n");
390 }
391 }
392
393 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
394 struct route_entry *re, json_object *json,
395 bool is_fib)
396 {
397 struct nexthop *nexthop;
398 int len = 0;
399 char buf[SRCDEST2STR_BUFFER];
400 json_object *json_nexthops = NULL;
401 json_object *json_nexthop = NULL;
402 json_object *json_route = NULL;
403 json_object *json_labels = NULL;
404 time_t uptime;
405 struct tm *tm;
406 struct vrf *vrf = NULL;
407 rib_dest_t *dest = rib_dest_from_rnode(rn);
408 struct nexthop_group *nhg;
409
410 uptime = monotime(NULL);
411 uptime -= re->uptime;
412 tm = gmtime(&uptime);
413
414 /* If showing fib information, use the fib view of the
415 * nexthops.
416 */
417 if (is_fib)
418 nhg = rib_active_nhg(re);
419 else
420 nhg = re->nhe->nhg;
421
422 if (json) {
423 json_route = json_object_new_object();
424 json_nexthops = json_object_new_array();
425
426 json_object_string_add(json_route, "prefix",
427 srcdest_rnode2str(rn, buf, sizeof buf));
428 json_object_string_add(json_route, "protocol",
429 zebra_route_string(re->type));
430
431 if (re->instance)
432 json_object_int_add(json_route, "instance",
433 re->instance);
434
435 if (re->vrf_id) {
436 json_object_int_add(json_route, "vrfId", re->vrf_id);
437 vrf = vrf_lookup_by_id(re->vrf_id);
438 json_object_string_add(json_route, "vrfName",
439 vrf->name);
440
441 }
442 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
443 json_object_boolean_true_add(json_route, "selected");
444
445 if (dest->selected_fib == re)
446 json_object_boolean_true_add(json_route,
447 "destSelected");
448
449 json_object_int_add(json_route, "distance",
450 re->distance);
451 json_object_int_add(json_route, "metric", re->metric);
452
453 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
454 json_object_boolean_true_add(json_route, "installed");
455
456 if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
457 json_object_boolean_true_add(json_route, "failed");
458
459 if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
460 json_object_boolean_true_add(json_route, "queued");
461
462 if (re->tag)
463 json_object_int_add(json_route, "tag", re->tag);
464
465 if (re->table)
466 json_object_int_add(json_route, "table", re->table);
467
468 json_object_int_add(json_route, "internalStatus",
469 re->status);
470 json_object_int_add(json_route, "internalFlags",
471 re->flags);
472 json_object_int_add(json_route, "internalNextHopNum",
473 nexthop_group_nexthop_num(re->nhe->nhg));
474 json_object_int_add(json_route, "internalNextHopActiveNum",
475 nexthop_group_active_nexthop_num(
476 re->nhe->nhg));
477 if (uptime < ONE_DAY_SECOND)
478 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
479 tm->tm_sec);
480 else if (uptime < ONE_WEEK_SECOND)
481 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
482 tm->tm_min);
483 else
484 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
485 tm->tm_yday - ((tm->tm_yday / 7) * 7),
486 tm->tm_hour);
487
488 json_object_string_add(json_route, "uptime", buf);
489
490 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
491 json_nexthop = json_object_new_object();
492
493 json_object_int_add(json_nexthop, "flags",
494 nexthop->flags);
495
496 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
497 json_object_boolean_true_add(json_nexthop,
498 "duplicate");
499
500 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
501 json_object_boolean_true_add(json_nexthop,
502 "fib");
503
504 switch (nexthop->type) {
505 case NEXTHOP_TYPE_IPV4:
506 case NEXTHOP_TYPE_IPV4_IFINDEX:
507 json_object_string_add(
508 json_nexthop, "ip",
509 inet_ntoa(nexthop->gate.ipv4));
510 json_object_string_add(json_nexthop, "afi",
511 "ipv4");
512
513 if (nexthop->ifindex) {
514 json_object_int_add(json_nexthop,
515 "interfaceIndex",
516 nexthop->ifindex);
517 json_object_string_add(
518 json_nexthop, "interfaceName",
519 ifindex2ifname(
520 nexthop->ifindex,
521 nexthop->vrf_id));
522 }
523 break;
524 case NEXTHOP_TYPE_IPV6:
525 case NEXTHOP_TYPE_IPV6_IFINDEX:
526 json_object_string_add(
527 json_nexthop, "ip",
528 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
529 buf, sizeof buf));
530 json_object_string_add(json_nexthop, "afi",
531 "ipv6");
532
533 if (nexthop->ifindex) {
534 json_object_int_add(json_nexthop,
535 "interfaceIndex",
536 nexthop->ifindex);
537 json_object_string_add(
538 json_nexthop, "interfaceName",
539 ifindex2ifname(
540 nexthop->ifindex,
541 nexthop->vrf_id));
542 }
543 break;
544
545 case NEXTHOP_TYPE_IFINDEX:
546 json_object_boolean_true_add(
547 json_nexthop, "directlyConnected");
548 json_object_int_add(json_nexthop,
549 "interfaceIndex",
550 nexthop->ifindex);
551 json_object_string_add(
552 json_nexthop, "interfaceName",
553 ifindex2ifname(nexthop->ifindex,
554 nexthop->vrf_id));
555 break;
556 case NEXTHOP_TYPE_BLACKHOLE:
557 json_object_boolean_true_add(json_nexthop,
558 "unreachable");
559 switch (nexthop->bh_type) {
560 case BLACKHOLE_REJECT:
561 json_object_boolean_true_add(
562 json_nexthop, "reject");
563 break;
564 case BLACKHOLE_ADMINPROHIB:
565 json_object_boolean_true_add(
566 json_nexthop,
567 "admin-prohibited");
568 break;
569 case BLACKHOLE_NULL:
570 json_object_boolean_true_add(
571 json_nexthop, "blackhole");
572 break;
573 case BLACKHOLE_UNSPEC:
574 break;
575 }
576 break;
577 default:
578 break;
579 }
580
581 if ((nexthop->vrf_id != re->vrf_id)
582 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
583 vrf = vrf_lookup_by_id(nexthop->vrf_id);
584 json_object_string_add(json_nexthop, "vrf",
585 vrf->name);
586 }
587 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
588 json_object_boolean_true_add(json_nexthop,
589 "duplicate");
590
591 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
592 json_object_boolean_true_add(json_nexthop,
593 "active");
594
595 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
596 json_object_boolean_true_add(json_nexthop,
597 "onLink");
598
599 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
600 json_object_boolean_true_add(json_nexthop,
601 "recursive");
602
603 switch (nexthop->type) {
604 case NEXTHOP_TYPE_IPV4:
605 case NEXTHOP_TYPE_IPV4_IFINDEX:
606 if (nexthop->src.ipv4.s_addr) {
607 if (inet_ntop(AF_INET,
608 &nexthop->src.ipv4, buf,
609 sizeof buf))
610 json_object_string_add(
611 json_nexthop, "source",
612 buf);
613 }
614 break;
615 case NEXTHOP_TYPE_IPV6:
616 case NEXTHOP_TYPE_IPV6_IFINDEX:
617 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
618 &in6addr_any)) {
619 if (inet_ntop(AF_INET6,
620 &nexthop->src.ipv6, buf,
621 sizeof buf))
622 json_object_string_add(
623 json_nexthop, "source",
624 buf);
625 }
626 break;
627 default:
628 break;
629 }
630
631 if (nexthop->nh_label
632 && nexthop->nh_label->num_labels) {
633 json_labels = json_object_new_array();
634
635 for (int label_index = 0;
636 label_index
637 < nexthop->nh_label->num_labels;
638 label_index++)
639 json_object_array_add(
640 json_labels,
641 json_object_new_int(
642 nexthop->nh_label->label
643 [label_index]));
644
645 json_object_object_add(json_nexthop, "labels",
646 json_labels);
647 }
648
649 json_object_array_add(json_nexthops, json_nexthop);
650 }
651
652 json_object_object_add(json_route, "nexthops", json_nexthops);
653 json_object_array_add(json, json_route);
654 return;
655 }
656
657 /* Nexthop information. */
658 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
659 if (nexthop == nhg->nexthop) {
660 /* Prefix information. */
661 len = vty_out(vty, "%c", zebra_route_char(re->type));
662 if (re->instance)
663 len += vty_out(vty, "[%d]", re->instance);
664 len += vty_out(
665 vty, "%c%c %s",
666 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
667 ? '>'
668 : ' ',
669 re_status_output_char(re, nexthop),
670 srcdest_rnode2str(rn, buf, sizeof buf));
671
672 /* Distance and metric display. */
673 if (((re->type == ZEBRA_ROUTE_CONNECT) &&
674 (re->distance || re->metric)) ||
675 (re->type != ZEBRA_ROUTE_CONNECT))
676 len += vty_out(vty, " [%u/%u]", re->distance,
677 re->metric);
678 } else {
679 vty_out(vty, " %c%*c",
680 re_status_output_char(re, nexthop),
681 len - 3 + (2 * nexthop_level(nexthop)), ' ');
682 }
683
684 switch (nexthop->type) {
685 case NEXTHOP_TYPE_IPV4:
686 case NEXTHOP_TYPE_IPV4_IFINDEX:
687 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
688 if (nexthop->ifindex)
689 vty_out(vty, ", %s",
690 ifindex2ifname(nexthop->ifindex,
691 nexthop->vrf_id));
692 break;
693 case NEXTHOP_TYPE_IPV6:
694 case NEXTHOP_TYPE_IPV6_IFINDEX:
695 vty_out(vty, " via %s",
696 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
697 sizeof buf));
698 if (nexthop->ifindex)
699 vty_out(vty, ", %s",
700 ifindex2ifname(nexthop->ifindex,
701 nexthop->vrf_id));
702 break;
703
704 case NEXTHOP_TYPE_IFINDEX:
705 vty_out(vty, " is directly connected, %s",
706 ifindex2ifname(nexthop->ifindex,
707 nexthop->vrf_id));
708 break;
709 case NEXTHOP_TYPE_BLACKHOLE:
710 vty_out(vty, " unreachable");
711 switch (nexthop->bh_type) {
712 case BLACKHOLE_REJECT:
713 vty_out(vty, " (ICMP unreachable)");
714 break;
715 case BLACKHOLE_ADMINPROHIB:
716 vty_out(vty, " (ICMP admin-prohibited)");
717 break;
718 case BLACKHOLE_NULL:
719 vty_out(vty, " (blackhole)");
720 break;
721 case BLACKHOLE_UNSPEC:
722 break;
723 }
724 break;
725 default:
726 break;
727 }
728
729 if ((nexthop->vrf_id != re->vrf_id)
730 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
731 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
732
733 if (vrf)
734 vty_out(vty, "(vrf %s)", vrf->name);
735 else
736 vty_out(vty, "(vrf UNKNOWN)");
737 }
738
739 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
740 vty_out(vty, " inactive");
741
742 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
743 vty_out(vty, " onlink");
744
745 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
746 vty_out(vty, " (recursive)");
747
748 switch (nexthop->type) {
749 case NEXTHOP_TYPE_IPV4:
750 case NEXTHOP_TYPE_IPV4_IFINDEX:
751 if (nexthop->src.ipv4.s_addr) {
752 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
753 sizeof buf))
754 vty_out(vty, ", src %s", buf);
755 }
756 break;
757 case NEXTHOP_TYPE_IPV6:
758 case NEXTHOP_TYPE_IPV6_IFINDEX:
759 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
760 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
761 sizeof buf))
762 vty_out(vty, ", src %s", buf);
763 }
764 break;
765 default:
766 break;
767 }
768
769 /* Label information */
770 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
771 vty_out(vty, ", label %s",
772 mpls_label2str(nexthop->nh_label->num_labels,
773 nexthop->nh_label->label, buf,
774 sizeof buf, 1));
775 }
776
777 if (uptime < ONE_DAY_SECOND)
778 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
779 tm->tm_min, tm->tm_sec);
780 else if (uptime < ONE_WEEK_SECOND)
781 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
782 tm->tm_hour, tm->tm_min);
783 else
784 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
785 tm->tm_yday - ((tm->tm_yday / 7) * 7),
786 tm->tm_hour);
787 vty_out(vty, "\n");
788 }
789 }
790
791 static void vty_show_ip_route_detail_json(struct vty *vty,
792 struct route_node *rn, bool use_fib)
793 {
794 json_object *json = NULL;
795 json_object *json_prefix = NULL;
796 struct route_entry *re;
797 char buf[BUFSIZ];
798 rib_dest_t *dest;
799
800 dest = rib_dest_from_rnode(rn);
801
802 json = json_object_new_object();
803 json_prefix = json_object_new_array();
804
805 RNODE_FOREACH_RE (rn, re) {
806 /*
807 * If re not selected for forwarding, skip re
808 * for "show ip/ipv6 fib <prefix> json"
809 */
810 if (use_fib && re != dest->selected_fib)
811 continue;
812 vty_show_ip_route(vty, rn, re, json_prefix, use_fib);
813 }
814
815 prefix2str(&rn->p, buf, sizeof(buf));
816 json_object_object_add(json, buf, json_prefix);
817 vty_out(vty, "%s\n", json_object_to_json_string_ext(
818 json, JSON_C_TO_STRING_PRETTY));
819 json_object_free(json);
820 }
821
822 static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
823 struct route_table *table, afi_t afi,
824 bool use_fib, route_tag_t tag,
825 const struct prefix *longer_prefix_p,
826 bool supernets_only, int type,
827 unsigned short ospf_instance_id, bool use_json,
828 uint32_t tableid)
829 {
830 struct route_node *rn;
831 struct route_entry *re;
832 int first = 1;
833 rib_dest_t *dest;
834 json_object *json = NULL;
835 json_object *json_prefix = NULL;
836 uint32_t addr;
837 char buf[BUFSIZ];
838
839 if (use_json)
840 json = json_object_new_object();
841
842 /* Show all routes. */
843 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
844 dest = rib_dest_from_rnode(rn);
845
846 RNODE_FOREACH_RE (rn, re) {
847 if (use_fib && re != dest->selected_fib)
848 continue;
849
850 if (tag && re->tag != tag)
851 continue;
852
853 if (longer_prefix_p
854 && !prefix_match(longer_prefix_p, &rn->p))
855 continue;
856
857 /* This can only be true when the afi is IPv4 */
858 if (supernets_only) {
859 addr = ntohl(rn->p.u.prefix4.s_addr);
860
861 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
862 continue;
863
864 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
865 continue;
866
867 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
868 continue;
869 }
870
871 if (type && re->type != type)
872 continue;
873
874 if (ospf_instance_id
875 && (re->type != ZEBRA_ROUTE_OSPF
876 || re->instance != ospf_instance_id))
877 continue;
878
879 if (use_json) {
880 if (!json_prefix)
881 json_prefix = json_object_new_array();
882 } else {
883 if (first) {
884 if (afi == AFI_IP)
885 vty_out(vty,
886 SHOW_ROUTE_V4_HEADER);
887 else
888 vty_out(vty,
889 SHOW_ROUTE_V6_HEADER);
890
891 if (tableid && tableid != RT_TABLE_MAIN)
892 vty_out(vty, "\nVRF %s table %u:\n",
893 zvrf_name(zvrf), tableid);
894 else if (zvrf_id(zvrf) != VRF_DEFAULT)
895 vty_out(vty, "\nVRF %s:\n",
896 zvrf_name(zvrf));
897 first = 0;
898 }
899 }
900
901 vty_show_ip_route(vty, rn, re, json_prefix, use_fib);
902 }
903
904 if (json_prefix) {
905 prefix2str(&rn->p, buf, sizeof(buf));
906 json_object_object_add(json, buf, json_prefix);
907 json_prefix = NULL;
908 }
909 }
910
911 if (use_json) {
912 vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
913 JSON_C_TO_STRING_PRETTY));
914 json_object_free(json);
915 }
916 }
917
918 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
919 safi_t safi, bool use_fib, bool use_json,
920 route_tag_t tag,
921 const struct prefix *longer_prefix_p,
922 bool supernets_only, int type,
923 unsigned short ospf_instance_id)
924 {
925 struct route_table *table;
926 struct zebra_vrf *zvrf = NULL;
927
928 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
929 if (use_json)
930 vty_out(vty, "{}\n");
931 else
932 vty_out(vty, "vrf %s not defined\n", vrf_name);
933 return CMD_SUCCESS;
934 }
935
936 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
937 if (use_json)
938 vty_out(vty, "{}\n");
939 else
940 vty_out(vty, "vrf %s inactive\n", vrf_name);
941 return CMD_SUCCESS;
942 }
943
944 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
945 if (!table) {
946 if (use_json)
947 vty_out(vty, "{}\n");
948 return CMD_SUCCESS;
949 }
950
951 do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
952 longer_prefix_p, supernets_only, type,
953 ospf_instance_id, use_json, 0);
954
955 return CMD_SUCCESS;
956 }
957
958 DEFPY (show_route_table,
959 show_route_table_cmd,
960 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
961 SHOW_STR
962 IP_STR
963 IP6_STR
964 "IP routing table\n"
965 "Table to display\n"
966 "The table number to display, if available\n"
967 JSON_STR)
968 {
969 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
970 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
971 struct route_table *t;
972
973 t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST);
974 if (t)
975 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
976 0, 0, !!json, table);
977
978 return CMD_SUCCESS;
979 }
980
981 DEFPY (show_route_table_vrf,
982 show_route_table_vrf_cmd,
983 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
984 SHOW_STR
985 IP_STR
986 IP6_STR
987 "IP routing table\n"
988 "Table to display\n"
989 "The table number to display, if available\n"
990 VRF_CMD_HELP_STR
991 JSON_STR)
992 {
993 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
994 struct zebra_vrf *zvrf;
995 struct route_table *t;
996 vrf_id_t vrf_id = VRF_DEFAULT;
997
998 if (vrf_name)
999 VRF_GET_ID(vrf_id, vrf_name, !!json);
1000 zvrf = zebra_vrf_lookup_by_id(vrf_id);
1001
1002 t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST);
1003 if (t)
1004 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
1005 0, 0, !!json, table);
1006
1007 return CMD_SUCCESS;
1008 }
1009
1010 DEFPY (show_route_all_table_vrf,
1011 show_route_all_table_vrf_cmd,
1012 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] tables [json$json]",
1013 SHOW_STR
1014 IP_STR
1015 IP6_STR
1016 "IP routing table\n"
1017 "Display all tables\n"
1018 VRF_FULL_CMD_HELP_STR
1019 JSON_STR)
1020 {
1021 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1022 struct zebra_vrf *zvrf = NULL;
1023 vrf_id_t vrf_id = VRF_UNKNOWN;
1024 struct zebra_router_table *zrt;
1025
1026 if (vrf_name) {
1027 VRF_GET_ID(vrf_id, vrf_name, !!json);
1028 zvrf = zebra_vrf_lookup_by_id(vrf_id);
1029 }
1030
1031 RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
1032 rib_table_info_t *info = route_table_get_info(zrt->table);
1033
1034 if (zvrf && zvrf != info->zvrf)
1035 continue;
1036 if (zrt->afi != afi || zrt->safi != SAFI_UNICAST)
1037 continue;
1038
1039 do_show_route_helper(vty, info->zvrf, zrt->table, afi, false, 0,
1040 false, false, 0, 0, !!json, zrt->tableid);
1041 }
1042 return CMD_SUCCESS;
1043 }
1044
1045 DEFPY (show_ip_nht,
1046 show_ip_nht_cmd,
1047 "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]",
1048 SHOW_STR
1049 IP_STR
1050 IP6_STR
1051 "IP nexthop tracking table\n"
1052 "IP import check tracking table\n"
1053 "IPv4 Address\n"
1054 "IPv6 Address\n"
1055 VRF_CMD_HELP_STR
1056 "IPv4 Address\n"
1057 "IPv6 Address\n"
1058 VRF_ALL_CMD_HELP_STR)
1059 {
1060 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1061 vrf_id_t vrf_id = VRF_DEFAULT;
1062 struct prefix prefix, *p = NULL;
1063 rnh_type_t rtype;
1064
1065 if (strcmp(type, "nht") == 0)
1066 rtype = RNH_NEXTHOP_TYPE;
1067 else
1068 rtype = RNH_IMPORT_CHECK_TYPE;
1069
1070 if (vrf_all) {
1071 struct vrf *vrf;
1072 struct zebra_vrf *zvrf;
1073
1074 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1075 if ((zvrf = vrf->info) != NULL) {
1076 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1077 zebra_print_rnh_table(zvrf_id(zvrf), afi, vty,
1078 rtype, NULL);
1079 }
1080 return CMD_SUCCESS;
1081 }
1082 if (vrf_name)
1083 VRF_GET_ID(vrf_id, vrf_name, false);
1084
1085 memset(&prefix, 0, sizeof(prefix));
1086 if (addr)
1087 p = sockunion2hostprefix(addr, &prefix);
1088
1089 zebra_print_rnh_table(vrf_id, afi, vty, rtype, p);
1090 return CMD_SUCCESS;
1091 }
1092
1093 DEFUN (ip_nht_default_route,
1094 ip_nht_default_route_cmd,
1095 "ip nht resolve-via-default",
1096 IP_STR
1097 "Filter Next Hop tracking route resolution\n"
1098 "Resolve via default route\n")
1099 {
1100 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1101
1102 if (!zvrf)
1103 return CMD_WARNING;
1104
1105 if (zvrf->zebra_rnh_ip_default_route)
1106 return CMD_SUCCESS;
1107
1108 zvrf->zebra_rnh_ip_default_route = 1;
1109
1110 zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
1111 return CMD_SUCCESS;
1112 }
1113
1114 static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
1115 {
1116 struct nexthop *nexthop = NULL;
1117 struct nhg_connected *rb_node_dep = NULL;
1118 char buf[SRCDEST2STR_BUFFER];
1119
1120 struct vrf *nhe_vrf = vrf_lookup_by_id(nhe->vrf_id);
1121
1122 vty_out(vty, "ID: %u\n", nhe->id);
1123 vty_out(vty, " RefCnt: %d\n", nhe->refcnt);
1124
1125 if (nhe_vrf)
1126 vty_out(vty, " VRF: %s AFI: %s\n", nhe_vrf->name,
1127 afi2str(nhe->afi));
1128 else
1129 vty_out(vty, " VRF: UNKNOWN AFI: %s\n",
1130 afi2str(nhe->afi));
1131
1132 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE))
1133 vty_out(vty, " Duplicate - from kernel not hashable\n");
1134
1135 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
1136 vty_out(vty, " Valid");
1137 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED))
1138 vty_out(vty, ", Installed");
1139 vty_out(vty, "\n");
1140 }
1141 if (nhe->ifp)
1142 vty_out(vty, " Interface Index: %d\n", nhe->ifp->ifindex);
1143
1144 if (!zebra_nhg_depends_is_empty(nhe)) {
1145 vty_out(vty, " Depends:");
1146 frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
1147 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1148 }
1149 vty_out(vty, "\n");
1150 }
1151
1152 for (ALL_NEXTHOPS_PTR(nhe->nhg, nexthop)) {
1153 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1154 vty_out(vty, " ");
1155 else
1156 /* Make recursive nexthops a bit more clear */
1157 vty_out(vty, " ");
1158
1159 switch (nexthop->type) {
1160 case NEXTHOP_TYPE_IPV4:
1161 case NEXTHOP_TYPE_IPV4_IFINDEX:
1162 vty_out(vty, " %s", inet_ntoa(nexthop->gate.ipv4));
1163 if (nexthop->ifindex)
1164 vty_out(vty, ", %s",
1165 ifindex2ifname(nexthop->ifindex,
1166 nexthop->vrf_id));
1167 break;
1168 case NEXTHOP_TYPE_IPV6:
1169 case NEXTHOP_TYPE_IPV6_IFINDEX:
1170 vty_out(vty, " %s",
1171 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
1172 sizeof(buf)));
1173 if (nexthop->ifindex)
1174 vty_out(vty, ", %s",
1175 ifindex2ifname(nexthop->ifindex,
1176 nexthop->vrf_id));
1177 break;
1178
1179 case NEXTHOP_TYPE_IFINDEX:
1180 vty_out(vty, " directly connected %s",
1181 ifindex2ifname(nexthop->ifindex,
1182 nexthop->vrf_id));
1183 break;
1184 case NEXTHOP_TYPE_BLACKHOLE:
1185 vty_out(vty, " unreachable");
1186 switch (nexthop->bh_type) {
1187 case BLACKHOLE_REJECT:
1188 vty_out(vty, " (ICMP unreachable)");
1189 break;
1190 case BLACKHOLE_ADMINPROHIB:
1191 vty_out(vty, " (ICMP admin-prohibited)");
1192 break;
1193 case BLACKHOLE_NULL:
1194 vty_out(vty, " (blackhole)");
1195 break;
1196 case BLACKHOLE_UNSPEC:
1197 break;
1198 }
1199 break;
1200 default:
1201 break;
1202 }
1203
1204 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
1205
1206 if (vrf)
1207 vty_out(vty, " (vrf %s)", vrf->name);
1208 else
1209 vty_out(vty, " (vrf UNKNOWN)");
1210
1211 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1212 vty_out(vty, " inactive");
1213
1214 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1215 vty_out(vty, " onlink");
1216
1217 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1218 vty_out(vty, " (recursive)");
1219
1220 switch (nexthop->type) {
1221 case NEXTHOP_TYPE_IPV4:
1222 case NEXTHOP_TYPE_IPV4_IFINDEX:
1223 if (nexthop->src.ipv4.s_addr) {
1224 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
1225 sizeof(buf)))
1226 vty_out(vty, ", src %s", buf);
1227 }
1228 break;
1229 case NEXTHOP_TYPE_IPV6:
1230 case NEXTHOP_TYPE_IPV6_IFINDEX:
1231 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
1232 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
1233 sizeof(buf)))
1234 vty_out(vty, ", src %s", buf);
1235 }
1236 break;
1237 default:
1238 break;
1239 }
1240
1241 /* Label information */
1242 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
1243 vty_out(vty, ", label %s",
1244 mpls_label2str(nexthop->nh_label->num_labels,
1245 nexthop->nh_label->label, buf,
1246 sizeof(buf), 1));
1247 }
1248
1249 if (nexthop->weight)
1250 vty_out(vty, ", weight %u", nexthop->weight);
1251
1252 vty_out(vty, "\n");
1253 }
1254
1255 if (!zebra_nhg_dependents_is_empty(nhe)) {
1256 vty_out(vty, " Dependents:");
1257 frr_each(nhg_connected_tree, &nhe->nhg_dependents,
1258 rb_node_dep) {
1259 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1260 }
1261 vty_out(vty, "\n");
1262 }
1263
1264 }
1265
1266 static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id)
1267 {
1268 struct nhg_hash_entry *nhe = NULL;
1269
1270 nhe = zebra_nhg_lookup_id(id);
1271
1272 if (nhe)
1273 show_nexthop_group_out(vty, nhe);
1274 else {
1275 vty_out(vty, "Nexthop Group ID: %u does not exist\n", id);
1276 return CMD_WARNING;
1277 }
1278 return CMD_SUCCESS;
1279 }
1280
1281 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1282
1283 struct nhe_show_context {
1284 struct vty *vty;
1285 vrf_id_t vrf_id;
1286 afi_t afi;
1287 };
1288
1289 static int nhe_show_walker(struct hash_bucket *bucket, void *arg)
1290 {
1291 struct nhe_show_context *ctx = arg;
1292 struct nhg_hash_entry *nhe;
1293
1294 nhe = bucket->data; /* We won't be offered NULL buckets */
1295
1296 if (ctx->afi && nhe->afi != ctx->afi)
1297 goto done;
1298
1299 if (ctx->vrf_id && nhe->vrf_id != ctx->vrf_id)
1300 goto done;
1301
1302 show_nexthop_group_out(ctx->vty, nhe);
1303
1304 done:
1305 return HASHWALK_CONTINUE;
1306 }
1307
1308 static void show_nexthop_group_cmd_helper(struct vty *vty,
1309 struct zebra_vrf *zvrf,
1310 afi_t afi)
1311 {
1312 struct nhe_show_context ctx;
1313
1314 ctx.vty = vty;
1315 ctx.afi = afi;
1316 ctx.vrf_id = zvrf->vrf->vrf_id;
1317
1318 hash_walk(zrouter.nhgs_id, nhe_show_walker, &ctx);
1319 }
1320
1321 static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
1322 {
1323 struct zebra_if *zebra_if = NULL;
1324 struct nhg_connected *rb_node_dep = NULL;
1325
1326 zebra_if = ifp->info;
1327
1328 if (!if_nhg_dependents_is_empty(ifp)) {
1329 vty_out(vty, "Interface %s:\n", ifp->name);
1330
1331 frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
1332 rb_node_dep) {
1333 vty_out(vty, " ");
1334 show_nexthop_group_out(vty, rb_node_dep->nhe);
1335 }
1336 }
1337 }
1338
1339 DEFPY (show_interface_nexthop_group,
1340 show_interface_nexthop_group_cmd,
1341 "show interface [IFNAME$if_name] nexthop-group",
1342 SHOW_STR
1343 "Interface status and configuration\n"
1344 "Interface name\n"
1345 "Show Nexthop Groups\n")
1346 {
1347 struct vrf *vrf = NULL;
1348 struct interface *ifp = NULL;
1349 bool found = false;
1350
1351 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1352 if (if_name) {
1353 ifp = if_lookup_by_name(if_name, vrf->vrf_id);
1354 if (ifp) {
1355 if_nexthop_group_dump_vty(vty, ifp);
1356 found = true;
1357 }
1358 } else {
1359 FOR_ALL_INTERFACES (vrf, ifp)
1360 if_nexthop_group_dump_vty(vty, ifp);
1361 found = true;
1362 }
1363 }
1364
1365 if (!found) {
1366 vty_out(vty, "%% Can't find interface %s\n", if_name);
1367 return CMD_WARNING;
1368 }
1369
1370 return CMD_SUCCESS;
1371 }
1372
1373 DEFPY (show_nexthop_group,
1374 show_nexthop_group_cmd,
1375 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [vrf <NAME$vrf_name|all$vrf_all>]>",
1376 SHOW_STR
1377 "Show Nexthop Groups\n"
1378 "RIB information\n"
1379 "Nexthop Group ID\n"
1380 "Show Singleton Nexthop-Groups\n"
1381 IP_STR
1382 IP6_STR
1383 VRF_FULL_CMD_HELP_STR)
1384 {
1385
1386 struct zebra_vrf *zvrf = NULL;
1387 afi_t afi = AFI_UNSPEC;
1388
1389 if (id)
1390 return show_nexthop_group_id_cmd_helper(vty, id);
1391
1392 if (v4)
1393 afi = AFI_IP;
1394 else if (v6)
1395 afi = AFI_IP6;
1396
1397 if (vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1398 vty_out(vty, "VRF subcommand does not make any sense in l3mdev based vrf's");
1399 return CMD_WARNING;
1400 }
1401
1402 if (vrf_all) {
1403 struct vrf *vrf;
1404
1405 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1406 struct zebra_vrf *zvrf;
1407
1408 zvrf = vrf->info;
1409 if (!zvrf)
1410 continue;
1411
1412 vty_out(vty, "VRF: %s\n", vrf->name);
1413 show_nexthop_group_cmd_helper(vty, zvrf, afi);
1414 }
1415
1416 return CMD_SUCCESS;
1417 }
1418
1419 if (vrf_name)
1420 zvrf = zebra_vrf_lookup_by_name(vrf_name);
1421 else
1422 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1423
1424 if (!zvrf) {
1425 vty_out(vty, "%% VRF '%s' specified does not exist\n",
1426 vrf_name);
1427 return CMD_WARNING;
1428 }
1429
1430 show_nexthop_group_cmd_helper(vty, zvrf, afi);
1431
1432 return CMD_SUCCESS;
1433 }
1434
1435 DEFPY_HIDDEN(nexthop_group_use_enable,
1436 nexthop_group_use_enable_cmd,
1437 "[no] zebra nexthop kernel enable",
1438 NO_STR
1439 ZEBRA_STR
1440 "Nexthop configuration \n"
1441 "Configure use of kernel nexthops\n"
1442 "Enable kernel nexthops\n")
1443 {
1444 zebra_nhg_enable_kernel_nexthops(!no);
1445 return CMD_SUCCESS;
1446 }
1447
1448 DEFUN (no_ip_nht_default_route,
1449 no_ip_nht_default_route_cmd,
1450 "no ip nht resolve-via-default",
1451 NO_STR
1452 IP_STR
1453 "Filter Next Hop tracking route resolution\n"
1454 "Resolve via default route\n")
1455 {
1456 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1457
1458 if (!zvrf)
1459 return CMD_WARNING;
1460
1461 if (!zvrf->zebra_rnh_ip_default_route)
1462 return CMD_SUCCESS;
1463
1464 zvrf->zebra_rnh_ip_default_route = 0;
1465 zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
1466 return CMD_SUCCESS;
1467 }
1468
1469 DEFUN (ipv6_nht_default_route,
1470 ipv6_nht_default_route_cmd,
1471 "ipv6 nht resolve-via-default",
1472 IP6_STR
1473 "Filter Next Hop tracking route resolution\n"
1474 "Resolve via default route\n")
1475 {
1476 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1477
1478 if (!zvrf)
1479 return CMD_WARNING;
1480
1481 if (zvrf->zebra_rnh_ipv6_default_route)
1482 return CMD_SUCCESS;
1483
1484 zvrf->zebra_rnh_ipv6_default_route = 1;
1485 zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL);
1486 return CMD_SUCCESS;
1487 }
1488
1489 DEFUN (no_ipv6_nht_default_route,
1490 no_ipv6_nht_default_route_cmd,
1491 "no ipv6 nht resolve-via-default",
1492 NO_STR
1493 IP6_STR
1494 "Filter Next Hop tracking route resolution\n"
1495 "Resolve via default route\n")
1496 {
1497
1498 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1499
1500 if (!zvrf)
1501 return CMD_WARNING;
1502
1503 if (!zvrf->zebra_rnh_ipv6_default_route)
1504 return CMD_SUCCESS;
1505
1506 zvrf->zebra_rnh_ipv6_default_route = 0;
1507 zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL);
1508 return CMD_SUCCESS;
1509 }
1510
1511 DEFPY (show_route,
1512 show_route_cmd,
1513 "show\
1514 <\
1515 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1516 [{\
1517 tag (1-4294967295)\
1518 |A.B.C.D/M$prefix longer-prefixes\
1519 |supernets-only$supernets_only\
1520 }]\
1521 [<\
1522 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1523 |ospf$type_str (1-65535)$ospf_instance_id\
1524 >]\
1525 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1526 [{\
1527 tag (1-4294967295)\
1528 |X:X::X:X/M$prefix longer-prefixes\
1529 }]\
1530 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1531 >\
1532 [json$json]",
1533 SHOW_STR
1534 IP_STR
1535 "IP forwarding table\n"
1536 "IP routing table\n"
1537 VRF_FULL_CMD_HELP_STR
1538 "Show only routes with tag\n"
1539 "Tag value\n"
1540 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1541 "Show route matching the specified Network/Mask pair only\n"
1542 "Show supernet entries only\n"
1543 FRR_IP_REDIST_HELP_STR_ZEBRA
1544 "Open Shortest Path First (OSPFv2)\n"
1545 "Instance ID\n"
1546 IPV6_STR
1547 "IP forwarding table\n"
1548 "IP routing table\n"
1549 VRF_FULL_CMD_HELP_STR
1550 "Show only routes with tag\n"
1551 "Tag value\n"
1552 "IPv6 prefix\n"
1553 "Show route matching the specified Network/Mask pair only\n"
1554 FRR_IP6_REDIST_HELP_STR_ZEBRA
1555 JSON_STR)
1556 {
1557 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1558 struct vrf *vrf;
1559 int type = 0;
1560
1561 if (type_str) {
1562 type = proto_redistnum(afi, type_str);
1563 if (type < 0) {
1564 vty_out(vty, "Unknown route type\n");
1565 return CMD_WARNING;
1566 }
1567 }
1568
1569 if (vrf_all) {
1570 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1571 struct zebra_vrf *zvrf;
1572 struct route_table *table;
1573
1574 if ((zvrf = vrf->info) == NULL
1575 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1576 continue;
1577
1578 do_show_ip_route(
1579 vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
1580 !!json, tag, prefix_str ? prefix : NULL,
1581 !!supernets_only, type, ospf_instance_id);
1582 }
1583 } else {
1584 vrf_id_t vrf_id = VRF_DEFAULT;
1585
1586 if (vrf_name)
1587 VRF_GET_ID(vrf_id, vrf_name, !!json);
1588 vrf = vrf_lookup_by_id(vrf_id);
1589 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
1590 !!json, tag, prefix_str ? prefix : NULL,
1591 !!supernets_only, type, ospf_instance_id);
1592 }
1593
1594 return CMD_SUCCESS;
1595 }
1596
1597 DEFPY (show_route_detail,
1598 show_route_detail_cmd,
1599 "show\
1600 <\
1601 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1602 <\
1603 A.B.C.D$address\
1604 |A.B.C.D/M$prefix\
1605 >\
1606 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1607 <\
1608 X:X::X:X$address\
1609 |X:X::X:X/M$prefix\
1610 >\
1611 >\
1612 [json$json] [nexthop-group$ng]",
1613 SHOW_STR
1614 IP_STR
1615 "IPv6 forwarding table\n"
1616 "IP routing table\n"
1617 VRF_FULL_CMD_HELP_STR
1618 "Network in the IP routing table to display\n"
1619 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1620 IP6_STR
1621 "IPv6 forwarding table\n"
1622 "IPv6 routing table\n"
1623 VRF_FULL_CMD_HELP_STR
1624 "IPv6 Address\n"
1625 "IPv6 prefix\n"
1626 JSON_STR
1627 "Nexthop Group Information\n")
1628 {
1629 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1630 struct route_table *table;
1631 struct prefix p;
1632 struct route_node *rn;
1633 bool use_fib = !!fib;
1634 rib_dest_t *dest;
1635 bool network_found = false;
1636 bool show_ng = !!ng;
1637
1638 if (address_str)
1639 prefix_str = address_str;
1640 if (str2prefix(prefix_str, &p) < 0) {
1641 vty_out(vty, "%% Malformed address\n");
1642 return CMD_WARNING;
1643 }
1644
1645 if (vrf_all) {
1646 struct vrf *vrf;
1647 struct zebra_vrf *zvrf;
1648
1649 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1650 if ((zvrf = vrf->info) == NULL
1651 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1652 continue;
1653
1654 rn = route_node_match(table, &p);
1655 if (!rn)
1656 continue;
1657 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1658 route_unlock_node(rn);
1659 continue;
1660 }
1661
1662 dest = rib_dest_from_rnode(rn);
1663 if (use_fib && !dest->selected_fib) {
1664 route_unlock_node(rn);
1665 continue;
1666 }
1667
1668 network_found = true;
1669 if (json)
1670 vty_show_ip_route_detail_json(vty, rn, use_fib);
1671 else
1672 vty_show_ip_route_detail(vty, rn, 0, use_fib,
1673 show_ng);
1674
1675 route_unlock_node(rn);
1676 }
1677
1678 if (!network_found) {
1679 if (json)
1680 vty_out(vty, "{}\n");
1681 else {
1682 if (use_fib)
1683 vty_out(vty,
1684 "%% Network not in FIB\n");
1685 else
1686 vty_out(vty,
1687 "%% Network not in RIB\n");
1688 }
1689 return CMD_WARNING;
1690 }
1691 } else {
1692 vrf_id_t vrf_id = VRF_DEFAULT;
1693
1694 if (vrf_name)
1695 VRF_GET_ID(vrf_id, vrf_name, false);
1696
1697 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1698 if (!table)
1699 return CMD_SUCCESS;
1700
1701 rn = route_node_match(table, &p);
1702 if (rn)
1703 dest = rib_dest_from_rnode(rn);
1704
1705 if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
1706 (use_fib && dest && !dest->selected_fib)) {
1707 if (json)
1708 vty_out(vty, "{}\n");
1709 else {
1710 if (use_fib)
1711 vty_out(vty,
1712 "%% Network not in FIB\n");
1713 else
1714 vty_out(vty,
1715 "%% Network not in table\n");
1716 }
1717 if (rn)
1718 route_unlock_node(rn);
1719 return CMD_WARNING;
1720 }
1721
1722 if (json)
1723 vty_show_ip_route_detail_json(vty, rn, use_fib);
1724 else
1725 vty_show_ip_route_detail(vty, rn, 0, use_fib, show_ng);
1726
1727 route_unlock_node(rn);
1728 }
1729
1730 return CMD_SUCCESS;
1731 }
1732
1733 DEFPY (show_route_summary,
1734 show_route_summary_cmd,
1735 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
1736 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
1737 SHOW_STR
1738 IP_STR
1739 IP6_STR
1740 "IP routing table\n"
1741 VRF_FULL_CMD_HELP_STR
1742 "Summary of all routes\n"
1743 "Table to display summary for\n"
1744 "The table number\n"
1745 "Prefix routes\n"
1746 JSON_STR)
1747 {
1748 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1749 struct route_table *table;
1750 bool uj = use_json(argc, argv);
1751
1752 if (table_id == 0)
1753 table_id = RT_TABLE_MAIN;
1754
1755 if (vrf_all) {
1756 struct vrf *vrf;
1757 struct zebra_vrf *zvrf;
1758
1759 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1760 if ((zvrf = vrf->info) == NULL)
1761 continue;
1762
1763 table = zebra_vrf_lookup_table_with_table_id(
1764 afi, SAFI_UNICAST, zvrf->vrf->vrf_id, table_id);
1765
1766 if (!table)
1767 continue;
1768
1769 if (prefix)
1770 vty_show_ip_route_summary_prefix(vty, table,
1771 uj);
1772 else
1773 vty_show_ip_route_summary(vty, table, uj);
1774 }
1775 } else {
1776 vrf_id_t vrf_id = VRF_DEFAULT;
1777
1778 if (vrf_name)
1779 VRF_GET_ID(vrf_id, vrf_name, false);
1780
1781 table = zebra_vrf_lookup_table_with_table_id(afi, SAFI_UNICAST,
1782 vrf_id, table_id);
1783 if (!table)
1784 return CMD_SUCCESS;
1785
1786 if (prefix)
1787 vty_show_ip_route_summary_prefix(vty, table, uj);
1788 else
1789 vty_show_ip_route_summary(vty, table, uj);
1790 }
1791
1792 return CMD_SUCCESS;
1793 }
1794
1795 static void vty_show_ip_route_summary(struct vty *vty,
1796 struct route_table *table, bool use_json)
1797 {
1798 struct route_node *rn;
1799 struct route_entry *re;
1800 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1801 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1802 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1803 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1804 uint32_t i;
1805 uint32_t is_ibgp;
1806 json_object *json_route_summary = NULL;
1807 json_object *json_route_routes = NULL;
1808
1809 memset(&rib_cnt, 0, sizeof(rib_cnt));
1810 memset(&fib_cnt, 0, sizeof(fib_cnt));
1811
1812 if (use_json) {
1813 json_route_summary = json_object_new_object();
1814 json_route_routes = json_object_new_array();
1815 json_object_object_add(json_route_summary, "routes",
1816 json_route_routes);
1817 }
1818
1819 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1820 RNODE_FOREACH_RE (rn, re) {
1821 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1822 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1823
1824 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1825 if (is_ibgp)
1826 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1827 else
1828 rib_cnt[re->type]++;
1829
1830 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
1831 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1832
1833 if (is_ibgp)
1834 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1835 else
1836 fib_cnt[re->type]++;
1837 }
1838 }
1839
1840 if (!use_json)
1841 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1842 "Routes", "FIB",
1843 zvrf_name(((rib_table_info_t *)route_table_get_info(
1844 table))
1845 ->zvrf));
1846
1847 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1848 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
1849 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
1850 if (i == ZEBRA_ROUTE_BGP) {
1851 if (use_json) {
1852 json_object *json_route_ebgp =
1853 json_object_new_object();
1854
1855 json_object_int_add(
1856 json_route_ebgp, "fib",
1857 fib_cnt[ZEBRA_ROUTE_BGP]);
1858 json_object_int_add(
1859 json_route_ebgp, "rib",
1860 rib_cnt[ZEBRA_ROUTE_BGP]);
1861 json_object_string_add(json_route_ebgp,
1862 "type", "ebgp");
1863 json_object_array_add(json_route_routes,
1864 json_route_ebgp);
1865
1866 json_object *json_route_ibgp =
1867 json_object_new_object();
1868
1869 json_object_int_add(
1870 json_route_ibgp, "fib",
1871 fib_cnt[ZEBRA_ROUTE_IBGP]);
1872 json_object_int_add(
1873 json_route_ibgp, "rib",
1874 rib_cnt[ZEBRA_ROUTE_IBGP]);
1875 json_object_string_add(json_route_ibgp,
1876 "type", "ibgp");
1877 json_object_array_add(json_route_routes,
1878 json_route_ibgp);
1879 } else {
1880 vty_out(vty, "%-20s %-20d %-20d \n",
1881 "ebgp",
1882 rib_cnt[ZEBRA_ROUTE_BGP],
1883 fib_cnt[ZEBRA_ROUTE_BGP]);
1884 vty_out(vty, "%-20s %-20d %-20d \n",
1885 "ibgp",
1886 rib_cnt[ZEBRA_ROUTE_IBGP],
1887 fib_cnt[ZEBRA_ROUTE_IBGP]);
1888 }
1889 } else {
1890 if (use_json) {
1891 json_object *json_route_type =
1892 json_object_new_object();
1893
1894 json_object_int_add(json_route_type,
1895 "fib", fib_cnt[i]);
1896 json_object_int_add(json_route_type,
1897 "rib", rib_cnt[i]);
1898 json_object_string_add(
1899 json_route_type, "type",
1900 zebra_route_string(i));
1901 json_object_array_add(json_route_routes,
1902 json_route_type);
1903 } else
1904 vty_out(vty, "%-20s %-20d %-20d \n",
1905 zebra_route_string(i),
1906 rib_cnt[i], fib_cnt[i]);
1907 }
1908 }
1909 }
1910
1911 if (use_json) {
1912 json_object_int_add(json_route_summary, "routesTotal",
1913 rib_cnt[ZEBRA_ROUTE_TOTAL]);
1914 json_object_int_add(json_route_summary, "routesTotalFib",
1915 fib_cnt[ZEBRA_ROUTE_TOTAL]);
1916
1917 vty_out(vty, "%s\n",
1918 json_object_to_json_string_ext(
1919 json_route_summary, JSON_C_TO_STRING_PRETTY));
1920 json_object_free(json_route_summary);
1921 } else {
1922 vty_out(vty, "------\n");
1923 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1924 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1925 vty_out(vty, "\n");
1926 }
1927 }
1928
1929 /*
1930 * Implementation of the ip route summary prefix command.
1931 *
1932 * This command prints the primary prefixes that have been installed by various
1933 * protocols on the box.
1934 *
1935 */
1936 static void vty_show_ip_route_summary_prefix(struct vty *vty,
1937 struct route_table *table,
1938 bool use_json)
1939 {
1940 struct route_node *rn;
1941 struct route_entry *re;
1942 struct nexthop *nexthop;
1943 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1944 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1945 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1946 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1947 uint32_t i;
1948 int cnt;
1949 json_object *json_route_summary = NULL;
1950 json_object *json_route_routes = NULL;
1951
1952 memset(&rib_cnt, 0, sizeof(rib_cnt));
1953 memset(&fib_cnt, 0, sizeof(fib_cnt));
1954
1955 if (use_json) {
1956 json_route_summary = json_object_new_object();
1957 json_route_routes = json_object_new_array();
1958 json_object_object_add(json_route_summary, "prefixRoutes",
1959 json_route_routes);
1960 }
1961
1962 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1963 RNODE_FOREACH_RE (rn, re) {
1964
1965 /*
1966 * In case of ECMP, count only once.
1967 */
1968 cnt = 0;
1969 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
1970 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1971 fib_cnt[re->type]++;
1972 }
1973 for (nexthop = re->nhe->nhg->nexthop; (!cnt && nexthop);
1974 nexthop = nexthop->next) {
1975 cnt++;
1976 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1977 rib_cnt[re->type]++;
1978 if (re->type == ZEBRA_ROUTE_BGP
1979 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
1980 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1981 if (CHECK_FLAG(re->status,
1982 ROUTE_ENTRY_INSTALLED))
1983 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1984 }
1985 }
1986 }
1987
1988 if (!use_json)
1989 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1990 "Prefix Routes", "FIB",
1991 zvrf_name(((rib_table_info_t *)route_table_get_info(
1992 table))
1993 ->zvrf));
1994
1995 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1996 if (rib_cnt[i] > 0) {
1997 if (i == ZEBRA_ROUTE_BGP) {
1998 if (use_json) {
1999 json_object *json_route_ebgp =
2000 json_object_new_object();
2001
2002 json_object_int_add(
2003 json_route_ebgp, "fib",
2004 fib_cnt[ZEBRA_ROUTE_BGP]
2005 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2006 json_object_int_add(
2007 json_route_ebgp, "rib",
2008 rib_cnt[ZEBRA_ROUTE_BGP]
2009 - rib_cnt[ZEBRA_ROUTE_IBGP]);
2010 json_object_string_add(json_route_ebgp,
2011 "type", "ebgp");
2012 json_object_array_add(json_route_routes,
2013 json_route_ebgp);
2014
2015 json_object *json_route_ibgp =
2016 json_object_new_object();
2017
2018 json_object_int_add(
2019 json_route_ibgp, "fib",
2020 fib_cnt[ZEBRA_ROUTE_IBGP]);
2021 json_object_int_add(
2022 json_route_ibgp, "rib",
2023 rib_cnt[ZEBRA_ROUTE_IBGP]);
2024 json_object_string_add(json_route_ibgp,
2025 "type", "ibgp");
2026 json_object_array_add(json_route_routes,
2027 json_route_ibgp);
2028 } else {
2029 vty_out(vty, "%-20s %-20d %-20d \n",
2030 "ebgp",
2031 rib_cnt[ZEBRA_ROUTE_BGP]
2032 - rib_cnt[ZEBRA_ROUTE_IBGP],
2033 fib_cnt[ZEBRA_ROUTE_BGP]
2034 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2035 vty_out(vty, "%-20s %-20d %-20d \n",
2036 "ibgp",
2037 rib_cnt[ZEBRA_ROUTE_IBGP],
2038 fib_cnt[ZEBRA_ROUTE_IBGP]);
2039 }
2040 } else {
2041 if (use_json) {
2042 json_object *json_route_type =
2043 json_object_new_object();
2044
2045 json_object_int_add(json_route_type,
2046 "fib", fib_cnt[i]);
2047 json_object_int_add(json_route_type,
2048 "rib", rib_cnt[i]);
2049 json_object_string_add(
2050 json_route_type, "type",
2051 zebra_route_string(i));
2052 json_object_array_add(json_route_routes,
2053 json_route_type);
2054 } else
2055 vty_out(vty, "%-20s %-20d %-20d \n",
2056 zebra_route_string(i),
2057 rib_cnt[i], fib_cnt[i]);
2058 }
2059 }
2060 }
2061
2062 if (use_json) {
2063 json_object_int_add(json_route_summary, "prefixRoutesTotal",
2064 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2065 json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
2066 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2067
2068 vty_out(vty, "%s\n",
2069 json_object_to_json_string_ext(
2070 json_route_summary, JSON_C_TO_STRING_PRETTY));
2071 json_object_free(json_route_summary);
2072 } else {
2073 vty_out(vty, "------\n");
2074 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2075 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2076 vty_out(vty, "\n");
2077 }
2078 }
2079
2080 /*
2081 * Show IPv6 mroute command.Used to dump
2082 * the Multicast routing table.
2083 */
2084 DEFUN (show_ipv6_mroute,
2085 show_ipv6_mroute_cmd,
2086 "show ipv6 mroute [vrf NAME]",
2087 SHOW_STR
2088 IP_STR
2089 "IPv6 Multicast routing table\n"
2090 VRF_CMD_HELP_STR)
2091 {
2092 struct route_table *table;
2093 struct route_node *rn;
2094 struct route_entry *re;
2095 int first = 1;
2096 vrf_id_t vrf_id = VRF_DEFAULT;
2097
2098 if (argc == 5)
2099 VRF_GET_ID(vrf_id, argv[4]->arg, false);
2100
2101 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2102 if (!table)
2103 return CMD_SUCCESS;
2104
2105 /* Show all IPv6 route. */
2106 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2107 RNODE_FOREACH_RE (rn, re) {
2108 if (first) {
2109 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2110 first = 0;
2111 }
2112 vty_show_ip_route(vty, rn, re, NULL, false);
2113 }
2114 return CMD_SUCCESS;
2115 }
2116
2117 DEFUN (show_ipv6_mroute_vrf_all,
2118 show_ipv6_mroute_vrf_all_cmd,
2119 "show ipv6 mroute vrf all",
2120 SHOW_STR
2121 IP_STR
2122 "IPv6 Multicast routing table\n"
2123 VRF_ALL_CMD_HELP_STR)
2124 {
2125 struct route_table *table;
2126 struct route_node *rn;
2127 struct route_entry *re;
2128 struct vrf *vrf;
2129 struct zebra_vrf *zvrf;
2130 int first = 1;
2131
2132 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2133 if ((zvrf = vrf->info) == NULL
2134 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2135 continue;
2136
2137 /* Show all IPv6 route. */
2138 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2139 RNODE_FOREACH_RE (rn, re) {
2140 if (first) {
2141 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2142 first = 0;
2143 }
2144 vty_show_ip_route(vty, rn, re, NULL, false);
2145 }
2146 }
2147 return CMD_SUCCESS;
2148 }
2149
2150 DEFUN (allow_external_route_update,
2151 allow_external_route_update_cmd,
2152 "allow-external-route-update",
2153 "Allow FRR routes to be overwritten by external processes\n")
2154 {
2155 allow_delete = 1;
2156
2157 return CMD_SUCCESS;
2158 }
2159
2160 DEFUN (no_allow_external_route_update,
2161 no_allow_external_route_update_cmd,
2162 "no allow-external-route-update",
2163 NO_STR
2164 "Allow FRR routes to be overwritten by external processes\n")
2165 {
2166 allow_delete = 0;
2167
2168 return CMD_SUCCESS;
2169 }
2170
2171 /* show vrf */
2172 DEFUN (show_vrf,
2173 show_vrf_cmd,
2174 "show vrf",
2175 SHOW_STR
2176 "VRF\n")
2177 {
2178 struct vrf *vrf;
2179 struct zebra_vrf *zvrf;
2180
2181 if (vrf_is_backend_netns())
2182 vty_out(vty, "netns-based vrfs\n");
2183
2184 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2185 if (!(zvrf = vrf->info))
2186 continue;
2187 if (zvrf_id(zvrf) == VRF_DEFAULT)
2188 continue;
2189
2190 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2191 if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2192 vty_out(vty, "inactive");
2193 else if (zvrf_ns_name(zvrf))
2194 vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2195 zvrf_ns_name(zvrf));
2196 else
2197 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2198 zvrf->table_id);
2199 if (vrf_is_user_cfged(vrf))
2200 vty_out(vty, " (configured)");
2201 vty_out(vty, "\n");
2202 }
2203
2204 return CMD_SUCCESS;
2205 }
2206
2207 DEFUN (default_vrf_vni_mapping,
2208 default_vrf_vni_mapping_cmd,
2209 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2210 "VNI corresponding to the DEFAULT VRF\n"
2211 "VNI-ID\n"
2212 "Prefix routes only \n")
2213 {
2214 int ret = 0;
2215 char err[ERR_STR_SZ];
2216 struct zebra_vrf *zvrf = NULL;
2217 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2218 int filter = 0;
2219
2220 zvrf = vrf_info_lookup(VRF_DEFAULT);
2221 if (!zvrf)
2222 return CMD_WARNING;
2223
2224 if (argc == 3)
2225 filter = 1;
2226
2227 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2228 filter, 1);
2229 if (ret != 0) {
2230 vty_out(vty, "%s\n", err);
2231 return CMD_WARNING;
2232 }
2233
2234 return CMD_SUCCESS;
2235 }
2236
2237 DEFUN (no_default_vrf_vni_mapping,
2238 no_default_vrf_vni_mapping_cmd,
2239 "no vni " CMD_VNI_RANGE,
2240 NO_STR
2241 "VNI corresponding to DEFAULT VRF\n"
2242 "VNI-ID")
2243 {
2244 int ret = 0;
2245 char err[ERR_STR_SZ];
2246 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2247 struct zebra_vrf *zvrf = NULL;
2248
2249 zvrf = vrf_info_lookup(VRF_DEFAULT);
2250 if (!zvrf)
2251 return CMD_WARNING;
2252
2253 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2254 if (ret != 0) {
2255 vty_out(vty, "%s\n", err);
2256 return CMD_WARNING;
2257 }
2258
2259 return CMD_SUCCESS;
2260 }
2261
2262 DEFUN (vrf_vni_mapping,
2263 vrf_vni_mapping_cmd,
2264 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2265 "VNI corresponding to tenant VRF\n"
2266 "VNI-ID\n"
2267 "prefix-routes-only\n")
2268 {
2269 int ret = 0;
2270 int filter = 0;
2271
2272 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2273 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2274 char err[ERR_STR_SZ];
2275
2276 assert(vrf);
2277 assert(zvrf);
2278
2279 if (argc == 3)
2280 filter = 1;
2281
2282 /* Mark as having FRR configuration */
2283 vrf_set_user_cfged(vrf);
2284 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2285 filter, 1);
2286 if (ret != 0) {
2287 vty_out(vty, "%s\n", err);
2288 return CMD_WARNING;
2289 }
2290
2291 return CMD_SUCCESS;
2292 }
2293
2294 DEFUN (no_vrf_vni_mapping,
2295 no_vrf_vni_mapping_cmd,
2296 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2297 NO_STR
2298 "VNI corresponding to tenant VRF\n"
2299 "VNI-ID\n"
2300 "prefix-routes-only\n")
2301 {
2302 int ret = 0;
2303 int filter = 0;
2304 char err[ERR_STR_SZ];
2305 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2306
2307 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2308
2309 assert(vrf);
2310 assert(zvrf);
2311
2312 if (argc == 4)
2313 filter = 1;
2314
2315 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err,
2316 ERR_STR_SZ, filter, 0);
2317 if (ret != 0) {
2318 vty_out(vty, "%s\n", err);
2319 return CMD_WARNING;
2320 }
2321
2322 /* If no other FRR config for this VRF, mark accordingly. */
2323 if (!zebra_vrf_has_config(zvrf))
2324 vrf_reset_user_cfged(vrf);
2325
2326 return CMD_SUCCESS;
2327 }
2328
2329 /* show vrf */
2330 DEFUN (show_vrf_vni,
2331 show_vrf_vni_cmd,
2332 "show vrf vni [json]",
2333 SHOW_STR
2334 "VRF\n"
2335 "VNI\n"
2336 JSON_STR)
2337 {
2338 struct vrf *vrf;
2339 struct zebra_vrf *zvrf;
2340 json_object *json = NULL;
2341 json_object *json_vrfs = NULL;
2342 bool uj = use_json(argc, argv);
2343
2344 if (uj) {
2345 json = json_object_new_object();
2346 json_vrfs = json_object_new_array();
2347 }
2348
2349 if (!uj)
2350 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2351 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2352
2353 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2354 zvrf = vrf->info;
2355 if (!zvrf)
2356 continue;
2357
2358 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2359 }
2360
2361 if (uj) {
2362 json_object_object_add(json, "vrfs", json_vrfs);
2363 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2364 json, JSON_C_TO_STRING_PRETTY));
2365 json_object_free(json);
2366 }
2367
2368 return CMD_SUCCESS;
2369 }
2370
2371 DEFUN (show_evpn_global,
2372 show_evpn_global_cmd,
2373 "show evpn [json]",
2374 SHOW_STR
2375 "EVPN\n"
2376 JSON_STR)
2377 {
2378 bool uj = use_json(argc, argv);
2379
2380 zebra_vxlan_print_evpn(vty, uj);
2381 return CMD_SUCCESS;
2382 }
2383
2384 DEFUN (show_evpn_vni,
2385 show_evpn_vni_cmd,
2386 "show evpn vni [json]",
2387 SHOW_STR
2388 "EVPN\n"
2389 "VxLAN Network Identifier\n"
2390 JSON_STR)
2391 {
2392 struct zebra_vrf *zvrf;
2393 bool uj = use_json(argc, argv);
2394
2395 zvrf = zebra_vrf_get_evpn();
2396 zebra_vxlan_print_vnis(vty, zvrf, uj);
2397 return CMD_SUCCESS;
2398 }
2399
2400 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
2401 "show evpn vni detail [json]",
2402 SHOW_STR
2403 "EVPN\n"
2404 "VxLAN Network Identifier\n"
2405 "Detailed Information On Each VNI\n"
2406 JSON_STR)
2407 {
2408 struct zebra_vrf *zvrf;
2409 bool uj = use_json(argc, argv);
2410
2411 zvrf = zebra_vrf_get_evpn();
2412 zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
2413 return CMD_SUCCESS;
2414 }
2415
2416 DEFUN (show_evpn_vni_vni,
2417 show_evpn_vni_vni_cmd,
2418 "show evpn vni " CMD_VNI_RANGE "[json]",
2419 SHOW_STR
2420 "EVPN\n"
2421 "VxLAN Network Identifier\n"
2422 "VNI number\n"
2423 JSON_STR)
2424 {
2425 struct zebra_vrf *zvrf;
2426 vni_t vni;
2427 bool uj = use_json(argc, argv);
2428
2429 vni = strtoul(argv[3]->arg, NULL, 10);
2430 zvrf = zebra_vrf_get_evpn();
2431 zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
2432 return CMD_SUCCESS;
2433 }
2434
2435 DEFUN (show_evpn_rmac_vni_mac,
2436 show_evpn_rmac_vni_mac_cmd,
2437 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
2438 SHOW_STR
2439 "EVPN\n"
2440 "RMAC\n"
2441 "L3 VNI\n"
2442 "VNI number\n"
2443 "MAC\n"
2444 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2445 JSON_STR)
2446 {
2447 vni_t l3vni = 0;
2448 struct ethaddr mac;
2449 bool uj = use_json(argc, argv);
2450
2451 l3vni = strtoul(argv[4]->arg, NULL, 10);
2452 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2453 vty_out(vty, "%% Malformed MAC address\n");
2454 return CMD_WARNING;
2455 }
2456 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
2457 return CMD_SUCCESS;
2458 }
2459
2460 DEFUN (show_evpn_rmac_vni,
2461 show_evpn_rmac_vni_cmd,
2462 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
2463 SHOW_STR
2464 "EVPN\n"
2465 "RMAC\n"
2466 "L3 VNI\n"
2467 "VNI number\n"
2468 JSON_STR)
2469 {
2470 vni_t l3vni = 0;
2471 bool uj = use_json(argc, argv);
2472
2473 l3vni = strtoul(argv[4]->arg, NULL, 10);
2474 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
2475
2476 return CMD_SUCCESS;
2477 }
2478
2479 DEFUN (show_evpn_rmac_vni_all,
2480 show_evpn_rmac_vni_all_cmd,
2481 "show evpn rmac vni all [json]",
2482 SHOW_STR
2483 "EVPN\n"
2484 "RMAC addresses\n"
2485 "L3 VNI\n"
2486 "All VNIs\n"
2487 JSON_STR)
2488 {
2489 bool uj = use_json(argc, argv);
2490
2491 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
2492
2493 return CMD_SUCCESS;
2494 }
2495
2496 DEFUN (show_evpn_nh_vni_ip,
2497 show_evpn_nh_vni_ip_cmd,
2498 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
2499 SHOW_STR
2500 "EVPN\n"
2501 "Remote Vteps\n"
2502 "L3 VNI\n"
2503 "VNI number\n"
2504 "Ip address\n"
2505 "Host address (ipv4 or ipv6)\n"
2506 JSON_STR)
2507 {
2508 vni_t l3vni;
2509 struct ipaddr ip;
2510 bool uj = use_json(argc, argv);
2511
2512 l3vni = strtoul(argv[4]->arg, NULL, 10);
2513 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2514 if (!uj)
2515 vty_out(vty, "%% Malformed Neighbor address\n");
2516 return CMD_WARNING;
2517 }
2518 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
2519
2520 return CMD_SUCCESS;
2521 }
2522
2523 DEFUN (show_evpn_nh_vni,
2524 show_evpn_nh_vni_cmd,
2525 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
2526 SHOW_STR
2527 "EVPN\n"
2528 "Remote Vteps\n"
2529 "L3 VNI\n"
2530 "VNI number\n"
2531 JSON_STR)
2532 {
2533 vni_t l3vni;
2534 bool uj = use_json(argc, argv);
2535
2536 l3vni = strtoul(argv[4]->arg, NULL, 10);
2537 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
2538
2539 return CMD_SUCCESS;
2540 }
2541
2542 DEFUN (show_evpn_nh_vni_all,
2543 show_evpn_nh_vni_all_cmd,
2544 "show evpn next-hops vni all [json]",
2545 SHOW_STR
2546 "EVPN\n"
2547 "Remote VTEPs\n"
2548 "L3 VNI\n"
2549 "All VNIs\n"
2550 JSON_STR)
2551 {
2552 bool uj = use_json(argc, argv);
2553
2554 zebra_vxlan_print_nh_all_l3vni(vty, uj);
2555
2556 return CMD_SUCCESS;
2557 }
2558
2559 DEFUN (show_evpn_mac_vni,
2560 show_evpn_mac_vni_cmd,
2561 "show evpn mac vni " CMD_VNI_RANGE "[json]",
2562 SHOW_STR
2563 "EVPN\n"
2564 "MAC addresses\n"
2565 "VxLAN Network Identifier\n"
2566 "VNI number\n"
2567 JSON_STR)
2568 {
2569 struct zebra_vrf *zvrf;
2570 vni_t vni;
2571 bool uj = use_json(argc, argv);
2572
2573 vni = strtoul(argv[4]->arg, NULL, 10);
2574 zvrf = zebra_vrf_get_evpn();
2575 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2576 return CMD_SUCCESS;
2577 }
2578
2579 DEFUN (show_evpn_mac_vni_all,
2580 show_evpn_mac_vni_all_cmd,
2581 "show evpn mac vni all [json]",
2582 SHOW_STR
2583 "EVPN\n"
2584 "MAC addresses\n"
2585 "VxLAN Network Identifier\n"
2586 "All VNIs\n"
2587 JSON_STR)
2588 {
2589 struct zebra_vrf *zvrf;
2590 bool uj = use_json(argc, argv);
2591
2592 zvrf = zebra_vrf_get_evpn();
2593 zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
2594 return CMD_SUCCESS;
2595 }
2596
2597 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
2598 "show evpn mac vni all detail [json]",
2599 SHOW_STR
2600 "EVPN\n"
2601 "MAC addresses\n"
2602 "VxLAN Network Identifier\n"
2603 "All VNIs\n"
2604 "Detailed Information On Each VNI MAC\n"
2605 JSON_STR)
2606 {
2607 struct zebra_vrf *zvrf;
2608 bool uj = use_json(argc, argv);
2609
2610 zvrf = zebra_vrf_get_evpn();
2611 zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
2612 return CMD_SUCCESS;
2613 }
2614
2615 DEFUN (show_evpn_mac_vni_all_vtep,
2616 show_evpn_mac_vni_all_vtep_cmd,
2617 "show evpn mac vni all vtep A.B.C.D [json]",
2618 SHOW_STR
2619 "EVPN\n"
2620 "MAC addresses\n"
2621 "VxLAN Network Identifier\n"
2622 "All VNIs\n"
2623 "Remote VTEP\n"
2624 "Remote VTEP IP address\n"
2625 JSON_STR)
2626 {
2627 struct zebra_vrf *zvrf;
2628 struct in_addr vtep_ip;
2629 bool uj = use_json(argc, argv);
2630
2631 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2632 if (!uj)
2633 vty_out(vty, "%% Malformed VTEP IP address\n");
2634 return CMD_WARNING;
2635 }
2636 zvrf = zebra_vrf_get_evpn();
2637 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2638
2639 return CMD_SUCCESS;
2640 }
2641
2642
2643 DEFUN (show_evpn_mac_vni_mac,
2644 show_evpn_mac_vni_mac_cmd,
2645 "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
2646 SHOW_STR
2647 "EVPN\n"
2648 "MAC addresses\n"
2649 "VxLAN Network Identifier\n"
2650 "VNI number\n"
2651 "MAC\n"
2652 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2653 JSON_STR)
2654
2655 {
2656 struct zebra_vrf *zvrf;
2657 vni_t vni;
2658 struct ethaddr mac;
2659 bool uj = use_json(argc, argv);
2660
2661 vni = strtoul(argv[4]->arg, NULL, 10);
2662 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2663 vty_out(vty, "%% Malformed MAC address");
2664 return CMD_WARNING;
2665 }
2666 zvrf = zebra_vrf_get_evpn();
2667 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
2668 return CMD_SUCCESS;
2669 }
2670
2671 DEFUN (show_evpn_mac_vni_vtep,
2672 show_evpn_mac_vni_vtep_cmd,
2673 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2674 SHOW_STR
2675 "EVPN\n"
2676 "MAC addresses\n"
2677 "VxLAN Network Identifier\n"
2678 "VNI number\n"
2679 "Remote VTEP\n"
2680 "Remote VTEP IP address\n"
2681 JSON_STR)
2682 {
2683 struct zebra_vrf *zvrf;
2684 vni_t vni;
2685 struct in_addr vtep_ip;
2686 bool uj = use_json(argc, argv);
2687
2688 vni = strtoul(argv[4]->arg, NULL, 10);
2689 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2690 if (!uj)
2691 vty_out(vty, "%% Malformed VTEP IP address\n");
2692 return CMD_WARNING;
2693 }
2694
2695 zvrf = zebra_vrf_get_evpn();
2696 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2697 return CMD_SUCCESS;
2698 }
2699
2700 DEFPY (show_evpn_mac_vni_all_dad,
2701 show_evpn_mac_vni_all_dad_cmd,
2702 "show evpn mac vni all duplicate [json]",
2703 SHOW_STR
2704 "EVPN\n"
2705 "MAC addresses\n"
2706 "VxLAN Network Identifier\n"
2707 "All VNIs\n"
2708 "Duplicate address list\n"
2709 JSON_STR)
2710 {
2711 struct zebra_vrf *zvrf;
2712 bool uj = use_json(argc, argv);
2713
2714 zvrf = zebra_vrf_get_evpn();
2715 zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
2716 return CMD_SUCCESS;
2717 }
2718
2719
2720 DEFPY (show_evpn_mac_vni_dad,
2721 show_evpn_mac_vni_dad_cmd,
2722 "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
2723 SHOW_STR
2724 "EVPN\n"
2725 "MAC addresses\n"
2726 "VxLAN Network Identifier\n"
2727 "VNI number\n"
2728 "Duplicate address list\n"
2729 JSON_STR)
2730 {
2731 struct zebra_vrf *zvrf;
2732 bool uj = use_json(argc, argv);
2733
2734 zvrf = zebra_vrf_get_evpn();
2735
2736 zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
2737
2738 return CMD_SUCCESS;
2739 }
2740
2741 DEFPY (show_evpn_neigh_vni_dad,
2742 show_evpn_neigh_vni_dad_cmd,
2743 "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
2744 SHOW_STR
2745 "EVPN\n"
2746 "ARP and ND cache\n"
2747 "VxLAN Network Identifier\n"
2748 "VNI number\n"
2749 "Duplicate address list\n"
2750 JSON_STR)
2751 {
2752 struct zebra_vrf *zvrf;
2753 bool uj = use_json(argc, argv);
2754
2755 zvrf = zebra_vrf_get_evpn();
2756 zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
2757 return CMD_SUCCESS;
2758 }
2759
2760 DEFPY (show_evpn_neigh_vni_all_dad,
2761 show_evpn_neigh_vni_all_dad_cmd,
2762 "show evpn arp-cache vni all duplicate [json]",
2763 SHOW_STR
2764 "EVPN\n"
2765 "ARP and ND cache\n"
2766 "VxLAN Network Identifier\n"
2767 "All VNIs\n"
2768 "Duplicate address list\n"
2769 JSON_STR)
2770 {
2771 struct zebra_vrf *zvrf;
2772 bool uj = use_json(argc, argv);
2773
2774 zvrf = zebra_vrf_get_evpn();
2775 zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
2776 return CMD_SUCCESS;
2777 }
2778
2779
2780 DEFUN (show_evpn_neigh_vni,
2781 show_evpn_neigh_vni_cmd,
2782 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
2783 SHOW_STR
2784 "EVPN\n"
2785 "ARP and ND cache\n"
2786 "VxLAN Network Identifier\n"
2787 "VNI number\n"
2788 JSON_STR)
2789 {
2790 struct zebra_vrf *zvrf;
2791 vni_t vni;
2792 bool uj = use_json(argc, argv);
2793
2794 vni = strtoul(argv[4]->arg, NULL, 10);
2795 zvrf = zebra_vrf_get_evpn();
2796 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
2797 return CMD_SUCCESS;
2798 }
2799
2800 DEFUN (show_evpn_neigh_vni_all,
2801 show_evpn_neigh_vni_all_cmd,
2802 "show evpn arp-cache vni all [json]",
2803 SHOW_STR
2804 "EVPN\n"
2805 "ARP and ND cache\n"
2806 "VxLAN Network Identifier\n"
2807 "All VNIs\n"
2808 JSON_STR)
2809 {
2810 struct zebra_vrf *zvrf;
2811 bool uj = use_json(argc, argv);
2812
2813 zvrf = zebra_vrf_get_evpn();
2814 zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
2815 return CMD_SUCCESS;
2816 }
2817
2818 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
2819 "show evpn arp-cache vni all detail [json]",
2820 SHOW_STR
2821 "EVPN\n"
2822 "ARP and ND cache\n"
2823 "VxLAN Network Identifier\n"
2824 "All VNIs\n"
2825 "Neighbor details for all vnis in detail\n" JSON_STR)
2826 {
2827 struct zebra_vrf *zvrf;
2828 bool uj = use_json(argc, argv);
2829
2830 zvrf = zebra_vrf_get_evpn();
2831 zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
2832 return CMD_SUCCESS;
2833 }
2834
2835 DEFUN (show_evpn_neigh_vni_neigh,
2836 show_evpn_neigh_vni_neigh_cmd,
2837 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
2838 SHOW_STR
2839 "EVPN\n"
2840 "ARP and ND cache\n"
2841 "VxLAN Network Identifier\n"
2842 "VNI number\n"
2843 "Neighbor\n"
2844 "Neighbor address (IPv4 or IPv6 address)\n"
2845 JSON_STR)
2846 {
2847 struct zebra_vrf *zvrf;
2848 vni_t vni;
2849 struct ipaddr ip;
2850 bool uj = use_json(argc, argv);
2851
2852 vni = strtoul(argv[4]->arg, NULL, 10);
2853 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2854 if (!uj)
2855 vty_out(vty, "%% Malformed Neighbor address\n");
2856 return CMD_WARNING;
2857 }
2858 zvrf = zebra_vrf_get_evpn();
2859 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
2860 return CMD_SUCCESS;
2861 }
2862
2863 DEFUN (show_evpn_neigh_vni_vtep,
2864 show_evpn_neigh_vni_vtep_cmd,
2865 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
2866 SHOW_STR
2867 "EVPN\n"
2868 "ARP and ND cache\n"
2869 "VxLAN Network Identifier\n"
2870 "VNI number\n"
2871 "Remote VTEP\n"
2872 "Remote VTEP IP address\n"
2873 JSON_STR)
2874 {
2875 struct zebra_vrf *zvrf;
2876 vni_t vni;
2877 struct in_addr vtep_ip;
2878 bool uj = use_json(argc, argv);
2879
2880 vni = strtoul(argv[4]->arg, NULL, 10);
2881 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2882 if (!uj)
2883 vty_out(vty, "%% Malformed VTEP IP address\n");
2884 return CMD_WARNING;
2885 }
2886
2887 zvrf = zebra_vrf_get_evpn();
2888 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2889 return CMD_SUCCESS;
2890 }
2891
2892 /* policy routing contexts */
2893 DEFUN (show_pbr_ipset,
2894 show_pbr_ipset_cmd,
2895 "show pbr ipset [WORD]",
2896 SHOW_STR
2897 "Policy-Based Routing\n"
2898 "IPset Context information\n"
2899 "IPset Name information\n")
2900 {
2901 int idx = 0;
2902 int found = 0;
2903 found = argv_find(argv, argc, "WORD", &idx);
2904 if (!found)
2905 zebra_pbr_show_ipset_list(vty, NULL);
2906 else
2907 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
2908 return CMD_SUCCESS;
2909 }
2910
2911 /* policy routing contexts */
2912 DEFUN (show_pbr_iptable,
2913 show_pbr_iptable_cmd,
2914 "show pbr iptable [WORD]",
2915 SHOW_STR
2916 "Policy-Based Routing\n"
2917 "IPtable Context information\n"
2918 "IPtable Name information\n")
2919 {
2920 int idx = 0;
2921 int found = 0;
2922
2923 found = argv_find(argv, argc, "WORD", &idx);
2924 if (!found)
2925 zebra_pbr_show_iptable(vty, NULL);
2926 else
2927 zebra_pbr_show_iptable(vty, argv[idx]->arg);
2928 return CMD_SUCCESS;
2929 }
2930
2931 DEFPY (clear_evpn_dup_addr,
2932 clear_evpn_dup_addr_cmd,
2933 "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>]>",
2934 CLEAR_STR
2935 "EVPN\n"
2936 "Duplicate address \n"
2937 "VxLAN Network Identifier\n"
2938 "VNI number\n"
2939 "All VNIs\n"
2940 "MAC\n"
2941 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2942 "IP\n"
2943 "IPv4 address\n"
2944 "IPv6 address\n")
2945 {
2946 struct zebra_vrf *zvrf;
2947 struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
2948 int ret = CMD_SUCCESS;
2949
2950 zvrf = zebra_vrf_get_evpn();
2951 if (vni_str) {
2952 if (!is_zero_mac(&mac->eth_addr)) {
2953 ret = zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf,
2954 vni,
2955 &mac->eth_addr);
2956 } else if (ip) {
2957 if (sockunion_family(ip) == AF_INET) {
2958 host_ip.ipa_type = IPADDR_V4;
2959 host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
2960 } else {
2961 host_ip.ipa_type = IPADDR_V6;
2962 memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
2963 sizeof(struct in6_addr));
2964 }
2965 ret = zebra_vxlan_clear_dup_detect_vni_ip(vty, zvrf,
2966 vni,
2967 &host_ip);
2968 } else
2969 ret = zebra_vxlan_clear_dup_detect_vni(vty, zvrf, vni);
2970
2971 } else {
2972 ret = zebra_vxlan_clear_dup_detect_vni_all(vty, zvrf);
2973 }
2974
2975 return ret;
2976 }
2977
2978 /* Static ip route configuration write function. */
2979 static int zebra_ip_config(struct vty *vty)
2980 {
2981 int write = 0;
2982
2983 write += zebra_import_table_config(vty, VRF_DEFAULT);
2984
2985 return write;
2986 }
2987
2988 DEFUN (ip_zebra_import_table_distance,
2989 ip_zebra_import_table_distance_cmd,
2990 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
2991 IP_STR
2992 "import routes from non-main kernel table\n"
2993 "kernel routing table id\n"
2994 "Distance for imported routes\n"
2995 "Default distance value\n"
2996 "route-map for filtering\n"
2997 "route-map name\n")
2998 {
2999 uint32_t table_id = 0;
3000
3001 table_id = strtoul(argv[2]->arg, NULL, 10);
3002 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3003 char *rmap =
3004 strmatch(argv[argc - 2]->text, "route-map")
3005 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3006 : NULL;
3007 int ret;
3008
3009 if (argc == 7 || (argc == 5 && !rmap))
3010 distance = strtoul(argv[4]->arg, NULL, 10);
3011
3012 if (!is_zebra_valid_kernel_table(table_id)) {
3013 vty_out(vty,
3014 "Invalid routing table ID, %d. Must be in range 1-252\n",
3015 table_id);
3016 if (rmap)
3017 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3018 return CMD_WARNING;
3019 }
3020
3021 if (is_zebra_main_routing_table(table_id)) {
3022 vty_out(vty,
3023 "Invalid routing table ID, %d. Must be non-default table\n",
3024 table_id);
3025 if (rmap)
3026 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3027 return CMD_WARNING;
3028 }
3029
3030 ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
3031 distance, rmap, 1);
3032 if (rmap)
3033 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3034
3035 return ret;
3036 }
3037
3038 DEFUN_HIDDEN (zebra_packet_process,
3039 zebra_packet_process_cmd,
3040 "zebra zapi-packets (1-10000)",
3041 ZEBRA_STR
3042 "Zapi Protocol\n"
3043 "Number of packets to process before relinquishing thread\n")
3044 {
3045 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3046
3047 atomic_store_explicit(&zrouter.packets_to_process, packets,
3048 memory_order_relaxed);
3049
3050 return CMD_SUCCESS;
3051 }
3052
3053 DEFUN_HIDDEN (no_zebra_packet_process,
3054 no_zebra_packet_process_cmd,
3055 "no zebra zapi-packets [(1-10000)]",
3056 NO_STR
3057 ZEBRA_STR
3058 "Zapi Protocol\n"
3059 "Number of packets to process before relinquishing thread\n")
3060 {
3061 atomic_store_explicit(&zrouter.packets_to_process,
3062 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3063 memory_order_relaxed);
3064
3065 return CMD_SUCCESS;
3066 }
3067
3068 DEFUN_HIDDEN (zebra_workqueue_timer,
3069 zebra_workqueue_timer_cmd,
3070 "zebra work-queue (0-10000)",
3071 ZEBRA_STR
3072 "Work Queue\n"
3073 "Time in milliseconds\n")
3074 {
3075 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3076 zrouter.ribq->spec.hold = timer;
3077
3078 return CMD_SUCCESS;
3079 }
3080
3081 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3082 no_zebra_workqueue_timer_cmd,
3083 "no zebra work-queue [(0-10000)]",
3084 NO_STR
3085 ZEBRA_STR
3086 "Work Queue\n"
3087 "Time in milliseconds\n")
3088 {
3089 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3090
3091 return CMD_SUCCESS;
3092 }
3093
3094 DEFUN (no_ip_zebra_import_table,
3095 no_ip_zebra_import_table_cmd,
3096 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3097 NO_STR
3098 IP_STR
3099 "import routes from non-main kernel table\n"
3100 "kernel routing table id\n"
3101 "Distance for imported routes\n"
3102 "Default distance value\n"
3103 "route-map for filtering\n"
3104 "route-map name\n")
3105 {
3106 uint32_t table_id = 0;
3107 table_id = strtoul(argv[3]->arg, NULL, 10);
3108
3109 if (!is_zebra_valid_kernel_table(table_id)) {
3110 vty_out(vty,
3111 "Invalid routing table ID. Must be in range 1-252\n");
3112 return CMD_WARNING;
3113 }
3114
3115 if (is_zebra_main_routing_table(table_id)) {
3116 vty_out(vty,
3117 "Invalid routing table ID, %d. Must be non-default table\n",
3118 table_id);
3119 return CMD_WARNING;
3120 }
3121
3122 if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3123 return CMD_SUCCESS;
3124
3125 return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3126 }
3127
3128 static int config_write_protocol(struct vty *vty)
3129 {
3130 if (allow_delete)
3131 vty_out(vty, "allow-external-route-update\n");
3132
3133 if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3134 vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3135
3136 if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3137 vty_out(vty, "zebra zapi-packets %u\n",
3138 zrouter.packets_to_process);
3139
3140 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3141
3142 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3143 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3144 ipv4_multicast_mode == MCAST_URIB_ONLY
3145 ? "urib-only"
3146 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3147 ? "mrib-only"
3148 : ipv4_multicast_mode
3149 == MCAST_MIX_MRIB_FIRST
3150 ? "mrib-then-urib"
3151 : ipv4_multicast_mode
3152 == MCAST_MIX_DISTANCE
3153 ? "lower-distance"
3154 : "longer-prefix");
3155
3156 /* Include dataplane info */
3157 dplane_config_write_helper(vty);
3158
3159 /* Include nexthop-group config */
3160 if (!zebra_nhg_kernel_nexthops_enabled())
3161 vty_out(vty, "no zebra nexthop kernel enable\n");
3162
3163 return 1;
3164 }
3165
3166 DEFUN (show_zebra,
3167 show_zebra_cmd,
3168 "show zebra",
3169 SHOW_STR
3170 ZEBRA_STR)
3171 {
3172 struct vrf *vrf;
3173
3174 vty_out(vty,
3175 " Route Route Neighbor LSP LSP\n");
3176 vty_out(vty,
3177 "VRF Installs Removals Updates Installs Removals\n");
3178
3179 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3180 struct zebra_vrf *zvrf = vrf->info;
3181
3182 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
3183 " %10" PRIu64 " %10" PRIu64 "\n",
3184 vrf->name, zvrf->installs, zvrf->removals,
3185 zvrf->neigh_updates, zvrf->lsp_installs,
3186 zvrf->lsp_removals);
3187 }
3188
3189 return CMD_SUCCESS;
3190 }
3191
3192 DEFUN (ip_forwarding,
3193 ip_forwarding_cmd,
3194 "ip forwarding",
3195 IP_STR
3196 "Turn on IP forwarding\n")
3197 {
3198 int ret;
3199
3200 ret = ipforward();
3201 if (ret == 0)
3202 ret = ipforward_on();
3203
3204 if (ret == 0) {
3205 vty_out(vty, "Can't turn on IP forwarding\n");
3206 return CMD_WARNING_CONFIG_FAILED;
3207 }
3208
3209 return CMD_SUCCESS;
3210 }
3211
3212 DEFUN (no_ip_forwarding,
3213 no_ip_forwarding_cmd,
3214 "no ip forwarding",
3215 NO_STR
3216 IP_STR
3217 "Turn off IP forwarding\n")
3218 {
3219 int ret;
3220
3221 ret = ipforward();
3222 if (ret != 0)
3223 ret = ipforward_off();
3224
3225 if (ret != 0) {
3226 vty_out(vty, "Can't turn off IP forwarding\n");
3227 return CMD_WARNING_CONFIG_FAILED;
3228 }
3229
3230 return CMD_SUCCESS;
3231 }
3232
3233 /* Only display ip forwarding is enabled or not. */
3234 DEFUN (show_ip_forwarding,
3235 show_ip_forwarding_cmd,
3236 "show ip forwarding",
3237 SHOW_STR
3238 IP_STR
3239 "IP forwarding status\n")
3240 {
3241 int ret;
3242
3243 ret = ipforward();
3244
3245 if (ret == 0)
3246 vty_out(vty, "IP forwarding is off\n");
3247 else
3248 vty_out(vty, "IP forwarding is on\n");
3249 return CMD_SUCCESS;
3250 }
3251
3252 /* Only display ipv6 forwarding is enabled or not. */
3253 DEFUN (show_ipv6_forwarding,
3254 show_ipv6_forwarding_cmd,
3255 "show ipv6 forwarding",
3256 SHOW_STR
3257 "IPv6 information\n"
3258 "Forwarding status\n")
3259 {
3260 int ret;
3261
3262 ret = ipforward_ipv6();
3263
3264 switch (ret) {
3265 case -1:
3266 vty_out(vty, "ipv6 forwarding is unknown\n");
3267 break;
3268 case 0:
3269 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3270 break;
3271 case 1:
3272 vty_out(vty, "ipv6 forwarding is %s\n", "on");
3273 break;
3274 default:
3275 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3276 break;
3277 }
3278 return CMD_SUCCESS;
3279 }
3280
3281 DEFUN (ipv6_forwarding,
3282 ipv6_forwarding_cmd,
3283 "ipv6 forwarding",
3284 IPV6_STR
3285 "Turn on IPv6 forwarding\n")
3286 {
3287 int ret;
3288
3289 ret = ipforward_ipv6();
3290 if (ret == 0)
3291 ret = ipforward_ipv6_on();
3292
3293 if (ret == 0) {
3294 vty_out(vty, "Can't turn on IPv6 forwarding\n");
3295 return CMD_WARNING_CONFIG_FAILED;
3296 }
3297
3298 return CMD_SUCCESS;
3299 }
3300
3301 DEFUN (no_ipv6_forwarding,
3302 no_ipv6_forwarding_cmd,
3303 "no ipv6 forwarding",
3304 NO_STR
3305 IPV6_STR
3306 "Turn off IPv6 forwarding\n")
3307 {
3308 int ret;
3309
3310 ret = ipforward_ipv6();
3311 if (ret != 0)
3312 ret = ipforward_ipv6_off();
3313
3314 if (ret != 0) {
3315 vty_out(vty, "Can't turn off IPv6 forwarding\n");
3316 return CMD_WARNING_CONFIG_FAILED;
3317 }
3318
3319 return CMD_SUCCESS;
3320 }
3321
3322 /* Display dataplane info */
3323 DEFUN (show_dataplane,
3324 show_dataplane_cmd,
3325 "show zebra dplane [detailed]",
3326 SHOW_STR
3327 ZEBRA_STR
3328 "Zebra dataplane information\n"
3329 "Detailed output\n")
3330 {
3331 int idx = 0;
3332 bool detailed = false;
3333
3334 if (argv_find(argv, argc, "detailed", &idx))
3335 detailed = true;
3336
3337 return dplane_show_helper(vty, detailed);
3338 }
3339
3340 /* Display dataplane providers info */
3341 DEFUN (show_dataplane_providers,
3342 show_dataplane_providers_cmd,
3343 "show zebra dplane providers [detailed]",
3344 SHOW_STR
3345 ZEBRA_STR
3346 "Zebra dataplane information\n"
3347 "Zebra dataplane provider information\n"
3348 "Detailed output\n")
3349 {
3350 int idx = 0;
3351 bool detailed = false;
3352
3353 if (argv_find(argv, argc, "detailed", &idx))
3354 detailed = true;
3355
3356 return dplane_show_provs_helper(vty, detailed);
3357 }
3358
3359 /* Configure dataplane incoming queue limit */
3360 DEFUN (zebra_dplane_queue_limit,
3361 zebra_dplane_queue_limit_cmd,
3362 "zebra dplane limit (0-10000)",
3363 ZEBRA_STR
3364 "Zebra dataplane\n"
3365 "Limit incoming queued updates\n"
3366 "Number of queued updates\n")
3367 {
3368 uint32_t limit = 0;
3369
3370 limit = strtoul(argv[3]->arg, NULL, 10);
3371
3372 dplane_set_in_queue_limit(limit, true);
3373
3374 return CMD_SUCCESS;
3375 }
3376
3377 /* Reset dataplane queue limit to default value */
3378 DEFUN (no_zebra_dplane_queue_limit,
3379 no_zebra_dplane_queue_limit_cmd,
3380 "no zebra dplane limit [(0-10000)]",
3381 NO_STR
3382 ZEBRA_STR
3383 "Zebra dataplane\n"
3384 "Limit incoming queued updates\n"
3385 "Number of queued updates\n")
3386 {
3387 dplane_set_in_queue_limit(0, false);
3388
3389 return CMD_SUCCESS;
3390 }
3391
3392 DEFUN (zebra_show_routing_tables_summary,
3393 zebra_show_routing_tables_summary_cmd,
3394 "show zebra router table summary",
3395 SHOW_STR
3396 ZEBRA_STR
3397 "The Zebra Router Information\n"
3398 "Table Information about this Zebra Router\n"
3399 "Summary Information\n")
3400 {
3401 zebra_router_show_table_summary(vty);
3402
3403 return CMD_SUCCESS;
3404 }
3405
3406 /* Table configuration write function. */
3407 static int config_write_table(struct vty *vty)
3408 {
3409 return 0;
3410 }
3411
3412 /* IPForwarding configuration write function. */
3413 static int config_write_forwarding(struct vty *vty)
3414 {
3415 /* FIXME: Find better place for that. */
3416 router_id_write(vty);
3417
3418 if (!ipforward())
3419 vty_out(vty, "no ip forwarding\n");
3420 if (!ipforward_ipv6())
3421 vty_out(vty, "no ipv6 forwarding\n");
3422 vty_out(vty, "!\n");
3423 return 0;
3424 }
3425
3426 DEFUN_HIDDEN (show_frr,
3427 show_frr_cmd,
3428 "show frr",
3429 SHOW_STR
3430 "FRR\n")
3431 {
3432 vty_out(vty, "........ .. . .. . ..... ...77:................................................\n");
3433 vty_out(vty, ".............................7777:..............................................\n");
3434 vty_out(vty, ".............................777777,............................................\n");
3435 vty_out(vty, "... .........................77777777,..........................................\n");
3436 vty_out(vty, "............................=7777777777:........................................\n");
3437 vty_out(vty, "........................:7777777777777777,......................................\n");
3438 vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
3439 vty_out(vty, "...................I7777777777+.................................................\n");
3440 vty_out(vty, "................,777777777?............ .......................................\n");
3441 vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
3442 vty_out(vty, ".............77777777~........=7777777777.......................................\n");
3443 vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
3444 vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
3445 vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
3446 vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
3447 vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
3448 vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
3449 vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
3450 vty_out(vty, "...~77777+.....7777777777777777=........................?777777...... .......\n");
3451 vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
3452 vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
3453 vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
3454 vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
3455 vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
3456 vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
3457 vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
3458 vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
3459 vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
3460 vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
3461 vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
3462 vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
3463 vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
3464 vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
3465 vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
3466 vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
3467 vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
3468 vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
3469 vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
3470 vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
3471 vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
3472 vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
3473 vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
3474 vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
3475 vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
3476 vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
3477 vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
3478 vty_out(vty, ".......................=77777777777777777............777777I....................\n");
3479 vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
3480 vty_out(vty, "............................~777777777777..............+777777..................\n");
3481 vty_out(vty, "................................~77777777...............=777777.................\n");
3482 vty_out(vty, ".....................................:=?I................~777777................\n");
3483 vty_out(vty, "..........................................................:777777,..............\n");
3484 vty_out(vty, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
3485
3486 return CMD_SUCCESS;
3487 }
3488
3489 /* IP node for static routes. */
3490 static struct cmd_node ip_node = {IP_NODE, "", 1};
3491 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
3492 /* table node for routing tables. */
3493 static struct cmd_node table_node = {TABLE_NODE,
3494 "", /* This node has no interface. */
3495 1};
3496 static struct cmd_node forwarding_node = {FORWARDING_NODE,
3497 "", /* This node has no interface. */
3498 1};
3499
3500 /* Route VTY. */
3501 void zebra_vty_init(void)
3502 {
3503 /* Install configuration write function. */
3504 install_node(&table_node, config_write_table);
3505 install_node(&forwarding_node, config_write_forwarding);
3506
3507 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3508 install_element(CONFIG_NODE, &ip_forwarding_cmd);
3509 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3510 install_element(ENABLE_NODE, &show_zebra_cmd);
3511
3512 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3513 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3514 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3515
3516 /* Route-map */
3517 zebra_route_map_init();
3518
3519 install_node(&ip_node, zebra_ip_config);
3520 install_node(&protocol_node, config_write_protocol);
3521
3522 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3523 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3524
3525 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3526 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3527
3528 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3529 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3530 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3531 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3532 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3533 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3534 install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
3535
3536 install_element(VIEW_NODE, &show_nexthop_group_cmd);
3537 install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
3538
3539 install_element(VIEW_NODE, &show_vrf_cmd);
3540 install_element(VIEW_NODE, &show_vrf_vni_cmd);
3541 install_element(VIEW_NODE, &show_route_cmd);
3542 install_element(VIEW_NODE, &show_route_table_cmd);
3543 if (vrf_is_backend_netns())
3544 install_element(VIEW_NODE, &show_route_table_vrf_cmd);
3545 install_element(VIEW_NODE, &show_route_all_table_vrf_cmd);
3546 install_element(VIEW_NODE, &show_route_detail_cmd);
3547 install_element(VIEW_NODE, &show_route_summary_cmd);
3548 install_element(VIEW_NODE, &show_ip_nht_cmd);
3549
3550 install_element(VIEW_NODE, &show_ip_rpf_cmd);
3551 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3552
3553 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3554 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3555 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3556 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3557 install_element(VRF_NODE, &ip_nht_default_route_cmd);
3558 install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
3559 install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
3560 install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
3561 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3562
3563 /* Commands for VRF */
3564 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3565
3566 install_element(VIEW_NODE, &show_frr_cmd);
3567 install_element(VIEW_NODE, &show_evpn_global_cmd);
3568 install_element(VIEW_NODE, &show_evpn_vni_cmd);
3569 install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
3570 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3571 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3572 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3573 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3574 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3575 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3576 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3577 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3578 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3579 install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
3580 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3581 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
3582 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
3583 install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
3584 install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
3585 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
3586 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
3587 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
3588 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
3589 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
3590 install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
3591 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
3592 install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
3593
3594 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
3595 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
3596
3597 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
3598 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
3599 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
3600 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
3601
3602 install_element(VIEW_NODE, &show_dataplane_cmd);
3603 install_element(VIEW_NODE, &show_dataplane_providers_cmd);
3604 install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
3605 install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
3606
3607 install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
3608 }