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