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