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