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