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