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