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