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