]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
Merge pull request #5545 from ton31337/feature/show_bgp_json_regexp
[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\n", nhe_vrf->name);
1127 else
1128 vty_out(vty, " VRF: UNKNOWN\n");
1129
1130 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE))
1131 vty_out(vty, " Duplicate - from kernel not hashable\n");
1132
1133 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
1134 vty_out(vty, " Valid");
1135 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED))
1136 vty_out(vty, ", Installed");
1137 vty_out(vty, "\n");
1138 }
1139 if (nhe->ifp)
1140 vty_out(vty, " Interface Index: %d\n", nhe->ifp->ifindex);
1141
1142 if (!zebra_nhg_depends_is_empty(nhe)) {
1143 vty_out(vty, " Depends:");
1144 frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
1145 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1146 }
1147 vty_out(vty, "\n");
1148 }
1149
1150 for (ALL_NEXTHOPS_PTR(nhe->nhg, nexthop)) {
1151 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1152 vty_out(vty, " ");
1153 else
1154 /* Make recursive nexthops a bit more clear */
1155 vty_out(vty, " ");
1156
1157 switch (nexthop->type) {
1158 case NEXTHOP_TYPE_IPV4:
1159 case NEXTHOP_TYPE_IPV4_IFINDEX:
1160 vty_out(vty, " %s", inet_ntoa(nexthop->gate.ipv4));
1161 if (nexthop->ifindex)
1162 vty_out(vty, ", %s",
1163 ifindex2ifname(nexthop->ifindex,
1164 nexthop->vrf_id));
1165 break;
1166 case NEXTHOP_TYPE_IPV6:
1167 case NEXTHOP_TYPE_IPV6_IFINDEX:
1168 vty_out(vty, " %s",
1169 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
1170 sizeof(buf)));
1171 if (nexthop->ifindex)
1172 vty_out(vty, ", %s",
1173 ifindex2ifname(nexthop->ifindex,
1174 nexthop->vrf_id));
1175 break;
1176
1177 case NEXTHOP_TYPE_IFINDEX:
1178 vty_out(vty, " directly connected %s",
1179 ifindex2ifname(nexthop->ifindex,
1180 nexthop->vrf_id));
1181 break;
1182 case NEXTHOP_TYPE_BLACKHOLE:
1183 vty_out(vty, " unreachable");
1184 switch (nexthop->bh_type) {
1185 case BLACKHOLE_REJECT:
1186 vty_out(vty, " (ICMP unreachable)");
1187 break;
1188 case BLACKHOLE_ADMINPROHIB:
1189 vty_out(vty, " (ICMP admin-prohibited)");
1190 break;
1191 case BLACKHOLE_NULL:
1192 vty_out(vty, " (blackhole)");
1193 break;
1194 case BLACKHOLE_UNSPEC:
1195 break;
1196 }
1197 break;
1198 default:
1199 break;
1200 }
1201
1202 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
1203
1204 if (vrf)
1205 vty_out(vty, " (vrf %s)", vrf->name);
1206 else
1207 vty_out(vty, " (vrf UNKNOWN)");
1208
1209 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1210 vty_out(vty, " inactive");
1211
1212 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1213 vty_out(vty, " onlink");
1214
1215 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1216 vty_out(vty, " (recursive)");
1217
1218 switch (nexthop->type) {
1219 case NEXTHOP_TYPE_IPV4:
1220 case NEXTHOP_TYPE_IPV4_IFINDEX:
1221 if (nexthop->src.ipv4.s_addr) {
1222 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
1223 sizeof(buf)))
1224 vty_out(vty, ", src %s", buf);
1225 }
1226 break;
1227 case NEXTHOP_TYPE_IPV6:
1228 case NEXTHOP_TYPE_IPV6_IFINDEX:
1229 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
1230 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
1231 sizeof(buf)))
1232 vty_out(vty, ", src %s", buf);
1233 }
1234 break;
1235 default:
1236 break;
1237 }
1238
1239 /* Label information */
1240 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
1241 vty_out(vty, ", label %s",
1242 mpls_label2str(nexthop->nh_label->num_labels,
1243 nexthop->nh_label->label, buf,
1244 sizeof(buf), 1));
1245 }
1246
1247 if (nexthop->weight)
1248 vty_out(vty, ", weight %u", nexthop->weight);
1249
1250 vty_out(vty, "\n");
1251 }
1252
1253 if (!zebra_nhg_dependents_is_empty(nhe)) {
1254 vty_out(vty, " Dependents:");
1255 frr_each(nhg_connected_tree, &nhe->nhg_dependents,
1256 rb_node_dep) {
1257 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1258 }
1259 vty_out(vty, "\n");
1260 }
1261
1262 }
1263
1264 static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id)
1265 {
1266 struct nhg_hash_entry *nhe = NULL;
1267
1268 nhe = zebra_nhg_lookup_id(id);
1269
1270 if (nhe)
1271 show_nexthop_group_out(vty, nhe);
1272 else {
1273 vty_out(vty, "Nexthop Group ID: %u does not exist\n", id);
1274 return CMD_WARNING;
1275 }
1276 return CMD_SUCCESS;
1277 }
1278
1279 static void show_nexthop_group_cmd_helper(struct vty *vty,
1280 struct zebra_vrf *zvrf, afi_t afi)
1281 {
1282 struct list *list = hash_to_list(zrouter.nhgs);
1283 struct nhg_hash_entry *nhe = NULL;
1284 struct listnode *node = NULL;
1285
1286 for (ALL_LIST_ELEMENTS_RO(list, node, nhe)) {
1287
1288 if (afi && nhe->afi != afi)
1289 continue;
1290
1291 if (nhe->vrf_id != zvrf->vrf->vrf_id)
1292 continue;
1293
1294 show_nexthop_group_out(vty, nhe);
1295 }
1296
1297 list_delete(&list);
1298 }
1299
1300 static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
1301 {
1302 struct zebra_if *zebra_if = NULL;
1303 struct nhg_connected *rb_node_dep = NULL;
1304
1305 zebra_if = ifp->info;
1306
1307 if (!if_nhg_dependents_is_empty(ifp)) {
1308 vty_out(vty, "Interface %s:\n", ifp->name);
1309
1310 frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
1311 rb_node_dep) {
1312 vty_out(vty, " ");
1313 show_nexthop_group_out(vty, rb_node_dep->nhe);
1314 }
1315 }
1316 }
1317
1318 DEFPY (show_interface_nexthop_group,
1319 show_interface_nexthop_group_cmd,
1320 "show interface [IFNAME$if_name] nexthop-group",
1321 SHOW_STR
1322 "Interface status and configuration\n"
1323 "Interface name\n"
1324 "Show Nexthop Groups\n")
1325 {
1326 struct vrf *vrf = NULL;
1327 struct interface *ifp = NULL;
1328 bool found = false;
1329
1330 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1331 if (if_name) {
1332 ifp = if_lookup_by_name(if_name, vrf->vrf_id);
1333 if (ifp) {
1334 if_nexthop_group_dump_vty(vty, ifp);
1335 found = true;
1336 }
1337 } else {
1338 FOR_ALL_INTERFACES (vrf, ifp)
1339 if_nexthop_group_dump_vty(vty, ifp);
1340 found = true;
1341 }
1342 }
1343
1344 if (!found) {
1345 vty_out(vty, "%% Can't find interface %s\n", if_name);
1346 return CMD_WARNING;
1347 }
1348
1349 return CMD_SUCCESS;
1350 }
1351
1352 DEFPY (show_nexthop_group,
1353 show_nexthop_group_cmd,
1354 "show nexthop-group <(0-4294967295)$id|[<ip$v4|ipv6$v6>] [vrf <NAME$vrf_name|all$vrf_all>]>",
1355 SHOW_STR
1356 "Show Nexthop Groups\n"
1357 "Nexthop Group ID\n"
1358 IP_STR
1359 IP6_STR
1360 VRF_FULL_CMD_HELP_STR)
1361 {
1362
1363 struct zebra_vrf *zvrf = NULL;
1364 afi_t afi = 0;
1365
1366 if (id)
1367 return show_nexthop_group_id_cmd_helper(vty, id);
1368
1369 if (v4)
1370 afi = AFI_IP;
1371 else if (v6)
1372 afi = AFI_IP6;
1373
1374 if (vrf_all) {
1375 struct vrf *vrf;
1376
1377 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1378 struct zebra_vrf *zvrf;
1379
1380 zvrf = vrf->info;
1381 if (!zvrf)
1382 continue;
1383
1384 vty_out(vty, "VRF: %s\n", vrf->name);
1385 show_nexthop_group_cmd_helper(vty, zvrf, afi);
1386 }
1387
1388 return CMD_SUCCESS;
1389 }
1390
1391 if (vrf_name)
1392 zvrf = zebra_vrf_lookup_by_name(vrf_name);
1393 else
1394 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1395
1396 if (!zvrf) {
1397 vty_out(vty, "VRF %s specified does not exist", vrf_name);
1398 return CMD_WARNING;
1399 }
1400
1401 show_nexthop_group_cmd_helper(vty, zvrf, afi);
1402
1403 return CMD_SUCCESS;
1404 }
1405
1406 DEFUN (no_ip_nht_default_route,
1407 no_ip_nht_default_route_cmd,
1408 "no ip nht resolve-via-default",
1409 NO_STR
1410 IP_STR
1411 "Filter Next Hop tracking route resolution\n"
1412 "Resolve via default route\n")
1413 {
1414 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1415
1416 if (!zvrf)
1417 return CMD_WARNING;
1418
1419 if (!zvrf->zebra_rnh_ip_default_route)
1420 return CMD_SUCCESS;
1421
1422 zvrf->zebra_rnh_ip_default_route = 0;
1423 zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
1424 return CMD_SUCCESS;
1425 }
1426
1427 DEFUN (ipv6_nht_default_route,
1428 ipv6_nht_default_route_cmd,
1429 "ipv6 nht resolve-via-default",
1430 IP6_STR
1431 "Filter Next Hop tracking route resolution\n"
1432 "Resolve via default route\n")
1433 {
1434 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1435
1436 if (!zvrf)
1437 return CMD_WARNING;
1438
1439 if (zvrf->zebra_rnh_ipv6_default_route)
1440 return CMD_SUCCESS;
1441
1442 zvrf->zebra_rnh_ipv6_default_route = 1;
1443 zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL);
1444 return CMD_SUCCESS;
1445 }
1446
1447 DEFUN (no_ipv6_nht_default_route,
1448 no_ipv6_nht_default_route_cmd,
1449 "no ipv6 nht resolve-via-default",
1450 NO_STR
1451 IP6_STR
1452 "Filter Next Hop tracking route resolution\n"
1453 "Resolve via default route\n")
1454 {
1455
1456 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1457
1458 if (!zvrf)
1459 return CMD_WARNING;
1460
1461 if (!zvrf->zebra_rnh_ipv6_default_route)
1462 return CMD_SUCCESS;
1463
1464 zvrf->zebra_rnh_ipv6_default_route = 0;
1465 zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL);
1466 return CMD_SUCCESS;
1467 }
1468
1469 DEFPY (show_route,
1470 show_route_cmd,
1471 "show\
1472 <\
1473 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1474 [{\
1475 tag (1-4294967295)\
1476 |A.B.C.D/M$prefix longer-prefixes\
1477 |supernets-only$supernets_only\
1478 }]\
1479 [<\
1480 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1481 |ospf$type_str (1-65535)$ospf_instance_id\
1482 >]\
1483 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1484 [{\
1485 tag (1-4294967295)\
1486 |X:X::X:X/M$prefix longer-prefixes\
1487 }]\
1488 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1489 >\
1490 [json$json]",
1491 SHOW_STR
1492 IP_STR
1493 "IP forwarding table\n"
1494 "IP routing table\n"
1495 VRF_FULL_CMD_HELP_STR
1496 "Show only routes with tag\n"
1497 "Tag value\n"
1498 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1499 "Show route matching the specified Network/Mask pair only\n"
1500 "Show supernet entries only\n"
1501 FRR_IP_REDIST_HELP_STR_ZEBRA
1502 "Open Shortest Path First (OSPFv2)\n"
1503 "Instance ID\n"
1504 IPV6_STR
1505 "IP forwarding table\n"
1506 "IP routing table\n"
1507 VRF_FULL_CMD_HELP_STR
1508 "Show only routes with tag\n"
1509 "Tag value\n"
1510 "IPv6 prefix\n"
1511 "Show route matching the specified Network/Mask pair only\n"
1512 FRR_IP6_REDIST_HELP_STR_ZEBRA
1513 JSON_STR)
1514 {
1515 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1516 struct vrf *vrf;
1517 int type = 0;
1518
1519 if (type_str) {
1520 type = proto_redistnum(afi, type_str);
1521 if (type < 0) {
1522 vty_out(vty, "Unknown route type\n");
1523 return CMD_WARNING;
1524 }
1525 }
1526
1527 if (vrf_all) {
1528 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1529 struct zebra_vrf *zvrf;
1530 struct route_table *table;
1531
1532 if ((zvrf = vrf->info) == NULL
1533 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1534 continue;
1535
1536 do_show_ip_route(
1537 vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
1538 !!json, tag, prefix_str ? prefix : NULL,
1539 !!supernets_only, type, ospf_instance_id);
1540 }
1541 } else {
1542 vrf_id_t vrf_id = VRF_DEFAULT;
1543
1544 if (vrf_name)
1545 VRF_GET_ID(vrf_id, vrf_name, !!json);
1546 vrf = vrf_lookup_by_id(vrf_id);
1547 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
1548 !!json, tag, prefix_str ? prefix : NULL,
1549 !!supernets_only, type, ospf_instance_id);
1550 }
1551
1552 return CMD_SUCCESS;
1553 }
1554
1555 DEFPY (show_route_detail,
1556 show_route_detail_cmd,
1557 "show\
1558 <\
1559 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1560 <\
1561 A.B.C.D$address\
1562 |A.B.C.D/M$prefix\
1563 >\
1564 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1565 <\
1566 X:X::X:X$address\
1567 |X:X::X:X/M$prefix\
1568 >\
1569 >\
1570 [json$json] [nexthop-group$ng]",
1571 SHOW_STR
1572 IP_STR
1573 "IPv6 forwarding table\n"
1574 "IP routing table\n"
1575 VRF_FULL_CMD_HELP_STR
1576 "Network in the IP routing table to display\n"
1577 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1578 IP6_STR
1579 "IPv6 forwarding table\n"
1580 "IPv6 routing table\n"
1581 VRF_FULL_CMD_HELP_STR
1582 "IPv6 Address\n"
1583 "IPv6 prefix\n"
1584 JSON_STR
1585 "Nexthop Group Information\n")
1586 {
1587 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1588 struct route_table *table;
1589 struct prefix p;
1590 struct route_node *rn;
1591 bool use_fib = !!fib;
1592 rib_dest_t *dest;
1593 bool network_found = false;
1594 bool show_ng = !!ng;
1595
1596 if (address_str)
1597 prefix_str = address_str;
1598 if (str2prefix(prefix_str, &p) < 0) {
1599 vty_out(vty, "%% Malformed address\n");
1600 return CMD_WARNING;
1601 }
1602
1603 if (vrf_all) {
1604 struct vrf *vrf;
1605 struct zebra_vrf *zvrf;
1606
1607 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1608 if ((zvrf = vrf->info) == NULL
1609 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1610 continue;
1611
1612 rn = route_node_match(table, &p);
1613 if (!rn)
1614 continue;
1615 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1616 route_unlock_node(rn);
1617 continue;
1618 }
1619
1620 dest = rib_dest_from_rnode(rn);
1621 if (use_fib && !dest->selected_fib) {
1622 route_unlock_node(rn);
1623 continue;
1624 }
1625
1626 network_found = true;
1627 if (json)
1628 vty_show_ip_route_detail_json(vty, rn, use_fib);
1629 else
1630 vty_show_ip_route_detail(vty, rn, 0, use_fib,
1631 show_ng);
1632
1633 route_unlock_node(rn);
1634 }
1635
1636 if (!network_found) {
1637 if (json)
1638 vty_out(vty, "{}\n");
1639 else {
1640 if (use_fib)
1641 vty_out(vty,
1642 "%% Network not in FIB\n");
1643 else
1644 vty_out(vty,
1645 "%% Network not in RIB\n");
1646 }
1647 return CMD_WARNING;
1648 }
1649 } else {
1650 vrf_id_t vrf_id = VRF_DEFAULT;
1651
1652 if (vrf_name)
1653 VRF_GET_ID(vrf_id, vrf_name, false);
1654
1655 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1656 if (!table)
1657 return CMD_SUCCESS;
1658
1659 rn = route_node_match(table, &p);
1660 if (rn)
1661 dest = rib_dest_from_rnode(rn);
1662
1663 if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
1664 (use_fib && dest && !dest->selected_fib)) {
1665 if (json)
1666 vty_out(vty, "{}\n");
1667 else {
1668 if (use_fib)
1669 vty_out(vty,
1670 "%% Network not in FIB\n");
1671 else
1672 vty_out(vty,
1673 "%% Network not in table\n");
1674 }
1675 if (rn)
1676 route_unlock_node(rn);
1677 return CMD_WARNING;
1678 }
1679
1680 if (json)
1681 vty_show_ip_route_detail_json(vty, rn, use_fib);
1682 else
1683 vty_show_ip_route_detail(vty, rn, 0, use_fib, show_ng);
1684
1685 route_unlock_node(rn);
1686 }
1687
1688 return CMD_SUCCESS;
1689 }
1690
1691 DEFPY (show_route_summary,
1692 show_route_summary_cmd,
1693 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
1694 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
1695 SHOW_STR
1696 IP_STR
1697 IP6_STR
1698 "IP routing table\n"
1699 VRF_FULL_CMD_HELP_STR
1700 "Summary of all routes\n"
1701 "Table to display summary for\n"
1702 "The table number\n"
1703 "Prefix routes\n"
1704 JSON_STR)
1705 {
1706 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1707 struct route_table *table;
1708 bool uj = use_json(argc, argv);
1709
1710 if (table_id == 0)
1711 table_id = RT_TABLE_MAIN;
1712
1713 if (vrf_all) {
1714 struct vrf *vrf;
1715 struct zebra_vrf *zvrf;
1716
1717 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1718 if ((zvrf = vrf->info) == NULL)
1719 continue;
1720
1721 table = zebra_vrf_lookup_table_with_table_id(
1722 afi, SAFI_UNICAST, zvrf->vrf->vrf_id, table_id);
1723
1724 if (!table)
1725 continue;
1726
1727 if (prefix)
1728 vty_show_ip_route_summary_prefix(vty, table,
1729 uj);
1730 else
1731 vty_show_ip_route_summary(vty, table, uj);
1732 }
1733 } else {
1734 vrf_id_t vrf_id = VRF_DEFAULT;
1735
1736 if (vrf_name)
1737 VRF_GET_ID(vrf_id, vrf_name, false);
1738
1739 table = zebra_vrf_lookup_table_with_table_id(afi, SAFI_UNICAST,
1740 vrf_id, table_id);
1741 if (!table)
1742 return CMD_SUCCESS;
1743
1744 if (prefix)
1745 vty_show_ip_route_summary_prefix(vty, table, uj);
1746 else
1747 vty_show_ip_route_summary(vty, table, uj);
1748 }
1749
1750 return CMD_SUCCESS;
1751 }
1752
1753 static void vty_show_ip_route_summary(struct vty *vty,
1754 struct route_table *table, bool use_json)
1755 {
1756 struct route_node *rn;
1757 struct route_entry *re;
1758 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1759 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1760 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1761 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1762 uint32_t i;
1763 uint32_t is_ibgp;
1764 json_object *json_route_summary = NULL;
1765 json_object *json_route_routes = NULL;
1766
1767 memset(&rib_cnt, 0, sizeof(rib_cnt));
1768 memset(&fib_cnt, 0, sizeof(fib_cnt));
1769
1770 if (use_json) {
1771 json_route_summary = json_object_new_object();
1772 json_route_routes = json_object_new_array();
1773 json_object_object_add(json_route_summary, "routes",
1774 json_route_routes);
1775 }
1776
1777 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1778 RNODE_FOREACH_RE (rn, re) {
1779 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1780 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1781
1782 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1783 if (is_ibgp)
1784 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1785 else
1786 rib_cnt[re->type]++;
1787
1788 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
1789 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1790
1791 if (is_ibgp)
1792 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1793 else
1794 fib_cnt[re->type]++;
1795 }
1796 }
1797
1798 if (!use_json)
1799 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1800 "Routes", "FIB",
1801 zvrf_name(((rib_table_info_t *)route_table_get_info(
1802 table))
1803 ->zvrf));
1804
1805 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1806 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
1807 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
1808 if (i == ZEBRA_ROUTE_BGP) {
1809 if (use_json) {
1810 json_object *json_route_ebgp =
1811 json_object_new_object();
1812
1813 json_object_int_add(
1814 json_route_ebgp, "fib",
1815 fib_cnt[ZEBRA_ROUTE_BGP]);
1816 json_object_int_add(
1817 json_route_ebgp, "rib",
1818 rib_cnt[ZEBRA_ROUTE_BGP]);
1819 json_object_string_add(json_route_ebgp,
1820 "type", "ebgp");
1821 json_object_array_add(json_route_routes,
1822 json_route_ebgp);
1823
1824 json_object *json_route_ibgp =
1825 json_object_new_object();
1826
1827 json_object_int_add(
1828 json_route_ibgp, "fib",
1829 fib_cnt[ZEBRA_ROUTE_IBGP]);
1830 json_object_int_add(
1831 json_route_ibgp, "rib",
1832 rib_cnt[ZEBRA_ROUTE_IBGP]);
1833 json_object_string_add(json_route_ibgp,
1834 "type", "ibgp");
1835 json_object_array_add(json_route_routes,
1836 json_route_ibgp);
1837 } else {
1838 vty_out(vty, "%-20s %-20d %-20d \n",
1839 "ebgp",
1840 rib_cnt[ZEBRA_ROUTE_BGP],
1841 fib_cnt[ZEBRA_ROUTE_BGP]);
1842 vty_out(vty, "%-20s %-20d %-20d \n",
1843 "ibgp",
1844 rib_cnt[ZEBRA_ROUTE_IBGP],
1845 fib_cnt[ZEBRA_ROUTE_IBGP]);
1846 }
1847 } else {
1848 if (use_json) {
1849 json_object *json_route_type =
1850 json_object_new_object();
1851
1852 json_object_int_add(json_route_type,
1853 "fib", fib_cnt[i]);
1854 json_object_int_add(json_route_type,
1855 "rib", rib_cnt[i]);
1856 json_object_string_add(
1857 json_route_type, "type",
1858 zebra_route_string(i));
1859 json_object_array_add(json_route_routes,
1860 json_route_type);
1861 } else
1862 vty_out(vty, "%-20s %-20d %-20d \n",
1863 zebra_route_string(i),
1864 rib_cnt[i], fib_cnt[i]);
1865 }
1866 }
1867 }
1868
1869 if (use_json) {
1870 json_object_int_add(json_route_summary, "routesTotal",
1871 rib_cnt[ZEBRA_ROUTE_TOTAL]);
1872 json_object_int_add(json_route_summary, "routesTotalFib",
1873 fib_cnt[ZEBRA_ROUTE_TOTAL]);
1874
1875 vty_out(vty, "%s\n",
1876 json_object_to_json_string_ext(
1877 json_route_summary, JSON_C_TO_STRING_PRETTY));
1878 json_object_free(json_route_summary);
1879 } else {
1880 vty_out(vty, "------\n");
1881 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1882 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1883 vty_out(vty, "\n");
1884 }
1885 }
1886
1887 /*
1888 * Implementation of the ip route summary prefix command.
1889 *
1890 * This command prints the primary prefixes that have been installed by various
1891 * protocols on the box.
1892 *
1893 */
1894 static void vty_show_ip_route_summary_prefix(struct vty *vty,
1895 struct route_table *table,
1896 bool use_json)
1897 {
1898 struct route_node *rn;
1899 struct route_entry *re;
1900 struct nexthop *nexthop;
1901 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1902 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1903 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1904 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1905 uint32_t i;
1906 int cnt;
1907 json_object *json_route_summary = NULL;
1908 json_object *json_route_routes = NULL;
1909
1910 memset(&rib_cnt, 0, sizeof(rib_cnt));
1911 memset(&fib_cnt, 0, sizeof(fib_cnt));
1912
1913 if (use_json) {
1914 json_route_summary = json_object_new_object();
1915 json_route_routes = json_object_new_array();
1916 json_object_object_add(json_route_summary, "prefixRoutes",
1917 json_route_routes);
1918 }
1919
1920 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1921 RNODE_FOREACH_RE (rn, re) {
1922
1923 /*
1924 * In case of ECMP, count only once.
1925 */
1926 cnt = 0;
1927 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
1928 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1929 fib_cnt[re->type]++;
1930 }
1931 for (nexthop = re->nhe->nhg->nexthop; (!cnt && nexthop);
1932 nexthop = nexthop->next) {
1933 cnt++;
1934 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1935 rib_cnt[re->type]++;
1936 if (re->type == ZEBRA_ROUTE_BGP
1937 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
1938 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1939 if (CHECK_FLAG(re->status,
1940 ROUTE_ENTRY_INSTALLED))
1941 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1942 }
1943 }
1944 }
1945
1946 if (!use_json)
1947 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1948 "Prefix Routes", "FIB",
1949 zvrf_name(((rib_table_info_t *)route_table_get_info(
1950 table))
1951 ->zvrf));
1952
1953 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1954 if (rib_cnt[i] > 0) {
1955 if (i == ZEBRA_ROUTE_BGP) {
1956 if (use_json) {
1957 json_object *json_route_ebgp =
1958 json_object_new_object();
1959
1960 json_object_int_add(
1961 json_route_ebgp, "fib",
1962 fib_cnt[ZEBRA_ROUTE_BGP]
1963 - fib_cnt[ZEBRA_ROUTE_IBGP]);
1964 json_object_int_add(
1965 json_route_ebgp, "rib",
1966 rib_cnt[ZEBRA_ROUTE_BGP]
1967 - rib_cnt[ZEBRA_ROUTE_IBGP]);
1968 json_object_string_add(json_route_ebgp,
1969 "type", "ebgp");
1970 json_object_array_add(json_route_routes,
1971 json_route_ebgp);
1972
1973 json_object *json_route_ibgp =
1974 json_object_new_object();
1975
1976 json_object_int_add(
1977 json_route_ibgp, "fib",
1978 fib_cnt[ZEBRA_ROUTE_IBGP]);
1979 json_object_int_add(
1980 json_route_ibgp, "rib",
1981 rib_cnt[ZEBRA_ROUTE_IBGP]);
1982 json_object_string_add(json_route_ibgp,
1983 "type", "ibgp");
1984 json_object_array_add(json_route_routes,
1985 json_route_ibgp);
1986 } else {
1987 vty_out(vty, "%-20s %-20d %-20d \n",
1988 "ebgp",
1989 rib_cnt[ZEBRA_ROUTE_BGP]
1990 - rib_cnt[ZEBRA_ROUTE_IBGP],
1991 fib_cnt[ZEBRA_ROUTE_BGP]
1992 - fib_cnt[ZEBRA_ROUTE_IBGP]);
1993 vty_out(vty, "%-20s %-20d %-20d \n",
1994 "ibgp",
1995 rib_cnt[ZEBRA_ROUTE_IBGP],
1996 fib_cnt[ZEBRA_ROUTE_IBGP]);
1997 }
1998 } else {
1999 if (use_json) {
2000 json_object *json_route_type =
2001 json_object_new_object();
2002
2003 json_object_int_add(json_route_type,
2004 "fib", fib_cnt[i]);
2005 json_object_int_add(json_route_type,
2006 "rib", rib_cnt[i]);
2007 json_object_string_add(
2008 json_route_type, "type",
2009 zebra_route_string(i));
2010 json_object_array_add(json_route_routes,
2011 json_route_type);
2012 } else
2013 vty_out(vty, "%-20s %-20d %-20d \n",
2014 zebra_route_string(i),
2015 rib_cnt[i], fib_cnt[i]);
2016 }
2017 }
2018 }
2019
2020 if (use_json) {
2021 json_object_int_add(json_route_summary, "prefixRoutesTotal",
2022 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2023 json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
2024 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2025
2026 vty_out(vty, "%s\n",
2027 json_object_to_json_string_ext(
2028 json_route_summary, JSON_C_TO_STRING_PRETTY));
2029 json_object_free(json_route_summary);
2030 } else {
2031 vty_out(vty, "------\n");
2032 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2033 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2034 vty_out(vty, "\n");
2035 }
2036 }
2037
2038 /*
2039 * Show IPv6 mroute command.Used to dump
2040 * the Multicast routing table.
2041 */
2042 DEFUN (show_ipv6_mroute,
2043 show_ipv6_mroute_cmd,
2044 "show ipv6 mroute [vrf NAME]",
2045 SHOW_STR
2046 IP_STR
2047 "IPv6 Multicast routing table\n"
2048 VRF_CMD_HELP_STR)
2049 {
2050 struct route_table *table;
2051 struct route_node *rn;
2052 struct route_entry *re;
2053 int first = 1;
2054 vrf_id_t vrf_id = VRF_DEFAULT;
2055
2056 if (argc == 5)
2057 VRF_GET_ID(vrf_id, argv[4]->arg, false);
2058
2059 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2060 if (!table)
2061 return CMD_SUCCESS;
2062
2063 /* Show all IPv6 route. */
2064 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2065 RNODE_FOREACH_RE (rn, re) {
2066 if (first) {
2067 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2068 first = 0;
2069 }
2070 vty_show_ip_route(vty, rn, re, NULL, false);
2071 }
2072 return CMD_SUCCESS;
2073 }
2074
2075 DEFUN (show_ipv6_mroute_vrf_all,
2076 show_ipv6_mroute_vrf_all_cmd,
2077 "show ipv6 mroute vrf all",
2078 SHOW_STR
2079 IP_STR
2080 "IPv6 Multicast routing table\n"
2081 VRF_ALL_CMD_HELP_STR)
2082 {
2083 struct route_table *table;
2084 struct route_node *rn;
2085 struct route_entry *re;
2086 struct vrf *vrf;
2087 struct zebra_vrf *zvrf;
2088 int first = 1;
2089
2090 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2091 if ((zvrf = vrf->info) == NULL
2092 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2093 continue;
2094
2095 /* Show all IPv6 route. */
2096 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2097 RNODE_FOREACH_RE (rn, re) {
2098 if (first) {
2099 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2100 first = 0;
2101 }
2102 vty_show_ip_route(vty, rn, re, NULL, false);
2103 }
2104 }
2105 return CMD_SUCCESS;
2106 }
2107
2108 DEFUN (allow_external_route_update,
2109 allow_external_route_update_cmd,
2110 "allow-external-route-update",
2111 "Allow FRR routes to be overwritten by external processes\n")
2112 {
2113 allow_delete = 1;
2114
2115 return CMD_SUCCESS;
2116 }
2117
2118 DEFUN (no_allow_external_route_update,
2119 no_allow_external_route_update_cmd,
2120 "no allow-external-route-update",
2121 NO_STR
2122 "Allow FRR routes to be overwritten by external processes\n")
2123 {
2124 allow_delete = 0;
2125
2126 return CMD_SUCCESS;
2127 }
2128
2129 /* show vrf */
2130 DEFUN (show_vrf,
2131 show_vrf_cmd,
2132 "show vrf",
2133 SHOW_STR
2134 "VRF\n")
2135 {
2136 struct vrf *vrf;
2137 struct zebra_vrf *zvrf;
2138
2139 if (vrf_is_backend_netns())
2140 vty_out(vty, "netns-based vrfs\n");
2141
2142 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2143 if (!(zvrf = vrf->info))
2144 continue;
2145 if (zvrf_id(zvrf) == VRF_DEFAULT)
2146 continue;
2147
2148 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2149 if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2150 vty_out(vty, "inactive");
2151 else if (zvrf_ns_name(zvrf))
2152 vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2153 zvrf_ns_name(zvrf));
2154 else
2155 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2156 zvrf->table_id);
2157 if (vrf_is_user_cfged(vrf))
2158 vty_out(vty, " (configured)");
2159 vty_out(vty, "\n");
2160 }
2161
2162 return CMD_SUCCESS;
2163 }
2164
2165 DEFUN (default_vrf_vni_mapping,
2166 default_vrf_vni_mapping_cmd,
2167 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2168 "VNI corresponding to the DEFAULT VRF\n"
2169 "VNI-ID\n"
2170 "Prefix routes only \n")
2171 {
2172 int ret = 0;
2173 char err[ERR_STR_SZ];
2174 struct zebra_vrf *zvrf = NULL;
2175 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2176 int filter = 0;
2177
2178 zvrf = vrf_info_lookup(VRF_DEFAULT);
2179 if (!zvrf)
2180 return CMD_WARNING;
2181
2182 if (argc == 3)
2183 filter = 1;
2184
2185 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2186 filter, 1);
2187 if (ret != 0) {
2188 vty_out(vty, "%s\n", err);
2189 return CMD_WARNING;
2190 }
2191
2192 return CMD_SUCCESS;
2193 }
2194
2195 DEFUN (no_default_vrf_vni_mapping,
2196 no_default_vrf_vni_mapping_cmd,
2197 "no vni " CMD_VNI_RANGE,
2198 NO_STR
2199 "VNI corresponding to DEFAULT VRF\n"
2200 "VNI-ID")
2201 {
2202 int ret = 0;
2203 char err[ERR_STR_SZ];
2204 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2205 struct zebra_vrf *zvrf = NULL;
2206
2207 zvrf = vrf_info_lookup(VRF_DEFAULT);
2208 if (!zvrf)
2209 return CMD_WARNING;
2210
2211 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2212 if (ret != 0) {
2213 vty_out(vty, "%s\n", err);
2214 return CMD_WARNING;
2215 }
2216
2217 return CMD_SUCCESS;
2218 }
2219
2220 DEFUN (vrf_vni_mapping,
2221 vrf_vni_mapping_cmd,
2222 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2223 "VNI corresponding to tenant VRF\n"
2224 "VNI-ID\n"
2225 "prefix-routes-only\n")
2226 {
2227 int ret = 0;
2228 int filter = 0;
2229
2230 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2231 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2232 char err[ERR_STR_SZ];
2233
2234 assert(vrf);
2235 assert(zvrf);
2236
2237 if (argc == 3)
2238 filter = 1;
2239
2240 /* Mark as having FRR configuration */
2241 vrf_set_user_cfged(vrf);
2242 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2243 filter, 1);
2244 if (ret != 0) {
2245 vty_out(vty, "%s\n", err);
2246 return CMD_WARNING;
2247 }
2248
2249 return CMD_SUCCESS;
2250 }
2251
2252 DEFUN (no_vrf_vni_mapping,
2253 no_vrf_vni_mapping_cmd,
2254 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2255 NO_STR
2256 "VNI corresponding to tenant VRF\n"
2257 "VNI-ID\n"
2258 "prefix-routes-only\n")
2259 {
2260 int ret = 0;
2261 int filter = 0;
2262 char err[ERR_STR_SZ];
2263 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2264
2265 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2266
2267 assert(vrf);
2268 assert(zvrf);
2269
2270 if (argc == 4)
2271 filter = 1;
2272
2273 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err,
2274 ERR_STR_SZ, filter, 0);
2275 if (ret != 0) {
2276 vty_out(vty, "%s\n", err);
2277 return CMD_WARNING;
2278 }
2279
2280 /* If no other FRR config for this VRF, mark accordingly. */
2281 if (!zebra_vrf_has_config(zvrf))
2282 vrf_reset_user_cfged(vrf);
2283
2284 return CMD_SUCCESS;
2285 }
2286
2287 /* show vrf */
2288 DEFUN (show_vrf_vni,
2289 show_vrf_vni_cmd,
2290 "show vrf vni [json]",
2291 SHOW_STR
2292 "VRF\n"
2293 "VNI\n"
2294 JSON_STR)
2295 {
2296 struct vrf *vrf;
2297 struct zebra_vrf *zvrf;
2298 json_object *json = NULL;
2299 json_object *json_vrfs = NULL;
2300 bool uj = use_json(argc, argv);
2301
2302 if (uj) {
2303 json = json_object_new_object();
2304 json_vrfs = json_object_new_array();
2305 }
2306
2307 if (!uj)
2308 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2309 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2310
2311 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2312 zvrf = vrf->info;
2313 if (!zvrf)
2314 continue;
2315
2316 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2317 }
2318
2319 if (uj) {
2320 json_object_object_add(json, "vrfs", json_vrfs);
2321 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2322 json, JSON_C_TO_STRING_PRETTY));
2323 json_object_free(json);
2324 }
2325
2326 return CMD_SUCCESS;
2327 }
2328
2329 DEFUN (show_evpn_global,
2330 show_evpn_global_cmd,
2331 "show evpn [json]",
2332 SHOW_STR
2333 "EVPN\n"
2334 JSON_STR)
2335 {
2336 bool uj = use_json(argc, argv);
2337
2338 zebra_vxlan_print_evpn(vty, uj);
2339 return CMD_SUCCESS;
2340 }
2341
2342 DEFUN (show_evpn_vni,
2343 show_evpn_vni_cmd,
2344 "show evpn vni [json]",
2345 SHOW_STR
2346 "EVPN\n"
2347 "VxLAN Network Identifier\n"
2348 JSON_STR)
2349 {
2350 struct zebra_vrf *zvrf;
2351 bool uj = use_json(argc, argv);
2352
2353 zvrf = zebra_vrf_get_evpn();
2354 zebra_vxlan_print_vnis(vty, zvrf, uj);
2355 return CMD_SUCCESS;
2356 }
2357
2358 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
2359 "show evpn vni detail [json]",
2360 SHOW_STR
2361 "EVPN\n"
2362 "VxLAN Network Identifier\n"
2363 "Detailed Information On Each VNI\n"
2364 JSON_STR)
2365 {
2366 struct zebra_vrf *zvrf;
2367 bool uj = use_json(argc, argv);
2368
2369 zvrf = zebra_vrf_get_evpn();
2370 zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
2371 return CMD_SUCCESS;
2372 }
2373
2374 DEFUN (show_evpn_vni_vni,
2375 show_evpn_vni_vni_cmd,
2376 "show evpn vni " CMD_VNI_RANGE "[json]",
2377 SHOW_STR
2378 "EVPN\n"
2379 "VxLAN Network Identifier\n"
2380 "VNI number\n"
2381 JSON_STR)
2382 {
2383 struct zebra_vrf *zvrf;
2384 vni_t vni;
2385 bool uj = use_json(argc, argv);
2386
2387 vni = strtoul(argv[3]->arg, NULL, 10);
2388 zvrf = zebra_vrf_get_evpn();
2389 zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
2390 return CMD_SUCCESS;
2391 }
2392
2393 DEFUN (show_evpn_rmac_vni_mac,
2394 show_evpn_rmac_vni_mac_cmd,
2395 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
2396 SHOW_STR
2397 "EVPN\n"
2398 "RMAC\n"
2399 "L3 VNI\n"
2400 "VNI number\n"
2401 "MAC\n"
2402 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2403 JSON_STR)
2404 {
2405 vni_t l3vni = 0;
2406 struct ethaddr mac;
2407 bool uj = use_json(argc, argv);
2408
2409 l3vni = strtoul(argv[4]->arg, NULL, 10);
2410 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2411 vty_out(vty, "%% Malformed MAC address\n");
2412 return CMD_WARNING;
2413 }
2414 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
2415 return CMD_SUCCESS;
2416 }
2417
2418 DEFUN (show_evpn_rmac_vni,
2419 show_evpn_rmac_vni_cmd,
2420 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
2421 SHOW_STR
2422 "EVPN\n"
2423 "RMAC\n"
2424 "L3 VNI\n"
2425 "VNI number\n"
2426 JSON_STR)
2427 {
2428 vni_t l3vni = 0;
2429 bool uj = use_json(argc, argv);
2430
2431 l3vni = strtoul(argv[4]->arg, NULL, 10);
2432 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
2433
2434 return CMD_SUCCESS;
2435 }
2436
2437 DEFUN (show_evpn_rmac_vni_all,
2438 show_evpn_rmac_vni_all_cmd,
2439 "show evpn rmac vni all [json]",
2440 SHOW_STR
2441 "EVPN\n"
2442 "RMAC addresses\n"
2443 "L3 VNI\n"
2444 "All VNIs\n"
2445 JSON_STR)
2446 {
2447 bool uj = use_json(argc, argv);
2448
2449 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
2450
2451 return CMD_SUCCESS;
2452 }
2453
2454 DEFUN (show_evpn_nh_vni_ip,
2455 show_evpn_nh_vni_ip_cmd,
2456 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
2457 SHOW_STR
2458 "EVPN\n"
2459 "Remote Vteps\n"
2460 "L3 VNI\n"
2461 "VNI number\n"
2462 "Ip address\n"
2463 "Host address (ipv4 or ipv6)\n"
2464 JSON_STR)
2465 {
2466 vni_t l3vni;
2467 struct ipaddr ip;
2468 bool uj = use_json(argc, argv);
2469
2470 l3vni = strtoul(argv[4]->arg, NULL, 10);
2471 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2472 if (!uj)
2473 vty_out(vty, "%% Malformed Neighbor address\n");
2474 return CMD_WARNING;
2475 }
2476 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
2477
2478 return CMD_SUCCESS;
2479 }
2480
2481 DEFUN (show_evpn_nh_vni,
2482 show_evpn_nh_vni_cmd,
2483 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
2484 SHOW_STR
2485 "EVPN\n"
2486 "Remote Vteps\n"
2487 "L3 VNI\n"
2488 "VNI number\n"
2489 JSON_STR)
2490 {
2491 vni_t l3vni;
2492 bool uj = use_json(argc, argv);
2493
2494 l3vni = strtoul(argv[4]->arg, NULL, 10);
2495 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
2496
2497 return CMD_SUCCESS;
2498 }
2499
2500 DEFUN (show_evpn_nh_vni_all,
2501 show_evpn_nh_vni_all_cmd,
2502 "show evpn next-hops vni all [json]",
2503 SHOW_STR
2504 "EVPN\n"
2505 "Remote VTEPs\n"
2506 "L3 VNI\n"
2507 "All VNIs\n"
2508 JSON_STR)
2509 {
2510 bool uj = use_json(argc, argv);
2511
2512 zebra_vxlan_print_nh_all_l3vni(vty, uj);
2513
2514 return CMD_SUCCESS;
2515 }
2516
2517 DEFUN (show_evpn_mac_vni,
2518 show_evpn_mac_vni_cmd,
2519 "show evpn mac vni " CMD_VNI_RANGE "[json]",
2520 SHOW_STR
2521 "EVPN\n"
2522 "MAC addresses\n"
2523 "VxLAN Network Identifier\n"
2524 "VNI number\n"
2525 JSON_STR)
2526 {
2527 struct zebra_vrf *zvrf;
2528 vni_t vni;
2529 bool uj = use_json(argc, argv);
2530
2531 vni = strtoul(argv[4]->arg, NULL, 10);
2532 zvrf = zebra_vrf_get_evpn();
2533 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2534 return CMD_SUCCESS;
2535 }
2536
2537 DEFUN (show_evpn_mac_vni_all,
2538 show_evpn_mac_vni_all_cmd,
2539 "show evpn mac vni all [json]",
2540 SHOW_STR
2541 "EVPN\n"
2542 "MAC addresses\n"
2543 "VxLAN Network Identifier\n"
2544 "All VNIs\n"
2545 JSON_STR)
2546 {
2547 struct zebra_vrf *zvrf;
2548 bool uj = use_json(argc, argv);
2549
2550 zvrf = zebra_vrf_get_evpn();
2551 zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
2552 return CMD_SUCCESS;
2553 }
2554
2555 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
2556 "show evpn mac vni all detail [json]",
2557 SHOW_STR
2558 "EVPN\n"
2559 "MAC addresses\n"
2560 "VxLAN Network Identifier\n"
2561 "All VNIs\n"
2562 "Detailed Information On Each VNI MAC\n"
2563 JSON_STR)
2564 {
2565 struct zebra_vrf *zvrf;
2566 bool uj = use_json(argc, argv);
2567
2568 zvrf = zebra_vrf_get_evpn();
2569 zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
2570 return CMD_SUCCESS;
2571 }
2572
2573 DEFUN (show_evpn_mac_vni_all_vtep,
2574 show_evpn_mac_vni_all_vtep_cmd,
2575 "show evpn mac vni all vtep A.B.C.D [json]",
2576 SHOW_STR
2577 "EVPN\n"
2578 "MAC addresses\n"
2579 "VxLAN Network Identifier\n"
2580 "All VNIs\n"
2581 "Remote VTEP\n"
2582 "Remote VTEP IP address\n"
2583 JSON_STR)
2584 {
2585 struct zebra_vrf *zvrf;
2586 struct in_addr vtep_ip;
2587 bool uj = use_json(argc, argv);
2588
2589 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2590 if (!uj)
2591 vty_out(vty, "%% Malformed VTEP IP address\n");
2592 return CMD_WARNING;
2593 }
2594 zvrf = zebra_vrf_get_evpn();
2595 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2596
2597 return CMD_SUCCESS;
2598 }
2599
2600
2601 DEFUN (show_evpn_mac_vni_mac,
2602 show_evpn_mac_vni_mac_cmd,
2603 "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
2604 SHOW_STR
2605 "EVPN\n"
2606 "MAC addresses\n"
2607 "VxLAN Network Identifier\n"
2608 "VNI number\n"
2609 "MAC\n"
2610 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2611 JSON_STR)
2612
2613 {
2614 struct zebra_vrf *zvrf;
2615 vni_t vni;
2616 struct ethaddr mac;
2617 bool uj = use_json(argc, argv);
2618
2619 vni = strtoul(argv[4]->arg, NULL, 10);
2620 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2621 vty_out(vty, "%% Malformed MAC address");
2622 return CMD_WARNING;
2623 }
2624 zvrf = zebra_vrf_get_evpn();
2625 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
2626 return CMD_SUCCESS;
2627 }
2628
2629 DEFUN (show_evpn_mac_vni_vtep,
2630 show_evpn_mac_vni_vtep_cmd,
2631 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2632 SHOW_STR
2633 "EVPN\n"
2634 "MAC addresses\n"
2635 "VxLAN Network Identifier\n"
2636 "VNI number\n"
2637 "Remote VTEP\n"
2638 "Remote VTEP IP address\n"
2639 JSON_STR)
2640 {
2641 struct zebra_vrf *zvrf;
2642 vni_t vni;
2643 struct in_addr vtep_ip;
2644 bool uj = use_json(argc, argv);
2645
2646 vni = strtoul(argv[4]->arg, NULL, 10);
2647 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2648 if (!uj)
2649 vty_out(vty, "%% Malformed VTEP IP address\n");
2650 return CMD_WARNING;
2651 }
2652
2653 zvrf = zebra_vrf_get_evpn();
2654 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2655 return CMD_SUCCESS;
2656 }
2657
2658 DEFPY (show_evpn_mac_vni_all_dad,
2659 show_evpn_mac_vni_all_dad_cmd,
2660 "show evpn mac vni all duplicate [json]",
2661 SHOW_STR
2662 "EVPN\n"
2663 "MAC addresses\n"
2664 "VxLAN Network Identifier\n"
2665 "All VNIs\n"
2666 "Duplicate address list\n"
2667 JSON_STR)
2668 {
2669 struct zebra_vrf *zvrf;
2670 bool uj = use_json(argc, argv);
2671
2672 zvrf = zebra_vrf_get_evpn();
2673 zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
2674 return CMD_SUCCESS;
2675 }
2676
2677
2678 DEFPY (show_evpn_mac_vni_dad,
2679 show_evpn_mac_vni_dad_cmd,
2680 "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
2681 SHOW_STR
2682 "EVPN\n"
2683 "MAC addresses\n"
2684 "VxLAN Network Identifier\n"
2685 "VNI number\n"
2686 "Duplicate address list\n"
2687 JSON_STR)
2688 {
2689 struct zebra_vrf *zvrf;
2690 bool uj = use_json(argc, argv);
2691
2692 zvrf = zebra_vrf_get_evpn();
2693
2694 zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
2695
2696 return CMD_SUCCESS;
2697 }
2698
2699 DEFPY (show_evpn_neigh_vni_dad,
2700 show_evpn_neigh_vni_dad_cmd,
2701 "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
2702 SHOW_STR
2703 "EVPN\n"
2704 "ARP and ND cache\n"
2705 "VxLAN Network Identifier\n"
2706 "VNI number\n"
2707 "Duplicate address list\n"
2708 JSON_STR)
2709 {
2710 struct zebra_vrf *zvrf;
2711 bool uj = use_json(argc, argv);
2712
2713 zvrf = zebra_vrf_get_evpn();
2714 zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
2715 return CMD_SUCCESS;
2716 }
2717
2718 DEFPY (show_evpn_neigh_vni_all_dad,
2719 show_evpn_neigh_vni_all_dad_cmd,
2720 "show evpn arp-cache vni all duplicate [json]",
2721 SHOW_STR
2722 "EVPN\n"
2723 "ARP and ND cache\n"
2724 "VxLAN Network Identifier\n"
2725 "All VNIs\n"
2726 "Duplicate address list\n"
2727 JSON_STR)
2728 {
2729 struct zebra_vrf *zvrf;
2730 bool uj = use_json(argc, argv);
2731
2732 zvrf = zebra_vrf_get_evpn();
2733 zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
2734 return CMD_SUCCESS;
2735 }
2736
2737
2738 DEFUN (show_evpn_neigh_vni,
2739 show_evpn_neigh_vni_cmd,
2740 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
2741 SHOW_STR
2742 "EVPN\n"
2743 "ARP and ND cache\n"
2744 "VxLAN Network Identifier\n"
2745 "VNI number\n"
2746 JSON_STR)
2747 {
2748 struct zebra_vrf *zvrf;
2749 vni_t vni;
2750 bool uj = use_json(argc, argv);
2751
2752 vni = strtoul(argv[4]->arg, NULL, 10);
2753 zvrf = zebra_vrf_get_evpn();
2754 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
2755 return CMD_SUCCESS;
2756 }
2757
2758 DEFUN (show_evpn_neigh_vni_all,
2759 show_evpn_neigh_vni_all_cmd,
2760 "show evpn arp-cache vni all [json]",
2761 SHOW_STR
2762 "EVPN\n"
2763 "ARP and ND cache\n"
2764 "VxLAN Network Identifier\n"
2765 "All VNIs\n"
2766 JSON_STR)
2767 {
2768 struct zebra_vrf *zvrf;
2769 bool uj = use_json(argc, argv);
2770
2771 zvrf = zebra_vrf_get_evpn();
2772 zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
2773 return CMD_SUCCESS;
2774 }
2775
2776 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
2777 "show evpn arp-cache vni all detail [json]",
2778 SHOW_STR
2779 "EVPN\n"
2780 "ARP and ND cache\n"
2781 "VxLAN Network Identifier\n"
2782 "All VNIs\n"
2783 "Neighbor details for all vnis in detail\n" JSON_STR)
2784 {
2785 struct zebra_vrf *zvrf;
2786 bool uj = use_json(argc, argv);
2787
2788 zvrf = zebra_vrf_get_evpn();
2789 zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
2790 return CMD_SUCCESS;
2791 }
2792
2793 DEFUN (show_evpn_neigh_vni_neigh,
2794 show_evpn_neigh_vni_neigh_cmd,
2795 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
2796 SHOW_STR
2797 "EVPN\n"
2798 "ARP and ND cache\n"
2799 "VxLAN Network Identifier\n"
2800 "VNI number\n"
2801 "Neighbor\n"
2802 "Neighbor address (IPv4 or IPv6 address)\n"
2803 JSON_STR)
2804 {
2805 struct zebra_vrf *zvrf;
2806 vni_t vni;
2807 struct ipaddr ip;
2808 bool uj = use_json(argc, argv);
2809
2810 vni = strtoul(argv[4]->arg, NULL, 10);
2811 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2812 if (!uj)
2813 vty_out(vty, "%% Malformed Neighbor address\n");
2814 return CMD_WARNING;
2815 }
2816 zvrf = zebra_vrf_get_evpn();
2817 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
2818 return CMD_SUCCESS;
2819 }
2820
2821 DEFUN (show_evpn_neigh_vni_vtep,
2822 show_evpn_neigh_vni_vtep_cmd,
2823 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
2824 SHOW_STR
2825 "EVPN\n"
2826 "ARP and ND cache\n"
2827 "VxLAN Network Identifier\n"
2828 "VNI number\n"
2829 "Remote VTEP\n"
2830 "Remote VTEP IP address\n"
2831 JSON_STR)
2832 {
2833 struct zebra_vrf *zvrf;
2834 vni_t vni;
2835 struct in_addr vtep_ip;
2836 bool uj = use_json(argc, argv);
2837
2838 vni = strtoul(argv[4]->arg, NULL, 10);
2839 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2840 if (!uj)
2841 vty_out(vty, "%% Malformed VTEP IP address\n");
2842 return CMD_WARNING;
2843 }
2844
2845 zvrf = zebra_vrf_get_evpn();
2846 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2847 return CMD_SUCCESS;
2848 }
2849
2850 /* policy routing contexts */
2851 DEFUN (show_pbr_ipset,
2852 show_pbr_ipset_cmd,
2853 "show pbr ipset [WORD]",
2854 SHOW_STR
2855 "Policy-Based Routing\n"
2856 "IPset Context information\n"
2857 "IPset Name information\n")
2858 {
2859 int idx = 0;
2860 int found = 0;
2861 found = argv_find(argv, argc, "WORD", &idx);
2862 if (!found)
2863 zebra_pbr_show_ipset_list(vty, NULL);
2864 else
2865 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
2866 return CMD_SUCCESS;
2867 }
2868
2869 /* policy routing contexts */
2870 DEFUN (show_pbr_iptable,
2871 show_pbr_iptable_cmd,
2872 "show pbr iptable [WORD]",
2873 SHOW_STR
2874 "Policy-Based Routing\n"
2875 "IPtable Context information\n"
2876 "IPtable Name information\n")
2877 {
2878 int idx = 0;
2879 int found = 0;
2880
2881 found = argv_find(argv, argc, "WORD", &idx);
2882 if (!found)
2883 zebra_pbr_show_iptable(vty, NULL);
2884 else
2885 zebra_pbr_show_iptable(vty, argv[idx]->arg);
2886 return CMD_SUCCESS;
2887 }
2888
2889 DEFPY (clear_evpn_dup_addr,
2890 clear_evpn_dup_addr_cmd,
2891 "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>]>",
2892 CLEAR_STR
2893 "EVPN\n"
2894 "Duplicate address \n"
2895 "VxLAN Network Identifier\n"
2896 "VNI number\n"
2897 "All VNIs\n"
2898 "MAC\n"
2899 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2900 "IP\n"
2901 "IPv4 address\n"
2902 "IPv6 address\n")
2903 {
2904 struct zebra_vrf *zvrf;
2905 struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
2906 int ret = CMD_SUCCESS;
2907
2908 zvrf = zebra_vrf_get_evpn();
2909 if (vni_str) {
2910 if (!is_zero_mac(&mac->eth_addr)) {
2911 ret = zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf,
2912 vni,
2913 &mac->eth_addr);
2914 } else if (ip) {
2915 if (sockunion_family(ip) == AF_INET) {
2916 host_ip.ipa_type = IPADDR_V4;
2917 host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
2918 } else {
2919 host_ip.ipa_type = IPADDR_V6;
2920 memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
2921 sizeof(struct in6_addr));
2922 }
2923 ret = zebra_vxlan_clear_dup_detect_vni_ip(vty, zvrf,
2924 vni,
2925 &host_ip);
2926 } else
2927 ret = zebra_vxlan_clear_dup_detect_vni(vty, zvrf, vni);
2928
2929 } else {
2930 ret = zebra_vxlan_clear_dup_detect_vni_all(vty, zvrf);
2931 }
2932
2933 return ret;
2934 }
2935
2936 /* Static ip route configuration write function. */
2937 static int zebra_ip_config(struct vty *vty)
2938 {
2939 int write = 0;
2940
2941 write += zebra_import_table_config(vty, VRF_DEFAULT);
2942
2943 return write;
2944 }
2945
2946 DEFUN (ip_zebra_import_table_distance,
2947 ip_zebra_import_table_distance_cmd,
2948 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
2949 IP_STR
2950 "import routes from non-main kernel table\n"
2951 "kernel routing table id\n"
2952 "Distance for imported routes\n"
2953 "Default distance value\n"
2954 "route-map for filtering\n"
2955 "route-map name\n")
2956 {
2957 uint32_t table_id = 0;
2958
2959 table_id = strtoul(argv[2]->arg, NULL, 10);
2960 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
2961 char *rmap =
2962 strmatch(argv[argc - 2]->text, "route-map")
2963 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
2964 : NULL;
2965 int ret;
2966
2967 if (argc == 7 || (argc == 5 && !rmap))
2968 distance = strtoul(argv[4]->arg, NULL, 10);
2969
2970 if (!is_zebra_valid_kernel_table(table_id)) {
2971 vty_out(vty,
2972 "Invalid routing table ID, %d. Must be in range 1-252\n",
2973 table_id);
2974 if (rmap)
2975 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2976 return CMD_WARNING;
2977 }
2978
2979 if (is_zebra_main_routing_table(table_id)) {
2980 vty_out(vty,
2981 "Invalid routing table ID, %d. Must be non-default table\n",
2982 table_id);
2983 if (rmap)
2984 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2985 return CMD_WARNING;
2986 }
2987
2988 ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
2989 distance, rmap, 1);
2990 if (rmap)
2991 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2992
2993 return ret;
2994 }
2995
2996 DEFUN_HIDDEN (zebra_packet_process,
2997 zebra_packet_process_cmd,
2998 "zebra zapi-packets (1-10000)",
2999 ZEBRA_STR
3000 "Zapi Protocol\n"
3001 "Number of packets to process before relinquishing thread\n")
3002 {
3003 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3004
3005 atomic_store_explicit(&zrouter.packets_to_process, packets,
3006 memory_order_relaxed);
3007
3008 return CMD_SUCCESS;
3009 }
3010
3011 DEFUN_HIDDEN (no_zebra_packet_process,
3012 no_zebra_packet_process_cmd,
3013 "no zebra zapi-packets [(1-10000)]",
3014 NO_STR
3015 ZEBRA_STR
3016 "Zapi Protocol\n"
3017 "Number of packets to process before relinquishing thread\n")
3018 {
3019 atomic_store_explicit(&zrouter.packets_to_process,
3020 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3021 memory_order_relaxed);
3022
3023 return CMD_SUCCESS;
3024 }
3025
3026 DEFUN_HIDDEN (zebra_workqueue_timer,
3027 zebra_workqueue_timer_cmd,
3028 "zebra work-queue (0-10000)",
3029 ZEBRA_STR
3030 "Work Queue\n"
3031 "Time in milliseconds\n")
3032 {
3033 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3034 zrouter.ribq->spec.hold = timer;
3035
3036 return CMD_SUCCESS;
3037 }
3038
3039 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3040 no_zebra_workqueue_timer_cmd,
3041 "no zebra work-queue [(0-10000)]",
3042 NO_STR
3043 ZEBRA_STR
3044 "Work Queue\n"
3045 "Time in milliseconds\n")
3046 {
3047 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3048
3049 return CMD_SUCCESS;
3050 }
3051
3052 DEFUN (no_ip_zebra_import_table,
3053 no_ip_zebra_import_table_cmd,
3054 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3055 NO_STR
3056 IP_STR
3057 "import routes from non-main kernel table\n"
3058 "kernel routing table id\n"
3059 "Distance for imported routes\n"
3060 "Default distance value\n"
3061 "route-map for filtering\n"
3062 "route-map name\n")
3063 {
3064 uint32_t table_id = 0;
3065 table_id = strtoul(argv[3]->arg, NULL, 10);
3066
3067 if (!is_zebra_valid_kernel_table(table_id)) {
3068 vty_out(vty,
3069 "Invalid routing table ID. Must be in range 1-252\n");
3070 return CMD_WARNING;
3071 }
3072
3073 if (is_zebra_main_routing_table(table_id)) {
3074 vty_out(vty,
3075 "Invalid routing table ID, %d. Must be non-default table\n",
3076 table_id);
3077 return CMD_WARNING;
3078 }
3079
3080 if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3081 return CMD_SUCCESS;
3082
3083 return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3084 }
3085
3086 static int config_write_protocol(struct vty *vty)
3087 {
3088 if (allow_delete)
3089 vty_out(vty, "allow-external-route-update\n");
3090
3091 if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3092 vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3093
3094 if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3095 vty_out(vty, "zebra zapi-packets %u\n",
3096 zrouter.packets_to_process);
3097
3098 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3099
3100 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3101 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3102 ipv4_multicast_mode == MCAST_URIB_ONLY
3103 ? "urib-only"
3104 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3105 ? "mrib-only"
3106 : ipv4_multicast_mode
3107 == MCAST_MIX_MRIB_FIRST
3108 ? "mrib-then-urib"
3109 : ipv4_multicast_mode
3110 == MCAST_MIX_DISTANCE
3111 ? "lower-distance"
3112 : "longer-prefix");
3113
3114 /* Include dataplane info */
3115 dplane_config_write_helper(vty);
3116
3117 return 1;
3118 }
3119
3120 DEFUN (show_zebra,
3121 show_zebra_cmd,
3122 "show zebra",
3123 SHOW_STR
3124 ZEBRA_STR)
3125 {
3126 struct vrf *vrf;
3127
3128 vty_out(vty,
3129 " Route Route Neighbor LSP LSP\n");
3130 vty_out(vty,
3131 "VRF Installs Removals Updates Installs Removals\n");
3132
3133 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3134 struct zebra_vrf *zvrf = vrf->info;
3135
3136 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
3137 " %10" PRIu64 " %10" PRIu64 "\n",
3138 vrf->name, zvrf->installs, zvrf->removals,
3139 zvrf->neigh_updates, zvrf->lsp_installs,
3140 zvrf->lsp_removals);
3141 }
3142
3143 return CMD_SUCCESS;
3144 }
3145
3146 DEFUN (ip_forwarding,
3147 ip_forwarding_cmd,
3148 "ip forwarding",
3149 IP_STR
3150 "Turn on IP forwarding\n")
3151 {
3152 int ret;
3153
3154 ret = ipforward();
3155 if (ret == 0)
3156 ret = ipforward_on();
3157
3158 if (ret == 0) {
3159 vty_out(vty, "Can't turn on IP forwarding\n");
3160 return CMD_WARNING_CONFIG_FAILED;
3161 }
3162
3163 return CMD_SUCCESS;
3164 }
3165
3166 DEFUN (no_ip_forwarding,
3167 no_ip_forwarding_cmd,
3168 "no ip forwarding",
3169 NO_STR
3170 IP_STR
3171 "Turn off IP forwarding\n")
3172 {
3173 int ret;
3174
3175 ret = ipforward();
3176 if (ret != 0)
3177 ret = ipforward_off();
3178
3179 if (ret != 0) {
3180 vty_out(vty, "Can't turn off IP forwarding\n");
3181 return CMD_WARNING_CONFIG_FAILED;
3182 }
3183
3184 return CMD_SUCCESS;
3185 }
3186
3187 /* Only display ip forwarding is enabled or not. */
3188 DEFUN (show_ip_forwarding,
3189 show_ip_forwarding_cmd,
3190 "show ip forwarding",
3191 SHOW_STR
3192 IP_STR
3193 "IP forwarding status\n")
3194 {
3195 int ret;
3196
3197 ret = ipforward();
3198
3199 if (ret == 0)
3200 vty_out(vty, "IP forwarding is off\n");
3201 else
3202 vty_out(vty, "IP forwarding is on\n");
3203 return CMD_SUCCESS;
3204 }
3205
3206 /* Only display ipv6 forwarding is enabled or not. */
3207 DEFUN (show_ipv6_forwarding,
3208 show_ipv6_forwarding_cmd,
3209 "show ipv6 forwarding",
3210 SHOW_STR
3211 "IPv6 information\n"
3212 "Forwarding status\n")
3213 {
3214 int ret;
3215
3216 ret = ipforward_ipv6();
3217
3218 switch (ret) {
3219 case -1:
3220 vty_out(vty, "ipv6 forwarding is unknown\n");
3221 break;
3222 case 0:
3223 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3224 break;
3225 case 1:
3226 vty_out(vty, "ipv6 forwarding is %s\n", "on");
3227 break;
3228 default:
3229 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3230 break;
3231 }
3232 return CMD_SUCCESS;
3233 }
3234
3235 DEFUN (ipv6_forwarding,
3236 ipv6_forwarding_cmd,
3237 "ipv6 forwarding",
3238 IPV6_STR
3239 "Turn on IPv6 forwarding\n")
3240 {
3241 int ret;
3242
3243 ret = ipforward_ipv6();
3244 if (ret == 0)
3245 ret = ipforward_ipv6_on();
3246
3247 if (ret == 0) {
3248 vty_out(vty, "Can't turn on IPv6 forwarding\n");
3249 return CMD_WARNING_CONFIG_FAILED;
3250 }
3251
3252 return CMD_SUCCESS;
3253 }
3254
3255 DEFUN (no_ipv6_forwarding,
3256 no_ipv6_forwarding_cmd,
3257 "no ipv6 forwarding",
3258 NO_STR
3259 IPV6_STR
3260 "Turn off IPv6 forwarding\n")
3261 {
3262 int ret;
3263
3264 ret = ipforward_ipv6();
3265 if (ret != 0)
3266 ret = ipforward_ipv6_off();
3267
3268 if (ret != 0) {
3269 vty_out(vty, "Can't turn off IPv6 forwarding\n");
3270 return CMD_WARNING_CONFIG_FAILED;
3271 }
3272
3273 return CMD_SUCCESS;
3274 }
3275
3276 /* Display dataplane info */
3277 DEFUN (show_dataplane,
3278 show_dataplane_cmd,
3279 "show zebra dplane [detailed]",
3280 SHOW_STR
3281 ZEBRA_STR
3282 "Zebra dataplane information\n"
3283 "Detailed output\n")
3284 {
3285 int idx = 0;
3286 bool detailed = false;
3287
3288 if (argv_find(argv, argc, "detailed", &idx))
3289 detailed = true;
3290
3291 return dplane_show_helper(vty, detailed);
3292 }
3293
3294 /* Display dataplane providers info */
3295 DEFUN (show_dataplane_providers,
3296 show_dataplane_providers_cmd,
3297 "show zebra dplane providers [detailed]",
3298 SHOW_STR
3299 ZEBRA_STR
3300 "Zebra dataplane information\n"
3301 "Zebra dataplane provider information\n"
3302 "Detailed output\n")
3303 {
3304 int idx = 0;
3305 bool detailed = false;
3306
3307 if (argv_find(argv, argc, "detailed", &idx))
3308 detailed = true;
3309
3310 return dplane_show_provs_helper(vty, detailed);
3311 }
3312
3313 /* Configure dataplane incoming queue limit */
3314 DEFUN (zebra_dplane_queue_limit,
3315 zebra_dplane_queue_limit_cmd,
3316 "zebra dplane limit (0-10000)",
3317 ZEBRA_STR
3318 "Zebra dataplane\n"
3319 "Limit incoming queued updates\n"
3320 "Number of queued updates\n")
3321 {
3322 uint32_t limit = 0;
3323
3324 limit = strtoul(argv[3]->arg, NULL, 10);
3325
3326 dplane_set_in_queue_limit(limit, true);
3327
3328 return CMD_SUCCESS;
3329 }
3330
3331 /* Reset dataplane queue limit to default value */
3332 DEFUN (no_zebra_dplane_queue_limit,
3333 no_zebra_dplane_queue_limit_cmd,
3334 "no zebra dplane limit [(0-10000)]",
3335 NO_STR
3336 ZEBRA_STR
3337 "Zebra dataplane\n"
3338 "Limit incoming queued updates\n"
3339 "Number of queued updates\n")
3340 {
3341 dplane_set_in_queue_limit(0, false);
3342
3343 return CMD_SUCCESS;
3344 }
3345
3346 DEFUN (zebra_show_routing_tables_summary,
3347 zebra_show_routing_tables_summary_cmd,
3348 "show zebra router table summary",
3349 SHOW_STR
3350 ZEBRA_STR
3351 "The Zebra Router Information\n"
3352 "Table Information about this Zebra Router\n"
3353 "Summary Information\n")
3354 {
3355 zebra_router_show_table_summary(vty);
3356
3357 return CMD_SUCCESS;
3358 }
3359
3360 /* Table configuration write function. */
3361 static int config_write_table(struct vty *vty)
3362 {
3363 return 0;
3364 }
3365
3366 /* IPForwarding configuration write function. */
3367 static int config_write_forwarding(struct vty *vty)
3368 {
3369 /* FIXME: Find better place for that. */
3370 router_id_write(vty);
3371
3372 if (!ipforward())
3373 vty_out(vty, "no ip forwarding\n");
3374 if (!ipforward_ipv6())
3375 vty_out(vty, "no ipv6 forwarding\n");
3376 vty_out(vty, "!\n");
3377 return 0;
3378 }
3379
3380 DEFUN_HIDDEN (show_frr,
3381 show_frr_cmd,
3382 "show frr",
3383 SHOW_STR
3384 "FRR\n")
3385 {
3386 vty_out(vty, "........ .. . .. . ..... ...77:................................................\n");
3387 vty_out(vty, ".............................7777:..............................................\n");
3388 vty_out(vty, ".............................777777,............................................\n");
3389 vty_out(vty, "... .........................77777777,..........................................\n");
3390 vty_out(vty, "............................=7777777777:........................................\n");
3391 vty_out(vty, "........................:7777777777777777,......................................\n");
3392 vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
3393 vty_out(vty, "...................I7777777777+.................................................\n");
3394 vty_out(vty, "................,777777777?............ .......................................\n");
3395 vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
3396 vty_out(vty, ".............77777777~........=7777777777.......................................\n");
3397 vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
3398 vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
3399 vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
3400 vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
3401 vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
3402 vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
3403 vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
3404 vty_out(vty, "...~77777+.....7777777777777777=........................?777777...... .......\n");
3405 vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
3406 vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
3407 vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
3408 vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
3409 vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
3410 vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
3411 vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
3412 vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
3413 vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
3414 vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
3415 vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
3416 vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
3417 vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
3418 vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
3419 vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
3420 vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
3421 vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
3422 vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
3423 vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
3424 vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
3425 vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
3426 vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
3427 vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
3428 vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
3429 vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
3430 vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
3431 vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
3432 vty_out(vty, ".......................=77777777777777777............777777I....................\n");
3433 vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
3434 vty_out(vty, "............................~777777777777..............+777777..................\n");
3435 vty_out(vty, "................................~77777777...............=777777.................\n");
3436 vty_out(vty, ".....................................:=?I................~777777................\n");
3437 vty_out(vty, "..........................................................:777777,..............\n");
3438 vty_out(vty, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
3439
3440 return CMD_SUCCESS;
3441 }
3442
3443 /* IP node for static routes. */
3444 static struct cmd_node ip_node = {IP_NODE, "", 1};
3445 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
3446 /* table node for routing tables. */
3447 static struct cmd_node table_node = {TABLE_NODE,
3448 "", /* This node has no interface. */
3449 1};
3450 static struct cmd_node forwarding_node = {FORWARDING_NODE,
3451 "", /* This node has no interface. */
3452 1};
3453
3454 /* Route VTY. */
3455 void zebra_vty_init(void)
3456 {
3457 /* Install configuration write function. */
3458 install_node(&table_node, config_write_table);
3459 install_node(&forwarding_node, config_write_forwarding);
3460
3461 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3462 install_element(CONFIG_NODE, &ip_forwarding_cmd);
3463 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3464 install_element(ENABLE_NODE, &show_zebra_cmd);
3465
3466 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3467 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3468 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3469
3470 /* Route-map */
3471 zebra_route_map_init();
3472
3473 install_node(&ip_node, zebra_ip_config);
3474 install_node(&protocol_node, config_write_protocol);
3475
3476 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3477 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3478
3479 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3480 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3481
3482 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3483 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3484 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3485 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3486 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3487 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3488
3489 install_element(VIEW_NODE, &show_nexthop_group_cmd);
3490 install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
3491
3492 install_element(VIEW_NODE, &show_vrf_cmd);
3493 install_element(VIEW_NODE, &show_vrf_vni_cmd);
3494 install_element(VIEW_NODE, &show_route_cmd);
3495 install_element(VIEW_NODE, &show_route_table_cmd);
3496 if (vrf_is_backend_netns())
3497 install_element(VIEW_NODE, &show_route_table_vrf_cmd);
3498 install_element(VIEW_NODE, &show_route_all_table_vrf_cmd);
3499 install_element(VIEW_NODE, &show_route_detail_cmd);
3500 install_element(VIEW_NODE, &show_route_summary_cmd);
3501 install_element(VIEW_NODE, &show_ip_nht_cmd);
3502
3503 install_element(VIEW_NODE, &show_ip_rpf_cmd);
3504 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3505
3506 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3507 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3508 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3509 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3510 install_element(VRF_NODE, &ip_nht_default_route_cmd);
3511 install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
3512 install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
3513 install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
3514 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3515
3516 /* Commands for VRF */
3517 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3518
3519 install_element(VIEW_NODE, &show_frr_cmd);
3520 install_element(VIEW_NODE, &show_evpn_global_cmd);
3521 install_element(VIEW_NODE, &show_evpn_vni_cmd);
3522 install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
3523 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3524 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3525 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3526 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3527 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3528 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3529 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3530 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3531 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3532 install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
3533 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3534 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
3535 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
3536 install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
3537 install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
3538 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
3539 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
3540 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
3541 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
3542 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
3543 install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
3544 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
3545 install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
3546
3547 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
3548 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
3549
3550 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
3551 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
3552 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
3553 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
3554
3555 install_element(VIEW_NODE, &show_dataplane_cmd);
3556 install_element(VIEW_NODE, &show_dataplane_providers_cmd);
3557 install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
3558 install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
3559
3560 install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
3561 }