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