]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
Merge pull request #12511 from opensourcerouting/accords-color
[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,
634 nexthop->vrf_id));
635 break;
636 case NEXTHOP_TYPE_BLACKHOLE:
637 vty_out(vty, " unreachable");
638 switch (nexthop->bh_type) {
639 case BLACKHOLE_REJECT:
640 vty_out(vty, " (ICMP unreachable)");
641 break;
642 case BLACKHOLE_ADMINPROHIB:
643 vty_out(vty, " (ICMP admin-prohibited)");
644 break;
645 case BLACKHOLE_NULL:
646 vty_out(vty, " (blackhole)");
647 break;
648 case BLACKHOLE_UNSPEC:
649 break;
650 }
651 break;
652 }
653
654 if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
655 vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
656
657 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
658 vty_out(vty, " inactive");
659
660 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
661 vty_out(vty, " onlink");
662
663 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
664 vty_out(vty, " linkdown");
665
666 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
667 vty_out(vty, " (recursive)");
668
669 switch (nexthop->type) {
670 case NEXTHOP_TYPE_IPV4:
671 case NEXTHOP_TYPE_IPV4_IFINDEX:
672 if (nexthop->src.ipv4.s_addr) {
673 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
674 sizeof(buf)))
675 vty_out(vty, ", src %s", buf);
676 /* SR-TE information */
677 if (nexthop->srte_color)
678 vty_out(vty, ", SR-TE color %u",
679 nexthop->srte_color);
680 }
681 break;
682 case NEXTHOP_TYPE_IPV6:
683 case NEXTHOP_TYPE_IPV6_IFINDEX:
684 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
685 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
686 sizeof(buf)))
687 vty_out(vty, ", src %s", buf);
688 }
689 break;
690 default:
691 break;
692 }
693
694 /* Label information */
695 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
696 vty_out(vty, ", label %s",
697 mpls_label2str(nexthop->nh_label->num_labels,
698 nexthop->nh_label->label, buf,
699 sizeof(buf), 1));
700 }
701
702 if (nexthop->nh_srv6) {
703 seg6local_context2str(buf, sizeof(buf),
704 &nexthop->nh_srv6->seg6local_ctx,
705 nexthop->nh_srv6->seg6local_action);
706 vty_out(vty, ", seg6local %s %s", seg6local_action2str(
707 nexthop->nh_srv6->seg6local_action), buf);
708
709 inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf,
710 sizeof(buf));
711 vty_out(vty, ", seg6 %s", buf);
712 }
713
714 if (nexthop->weight)
715 vty_out(vty, ", weight %u", nexthop->weight);
716
717 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
718 vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
719
720 for (i = 1; i < nexthop->backup_num; i++)
721 vty_out(vty, ",%d", nexthop->backup_idx[i]);
722 }
723 }
724
725 /*
726 * Render a nexthop into a json object; the caller allocates and owns
727 * the json object memory.
728 */
729 static void show_nexthop_json_helper(json_object *json_nexthop,
730 const struct nexthop *nexthop,
731 const struct route_entry *re)
732 {
733 char buf[SRCDEST2STR_BUFFER];
734 json_object *json_labels = NULL;
735 json_object *json_backups = NULL;
736 json_object *json_seg6local = NULL;
737 json_object *json_seg6 = NULL;
738 int i;
739
740 json_object_int_add(json_nexthop, "flags",
741 nexthop->flags);
742
743 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
744 json_object_boolean_true_add(json_nexthop,
745 "duplicate");
746
747 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
748 json_object_boolean_true_add(json_nexthop,
749 "fib");
750
751 switch (nexthop->type) {
752 case NEXTHOP_TYPE_IPV4:
753 case NEXTHOP_TYPE_IPV4_IFINDEX:
754 json_object_string_addf(json_nexthop, "ip", "%pI4",
755 &nexthop->gate.ipv4);
756 json_object_string_add(json_nexthop, "afi",
757 "ipv4");
758
759 if (nexthop->ifindex) {
760 json_object_int_add(json_nexthop,
761 "interfaceIndex",
762 nexthop->ifindex);
763 json_object_string_add(
764 json_nexthop, "interfaceName",
765 ifindex2ifname(
766 nexthop->ifindex,
767 nexthop->vrf_id));
768 }
769 break;
770 case NEXTHOP_TYPE_IPV6:
771 case NEXTHOP_TYPE_IPV6_IFINDEX:
772 json_object_string_addf(json_nexthop, "ip", "%pI6",
773 &nexthop->gate.ipv6);
774 json_object_string_add(json_nexthop, "afi",
775 "ipv6");
776
777 if (nexthop->ifindex) {
778 json_object_int_add(json_nexthop,
779 "interfaceIndex",
780 nexthop->ifindex);
781 json_object_string_add(
782 json_nexthop, "interfaceName",
783 ifindex2ifname(
784 nexthop->ifindex,
785 nexthop->vrf_id));
786 }
787 break;
788
789 case NEXTHOP_TYPE_IFINDEX:
790 json_object_boolean_true_add(
791 json_nexthop, "directlyConnected");
792 json_object_int_add(json_nexthop,
793 "interfaceIndex",
794 nexthop->ifindex);
795 json_object_string_add(
796 json_nexthop, "interfaceName",
797 ifindex2ifname(nexthop->ifindex,
798 nexthop->vrf_id));
799 break;
800 case NEXTHOP_TYPE_BLACKHOLE:
801 json_object_boolean_true_add(json_nexthop,
802 "unreachable");
803 switch (nexthop->bh_type) {
804 case BLACKHOLE_REJECT:
805 json_object_boolean_true_add(
806 json_nexthop, "reject");
807 break;
808 case BLACKHOLE_ADMINPROHIB:
809 json_object_boolean_true_add(
810 json_nexthop,
811 "admin-prohibited");
812 break;
813 case BLACKHOLE_NULL:
814 json_object_boolean_true_add(
815 json_nexthop, "blackhole");
816 break;
817 case BLACKHOLE_UNSPEC:
818 break;
819 }
820 break;
821 }
822
823 /* This nexthop is a resolver for the parent nexthop.
824 * Set resolver flag for better clarity and delimiter
825 * in flat list of nexthops in json.
826 */
827 if (nexthop->rparent)
828 json_object_boolean_true_add(json_nexthop, "resolver");
829
830 if (nexthop->vrf_id != re->vrf_id)
831 json_object_string_add(json_nexthop, "vrf",
832 vrf_id_to_name(nexthop->vrf_id));
833
834 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
835 json_object_boolean_true_add(json_nexthop,
836 "duplicate");
837
838 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
839 json_object_boolean_true_add(json_nexthop,
840 "active");
841
842 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
843 json_object_boolean_true_add(json_nexthop,
844 "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 {
1484 struct nexthop *nexthop = NULL;
1485 struct nhg_connected *rb_node_dep = NULL;
1486 struct nexthop_group *backup_nhg;
1487 char up_str[MONOTIME_STRLEN];
1488 char time_left[MONOTIME_STRLEN];
1489
1490 uptime2str(nhe->uptime, up_str, sizeof(up_str));
1491
1492 vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type));
1493 vty_out(vty, " RefCnt: %u", nhe->refcnt);
1494 if (thread_is_scheduled(nhe->timer))
1495 vty_out(vty, " Time to Deletion: %s",
1496 thread_timer_to_hhmmss(time_left, sizeof(time_left),
1497 nhe->timer));
1498 vty_out(vty, "\n");
1499
1500 vty_out(vty, " Uptime: %s\n", up_str);
1501 vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
1502
1503
1504 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
1505 vty_out(vty, " Valid");
1506 if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED))
1507 vty_out(vty, ", Installed");
1508 vty_out(vty, "\n");
1509 }
1510 if (nhe->ifp)
1511 vty_out(vty, " Interface Index: %d\n", nhe->ifp->ifindex);
1512
1513 if (!zebra_nhg_depends_is_empty(nhe)) {
1514 vty_out(vty, " Depends:");
1515 frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
1516 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1517 }
1518 vty_out(vty, "\n");
1519 }
1520
1521 /* Output nexthops */
1522 for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
1523 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1524 vty_out(vty, " ");
1525 else
1526 /* Make recursive nexthops a bit more clear */
1527 vty_out(vty, " ");
1528
1529 show_route_nexthop_helper(vty, NULL, nexthop);
1530
1531 if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) {
1532 if (CHECK_FLAG(nexthop->flags,
1533 NEXTHOP_FLAG_HAS_BACKUP))
1534 vty_out(vty, " [backup %d]",
1535 nexthop->backup_idx[0]);
1536
1537 vty_out(vty, "\n");
1538 continue;
1539 }
1540
1541 /* TODO -- print more useful backup info */
1542 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
1543 int i;
1544
1545 vty_out(vty, "[backup");
1546 for (i = 0; i < nexthop->backup_num; i++)
1547 vty_out(vty, " %d", nexthop->backup_idx[i]);
1548
1549 vty_out(vty, "]");
1550 }
1551
1552 vty_out(vty, "\n");
1553 }
1554
1555 /* Output backup nexthops (if any) */
1556 backup_nhg = zebra_nhg_get_backup_nhg(nhe);
1557 if (backup_nhg) {
1558 vty_out(vty, " Backups:\n");
1559
1560 for (ALL_NEXTHOPS_PTR(backup_nhg, nexthop)) {
1561 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1562 vty_out(vty, " ");
1563 else
1564 /* Make recursive nexthops a bit more clear */
1565 vty_out(vty, " ");
1566
1567 show_route_nexthop_helper(vty, NULL, nexthop);
1568 vty_out(vty, "\n");
1569 }
1570 }
1571
1572 if (!zebra_nhg_dependents_is_empty(nhe)) {
1573 vty_out(vty, " Dependents:");
1574 frr_each(nhg_connected_tree, &nhe->nhg_dependents,
1575 rb_node_dep) {
1576 vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1577 }
1578 vty_out(vty, "\n");
1579 }
1580
1581 if (nhe->nhg.nhgr.buckets)
1582 vty_out(vty,
1583 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64 "\n",
1584 nhe->nhg.nhgr.buckets, nhe->nhg.nhgr.idle_timer,
1585 nhe->nhg.nhgr.unbalanced_timer,
1586 nhe->nhg.nhgr.unbalanced_time);
1587 }
1588
1589 static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id)
1590 {
1591 struct nhg_hash_entry *nhe = NULL;
1592
1593 nhe = zebra_nhg_lookup_id(id);
1594
1595 if (nhe)
1596 show_nexthop_group_out(vty, nhe);
1597 else {
1598 vty_out(vty, "Nexthop Group ID: %u does not exist\n", id);
1599 return CMD_WARNING;
1600 }
1601 return CMD_SUCCESS;
1602 }
1603
1604 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1605
1606 struct nhe_show_context {
1607 struct vty *vty;
1608 vrf_id_t vrf_id;
1609 afi_t afi;
1610 int type;
1611 };
1612
1613 static int nhe_show_walker(struct hash_bucket *bucket, void *arg)
1614 {
1615 struct nhe_show_context *ctx = arg;
1616 struct nhg_hash_entry *nhe;
1617
1618 nhe = bucket->data; /* We won't be offered NULL buckets */
1619
1620 if (ctx->afi && nhe->afi != ctx->afi)
1621 goto done;
1622
1623 if (ctx->vrf_id && nhe->vrf_id != ctx->vrf_id)
1624 goto done;
1625
1626 if (ctx->type && nhe->type != ctx->type)
1627 goto done;
1628
1629 show_nexthop_group_out(ctx->vty, nhe);
1630
1631 done:
1632 return HASHWALK_CONTINUE;
1633 }
1634
1635 static void show_nexthop_group_cmd_helper(struct vty *vty,
1636 struct zebra_vrf *zvrf, afi_t afi,
1637 int type)
1638 {
1639 struct nhe_show_context ctx;
1640
1641 ctx.vty = vty;
1642 ctx.afi = afi;
1643 ctx.vrf_id = zvrf->vrf->vrf_id;
1644 ctx.type = type;
1645
1646 hash_walk(zrouter.nhgs_id, nhe_show_walker, &ctx);
1647 }
1648
1649 static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
1650 {
1651 struct zebra_if *zebra_if = NULL;
1652 struct nhg_connected *rb_node_dep = NULL;
1653
1654 zebra_if = ifp->info;
1655
1656 if (!if_nhg_dependents_is_empty(ifp)) {
1657 vty_out(vty, "Interface %s:\n", ifp->name);
1658
1659 frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
1660 rb_node_dep) {
1661 vty_out(vty, " ");
1662 show_nexthop_group_out(vty, rb_node_dep->nhe);
1663 }
1664 }
1665 }
1666
1667 DEFPY (show_interface_nexthop_group,
1668 show_interface_nexthop_group_cmd,
1669 "show interface [IFNAME$if_name] nexthop-group",
1670 SHOW_STR
1671 "Interface status and configuration\n"
1672 "Interface name\n"
1673 "Show Nexthop Groups\n")
1674 {
1675 struct vrf *vrf = NULL;
1676 struct interface *ifp = NULL;
1677 bool found = false;
1678
1679 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1680 if (if_name) {
1681 ifp = if_lookup_by_name(if_name, vrf->vrf_id);
1682 if (ifp) {
1683 if_nexthop_group_dump_vty(vty, ifp);
1684 found = true;
1685 }
1686 } else {
1687 FOR_ALL_INTERFACES (vrf, ifp)
1688 if_nexthop_group_dump_vty(vty, ifp);
1689 found = true;
1690 }
1691 }
1692
1693 if (!found) {
1694 vty_out(vty, "%% Can't find interface %s\n", if_name);
1695 return CMD_WARNING;
1696 }
1697
1698 return CMD_SUCCESS;
1699 }
1700
1701 DEFPY (show_nexthop_group,
1702 show_nexthop_group_cmd,
1703 "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>]>",
1704 SHOW_STR
1705 "Show Nexthop Groups\n"
1706 "RIB information\n"
1707 "Nexthop Group ID\n"
1708 "Show Singleton Nexthop-Groups\n"
1709 IP_STR
1710 IP6_STR
1711 "Kernel (not installed via the zebra RIB)\n"
1712 "Zebra (implicitly created by zebra)\n"
1713 "Border Gateway Protocol (BGP)\n"
1714 "Super Happy Advanced Routing Protocol (SHARP)\n"
1715 VRF_FULL_CMD_HELP_STR)
1716 {
1717
1718 struct zebra_vrf *zvrf = NULL;
1719 afi_t afi = AFI_UNSPEC;
1720 int type = 0;
1721
1722 if (id)
1723 return show_nexthop_group_id_cmd_helper(vty, id);
1724
1725 if (v4)
1726 afi = AFI_IP;
1727 else if (v6)
1728 afi = AFI_IP6;
1729
1730 if (type_str) {
1731 type = proto_redistnum((afi ? afi : AFI_IP), type_str);
1732 if (type < 0) {
1733 /* assume zebra */
1734 type = ZEBRA_ROUTE_NHG;
1735 }
1736 }
1737
1738 if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1739 vty_out(vty,
1740 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1741 return CMD_WARNING;
1742 }
1743
1744 if (vrf_all) {
1745 struct vrf *vrf;
1746
1747 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1748 struct zebra_vrf *zvrf;
1749
1750 zvrf = vrf->info;
1751 if (!zvrf)
1752 continue;
1753
1754 vty_out(vty, "VRF: %s\n", vrf->name);
1755 show_nexthop_group_cmd_helper(vty, zvrf, afi, type);
1756 }
1757
1758 return CMD_SUCCESS;
1759 }
1760
1761 if (vrf_name)
1762 zvrf = zebra_vrf_lookup_by_name(vrf_name);
1763 else
1764 zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1765
1766 if (!zvrf) {
1767 vty_out(vty, "%% VRF '%s' specified does not exist\n",
1768 vrf_name);
1769 return CMD_WARNING;
1770 }
1771
1772 show_nexthop_group_cmd_helper(vty, zvrf, afi, type);
1773
1774 return CMD_SUCCESS;
1775 }
1776
1777 DEFPY_HIDDEN(nexthop_group_use_enable,
1778 nexthop_group_use_enable_cmd,
1779 "[no] zebra nexthop kernel enable",
1780 NO_STR
1781 ZEBRA_STR
1782 "Nexthop configuration \n"
1783 "Configure use of kernel nexthops\n"
1784 "Enable kernel nexthops\n")
1785 {
1786 zebra_nhg_enable_kernel_nexthops(!no);
1787 return CMD_SUCCESS;
1788 }
1789
1790 DEFPY_HIDDEN(proto_nexthop_group_only, proto_nexthop_group_only_cmd,
1791 "[no] zebra nexthop proto only",
1792 NO_STR ZEBRA_STR
1793 "Nexthop configuration\n"
1794 "Configure exclusive use of proto nexthops\n"
1795 "Only use proto nexthops\n")
1796 {
1797 zebra_nhg_set_proto_nexthops_only(!no);
1798 return CMD_SUCCESS;
1799 }
1800
1801 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable,
1802 backup_nexthop_recursive_use_enable_cmd,
1803 "[no] zebra nexthop resolve-via-backup",
1804 NO_STR
1805 ZEBRA_STR
1806 "Nexthop configuration \n"
1807 "Configure use of backup nexthops in recursive resolution\n")
1808 {
1809 zebra_nhg_set_recursive_use_backups(!no);
1810 return CMD_SUCCESS;
1811 }
1812
1813 DEFUN (no_ip_nht_default_route,
1814 no_ip_nht_default_route_cmd,
1815 "no ip nht resolve-via-default",
1816 NO_STR
1817 IP_STR
1818 "Filter Next Hop tracking route resolution\n"
1819 "Resolve via default route\n")
1820 {
1821 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1822
1823 if (!zvrf)
1824 return CMD_WARNING;
1825
1826 if (!zvrf->zebra_rnh_ip_default_route)
1827 return CMD_SUCCESS;
1828
1829 zvrf->zebra_rnh_ip_default_route = false;
1830 zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
1831 return CMD_SUCCESS;
1832 }
1833
1834 DEFUN (ipv6_nht_default_route,
1835 ipv6_nht_default_route_cmd,
1836 "ipv6 nht resolve-via-default",
1837 IP6_STR
1838 "Filter Next Hop tracking route resolution\n"
1839 "Resolve via default route\n")
1840 {
1841 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1842
1843 if (!zvrf)
1844 return CMD_WARNING;
1845
1846 if (zvrf->zebra_rnh_ipv6_default_route)
1847 return CMD_SUCCESS;
1848
1849 zvrf->zebra_rnh_ipv6_default_route = true;
1850 zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
1851 return CMD_SUCCESS;
1852 }
1853
1854 DEFUN (no_ipv6_nht_default_route,
1855 no_ipv6_nht_default_route_cmd,
1856 "no ipv6 nht resolve-via-default",
1857 NO_STR
1858 IP6_STR
1859 "Filter Next Hop tracking route resolution\n"
1860 "Resolve via default route\n")
1861 {
1862 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
1863
1864 if (!zvrf)
1865 return CMD_WARNING;
1866
1867 if (!zvrf->zebra_rnh_ipv6_default_route)
1868 return CMD_SUCCESS;
1869
1870 zvrf->zebra_rnh_ipv6_default_route = false;
1871 zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
1872 return CMD_SUCCESS;
1873 }
1874
1875 DEFPY_HIDDEN(rnh_hide_backups, rnh_hide_backups_cmd,
1876 "[no] ip nht hide-backup-events",
1877 NO_STR
1878 IP_STR
1879 "Nexthop-tracking configuration\n"
1880 "Hide notification about backup nexthops\n")
1881 {
1882 rnh_set_hide_backups(!no);
1883 return CMD_SUCCESS;
1884 }
1885
1886 DEFPY (show_route,
1887 show_route_cmd,
1888 "show\
1889 <\
1890 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1891 [vrf <NAME$vrf_name|all$vrf_all>]\
1892 [{\
1893 tag (1-4294967295)\
1894 |A.B.C.D/M$prefix longer-prefixes\
1895 |supernets-only$supernets_only\
1896 }]\
1897 [<\
1898 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1899 |ospf$type_str (1-65535)$ospf_instance_id\
1900 >]\
1901 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1902 [vrf <NAME$vrf_name|all$vrf_all>]\
1903 [{\
1904 tag (1-4294967295)\
1905 |X:X::X:X/M$prefix longer-prefixes\
1906 }]\
1907 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1908 >\
1909 [<json$json|nexthop-group$ng>]",
1910 SHOW_STR
1911 IP_STR
1912 "IP forwarding table\n"
1913 "IP routing table\n"
1914 "Table to display\n"
1915 "The table number to display\n"
1916 "All tables\n"
1917 VRF_FULL_CMD_HELP_STR
1918 "Show only routes with tag\n"
1919 "Tag value\n"
1920 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1921 "Show route matching the specified Network/Mask pair only\n"
1922 "Show supernet entries only\n"
1923 FRR_IP_REDIST_HELP_STR_ZEBRA
1924 "Open Shortest Path First (OSPFv2)\n"
1925 "Instance ID\n"
1926 IPV6_STR
1927 "IP forwarding table\n"
1928 "IP routing table\n"
1929 "Table to display\n"
1930 "The table number to display\n"
1931 "All tables\n"
1932 VRF_FULL_CMD_HELP_STR
1933 "Show only routes with tag\n"
1934 "Tag value\n"
1935 "IPv6 prefix\n"
1936 "Show route matching the specified Network/Mask pair only\n"
1937 FRR_IP6_REDIST_HELP_STR_ZEBRA
1938 JSON_STR
1939 "Nexthop Group Information\n")
1940 {
1941 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1942 struct vrf *vrf;
1943 int type = 0;
1944 struct zebra_vrf *zvrf;
1945 struct route_show_ctx ctx = {
1946 .multi = vrf_all || table_all,
1947 };
1948
1949 if (!vrf_is_backend_netns()) {
1950 if ((vrf_all || vrf_name) && (table || table_all)) {
1951 if (!!json)
1952 vty_out(vty, "{}\n");
1953 else {
1954 vty_out(vty, "Linux vrf backend already points to table id\n");
1955 vty_out(vty, "Either remove table parameter or vrf parameter\n");
1956 }
1957 return CMD_SUCCESS;
1958 }
1959 }
1960 if (type_str) {
1961 type = proto_redistnum(afi, type_str);
1962 if (type < 0) {
1963 vty_out(vty, "Unknown route type\n");
1964 return CMD_WARNING;
1965 }
1966 }
1967
1968 if (vrf_all) {
1969 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1970 if ((zvrf = vrf->info) == NULL
1971 || (zvrf->table[afi][SAFI_UNICAST] == NULL))
1972 continue;
1973
1974 if (table_all)
1975 do_show_ip_route_all(
1976 vty, zvrf, afi, !!fib, !!json, tag,
1977 prefix_str ? prefix : NULL,
1978 !!supernets_only, type,
1979 ospf_instance_id, !!ng, &ctx);
1980 else
1981 do_show_ip_route(
1982 vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
1983 !!fib, !!json, tag,
1984 prefix_str ? prefix : NULL,
1985 !!supernets_only, type,
1986 ospf_instance_id, table, !!ng, &ctx);
1987 }
1988 } else {
1989 vrf_id_t vrf_id = VRF_DEFAULT;
1990
1991 if (vrf_name)
1992 VRF_GET_ID(vrf_id, vrf_name, !!json);
1993 vrf = vrf_lookup_by_id(vrf_id);
1994 if (!vrf)
1995 return CMD_SUCCESS;
1996
1997 zvrf = vrf->info;
1998 if (!zvrf)
1999 return CMD_SUCCESS;
2000
2001 if (table_all)
2002 do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
2003 prefix_str ? prefix : NULL,
2004 !!supernets_only, type,
2005 ospf_instance_id, !!ng, &ctx);
2006 else
2007 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
2008 !!fib, !!json, tag,
2009 prefix_str ? prefix : NULL,
2010 !!supernets_only, type,
2011 ospf_instance_id, table, !!ng, &ctx);
2012 }
2013
2014 return CMD_SUCCESS;
2015 }
2016
2017 ALIAS_HIDDEN (show_route,
2018 show_ro_cmd,
2019 "show <ip$ipv4|ipv6$ipv6> ro",
2020 SHOW_STR
2021 IP_STR
2022 IPV6_STR
2023 "IP routing table\n");
2024
2025
2026 DEFPY (show_route_detail,
2027 show_route_detail_cmd,
2028 "show\
2029 <\
2030 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2031 <\
2032 A.B.C.D$address\
2033 |A.B.C.D/M$prefix\
2034 >\
2035 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2036 <\
2037 X:X::X:X$address\
2038 |X:X::X:X/M$prefix\
2039 >\
2040 >\
2041 [json$json] [nexthop-group$ng]",
2042 SHOW_STR
2043 IP_STR
2044 "IPv6 forwarding table\n"
2045 "IP routing table\n"
2046 VRF_FULL_CMD_HELP_STR
2047 "Network in the IP routing table to display\n"
2048 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2049 IP6_STR
2050 "IPv6 forwarding table\n"
2051 "IPv6 routing table\n"
2052 VRF_FULL_CMD_HELP_STR
2053 "IPv6 Address\n"
2054 "IPv6 prefix\n"
2055 JSON_STR
2056 "Nexthop Group Information\n")
2057 {
2058 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2059 struct route_table *table;
2060 struct prefix p;
2061 struct route_node *rn;
2062 bool use_fib = !!fib;
2063 rib_dest_t *dest;
2064 bool network_found = false;
2065 bool show_ng = !!ng;
2066
2067 if (address_str)
2068 prefix_str = address_str;
2069 if (str2prefix(prefix_str, &p) < 0) {
2070 vty_out(vty, "%% Malformed address\n");
2071 return CMD_WARNING;
2072 }
2073
2074 if (vrf_all) {
2075 struct vrf *vrf;
2076 struct zebra_vrf *zvrf;
2077
2078 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2079 if ((zvrf = vrf->info) == NULL
2080 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
2081 continue;
2082
2083 rn = route_node_match(table, &p);
2084 if (!rn)
2085 continue;
2086 if (!address_str && rn->p.prefixlen != p.prefixlen) {
2087 route_unlock_node(rn);
2088 continue;
2089 }
2090
2091 dest = rib_dest_from_rnode(rn);
2092 if (use_fib && !dest->selected_fib) {
2093 route_unlock_node(rn);
2094 continue;
2095 }
2096
2097 network_found = true;
2098 if (json)
2099 vty_show_ip_route_detail_json(vty, rn, use_fib);
2100 else
2101 vty_show_ip_route_detail(vty, rn, 0, use_fib,
2102 show_ng);
2103
2104 route_unlock_node(rn);
2105 }
2106
2107 if (!network_found) {
2108 if (json)
2109 vty_out(vty, "{}\n");
2110 else {
2111 if (use_fib)
2112 vty_out(vty,
2113 "%% Network not in FIB\n");
2114 else
2115 vty_out(vty,
2116 "%% Network not in RIB\n");
2117 }
2118 return CMD_WARNING;
2119 }
2120 } else {
2121 vrf_id_t vrf_id = VRF_DEFAULT;
2122
2123 if (vrf_name)
2124 VRF_GET_ID(vrf_id, vrf_name, false);
2125
2126 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2127 if (!table)
2128 return CMD_SUCCESS;
2129
2130 rn = route_node_match(table, &p);
2131 if (rn)
2132 dest = rib_dest_from_rnode(rn);
2133
2134 if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
2135 (use_fib && dest && !dest->selected_fib)) {
2136 if (json)
2137 vty_out(vty, "{}\n");
2138 else {
2139 if (use_fib)
2140 vty_out(vty,
2141 "%% Network not in FIB\n");
2142 else
2143 vty_out(vty,
2144 "%% Network not in table\n");
2145 }
2146 if (rn)
2147 route_unlock_node(rn);
2148 return CMD_WARNING;
2149 }
2150
2151 if (json)
2152 vty_show_ip_route_detail_json(vty, rn, use_fib);
2153 else
2154 vty_show_ip_route_detail(vty, rn, 0, use_fib, show_ng);
2155
2156 route_unlock_node(rn);
2157 }
2158
2159 return CMD_SUCCESS;
2160 }
2161
2162 DEFPY (show_route_summary,
2163 show_route_summary_cmd,
2164 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2165 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2166 SHOW_STR
2167 IP_STR
2168 IP6_STR
2169 "IP routing table\n"
2170 VRF_FULL_CMD_HELP_STR
2171 "Summary of all routes\n"
2172 "Table to display summary for\n"
2173 "The table number\n"
2174 "Prefix routes\n"
2175 JSON_STR)
2176 {
2177 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2178 struct route_table *table;
2179 bool uj = use_json(argc, argv);
2180
2181 if (vrf_all) {
2182 struct vrf *vrf;
2183 struct zebra_vrf *zvrf;
2184
2185 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2186 if ((zvrf = vrf->info) == NULL)
2187 continue;
2188
2189 if (table_id == 0)
2190 table = zebra_vrf_table(afi, SAFI_UNICAST,
2191 zvrf->vrf->vrf_id);
2192 else
2193 table = zebra_vrf_lookup_table_with_table_id(
2194 afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
2195 table_id);
2196
2197 if (!table)
2198 continue;
2199
2200 if (prefix)
2201 vty_show_ip_route_summary_prefix(vty, table,
2202 uj);
2203 else
2204 vty_show_ip_route_summary(vty, table, uj);
2205 }
2206 } else {
2207 vrf_id_t vrf_id = VRF_DEFAULT;
2208
2209 if (vrf_name)
2210 VRF_GET_ID(vrf_id, vrf_name, false);
2211
2212 if (table_id == 0)
2213 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2214 else
2215 table = zebra_vrf_lookup_table_with_table_id(
2216 afi, SAFI_UNICAST, vrf_id, table_id);
2217 if (!table)
2218 return CMD_SUCCESS;
2219
2220 if (prefix)
2221 vty_show_ip_route_summary_prefix(vty, table, uj);
2222 else
2223 vty_show_ip_route_summary(vty, table, uj);
2224 }
2225
2226 return CMD_SUCCESS;
2227 }
2228
2229 DEFUN_HIDDEN (show_route_zebra_dump,
2230 show_route_zebra_dump_cmd,
2231 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2232 SHOW_STR
2233 IP_STR
2234 IP6_STR
2235 "Zebra daemon\n"
2236 "Routing table\n"
2237 "All information\n"
2238 VRF_CMD_HELP_STR)
2239 {
2240 afi_t afi = AFI_IP;
2241 struct route_table *table;
2242 const char *vrf_name = NULL;
2243 int idx = 0;
2244
2245 afi = strmatch(argv[1]->text, "ipv6") ? AFI_IP6 : AFI_IP;
2246
2247 if (argv_find(argv, argc, "vrf", &idx))
2248 vrf_name = argv[++idx]->arg;
2249
2250 if (!vrf_name) {
2251 struct vrf *vrf;
2252 struct zebra_vrf *zvrf;
2253
2254 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2255 zvrf = vrf->info;
2256 if ((zvrf == NULL)
2257 || (zvrf->table[afi][SAFI_UNICAST] == NULL))
2258 continue;
2259
2260 table = zvrf->table[afi][SAFI_UNICAST];
2261 show_ip_route_dump_vty(vty, table);
2262 }
2263 } else {
2264 vrf_id_t vrf_id = VRF_DEFAULT;
2265
2266 VRF_GET_ID(vrf_id, vrf_name, true);
2267
2268 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2269 if (!table)
2270 return CMD_SUCCESS;
2271
2272 show_ip_route_dump_vty(vty, table);
2273 }
2274
2275 return CMD_SUCCESS;
2276 }
2277
2278 static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
2279 struct route_entry *re, unsigned int num)
2280 {
2281
2282 char buf[SRCDEST2STR_BUFFER];
2283
2284 vty_out(vty, " Nexthop %u:\n", num);
2285 vty_out(vty, " type: %u\n", nexthop->type);
2286 vty_out(vty, " flags: %u\n", nexthop->flags);
2287 switch (nexthop->type) {
2288 case NEXTHOP_TYPE_IPV4:
2289 case NEXTHOP_TYPE_IPV4_IFINDEX:
2290 vty_out(vty, " ip address: %s\n",
2291 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
2292 sizeof(buf)));
2293 vty_out(vty, " afi: ipv4\n");
2294
2295 if (nexthop->ifindex) {
2296 vty_out(vty, " interface index: %d\n",
2297 nexthop->ifindex);
2298 vty_out(vty, " interface name: %s\n",
2299 ifindex2ifname(nexthop->ifindex,
2300 nexthop->vrf_id));
2301 }
2302
2303 if (nexthop->src.ipv4.s_addr
2304 && (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
2305 sizeof(buf))))
2306 vty_out(vty, " source: %s\n", buf);
2307 break;
2308 case NEXTHOP_TYPE_IPV6:
2309 case NEXTHOP_TYPE_IPV6_IFINDEX:
2310 vty_out(vty, " ip: %s\n",
2311 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
2312 sizeof(buf)));
2313 vty_out(vty, " afi: ipv6\n");
2314
2315 if (nexthop->ifindex) {
2316 vty_out(vty, " interface index: %d\n",
2317 nexthop->ifindex);
2318 vty_out(vty, " interface name: %s\n",
2319 ifindex2ifname(nexthop->ifindex,
2320 nexthop->vrf_id));
2321 }
2322
2323 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
2324 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
2325 sizeof(buf)))
2326 vty_out(vty, " source: %s\n", buf);
2327 }
2328 break;
2329 case NEXTHOP_TYPE_IFINDEX:
2330 vty_out(vty,
2331 " Nexthop is an interface (directly connected).\n");
2332 vty_out(vty, " interface index: %d\n", nexthop->ifindex);
2333 vty_out(vty, " interface name: %s\n",
2334 ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
2335 break;
2336 case NEXTHOP_TYPE_BLACKHOLE:
2337 vty_out(vty, " Nexthop type is blackhole.\n");
2338
2339 switch (nexthop->bh_type) {
2340 case BLACKHOLE_REJECT:
2341 vty_out(vty, " Blackhole type: reject\n");
2342 break;
2343 case BLACKHOLE_ADMINPROHIB:
2344 vty_out(vty,
2345 " Blackhole type: admin-prohibited\n");
2346 break;
2347 case BLACKHOLE_NULL:
2348 vty_out(vty, " Blackhole type: NULL0\n");
2349 break;
2350 case BLACKHOLE_UNSPEC:
2351 break;
2352 }
2353 break;
2354 }
2355 }
2356
2357 static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
2358 {
2359 struct route_node *rn;
2360 struct route_entry *re;
2361 char buf[SRCDEST2STR_BUFFER];
2362 char time[20];
2363 time_t uptime;
2364 struct tm tm;
2365 struct timeval tv;
2366 struct nexthop *nexthop = NULL;
2367 int nexthop_num = 0;
2368
2369 vty_out(vty, "\nIPv4/IPv6 Routing table dump\n");
2370 vty_out(vty, "----------------------------\n");
2371
2372 for (rn = route_top(table); rn; rn = route_next(rn)) {
2373 RNODE_FOREACH_RE (rn, re) {
2374 vty_out(vty, "Route: %s\n",
2375 srcdest_rnode2str(rn, buf, sizeof(buf)));
2376 vty_out(vty, " protocol: %s\n",
2377 zebra_route_string(re->type));
2378 vty_out(vty, " instance: %u\n", re->instance);
2379 vty_out(vty, " VRF ID: %u\n", re->vrf_id);
2380 vty_out(vty, " VRF name: %s\n",
2381 vrf_id_to_name(re->vrf_id));
2382 vty_out(vty, " flags: %u\n", re->flags);
2383
2384 if (re->type != ZEBRA_ROUTE_CONNECT) {
2385 vty_out(vty, " distance: %u\n", re->distance);
2386 vty_out(vty, " metric: %u\n", re->metric);
2387 }
2388
2389 vty_out(vty, " tag: %u\n", re->tag);
2390
2391 uptime = monotime(&tv);
2392 uptime -= re->uptime;
2393 gmtime_r(&uptime, &tm);
2394
2395 if (uptime < ONE_DAY_SECOND)
2396 snprintf(time, sizeof(time), "%02d:%02d:%02d",
2397 tm.tm_hour, tm.tm_min, tm.tm_sec);
2398 else if (uptime < ONE_WEEK_SECOND)
2399 snprintf(time, sizeof(time), "%dd%02dh%02dm",
2400 tm.tm_yday, tm.tm_hour, tm.tm_min);
2401 else
2402 snprintf(time, sizeof(time), "%02dw%dd%02dh",
2403 tm.tm_yday / 7,
2404 tm.tm_yday - ((tm.tm_yday / 7) * 7),
2405 tm.tm_hour);
2406
2407 vty_out(vty, " status: %u\n", re->status);
2408 vty_out(vty, " nexthop_num: %u\n",
2409 nexthop_group_nexthop_num(&(re->nhe->nhg)));
2410 vty_out(vty, " nexthop_active_num: %u\n",
2411 nexthop_group_active_nexthop_num(
2412 &(re->nhe->nhg)));
2413 vty_out(vty, " table: %u\n", re->table);
2414 vty_out(vty, " uptime: %s\n", time);
2415
2416 for (ALL_NEXTHOPS_PTR(&(re->nhe->nhg), nexthop)) {
2417 nexthop_num++;
2418 show_ip_route_nht_dump(vty, nexthop, re,
2419 nexthop_num);
2420 }
2421
2422 nexthop_num = 0;
2423 vty_out(vty, "\n");
2424 }
2425 }
2426 }
2427
2428 static void vty_show_ip_route_summary(struct vty *vty,
2429 struct route_table *table, bool use_json)
2430 {
2431 struct route_node *rn;
2432 struct route_entry *re;
2433 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2434 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2435 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2436 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2437 uint32_t offload_cnt[ZEBRA_ROUTE_TOTAL + 1];
2438 uint32_t trap_cnt[ZEBRA_ROUTE_TOTAL + 1];
2439 uint32_t i;
2440 uint32_t is_ibgp;
2441 json_object *json_route_summary = NULL;
2442 json_object *json_route_routes = NULL;
2443
2444 memset(&rib_cnt, 0, sizeof(rib_cnt));
2445 memset(&fib_cnt, 0, sizeof(fib_cnt));
2446 memset(&offload_cnt, 0, sizeof(offload_cnt));
2447 memset(&trap_cnt, 0, sizeof(trap_cnt));
2448
2449 if (use_json) {
2450 json_route_summary = json_object_new_object();
2451 json_route_routes = json_object_new_array();
2452 json_object_object_add(json_route_summary, "routes",
2453 json_route_routes);
2454 }
2455
2456 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2457 RNODE_FOREACH_RE (rn, re) {
2458 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
2459 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
2460
2461 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2462 if (is_ibgp)
2463 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2464 else
2465 rib_cnt[re->type]++;
2466
2467 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
2468 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2469
2470 if (is_ibgp)
2471 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2472 else
2473 fib_cnt[re->type]++;
2474 }
2475
2476 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) {
2477 if (is_ibgp)
2478 trap_cnt[ZEBRA_ROUTE_IBGP]++;
2479 else
2480 trap_cnt[re->type]++;
2481 }
2482
2483 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) {
2484 if (is_ibgp)
2485 offload_cnt[ZEBRA_ROUTE_IBGP]++;
2486 else
2487 offload_cnt[re->type]++;
2488 }
2489 }
2490
2491 if (!use_json)
2492 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2493 "Routes", "FIB",
2494 zvrf_name(((struct rib_table_info *)
2495 route_table_get_info(table))
2496 ->zvrf));
2497
2498 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2499 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
2500 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
2501 if (i == ZEBRA_ROUTE_BGP) {
2502 if (use_json) {
2503 json_object *json_route_ebgp =
2504 json_object_new_object();
2505
2506 json_object_int_add(
2507 json_route_ebgp, "fib",
2508 fib_cnt[ZEBRA_ROUTE_BGP]);
2509 json_object_int_add(
2510 json_route_ebgp, "rib",
2511 rib_cnt[ZEBRA_ROUTE_BGP]);
2512 json_object_int_add(
2513 json_route_ebgp, "fibOffLoaded",
2514 offload_cnt[ZEBRA_ROUTE_BGP]);
2515 json_object_int_add(
2516 json_route_ebgp, "fibTrapped",
2517 trap_cnt[ZEBRA_ROUTE_BGP]);
2518
2519 json_object_string_add(json_route_ebgp,
2520 "type", "ebgp");
2521 json_object_array_add(json_route_routes,
2522 json_route_ebgp);
2523
2524 json_object *json_route_ibgp =
2525 json_object_new_object();
2526
2527 json_object_int_add(
2528 json_route_ibgp, "fib",
2529 fib_cnt[ZEBRA_ROUTE_IBGP]);
2530 json_object_int_add(
2531 json_route_ibgp, "rib",
2532 rib_cnt[ZEBRA_ROUTE_IBGP]);
2533 json_object_int_add(
2534 json_route_ibgp, "fibOffLoaded",
2535 offload_cnt[ZEBRA_ROUTE_IBGP]);
2536 json_object_int_add(
2537 json_route_ibgp, "fibTrapped",
2538 trap_cnt[ZEBRA_ROUTE_IBGP]);
2539 json_object_string_add(json_route_ibgp,
2540 "type", "ibgp");
2541 json_object_array_add(json_route_routes,
2542 json_route_ibgp);
2543 } else {
2544 vty_out(vty, "%-20s %-20d %-20d \n",
2545 "ebgp",
2546 rib_cnt[ZEBRA_ROUTE_BGP],
2547 fib_cnt[ZEBRA_ROUTE_BGP]);
2548 vty_out(vty, "%-20s %-20d %-20d \n",
2549 "ibgp",
2550 rib_cnt[ZEBRA_ROUTE_IBGP],
2551 fib_cnt[ZEBRA_ROUTE_IBGP]);
2552 }
2553 } else {
2554 if (use_json) {
2555 json_object *json_route_type =
2556 json_object_new_object();
2557
2558 json_object_int_add(json_route_type,
2559 "fib", fib_cnt[i]);
2560 json_object_int_add(json_route_type,
2561 "rib", rib_cnt[i]);
2562
2563 json_object_int_add(json_route_type,
2564 "fibOffLoaded",
2565 offload_cnt[i]);
2566 json_object_int_add(json_route_type,
2567 "fibTrapped",
2568 trap_cnt[i]);
2569 json_object_string_add(
2570 json_route_type, "type",
2571 zebra_route_string(i));
2572 json_object_array_add(json_route_routes,
2573 json_route_type);
2574 } else
2575 vty_out(vty, "%-20s %-20d %-20d \n",
2576 zebra_route_string(i),
2577 rib_cnt[i], fib_cnt[i]);
2578 }
2579 }
2580 }
2581
2582 if (use_json) {
2583 json_object_int_add(json_route_summary, "routesTotal",
2584 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2585 json_object_int_add(json_route_summary, "routesTotalFib",
2586 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2587
2588 vty_json(vty, json_route_summary);
2589 } else {
2590 vty_out(vty, "------\n");
2591 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2592 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2593 vty_out(vty, "\n");
2594 }
2595 }
2596
2597 /*
2598 * Implementation of the ip route summary prefix command.
2599 *
2600 * This command prints the primary prefixes that have been installed by various
2601 * protocols on the box.
2602 *
2603 */
2604 static void vty_show_ip_route_summary_prefix(struct vty *vty,
2605 struct route_table *table,
2606 bool use_json)
2607 {
2608 struct route_node *rn;
2609 struct route_entry *re;
2610 struct nexthop *nexthop;
2611 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2612 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2613 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2614 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2615 uint32_t i;
2616 int cnt;
2617 json_object *json_route_summary = NULL;
2618 json_object *json_route_routes = NULL;
2619
2620 memset(&rib_cnt, 0, sizeof(rib_cnt));
2621 memset(&fib_cnt, 0, sizeof(fib_cnt));
2622
2623 if (use_json) {
2624 json_route_summary = json_object_new_object();
2625 json_route_routes = json_object_new_array();
2626 json_object_object_add(json_route_summary, "prefixRoutes",
2627 json_route_routes);
2628 }
2629
2630 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2631 RNODE_FOREACH_RE (rn, re) {
2632
2633 /*
2634 * In case of ECMP, count only once.
2635 */
2636 cnt = 0;
2637 if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
2638 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2639 fib_cnt[re->type]++;
2640 }
2641 for (nexthop = re->nhe->nhg.nexthop; (!cnt && nexthop);
2642 nexthop = nexthop->next) {
2643 cnt++;
2644 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2645 rib_cnt[re->type]++;
2646 if (re->type == ZEBRA_ROUTE_BGP
2647 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
2648 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2649 if (CHECK_FLAG(re->status,
2650 ROUTE_ENTRY_INSTALLED))
2651 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2652 }
2653 }
2654 }
2655
2656 if (!use_json)
2657 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2658 "Prefix Routes", "FIB",
2659 zvrf_name(((struct rib_table_info *)
2660 route_table_get_info(table))
2661 ->zvrf));
2662
2663 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2664 if (rib_cnt[i] > 0) {
2665 if (i == ZEBRA_ROUTE_BGP) {
2666 if (use_json) {
2667 json_object *json_route_ebgp =
2668 json_object_new_object();
2669
2670 json_object_int_add(
2671 json_route_ebgp, "fib",
2672 fib_cnt[ZEBRA_ROUTE_BGP]
2673 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2674 json_object_int_add(
2675 json_route_ebgp, "rib",
2676 rib_cnt[ZEBRA_ROUTE_BGP]
2677 - rib_cnt[ZEBRA_ROUTE_IBGP]);
2678 json_object_string_add(json_route_ebgp,
2679 "type", "ebgp");
2680 json_object_array_add(json_route_routes,
2681 json_route_ebgp);
2682
2683 json_object *json_route_ibgp =
2684 json_object_new_object();
2685
2686 json_object_int_add(
2687 json_route_ibgp, "fib",
2688 fib_cnt[ZEBRA_ROUTE_IBGP]);
2689 json_object_int_add(
2690 json_route_ibgp, "rib",
2691 rib_cnt[ZEBRA_ROUTE_IBGP]);
2692 json_object_string_add(json_route_ibgp,
2693 "type", "ibgp");
2694 json_object_array_add(json_route_routes,
2695 json_route_ibgp);
2696 } else {
2697 vty_out(vty, "%-20s %-20d %-20d \n",
2698 "ebgp",
2699 rib_cnt[ZEBRA_ROUTE_BGP]
2700 - rib_cnt[ZEBRA_ROUTE_IBGP],
2701 fib_cnt[ZEBRA_ROUTE_BGP]
2702 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2703 vty_out(vty, "%-20s %-20d %-20d \n",
2704 "ibgp",
2705 rib_cnt[ZEBRA_ROUTE_IBGP],
2706 fib_cnt[ZEBRA_ROUTE_IBGP]);
2707 }
2708 } else {
2709 if (use_json) {
2710 json_object *json_route_type =
2711 json_object_new_object();
2712
2713 json_object_int_add(json_route_type,
2714 "fib", fib_cnt[i]);
2715 json_object_int_add(json_route_type,
2716 "rib", rib_cnt[i]);
2717 json_object_string_add(
2718 json_route_type, "type",
2719 zebra_route_string(i));
2720 json_object_array_add(json_route_routes,
2721 json_route_type);
2722 } else
2723 vty_out(vty, "%-20s %-20d %-20d \n",
2724 zebra_route_string(i),
2725 rib_cnt[i], fib_cnt[i]);
2726 }
2727 }
2728 }
2729
2730 if (use_json) {
2731 json_object_int_add(json_route_summary, "prefixRoutesTotal",
2732 rib_cnt[ZEBRA_ROUTE_TOTAL]);
2733 json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
2734 fib_cnt[ZEBRA_ROUTE_TOTAL]);
2735
2736 vty_json(vty, json_route_summary);
2737 } else {
2738 vty_out(vty, "------\n");
2739 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2740 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2741 vty_out(vty, "\n");
2742 }
2743 }
2744
2745 DEFUN (allow_external_route_update,
2746 allow_external_route_update_cmd,
2747 "allow-external-route-update",
2748 "Allow FRR routes to be overwritten by external processes\n")
2749 {
2750 zrouter.allow_delete = true;
2751
2752 return CMD_SUCCESS;
2753 }
2754
2755 DEFUN (no_allow_external_route_update,
2756 no_allow_external_route_update_cmd,
2757 "no allow-external-route-update",
2758 NO_STR
2759 "Allow FRR routes to be overwritten by external processes\n")
2760 {
2761 zrouter.allow_delete = false;
2762
2763 return CMD_SUCCESS;
2764 }
2765
2766 /* show vrf */
2767 DEFUN (show_vrf,
2768 show_vrf_cmd,
2769 "show vrf",
2770 SHOW_STR
2771 "VRF\n")
2772 {
2773 struct vrf *vrf;
2774 struct zebra_vrf *zvrf;
2775
2776 if (vrf_is_backend_netns())
2777 vty_out(vty, "netns-based vrfs\n");
2778
2779 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2780 if (!(zvrf = vrf->info))
2781 continue;
2782 if (zvrf_id(zvrf) == VRF_DEFAULT)
2783 continue;
2784
2785 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2786 if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2787 vty_out(vty, "inactive");
2788 else if (zvrf_ns_name(zvrf))
2789 vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2790 zvrf_ns_name(zvrf));
2791 else
2792 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2793 zvrf->table_id);
2794 if (vrf_is_user_cfged(vrf))
2795 vty_out(vty, " (configured)");
2796 vty_out(vty, "\n");
2797 }
2798
2799 return CMD_SUCCESS;
2800 }
2801
2802 DEFPY (evpn_mh_mac_holdtime,
2803 evpn_mh_mac_holdtime_cmd,
2804 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2805 NO_STR
2806 "EVPN\n"
2807 "Multihoming\n"
2808 "MAC hold time\n"
2809 "Duration in seconds\n")
2810 {
2811 return zebra_evpn_mh_mac_holdtime_update(vty, duration,
2812 no ? true : false);
2813 }
2814
2815 DEFPY (evpn_mh_neigh_holdtime,
2816 evpn_mh_neigh_holdtime_cmd,
2817 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2818 NO_STR
2819 "EVPN\n"
2820 "Multihoming\n"
2821 "Neighbor entry hold time\n"
2822 "Duration in seconds\n")
2823 {
2824
2825 return zebra_evpn_mh_neigh_holdtime_update(vty, duration,
2826 no ? true : false);
2827 }
2828
2829 DEFPY (evpn_mh_startup_delay,
2830 evpn_mh_startup_delay_cmd,
2831 "[no] evpn mh startup-delay(0-3600)$duration",
2832 NO_STR
2833 "EVPN\n"
2834 "Multihoming\n"
2835 "Startup delay\n"
2836 "duration in seconds\n")
2837 {
2838
2839 return zebra_evpn_mh_startup_delay_update(vty, duration,
2840 no ? true : false);
2841 }
2842
2843 DEFPY(evpn_mh_redirect_off, evpn_mh_redirect_off_cmd,
2844 "[no$no] evpn mh redirect-off",
2845 NO_STR
2846 "EVPN\n"
2847 "Multihoming\n"
2848 "ES bond redirect for fast-failover off\n")
2849 {
2850 bool redirect_off;
2851
2852 redirect_off = no ? false : true;
2853
2854 return zebra_evpn_mh_redirect_off(vty, redirect_off);
2855 }
2856
2857 DEFUN (default_vrf_vni_mapping,
2858 default_vrf_vni_mapping_cmd,
2859 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2860 "VNI corresponding to the DEFAULT VRF\n"
2861 "VNI-ID\n"
2862 "Prefix routes only \n")
2863 {
2864 char xpath[XPATH_MAXLEN];
2865 struct zebra_vrf *zvrf = NULL;
2866 int filter = 0;
2867
2868 zvrf = vrf_info_lookup(VRF_DEFAULT);
2869 if (!zvrf)
2870 return CMD_WARNING;
2871
2872 if (argc == 3)
2873 filter = 1;
2874
2875 snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
2876 VRF_DEFAULT_NAME);
2877 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
2878
2879 snprintf(xpath, sizeof(xpath),
2880 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
2881 VRF_DEFAULT_NAME);
2882 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[1]->arg);
2883
2884 if (filter) {
2885 snprintf(xpath, sizeof(xpath),
2886 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
2887 VRF_DEFAULT_NAME);
2888 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "true");
2889 }
2890
2891 return nb_cli_apply_changes(vty, NULL);
2892 }
2893
2894 DEFUN (no_default_vrf_vni_mapping,
2895 no_default_vrf_vni_mapping_cmd,
2896 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2897 NO_STR
2898 "VNI corresponding to DEFAULT VRF\n"
2899 "VNI-ID\n"
2900 "Prefix routes only \n")
2901 {
2902 char xpath[XPATH_MAXLEN];
2903 int filter = 0;
2904 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2905 struct zebra_vrf *zvrf = NULL;
2906
2907 zvrf = vrf_info_lookup(VRF_DEFAULT);
2908 if (!zvrf)
2909 return CMD_WARNING;
2910
2911 if (argc == 4)
2912 filter = 1;
2913
2914 if (zvrf->l3vni != vni) {
2915 vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
2916 zvrf->vrf->name);
2917 return CMD_WARNING;
2918 }
2919
2920 snprintf(xpath, sizeof(xpath),
2921 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/l3vni-id",
2922 VRF_DEFAULT_NAME);
2923 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, argv[2]->arg);
2924
2925 if (filter) {
2926 snprintf(xpath, sizeof(xpath),
2927 FRR_VRF_KEY_XPATH "/frr-zebra:zebra/prefix-only",
2928 VRF_DEFAULT_NAME);
2929 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, "true");
2930 }
2931
2932 snprintf(xpath, sizeof(xpath), FRR_VRF_KEY_XPATH "/frr-zebra:zebra",
2933 VRF_DEFAULT_NAME);
2934 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
2935
2936 return nb_cli_apply_changes(vty, NULL);
2937 }
2938
2939 DEFUN (vrf_vni_mapping,
2940 vrf_vni_mapping_cmd,
2941 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2942 "VNI corresponding to tenant VRF\n"
2943 "VNI-ID\n"
2944 "prefix-routes-only\n")
2945 {
2946 int filter = 0;
2947
2948 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
2949
2950 assert(vrf);
2951 assert(zvrf);
2952
2953 if (argc == 3)
2954 filter = 1;
2955
2956 nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_CREATE, NULL);
2957 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY,
2958 argv[1]->arg);
2959
2960 if (filter)
2961 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2962 NB_OP_MODIFY, "true");
2963
2964 return nb_cli_apply_changes(vty, NULL);
2965 }
2966
2967 DEFUN (no_vrf_vni_mapping,
2968 no_vrf_vni_mapping_cmd,
2969 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2970 NO_STR
2971 "VNI corresponding to tenant VRF\n"
2972 "VNI-ID\n"
2973 "prefix-routes-only\n")
2974 {
2975 int filter = 0;
2976
2977 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
2978 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2979
2980 assert(vrf);
2981 assert(zvrf);
2982
2983 if (argc == 4)
2984 filter = 1;
2985
2986 if (zvrf->l3vni != vni) {
2987 vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
2988 zvrf->vrf->name);
2989 return CMD_WARNING;
2990 }
2991
2992 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY,
2993 argv[2]->arg);
2994
2995 if (filter)
2996 nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2997 NB_OP_DESTROY, "true");
2998
2999 nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_DESTROY, NULL);
3000
3001 return nb_cli_apply_changes(vty, NULL);
3002 }
3003
3004 /* show vrf */
3005 DEFUN (show_vrf_vni,
3006 show_vrf_vni_cmd,
3007 "show vrf vni [json]",
3008 SHOW_STR
3009 "VRF\n"
3010 "VNI\n"
3011 JSON_STR)
3012 {
3013 struct vrf *vrf;
3014 struct zebra_vrf *zvrf;
3015 json_object *json = NULL;
3016 json_object *json_vrfs = NULL;
3017 bool uj = use_json(argc, argv);
3018
3019 if (uj) {
3020 json = json_object_new_object();
3021 json_vrfs = json_object_new_array();
3022 }
3023
3024 if (!uj)
3025 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3026 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3027
3028 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3029 zvrf = vrf->info;
3030 if (!zvrf)
3031 continue;
3032
3033 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
3034 }
3035
3036 if (uj) {
3037 json_object_object_add(json, "vrfs", json_vrfs);
3038 vty_json(vty, json);
3039 }
3040
3041 return CMD_SUCCESS;
3042 }
3043
3044 DEFUN (show_evpn_global,
3045 show_evpn_global_cmd,
3046 "show evpn [json]",
3047 SHOW_STR
3048 "EVPN\n"
3049 JSON_STR)
3050 {
3051 bool uj = use_json(argc, argv);
3052
3053 zebra_vxlan_print_evpn(vty, uj);
3054 return CMD_SUCCESS;
3055 }
3056
3057 DEFPY(show_evpn_neigh, show_neigh_cmd, "show ip neigh",
3058 SHOW_STR IP_STR "neighbors\n")
3059
3060 {
3061 zebra_neigh_show(vty);
3062
3063 return CMD_SUCCESS;
3064 }
3065
3066 DEFPY(show_evpn_l2_nh,
3067 show_evpn_l2_nh_cmd,
3068 "show evpn l2-nh [json$json]",
3069 SHOW_STR
3070 "EVPN\n"
3071 "Layer2 nexthops\n"
3072 JSON_STR)
3073 {
3074 bool uj = !!json;
3075
3076 zebra_evpn_l2_nh_show(vty, uj);
3077
3078 return CMD_SUCCESS;
3079 }
3080
3081 DEFPY(show_evpn_es,
3082 show_evpn_es_cmd,
3083 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3084 SHOW_STR
3085 "EVPN\n"
3086 "Ethernet Segment\n"
3087 "ES ID\n"
3088 "Detailed information\n"
3089 JSON_STR)
3090 {
3091 esi_t esi;
3092 bool uj = !!json;
3093
3094 if (esi_str) {
3095 if (!str_to_esi(esi_str, &esi)) {
3096 vty_out(vty, "%% Malformed ESI\n");
3097 return CMD_WARNING;
3098 }
3099 zebra_evpn_es_show_esi(vty, uj, &esi);
3100 } else {
3101 if (detail)
3102 zebra_evpn_es_show_detail(vty, uj);
3103 else
3104 zebra_evpn_es_show(vty, uj);
3105 }
3106
3107 return CMD_SUCCESS;
3108 }
3109
3110 DEFPY(show_evpn_es_evi,
3111 show_evpn_es_evi_cmd,
3112 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3113 SHOW_STR
3114 "EVPN\n"
3115 "Ethernet Segment per EVI\n"
3116 "VxLAN Network Identifier\n"
3117 "VNI\n"
3118 "Detailed information\n"
3119 JSON_STR)
3120 {
3121 bool uj = !!json;
3122 bool ud = !!detail;
3123
3124 if (vni)
3125 zebra_evpn_es_evi_show_vni(vty, uj, vni, ud);
3126 else
3127 zebra_evpn_es_evi_show(vty, uj, ud);
3128
3129 return CMD_SUCCESS;
3130 }
3131
3132 DEFPY(show_evpn_access_vlan,
3133 show_evpn_access_vlan_cmd,
3134 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3135 SHOW_STR
3136 "EVPN\n"
3137 "Access VLANs\n"
3138 "VLAN ID\n"
3139 "Detailed information\n"
3140 JSON_STR)
3141 {
3142 bool uj = !!json;
3143
3144 if (vid) {
3145 zebra_evpn_acc_vl_show_vid(vty, uj, vid);
3146 } else {
3147 if (detail)
3148 zebra_evpn_acc_vl_show_detail(vty, uj);
3149 else
3150 zebra_evpn_acc_vl_show(vty, uj);
3151 }
3152
3153 return CMD_SUCCESS;
3154 }
3155
3156 DEFUN (show_evpn_vni,
3157 show_evpn_vni_cmd,
3158 "show evpn vni [json]",
3159 SHOW_STR
3160 "EVPN\n"
3161 "VxLAN Network Identifier\n"
3162 JSON_STR)
3163 {
3164 struct zebra_vrf *zvrf;
3165 bool uj = use_json(argc, argv);
3166
3167 zvrf = zebra_vrf_get_evpn();
3168 zebra_vxlan_print_vnis(vty, zvrf, uj);
3169 return CMD_SUCCESS;
3170 }
3171
3172 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
3173 "show evpn vni detail [json]",
3174 SHOW_STR
3175 "EVPN\n"
3176 "VxLAN Network Identifier\n"
3177 "Detailed Information On Each VNI\n"
3178 JSON_STR)
3179 {
3180 struct zebra_vrf *zvrf;
3181 bool uj = use_json(argc, argv);
3182
3183 zvrf = zebra_vrf_get_evpn();
3184 zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
3185 return CMD_SUCCESS;
3186 }
3187
3188 DEFUN (show_evpn_vni_vni,
3189 show_evpn_vni_vni_cmd,
3190 "show evpn vni " CMD_VNI_RANGE "[json]",
3191 SHOW_STR
3192 "EVPN\n"
3193 "VxLAN Network Identifier\n"
3194 "VNI number\n"
3195 JSON_STR)
3196 {
3197 struct zebra_vrf *zvrf;
3198 vni_t vni;
3199 bool uj = use_json(argc, argv);
3200
3201 vni = strtoul(argv[3]->arg, NULL, 10);
3202 zvrf = zebra_vrf_get_evpn();
3203 zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
3204 return CMD_SUCCESS;
3205 }
3206
3207 DEFUN (show_evpn_rmac_vni_mac,
3208 show_evpn_rmac_vni_mac_cmd,
3209 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
3210 SHOW_STR
3211 "EVPN\n"
3212 "RMAC\n"
3213 "L3 VNI\n"
3214 "VNI number\n"
3215 "MAC\n"
3216 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3217 JSON_STR)
3218 {
3219 vni_t l3vni = 0;
3220 struct ethaddr mac;
3221 bool uj = use_json(argc, argv);
3222
3223 l3vni = strtoul(argv[4]->arg, NULL, 10);
3224 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3225 vty_out(vty, "%% Malformed MAC address\n");
3226 return CMD_WARNING;
3227 }
3228 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
3229 return CMD_SUCCESS;
3230 }
3231
3232 DEFUN (show_evpn_rmac_vni,
3233 show_evpn_rmac_vni_cmd,
3234 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
3235 SHOW_STR
3236 "EVPN\n"
3237 "RMAC\n"
3238 "L3 VNI\n"
3239 "VNI number\n"
3240 JSON_STR)
3241 {
3242 vni_t l3vni = 0;
3243 bool uj = use_json(argc, argv);
3244
3245 l3vni = strtoul(argv[4]->arg, NULL, 10);
3246 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
3247
3248 return CMD_SUCCESS;
3249 }
3250
3251 DEFUN (show_evpn_rmac_vni_all,
3252 show_evpn_rmac_vni_all_cmd,
3253 "show evpn rmac vni all [json]",
3254 SHOW_STR
3255 "EVPN\n"
3256 "RMAC addresses\n"
3257 "L3 VNI\n"
3258 "All VNIs\n"
3259 JSON_STR)
3260 {
3261 bool uj = use_json(argc, argv);
3262
3263 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
3264
3265 return CMD_SUCCESS;
3266 }
3267
3268 DEFUN (show_evpn_nh_vni_ip,
3269 show_evpn_nh_vni_ip_cmd,
3270 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
3271 SHOW_STR
3272 "EVPN\n"
3273 "Remote Vteps\n"
3274 "L3 VNI\n"
3275 "VNI number\n"
3276 "Ip address\n"
3277 "Host address (ipv4 or ipv6)\n"
3278 JSON_STR)
3279 {
3280 vni_t l3vni;
3281 struct ipaddr ip;
3282 bool uj = use_json(argc, argv);
3283
3284 l3vni = strtoul(argv[4]->arg, NULL, 10);
3285 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3286 if (!uj)
3287 vty_out(vty, "%% Malformed Neighbor address\n");
3288 return CMD_WARNING;
3289 }
3290 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
3291
3292 return CMD_SUCCESS;
3293 }
3294
3295 DEFUN (show_evpn_nh_vni,
3296 show_evpn_nh_vni_cmd,
3297 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
3298 SHOW_STR
3299 "EVPN\n"
3300 "Remote Vteps\n"
3301 "L3 VNI\n"
3302 "VNI number\n"
3303 JSON_STR)
3304 {
3305 vni_t l3vni;
3306 bool uj = use_json(argc, argv);
3307
3308 l3vni = strtoul(argv[4]->arg, NULL, 10);
3309 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
3310
3311 return CMD_SUCCESS;
3312 }
3313
3314 DEFUN (show_evpn_nh_vni_all,
3315 show_evpn_nh_vni_all_cmd,
3316 "show evpn next-hops vni all [json]",
3317 SHOW_STR
3318 "EVPN\n"
3319 "Remote VTEPs\n"
3320 "L3 VNI\n"
3321 "All VNIs\n"
3322 JSON_STR)
3323 {
3324 bool uj = use_json(argc, argv);
3325
3326 zebra_vxlan_print_nh_all_l3vni(vty, uj);
3327
3328 return CMD_SUCCESS;
3329 }
3330
3331 DEFUN (show_evpn_mac_vni,
3332 show_evpn_mac_vni_cmd,
3333 "show evpn mac vni " CMD_VNI_RANGE "[json]",
3334 SHOW_STR
3335 "EVPN\n"
3336 "MAC addresses\n"
3337 "VxLAN Network Identifier\n"
3338 "VNI number\n"
3339 JSON_STR)
3340 {
3341 struct zebra_vrf *zvrf;
3342 vni_t vni;
3343 bool uj = use_json(argc, argv);
3344
3345 vni = strtoul(argv[4]->arg, NULL, 10);
3346 zvrf = zebra_vrf_get_evpn();
3347 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
3348 return CMD_SUCCESS;
3349 }
3350
3351 DEFUN (show_evpn_mac_vni_all,
3352 show_evpn_mac_vni_all_cmd,
3353 "show evpn mac vni all [json]",
3354 SHOW_STR
3355 "EVPN\n"
3356 "MAC addresses\n"
3357 "VxLAN Network Identifier\n"
3358 "All VNIs\n"
3359 JSON_STR)
3360 {
3361 struct zebra_vrf *zvrf;
3362 bool uj = use_json(argc, argv);
3363
3364 zvrf = zebra_vrf_get_evpn();
3365 zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
3366 return CMD_SUCCESS;
3367 }
3368
3369 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
3370 "show evpn mac vni all detail [json]",
3371 SHOW_STR
3372 "EVPN\n"
3373 "MAC addresses\n"
3374 "VxLAN Network Identifier\n"
3375 "All VNIs\n"
3376 "Detailed Information On Each VNI MAC\n"
3377 JSON_STR)
3378 {
3379 struct zebra_vrf *zvrf;
3380 bool uj = use_json(argc, argv);
3381
3382 zvrf = zebra_vrf_get_evpn();
3383 zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
3384 return CMD_SUCCESS;
3385 }
3386
3387 DEFUN (show_evpn_mac_vni_all_vtep,
3388 show_evpn_mac_vni_all_vtep_cmd,
3389 "show evpn mac vni all vtep A.B.C.D [json]",
3390 SHOW_STR
3391 "EVPN\n"
3392 "MAC addresses\n"
3393 "VxLAN Network Identifier\n"
3394 "All VNIs\n"
3395 "Remote VTEP\n"
3396 "Remote VTEP IP address\n"
3397 JSON_STR)
3398 {
3399 struct zebra_vrf *zvrf;
3400 struct in_addr vtep_ip;
3401 bool uj = use_json(argc, argv);
3402
3403 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3404 if (!uj)
3405 vty_out(vty, "%% Malformed VTEP IP address\n");
3406 return CMD_WARNING;
3407 }
3408 zvrf = zebra_vrf_get_evpn();
3409 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
3410
3411 return CMD_SUCCESS;
3412 }
3413
3414
3415 DEFUN (show_evpn_mac_vni_mac,
3416 show_evpn_mac_vni_mac_cmd,
3417 "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
3418 SHOW_STR
3419 "EVPN\n"
3420 "MAC addresses\n"
3421 "VxLAN Network Identifier\n"
3422 "VNI number\n"
3423 "MAC\n"
3424 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3425 JSON_STR)
3426
3427 {
3428 struct zebra_vrf *zvrf;
3429 vni_t vni;
3430 struct ethaddr mac;
3431 bool uj = use_json(argc, argv);
3432
3433 vni = strtoul(argv[4]->arg, NULL, 10);
3434 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3435 vty_out(vty, "%% Malformed MAC address\n");
3436 return CMD_WARNING;
3437 }
3438 zvrf = zebra_vrf_get_evpn();
3439 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
3440 return CMD_SUCCESS;
3441 }
3442
3443 DEFUN (show_evpn_mac_vni_vtep,
3444 show_evpn_mac_vni_vtep_cmd,
3445 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
3446 SHOW_STR
3447 "EVPN\n"
3448 "MAC addresses\n"
3449 "VxLAN Network Identifier\n"
3450 "VNI number\n"
3451 "Remote VTEP\n"
3452 "Remote VTEP IP address\n"
3453 JSON_STR)
3454 {
3455 struct zebra_vrf *zvrf;
3456 vni_t vni;
3457 struct in_addr vtep_ip;
3458 bool uj = use_json(argc, argv);
3459
3460 vni = strtoul(argv[4]->arg, NULL, 10);
3461 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3462 if (!uj)
3463 vty_out(vty, "%% Malformed VTEP IP address\n");
3464 return CMD_WARNING;
3465 }
3466
3467 zvrf = zebra_vrf_get_evpn();
3468 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3469 return CMD_SUCCESS;
3470 }
3471
3472 DEFPY (show_evpn_mac_vni_all_dad,
3473 show_evpn_mac_vni_all_dad_cmd,
3474 "show evpn mac vni all duplicate [json]",
3475 SHOW_STR
3476 "EVPN\n"
3477 "MAC addresses\n"
3478 "VxLAN Network Identifier\n"
3479 "All VNIs\n"
3480 "Duplicate address list\n"
3481 JSON_STR)
3482 {
3483 struct zebra_vrf *zvrf;
3484 bool uj = use_json(argc, argv);
3485
3486 zvrf = zebra_vrf_get_evpn();
3487 zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
3488 return CMD_SUCCESS;
3489 }
3490
3491
3492 DEFPY (show_evpn_mac_vni_dad,
3493 show_evpn_mac_vni_dad_cmd,
3494 "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
3495 SHOW_STR
3496 "EVPN\n"
3497 "MAC addresses\n"
3498 "VxLAN Network Identifier\n"
3499 "VNI number\n"
3500 "Duplicate address list\n"
3501 JSON_STR)
3502 {
3503 struct zebra_vrf *zvrf;
3504 bool uj = use_json(argc, argv);
3505
3506 zvrf = zebra_vrf_get_evpn();
3507
3508 zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
3509
3510 return CMD_SUCCESS;
3511 }
3512
3513 DEFPY (show_evpn_neigh_vni_dad,
3514 show_evpn_neigh_vni_dad_cmd,
3515 "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
3516 SHOW_STR
3517 "EVPN\n"
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3520 "VNI number\n"
3521 "Duplicate address list\n"
3522 JSON_STR)
3523 {
3524 struct zebra_vrf *zvrf;
3525 bool uj = use_json(argc, argv);
3526
3527 zvrf = zebra_vrf_get_evpn();
3528 zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
3529 return CMD_SUCCESS;
3530 }
3531
3532 DEFPY (show_evpn_neigh_vni_all_dad,
3533 show_evpn_neigh_vni_all_dad_cmd,
3534 "show evpn arp-cache vni all duplicate [json]",
3535 SHOW_STR
3536 "EVPN\n"
3537 "ARP and ND cache\n"
3538 "VxLAN Network Identifier\n"
3539 "All VNIs\n"
3540 "Duplicate address list\n"
3541 JSON_STR)
3542 {
3543 struct zebra_vrf *zvrf;
3544 bool uj = use_json(argc, argv);
3545
3546 zvrf = zebra_vrf_get_evpn();
3547 zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
3548 return CMD_SUCCESS;
3549 }
3550
3551
3552 DEFUN (show_evpn_neigh_vni,
3553 show_evpn_neigh_vni_cmd,
3554 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
3555 SHOW_STR
3556 "EVPN\n"
3557 "ARP and ND cache\n"
3558 "VxLAN Network Identifier\n"
3559 "VNI number\n"
3560 JSON_STR)
3561 {
3562 struct zebra_vrf *zvrf;
3563 vni_t vni;
3564 bool uj = use_json(argc, argv);
3565
3566 vni = strtoul(argv[4]->arg, NULL, 10);
3567 zvrf = zebra_vrf_get_evpn();
3568 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
3569 return CMD_SUCCESS;
3570 }
3571
3572 DEFUN (show_evpn_neigh_vni_all,
3573 show_evpn_neigh_vni_all_cmd,
3574 "show evpn arp-cache vni all [json]",
3575 SHOW_STR
3576 "EVPN\n"
3577 "ARP and ND cache\n"
3578 "VxLAN Network Identifier\n"
3579 "All VNIs\n"
3580 JSON_STR)
3581 {
3582 struct zebra_vrf *zvrf;
3583 bool uj = use_json(argc, argv);
3584
3585 zvrf = zebra_vrf_get_evpn();
3586 zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
3587 return CMD_SUCCESS;
3588 }
3589
3590 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
3591 "show evpn arp-cache vni all detail [json]",
3592 SHOW_STR
3593 "EVPN\n"
3594 "ARP and ND cache\n"
3595 "VxLAN Network Identifier\n"
3596 "All VNIs\n"
3597 "Neighbor details for all vnis in detail\n" JSON_STR)
3598 {
3599 struct zebra_vrf *zvrf;
3600 bool uj = use_json(argc, argv);
3601
3602 zvrf = zebra_vrf_get_evpn();
3603 zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
3604 return CMD_SUCCESS;
3605 }
3606
3607 DEFUN (show_evpn_neigh_vni_neigh,
3608 show_evpn_neigh_vni_neigh_cmd,
3609 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
3610 SHOW_STR
3611 "EVPN\n"
3612 "ARP and ND cache\n"
3613 "VxLAN Network Identifier\n"
3614 "VNI number\n"
3615 "Neighbor\n"
3616 "Neighbor address (IPv4 or IPv6 address)\n"
3617 JSON_STR)
3618 {
3619 struct zebra_vrf *zvrf;
3620 vni_t vni;
3621 struct ipaddr ip;
3622 bool uj = use_json(argc, argv);
3623
3624 vni = strtoul(argv[4]->arg, NULL, 10);
3625 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3626 if (!uj)
3627 vty_out(vty, "%% Malformed Neighbor address\n");
3628 return CMD_WARNING;
3629 }
3630 zvrf = zebra_vrf_get_evpn();
3631 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
3632 return CMD_SUCCESS;
3633 }
3634
3635 DEFUN (show_evpn_neigh_vni_vtep,
3636 show_evpn_neigh_vni_vtep_cmd,
3637 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
3638 SHOW_STR
3639 "EVPN\n"
3640 "ARP and ND cache\n"
3641 "VxLAN Network Identifier\n"
3642 "VNI number\n"
3643 "Remote VTEP\n"
3644 "Remote VTEP IP address\n"
3645 JSON_STR)
3646 {
3647 struct zebra_vrf *zvrf;
3648 vni_t vni;
3649 struct in_addr vtep_ip;
3650 bool uj = use_json(argc, argv);
3651
3652 vni = strtoul(argv[4]->arg, NULL, 10);
3653 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3654 if (!uj)
3655 vty_out(vty, "%% Malformed VTEP IP address\n");
3656 return CMD_WARNING;
3657 }
3658
3659 zvrf = zebra_vrf_get_evpn();
3660 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3661 return CMD_SUCCESS;
3662 }
3663
3664 /* policy routing contexts */
3665 DEFUN (show_pbr_ipset,
3666 show_pbr_ipset_cmd,
3667 "show pbr ipset [WORD]",
3668 SHOW_STR
3669 "Policy-Based Routing\n"
3670 "IPset Context information\n"
3671 "IPset Name information\n")
3672 {
3673 int idx = 0;
3674 int found = 0;
3675 found = argv_find(argv, argc, "WORD", &idx);
3676 if (!found)
3677 zebra_pbr_show_ipset_list(vty, NULL);
3678 else
3679 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
3680 return CMD_SUCCESS;
3681 }
3682
3683 /* policy routing contexts */
3684 DEFUN (show_pbr_iptable,
3685 show_pbr_iptable_cmd,
3686 "show pbr iptable [WORD]",
3687 SHOW_STR
3688 "Policy-Based Routing\n"
3689 "IPtable Context information\n"
3690 "IPtable Name information\n")
3691 {
3692 int idx = 0;
3693 int found = 0;
3694
3695 found = argv_find(argv, argc, "WORD", &idx);
3696 if (!found)
3697 zebra_pbr_show_iptable(vty, NULL);
3698 else
3699 zebra_pbr_show_iptable(vty, argv[idx]->arg);
3700 return CMD_SUCCESS;
3701 }
3702
3703 /* policy routing contexts */
3704 DEFPY (show_pbr_rule,
3705 show_pbr_rule_cmd,
3706 "show pbr rule",
3707 SHOW_STR
3708 "Policy-Based Routing\n"
3709 "Rule\n")
3710 {
3711 zebra_pbr_show_rule(vty);
3712 return CMD_SUCCESS;
3713 }
3714
3715 DEFPY (pbr_nexthop_resolve,
3716 pbr_nexthop_resolve_cmd,
3717 "[no$no] pbr nexthop-resolve",
3718 NO_STR
3719 "Policy Based Routing\n"
3720 "Resolve nexthop for dataplane programming\n")
3721 {
3722 zebra_pbr_expand_action_update(!no);
3723 return CMD_SUCCESS;
3724 }
3725
3726 DEFPY (clear_evpn_dup_addr,
3727 clear_evpn_dup_addr_cmd,
3728 "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>]>",
3729 CLEAR_STR
3730 "EVPN\n"
3731 "Duplicate address \n"
3732 "VxLAN Network Identifier\n"
3733 "VNI number\n"
3734 "All VNIs\n"
3735 "MAC\n"
3736 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3737 "IP\n"
3738 "IPv4 address\n"
3739 "IPv6 address\n")
3740 {
3741 struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
3742 int ret = CMD_SUCCESS;
3743 struct list *input;
3744 struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
3745 *yang_dup_mac = NULL;
3746
3747 input = list_new();
3748
3749 if (!vni_str) {
3750 yang_dup = yang_data_new(
3751 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3752 "all-case");
3753 } else {
3754 yang_dup = yang_data_new_uint32(
3755 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3756 vni);
3757 if (!is_zero_mac(&mac->eth_addr)) {
3758 yang_dup_mac = yang_data_new_mac(
3759 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3760 &mac->eth_addr);
3761 if (yang_dup_mac)
3762 listnode_add(input, yang_dup_mac);
3763 } else if (ip) {
3764 if (sockunion_family(ip) == AF_INET) {
3765 host_ip.ipa_type = IPADDR_V4;
3766 host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
3767 } else {
3768 host_ip.ipa_type = IPADDR_V6;
3769 memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
3770 sizeof(struct in6_addr));
3771 }
3772
3773 yang_dup_ip = yang_data_new_ip(
3774 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3775 &host_ip);
3776
3777 if (yang_dup_ip)
3778 listnode_add(input, yang_dup_ip);
3779 }
3780 }
3781
3782 if (yang_dup) {
3783 listnode_add(input, yang_dup);
3784 ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input,
3785 NULL);
3786 }
3787
3788 list_delete(&input);
3789
3790 return ret;
3791 }
3792
3793 DEFPY_HIDDEN (evpn_accept_bgp_seq,
3794 evpn_accept_bgp_seq_cmd,
3795 "evpn accept-bgp-seq",
3796 "EVPN\n"
3797 "Accept all sequence numbers from BGP\n")
3798 {
3799 zebra_vxlan_set_accept_bgp_seq(true);
3800 return CMD_SUCCESS;
3801 }
3802
3803 DEFPY_HIDDEN (no_evpn_accept_bgp_seq,
3804 no_evpn_accept_bgp_seq_cmd,
3805 "no evpn accept-bgp-seq",
3806 NO_STR
3807 "EVPN\n"
3808 "Accept all sequence numbers from BGP\n")
3809 {
3810 zebra_vxlan_set_accept_bgp_seq(false);
3811 return CMD_SUCCESS;
3812 }
3813
3814 /* Static ip route configuration write function. */
3815 static int zebra_ip_config(struct vty *vty)
3816 {
3817 int write = 0;
3818
3819 write += zebra_import_table_config(vty, VRF_DEFAULT);
3820
3821 return write;
3822 }
3823
3824 DEFUN (ip_zebra_import_table_distance,
3825 ip_zebra_import_table_distance_cmd,
3826 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3827 IP_STR
3828 "import routes from non-main kernel table\n"
3829 "kernel routing table id\n"
3830 "Distance for imported routes\n"
3831 "Default distance value\n"
3832 "route-map for filtering\n"
3833 "route-map name\n")
3834 {
3835 uint32_t table_id = 0;
3836
3837 table_id = strtoul(argv[2]->arg, NULL, 10);
3838 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3839 char *rmap =
3840 strmatch(argv[argc - 2]->text, "route-map")
3841 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3842 : NULL;
3843 int ret;
3844
3845 if (argc == 7 || (argc == 5 && !rmap))
3846 distance = strtoul(argv[4]->arg, NULL, 10);
3847
3848 if (!is_zebra_valid_kernel_table(table_id)) {
3849 vty_out(vty,
3850 "Invalid routing table ID, %d. Must be in range 1-252\n",
3851 table_id);
3852 if (rmap)
3853 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3854 return CMD_WARNING;
3855 }
3856
3857 if (is_zebra_main_routing_table(table_id)) {
3858 vty_out(vty,
3859 "Invalid routing table ID, %d. Must be non-default table\n",
3860 table_id);
3861 if (rmap)
3862 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3863 return CMD_WARNING;
3864 }
3865
3866 ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
3867 distance, rmap, 1);
3868 if (rmap)
3869 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3870
3871 return ret;
3872 }
3873
3874 DEFUN_HIDDEN (zebra_packet_process,
3875 zebra_packet_process_cmd,
3876 "zebra zapi-packets (1-10000)",
3877 ZEBRA_STR
3878 "Zapi Protocol\n"
3879 "Number of packets to process before relinquishing thread\n")
3880 {
3881 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3882
3883 atomic_store_explicit(&zrouter.packets_to_process, packets,
3884 memory_order_relaxed);
3885
3886 return CMD_SUCCESS;
3887 }
3888
3889 DEFUN_HIDDEN (no_zebra_packet_process,
3890 no_zebra_packet_process_cmd,
3891 "no zebra zapi-packets [(1-10000)]",
3892 NO_STR
3893 ZEBRA_STR
3894 "Zapi Protocol\n"
3895 "Number of packets to process before relinquishing thread\n")
3896 {
3897 atomic_store_explicit(&zrouter.packets_to_process,
3898 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3899 memory_order_relaxed);
3900
3901 return CMD_SUCCESS;
3902 }
3903
3904 DEFUN_HIDDEN (zebra_workqueue_timer,
3905 zebra_workqueue_timer_cmd,
3906 "zebra work-queue (0-10000)",
3907 ZEBRA_STR
3908 "Work Queue\n"
3909 "Time in milliseconds\n")
3910 {
3911 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3912 zrouter.ribq->spec.hold = timer;
3913
3914 return CMD_SUCCESS;
3915 }
3916
3917 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3918 no_zebra_workqueue_timer_cmd,
3919 "no zebra work-queue [(0-10000)]",
3920 NO_STR
3921 ZEBRA_STR
3922 "Work Queue\n"
3923 "Time in milliseconds\n")
3924 {
3925 zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3926
3927 return CMD_SUCCESS;
3928 }
3929
3930 DEFUN (no_ip_zebra_import_table,
3931 no_ip_zebra_import_table_cmd,
3932 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3933 NO_STR
3934 IP_STR
3935 "import routes from non-main kernel table\n"
3936 "kernel routing table id\n"
3937 "Distance for imported routes\n"
3938 "Default distance value\n"
3939 "route-map for filtering\n"
3940 "route-map name\n")
3941 {
3942 uint32_t table_id = 0;
3943 table_id = strtoul(argv[3]->arg, NULL, 10);
3944
3945 if (!is_zebra_valid_kernel_table(table_id)) {
3946 vty_out(vty,
3947 "Invalid routing table ID. Must be in range 1-252\n");
3948 return CMD_WARNING;
3949 }
3950
3951 if (is_zebra_main_routing_table(table_id)) {
3952 vty_out(vty,
3953 "Invalid routing table ID, %d. Must be non-default table\n",
3954 table_id);
3955 return CMD_WARNING;
3956 }
3957
3958 if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3959 return CMD_SUCCESS;
3960
3961 return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3962 }
3963
3964 DEFPY (zebra_nexthop_group_keep,
3965 zebra_nexthop_group_keep_cmd,
3966 "[no] zebra nexthop-group keep (1-3600)",
3967 NO_STR
3968 ZEBRA_STR
3969 "Nexthop-Group\n"
3970 "How long to keep\n"
3971 "Time in seconds from 1-3600\n")
3972 {
3973 if (no)
3974 zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
3975 else
3976 zrouter.nhg_keep = keep;
3977
3978 return CMD_SUCCESS;
3979 }
3980
3981 static int config_write_protocol(struct vty *vty)
3982 {
3983 if (zrouter.allow_delete)
3984 vty_out(vty, "allow-external-route-update\n");
3985
3986 if (zrouter.nhg_keep != ZEBRA_DEFAULT_NHG_KEEP_TIMER)
3987 vty_out(vty, "zebra nexthop-group keep %u\n", zrouter.nhg_keep);
3988
3989 if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3990 vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3991
3992 if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3993 vty_out(vty, "zebra zapi-packets %u\n",
3994 zrouter.packets_to_process);
3995
3996 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3997
3998 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3999 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
4000 ipv4_multicast_mode == MCAST_URIB_ONLY
4001 ? "urib-only"
4002 : ipv4_multicast_mode == MCAST_MRIB_ONLY
4003 ? "mrib-only"
4004 : ipv4_multicast_mode
4005 == MCAST_MIX_MRIB_FIRST
4006 ? "mrib-then-urib"
4007 : ipv4_multicast_mode
4008 == MCAST_MIX_DISTANCE
4009 ? "lower-distance"
4010 : "longer-prefix");
4011
4012 /* Include dataplane info */
4013 dplane_config_write_helper(vty);
4014
4015 zebra_evpn_mh_config_write(vty);
4016
4017 zebra_pbr_config_write(vty);
4018
4019 if (!zebra_vxlan_get_accept_bgp_seq())
4020 vty_out(vty, "no evpn accept-bgp-seq\n");
4021
4022 /* Include nexthop-group config */
4023 if (!zebra_nhg_kernel_nexthops_enabled())
4024 vty_out(vty, "no zebra nexthop kernel enable\n");
4025
4026 if (zebra_nhg_proto_nexthops_only())
4027 vty_out(vty, "zebra nexthop proto only\n");
4028
4029 if (!zebra_nhg_recursive_use_backups())
4030 vty_out(vty, "no zebra nexthop resolve-via-backup\n");
4031
4032 if (rnh_get_hide_backups())
4033 vty_out(vty, "ip nht hide-backup-events\n");
4034
4035 #ifdef HAVE_NETLINK
4036 /* Include netlink info */
4037 netlink_config_write_helper(vty);
4038 #endif /* HAVE_NETLINK */
4039
4040 return 1;
4041 }
4042
4043 DEFUN (show_zebra,
4044 show_zebra_cmd,
4045 "show zebra",
4046 SHOW_STR
4047 ZEBRA_STR)
4048 {
4049 struct vrf *vrf;
4050 struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
4051 char *out;
4052
4053 ttable_rowseps(table, 0, BOTTOM, true, '-');
4054 ttable_add_row(table, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4055 ttable_add_row(table, "ECMP Maximum|%d", zrouter.multipath_num);
4056 ttable_add_row(table, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4057 ttable_add_row(table, "v6 Forwarding|%s",
4058 ipforward_ipv6() ? "On" : "Off");
4059 ttable_add_row(table, "MPLS|%s", mpls_enabled ? "On" : "Off");
4060 ttable_add_row(table, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4061 ttable_add_row(table, "Kernel socket buffer size|%d", rcvbufsize);
4062
4063
4064 #ifdef GNU_LINUX
4065 if (!vrf_is_backend_netns())
4066 ttable_add_row(table, "VRF|l3mdev Available");
4067 else
4068 ttable_add_row(table, "VRF|Namespaces");
4069 #else
4070 ttable_add_row(table, "VRF|Not Available");
4071 #endif
4072
4073 ttable_add_row(table, "ASIC offload|%s",
4074 zrouter.asic_offloaded ? "Used" : "Unavailable");
4075
4076 /*
4077 * Do not display this unless someone is actually using it
4078 *
4079 * Why this distinction? I think this is effectively dead code
4080 * and should not be exposed. Maybe someone proves me wrong.
4081 */
4082 if (zrouter.asic_notification_nexthop_control)
4083 ttable_add_row(table, "ASIC offload and nexthop control|Used");
4084
4085 ttable_add_row(table, "RA|%s",
4086 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4087 ttable_add_row(table, "RFC 5549|%s",
4088 rtadv_get_interfaces_configured_from_bgp()
4089 ? "BGP is using"
4090 : "BGP is not using");
4091
4092 ttable_add_row(table, "Kernel NHG|%s",
4093 zrouter.supports_nhgs ? "Available" : "Unavailable");
4094
4095 ttable_add_row(table, "Allow Non FRR route deletion|%s",
4096 zrouter.allow_delete ? "Yes" : "No");
4097 ttable_add_row(table, "v4 All LinkDown Routes|%s",
4098 zrouter.all_linkdownv4 ? "On" : "Off");
4099 ttable_add_row(table, "v4 Default LinkDown Routes|%s",
4100 zrouter.default_linkdownv4 ? "On" : "Off");
4101 ttable_add_row(table, "v6 All LinkDown Routes|%s",
4102 zrouter.all_linkdownv6 ? "On" : "Off");
4103 ttable_add_row(table, "v6 Default LinkDown Routes|%s",
4104 zrouter.default_linkdownv6 ? "On" : "Off");
4105
4106 ttable_add_row(table, "v4 All MC Forwarding|%s",
4107 zrouter.all_mc_forwardingv4 ? "On" : "Off");
4108 ttable_add_row(table, "v4 Default MC Forwarding|%s",
4109 zrouter.default_mc_forwardingv4 ? "On" : "Off");
4110 ttable_add_row(table, "v6 All MC Forwarding|%s",
4111 zrouter.all_mc_forwardingv6 ? "On" : "Off");
4112 ttable_add_row(table, "v6 Default MC Forwarding|%s",
4113 zrouter.default_mc_forwardingv6 ? "On" : "Off");
4114
4115 out = ttable_dump(table, "\n");
4116 vty_out(vty, "%s\n", out);
4117 XFREE(MTYPE_TMP, out);
4118
4119 ttable_del(table);
4120 vty_out(vty,
4121 " Route Route Neighbor LSP LSP\n");
4122 vty_out(vty,
4123 "VRF Installs Removals Updates Installs Removals\n");
4124
4125 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4126 struct zebra_vrf *zvrf = vrf->info;
4127
4128 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64" %10" PRIu64 " %10" PRIu64 "\n",
4129 vrf->name, zvrf->installs, zvrf->removals,
4130 zvrf->neigh_updates, zvrf->lsp_installs,
4131 zvrf->lsp_removals);
4132 }
4133
4134 return CMD_SUCCESS;
4135 }
4136
4137 DEFUN (ip_forwarding,
4138 ip_forwarding_cmd,
4139 "ip forwarding",
4140 IP_STR
4141 "Turn on IP forwarding\n")
4142 {
4143 int ret;
4144
4145 ret = ipforward();
4146 if (ret == 0)
4147 ret = ipforward_on();
4148
4149 if (ret == 0) {
4150 vty_out(vty, "Can't turn on IP forwarding\n");
4151 return CMD_WARNING_CONFIG_FAILED;
4152 }
4153
4154 return CMD_SUCCESS;
4155 }
4156
4157 DEFUN (no_ip_forwarding,
4158 no_ip_forwarding_cmd,
4159 "no ip forwarding",
4160 NO_STR
4161 IP_STR
4162 "Turn off IP forwarding\n")
4163 {
4164 int ret;
4165
4166 ret = ipforward();
4167 if (ret != 0)
4168 ret = ipforward_off();
4169
4170 if (ret != 0) {
4171 vty_out(vty, "Can't turn off IP forwarding\n");
4172 return CMD_WARNING_CONFIG_FAILED;
4173 }
4174
4175 return CMD_SUCCESS;
4176 }
4177
4178 /* Only display ip forwarding is enabled or not. */
4179 DEFUN (show_ip_forwarding,
4180 show_ip_forwarding_cmd,
4181 "show ip forwarding",
4182 SHOW_STR
4183 IP_STR
4184 "IP forwarding status\n")
4185 {
4186 int ret;
4187
4188 ret = ipforward();
4189
4190 if (ret == 0)
4191 vty_out(vty, "IP forwarding is off\n");
4192 else
4193 vty_out(vty, "IP forwarding is on\n");
4194 return CMD_SUCCESS;
4195 }
4196
4197 /* Only display ipv6 forwarding is enabled or not. */
4198 DEFUN (show_ipv6_forwarding,
4199 show_ipv6_forwarding_cmd,
4200 "show ipv6 forwarding",
4201 SHOW_STR
4202 "IPv6 information\n"
4203 "Forwarding status\n")
4204 {
4205 int ret;
4206
4207 ret = ipforward_ipv6();
4208
4209 switch (ret) {
4210 case -1:
4211 vty_out(vty, "ipv6 forwarding is unknown\n");
4212 break;
4213 case 0:
4214 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4215 break;
4216 case 1:
4217 vty_out(vty, "ipv6 forwarding is %s\n", "on");
4218 break;
4219 default:
4220 vty_out(vty, "ipv6 forwarding is %s\n", "off");
4221 break;
4222 }
4223 return CMD_SUCCESS;
4224 }
4225
4226 DEFUN (ipv6_forwarding,
4227 ipv6_forwarding_cmd,
4228 "ipv6 forwarding",
4229 IPV6_STR
4230 "Turn on IPv6 forwarding\n")
4231 {
4232 int ret;
4233
4234 ret = ipforward_ipv6();
4235 if (ret == 0)
4236 ret = ipforward_ipv6_on();
4237
4238 if (ret == 0) {
4239 vty_out(vty, "Can't turn on IPv6 forwarding\n");
4240 return CMD_WARNING_CONFIG_FAILED;
4241 }
4242
4243 return CMD_SUCCESS;
4244 }
4245
4246 DEFUN (no_ipv6_forwarding,
4247 no_ipv6_forwarding_cmd,
4248 "no ipv6 forwarding",
4249 NO_STR
4250 IPV6_STR
4251 "Turn off IPv6 forwarding\n")
4252 {
4253 int ret;
4254
4255 ret = ipforward_ipv6();
4256 if (ret != 0)
4257 ret = ipforward_ipv6_off();
4258
4259 if (ret != 0) {
4260 vty_out(vty, "Can't turn off IPv6 forwarding\n");
4261 return CMD_WARNING_CONFIG_FAILED;
4262 }
4263
4264 return CMD_SUCCESS;
4265 }
4266
4267 /* Display dataplane info */
4268 DEFUN (show_dataplane,
4269 show_dataplane_cmd,
4270 "show zebra dplane [detailed]",
4271 SHOW_STR
4272 ZEBRA_STR
4273 "Zebra dataplane information\n"
4274 "Detailed output\n")
4275 {
4276 int idx = 0;
4277 bool detailed = false;
4278
4279 if (argv_find(argv, argc, "detailed", &idx))
4280 detailed = true;
4281
4282 return dplane_show_helper(vty, detailed);
4283 }
4284
4285 /* Display dataplane providers info */
4286 DEFUN (show_dataplane_providers,
4287 show_dataplane_providers_cmd,
4288 "show zebra dplane providers [detailed]",
4289 SHOW_STR
4290 ZEBRA_STR
4291 "Zebra dataplane information\n"
4292 "Zebra dataplane provider information\n"
4293 "Detailed output\n")
4294 {
4295 int idx = 0;
4296 bool detailed = false;
4297
4298 if (argv_find(argv, argc, "detailed", &idx))
4299 detailed = true;
4300
4301 return dplane_show_provs_helper(vty, detailed);
4302 }
4303
4304 /* Configure dataplane incoming queue limit */
4305 DEFUN (zebra_dplane_queue_limit,
4306 zebra_dplane_queue_limit_cmd,
4307 "zebra dplane limit (0-10000)",
4308 ZEBRA_STR
4309 "Zebra dataplane\n"
4310 "Limit incoming queued updates\n"
4311 "Number of queued updates\n")
4312 {
4313 uint32_t limit = 0;
4314
4315 limit = strtoul(argv[3]->arg, NULL, 10);
4316
4317 dplane_set_in_queue_limit(limit, true);
4318
4319 return CMD_SUCCESS;
4320 }
4321
4322 /* Reset dataplane queue limit to default value */
4323 DEFUN (no_zebra_dplane_queue_limit,
4324 no_zebra_dplane_queue_limit_cmd,
4325 "no zebra dplane limit [(0-10000)]",
4326 NO_STR
4327 ZEBRA_STR
4328 "Zebra dataplane\n"
4329 "Limit incoming queued updates\n"
4330 "Number of queued updates\n")
4331 {
4332 dplane_set_in_queue_limit(0, false);
4333
4334 return CMD_SUCCESS;
4335 }
4336
4337 DEFUN (zebra_show_routing_tables_summary,
4338 zebra_show_routing_tables_summary_cmd,
4339 "show zebra router table summary",
4340 SHOW_STR
4341 ZEBRA_STR
4342 "The Zebra Router Information\n"
4343 "Table Information about this Zebra Router\n"
4344 "Summary Information\n")
4345 {
4346 zebra_router_show_table_summary(vty);
4347
4348 return CMD_SUCCESS;
4349 }
4350
4351 /* Table configuration write function. */
4352 static int config_write_table(struct vty *vty)
4353 {
4354 return 0;
4355 }
4356
4357 /* IPForwarding configuration write function. */
4358 static int config_write_forwarding(struct vty *vty)
4359 {
4360 if (!ipforward())
4361 vty_out(vty, "no ip forwarding\n");
4362 if (!ipforward_ipv6())
4363 vty_out(vty, "no ipv6 forwarding\n");
4364 vty_out(vty, "!\n");
4365 return 0;
4366 }
4367
4368 DEFUN_HIDDEN (show_frr,
4369 show_frr_cmd,
4370 "show frr",
4371 SHOW_STR
4372 "FRR\n")
4373 {
4374 vty_out(vty, "........ .. . .. . ..... ...77:................................................\n");
4375 vty_out(vty, ".............................7777:..............................................\n");
4376 vty_out(vty, ".............................777777,............................................\n");
4377 vty_out(vty, "... .........................77777777,..........................................\n");
4378 vty_out(vty, "............................=7777777777:........................................\n");
4379 vty_out(vty, "........................:7777777777777777,......................................\n");
4380 vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
4381 vty_out(vty, "...................I7777777777+.................................................\n");
4382 vty_out(vty, "................,777777777?............ .......................................\n");
4383 vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
4384 vty_out(vty, ".............77777777~........=7777777777.......................................\n");
4385 vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
4386 vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
4387 vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
4388 vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4389 vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4390 vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4391 vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4392 vty_out(vty, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4393 vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4394 vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4395 vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4396 vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4397 vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4398 vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4399 vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4400 vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4401 vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4402 vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4403 vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4404 vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4405 vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4406 vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
4407 vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4408 vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4409 vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4410 vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4411 vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4412 vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4413 vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4414 vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
4415 vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
4416 vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
4417 vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
4418 vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
4419 vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
4420 vty_out(vty, ".......................=77777777777777777............777777I....................\n");
4421 vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
4422 vty_out(vty, "............................~777777777777..............+777777..................\n");
4423 vty_out(vty, "................................~77777777...............=777777.................\n");
4424 vty_out(vty, ".....................................:=?I................~777777................\n");
4425 vty_out(vty, "..........................................................:777777,..............\n");
4426 vty_out(vty, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4427
4428 return CMD_SUCCESS;
4429 }
4430
4431 #ifdef HAVE_NETLINK
4432 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf,
4433 zebra_kernel_netlink_batch_tx_buf_cmd,
4434 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4435 ZEBRA_STR
4436 "Zebra kernel interface\n"
4437 "Set Netlink parameters\n"
4438 "Set batch buffer size and send threshold\n"
4439 "Size of the buffer\n"
4440 "Send threshold\n")
4441 {
4442 uint32_t bufsize = 0, threshold = 0;
4443
4444 bufsize = strtoul(argv[4]->arg, NULL, 10);
4445 threshold = strtoul(argv[5]->arg, NULL, 10);
4446
4447 netlink_set_batch_buffer_size(bufsize, threshold, true);
4448
4449 return CMD_SUCCESS;
4450 }
4451
4452 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf,
4453 no_zebra_kernel_netlink_batch_tx_buf_cmd,
4454 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4455 NO_STR ZEBRA_STR
4456 "Zebra kernel interface\n"
4457 "Set Netlink parameters\n"
4458 "Set batch buffer size and send threshold\n"
4459 "Size of the buffer\n"
4460 "Send threshold\n")
4461 {
4462 netlink_set_batch_buffer_size(0, 0, false);
4463
4464 return CMD_SUCCESS;
4465 }
4466
4467 DEFPY (zebra_protodown_bit,
4468 zebra_protodown_bit_cmd,
4469 "zebra protodown reason-bit (0-31)$bit",
4470 ZEBRA_STR
4471 "Protodown Configuration\n"
4472 "Reason Bit used in the kernel for application\n"
4473 "Reason Bit range\n")
4474 {
4475 if_netlink_set_frr_protodown_r_bit(bit);
4476 return CMD_SUCCESS;
4477 }
4478
4479 DEFPY (no_zebra_protodown_bit,
4480 no_zebra_protodown_bit_cmd,
4481 "no zebra protodown reason-bit [(0-31)$bit]",
4482 NO_STR
4483 ZEBRA_STR
4484 "Protodown Configuration\n"
4485 "Reason Bit used in the kernel for setting protodown\n"
4486 "Reason Bit Range\n")
4487 {
4488 if_netlink_unset_frr_protodown_r_bit();
4489 return CMD_SUCCESS;
4490 }
4491
4492 #endif /* HAVE_NETLINK */
4493
4494 DEFUN(ip_table_range, ip_table_range_cmd,
4495 "[no] ip table range (1-4294967295) (1-4294967295)",
4496 NO_STR IP_STR
4497 "table configuration\n"
4498 "Configure table range\n"
4499 "Start Routing Table\n"
4500 "End Routing Table\n")
4501 {
4502 ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
4503
4504 if (!zvrf)
4505 return CMD_WARNING;
4506
4507 if (zvrf_id(zvrf) != VRF_DEFAULT && !vrf_is_backend_netns()) {
4508 vty_out(vty,
4509 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4510 return CMD_WARNING;
4511 }
4512
4513 if (strmatch(argv[0]->text, "no"))
4514 return table_manager_range(vty, false, zvrf, NULL, NULL);
4515
4516 return table_manager_range(vty, true, zvrf, argv[3]->arg, argv[4]->arg);
4517 }
4518
4519 #ifdef HAVE_SCRIPTING
4520
4521 DEFUN(zebra_on_rib_process_script, zebra_on_rib_process_script_cmd,
4522 "zebra on-rib-process script SCRIPT",
4523 ZEBRA_STR
4524 "on_rib_process_dplane_results hook call\n"
4525 "Set a script\n"
4526 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4527 {
4528
4529 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
4530 argv[3]->arg)
4531 == 0) {
4532 vty_out(vty, "Successfully added script %s for hook call %s\n",
4533 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4534 } else {
4535 vty_out(vty, "Failed to add script %s for hook call %s\n",
4536 argv[3]->arg, ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
4537 }
4538 return CMD_SUCCESS;
4539 }
4540
4541 #endif /* HAVE_SCRIPTING */
4542
4543 /* IP node for static routes. */
4544 static int zebra_ip_config(struct vty *vty);
4545 static struct cmd_node ip_node = {
4546 .name = "static ip",
4547 .node = IP_NODE,
4548 .prompt = "",
4549 .config_write = zebra_ip_config,
4550 };
4551 static int config_write_protocol(struct vty *vty);
4552 static struct cmd_node protocol_node = {
4553 .name = "protocol",
4554 .node = PROTOCOL_NODE,
4555 .prompt = "",
4556 .config_write = config_write_protocol,
4557 };
4558 /* table node for routing tables. */
4559 static int config_write_table(struct vty *vty);
4560 static struct cmd_node table_node = {
4561 .name = "table",
4562 .node = TABLE_NODE,
4563 .prompt = "",
4564 .config_write = config_write_table,
4565 };
4566 static int config_write_forwarding(struct vty *vty);
4567 static struct cmd_node forwarding_node = {
4568 .name = "forwarding",
4569 .node = FORWARDING_NODE,
4570 .prompt = "",
4571 .config_write = config_write_forwarding,
4572 };
4573
4574 /* Route VTY. */
4575 void zebra_vty_init(void)
4576 {
4577 /* Install configuration write function. */
4578 install_node(&table_node);
4579 install_node(&forwarding_node);
4580
4581 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
4582 install_element(CONFIG_NODE, &ip_forwarding_cmd);
4583 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
4584 install_element(ENABLE_NODE, &show_zebra_cmd);
4585
4586 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
4587 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
4588 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
4589
4590 /* Route-map */
4591 zebra_route_map_init();
4592
4593 install_node(&ip_node);
4594 install_node(&protocol_node);
4595
4596 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
4597 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
4598
4599 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
4600 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
4601
4602 install_element(CONFIG_NODE, &zebra_nexthop_group_keep_cmd);
4603 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
4604 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
4605 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
4606 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
4607 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
4608 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
4609 install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
4610 install_element(CONFIG_NODE, &proto_nexthop_group_only_cmd);
4611 install_element(CONFIG_NODE, &backup_nexthop_recursive_use_enable_cmd);
4612
4613 install_element(VIEW_NODE, &show_nexthop_group_cmd);
4614 install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
4615
4616 install_element(VIEW_NODE, &show_vrf_cmd);
4617 install_element(VIEW_NODE, &show_vrf_vni_cmd);
4618 install_element(VIEW_NODE, &show_route_cmd);
4619 install_element(VIEW_NODE, &show_ro_cmd);
4620 install_element(VIEW_NODE, &show_route_detail_cmd);
4621 install_element(VIEW_NODE, &show_route_summary_cmd);
4622 install_element(VIEW_NODE, &show_ip_nht_cmd);
4623
4624 install_element(VIEW_NODE, &show_ip_rpf_cmd);
4625 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
4626
4627 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
4628 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
4629 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
4630 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
4631 install_element(VRF_NODE, &ip_nht_default_route_cmd);
4632 install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
4633 install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
4634 install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
4635 install_element(CONFIG_NODE, &rnh_hide_backups_cmd);
4636
4637 install_element(VIEW_NODE, &show_frr_cmd);
4638 install_element(VIEW_NODE, &show_evpn_global_cmd);
4639 install_element(VIEW_NODE, &show_evpn_vni_cmd);
4640 install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
4641 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
4642 install_element(VIEW_NODE, &show_evpn_l2_nh_cmd);
4643 install_element(VIEW_NODE, &show_evpn_es_cmd);
4644 install_element(VIEW_NODE, &show_evpn_es_evi_cmd);
4645 install_element(VIEW_NODE, &show_evpn_access_vlan_cmd);
4646 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
4647 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
4648 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
4649 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
4650 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
4651 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
4652 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
4653 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
4654 install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
4655 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
4656 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
4657 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
4658 install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
4659 install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
4660 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
4661 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
4662 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
4663 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
4664 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
4665 install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
4666 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
4667 install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
4668 install_element(CONFIG_NODE, &evpn_accept_bgp_seq_cmd);
4669 install_element(CONFIG_NODE, &no_evpn_accept_bgp_seq_cmd);
4670
4671 install_element(VIEW_NODE, &show_neigh_cmd);
4672
4673 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
4674 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
4675 install_element(VIEW_NODE, &show_pbr_rule_cmd);
4676 install_element(CONFIG_NODE, &pbr_nexthop_resolve_cmd);
4677 install_element(VIEW_NODE, &show_route_zebra_dump_cmd);
4678
4679 install_element(CONFIG_NODE, &evpn_mh_mac_holdtime_cmd);
4680 install_element(CONFIG_NODE, &evpn_mh_neigh_holdtime_cmd);
4681 install_element(CONFIG_NODE, &evpn_mh_startup_delay_cmd);
4682 install_element(CONFIG_NODE, &evpn_mh_redirect_off_cmd);
4683 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
4684 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
4685 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
4686 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
4687
4688 install_element(VIEW_NODE, &show_dataplane_cmd);
4689 install_element(VIEW_NODE, &show_dataplane_providers_cmd);
4690 install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
4691 install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
4692
4693 install_element(CONFIG_NODE, &ip_table_range_cmd);
4694 install_element(VRF_NODE, &ip_table_range_cmd);
4695
4696 #ifdef HAVE_NETLINK
4697 install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd);
4698 install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
4699 install_element(CONFIG_NODE, &zebra_protodown_bit_cmd);
4700 install_element(CONFIG_NODE, &no_zebra_protodown_bit_cmd);
4701 #endif /* HAVE_NETLINK */
4702
4703 #ifdef HAVE_SCRIPTING
4704 install_element(CONFIG_NODE, &zebra_on_rib_process_script_cmd);
4705 #endif /* HAVE_SCRIPTING */
4706
4707 install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
4708 }