Coverage Report

Created: 2026-01-13 06:56

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