Coverage Report

Created: 2026-04-27 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/pimd/pim_cmd_common.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * PIM for IPv6 FRR
4
 * Copyright (C) 2022  Vmware, Inc.
5
 *           Mobashshera Rasool <mrasool@vmware.com>
6
 */
7
8
#include <zebra.h>
9
10
#include "lib/json.h"
11
#include "command.h"
12
#include "if.h"
13
#include "prefix.h"
14
#include "zclient.h"
15
#include "plist.h"
16
#include "hash.h"
17
#include "nexthop.h"
18
#include "vrf.h"
19
#include "ferr.h"
20
#include "lib/srcdest_table.h"
21
#include "lib/linklist.h"
22
#include "termtable.h"
23
24
#include "pimd.h"
25
#include "pim_instance.h"
26
#include "pim_vty.h"
27
#include "lib/northbound_cli.h"
28
#include "pim_errors.h"
29
#include "pim_nb.h"
30
#include "pim_mroute.h"
31
#include "pim_cmd.h"
32
#include "pim6_cmd.h"
33
#include "pim_cmd_common.h"
34
#include "pim_time.h"
35
#include "pim_zebra.h"
36
#include "pim_zlookup.h"
37
#include "pim_iface.h"
38
#include "pim_macro.h"
39
#include "pim_neighbor.h"
40
#include "pim_nht.h"
41
#include "pim_sock.h"
42
#include "pim_ssm.h"
43
#include "pim_static.h"
44
#include "pim_addr.h"
45
#include "pim_static.h"
46
#include "pim_util.h"
47
#include "pim6_mld.h"
48
49
/**
50
 * Get current node VRF name.
51
 *
52
 * NOTE:
53
 * In case of failure it will print error message to user.
54
 *
55
 * \returns name or NULL if failed to get VRF.
56
 */
57
const char *pim_cli_get_vrf_name(struct vty *vty)
58
0
{
59
0
  const struct lyd_node *vrf_node;
60
61
  /* Not inside any VRF context. */
62
0
  if (vty->xpath_index == 0)
63
0
    return VRF_DEFAULT_NAME;
64
65
0
  vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
66
0
  if (vrf_node == NULL) {
67
0
    vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
68
0
    return NULL;
69
0
  }
70
71
0
  return yang_dnode_get_string(vrf_node, "./name");
72
0
}
73
74
int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
75
0
{
76
0
  char xpath[XPATH_MAXLEN];
77
78
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
79
0
     FRR_PIM_AF_XPATH_VAL);
80
0
  strlcat(xpath, "/join-prune-interval", sizeof(xpath));
81
82
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
83
84
0
  return nb_cli_apply_changes(vty, NULL);
85
0
}
86
87
int pim_process_no_join_prune_cmd(struct vty *vty)
88
0
{
89
0
  char xpath[XPATH_MAXLEN];
90
91
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
92
0
     FRR_PIM_AF_XPATH_VAL);
93
0
  strlcat(xpath, "/join-prune-interval", sizeof(xpath));
94
95
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
96
97
0
  return nb_cli_apply_changes(vty, NULL);
98
0
}
99
100
int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
101
0
{
102
0
  const char *vrfname;
103
0
  char spt_plist_xpath[XPATH_MAXLEN];
104
0
  char spt_action_xpath[XPATH_MAXLEN];
105
106
0
  vrfname = pim_cli_get_vrf_name(vty);
107
0
  if (vrfname == NULL)
108
0
    return CMD_WARNING_CONFIG_FAILED;
109
110
0
  snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
111
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
112
0
     FRR_PIM_AF_XPATH_VAL);
113
0
  strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
114
0
    sizeof(spt_plist_xpath));
115
116
0
  snprintf(spt_action_xpath, sizeof(spt_action_xpath),
117
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
118
0
     FRR_PIM_AF_XPATH_VAL);
119
0
  strlcat(spt_action_xpath, "/spt-switchover/spt-action",
120
0
    sizeof(spt_action_xpath));
121
122
0
  if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
123
0
    nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
124
0
              NULL);
125
0
  nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
126
0
            "PIM_SPT_INFINITY");
127
128
0
  return nb_cli_apply_changes(vty, NULL);
129
0
}
130
131
int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
132
                const char *plist)
133
0
{
134
0
  const char *vrfname;
135
0
  char spt_plist_xpath[XPATH_MAXLEN];
136
0
  char spt_action_xpath[XPATH_MAXLEN];
137
138
0
  vrfname = pim_cli_get_vrf_name(vty);
139
0
  if (vrfname == NULL)
140
0
    return CMD_WARNING_CONFIG_FAILED;
141
142
0
  snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
143
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
144
0
     FRR_PIM_AF_XPATH_VAL);
145
0
  strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
146
0
    sizeof(spt_plist_xpath));
147
148
0
  snprintf(spt_action_xpath, sizeof(spt_action_xpath),
149
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
150
0
     FRR_PIM_AF_XPATH_VAL);
151
0
  strlcat(spt_action_xpath, "/spt-switchover/spt-action",
152
0
    sizeof(spt_action_xpath));
153
154
0
  nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
155
0
            "PIM_SPT_INFINITY");
156
0
  nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
157
0
            plist);
158
159
0
  return nb_cli_apply_changes(vty, NULL);
160
0
}
161
162
int pim_process_no_spt_switchover_cmd(struct vty *vty)
163
0
{
164
0
  const char *vrfname;
165
0
  char spt_plist_xpath[XPATH_MAXLEN];
166
0
  char spt_action_xpath[XPATH_MAXLEN];
167
168
0
  vrfname = pim_cli_get_vrf_name(vty);
169
0
  if (vrfname == NULL)
170
0
    return CMD_WARNING_CONFIG_FAILED;
171
172
0
  snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
173
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
174
0
     FRR_PIM_AF_XPATH_VAL);
175
0
  strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
176
0
    sizeof(spt_plist_xpath));
177
178
0
  snprintf(spt_action_xpath, sizeof(spt_action_xpath),
179
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
180
0
     FRR_PIM_AF_XPATH_VAL);
181
0
  strlcat(spt_action_xpath, "/spt-switchover/spt-action",
182
0
    sizeof(spt_action_xpath));
183
184
0
  nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
185
0
  nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
186
0
            "PIM_SPT_IMMEDIATE");
187
188
0
  return nb_cli_apply_changes(vty, NULL);
189
0
}
190
191
int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
192
0
{
193
0
  char xpath[XPATH_MAXLEN];
194
195
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
196
0
     FRR_PIM_AF_XPATH_VAL);
197
0
  strlcat(xpath, "/packets", sizeof(xpath));
198
199
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
200
201
0
  return nb_cli_apply_changes(vty, NULL);
202
0
}
203
204
int pim_process_no_pim_packet_cmd(struct vty *vty)
205
0
{
206
0
  char xpath[XPATH_MAXLEN];
207
208
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
209
0
     FRR_PIM_AF_XPATH_VAL);
210
0
  strlcat(xpath, "/packets", sizeof(xpath));
211
212
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
213
214
0
  return nb_cli_apply_changes(vty, NULL);
215
0
}
216
217
int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
218
0
{
219
0
  const char *vrfname;
220
0
  char ka_timer_xpath[XPATH_MAXLEN];
221
222
0
  vrfname = pim_cli_get_vrf_name(vty);
223
0
  if (vrfname == NULL)
224
0
    return CMD_WARNING_CONFIG_FAILED;
225
226
0
  snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
227
0
     "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
228
0
  strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
229
230
0
  nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
231
0
            kat);
232
233
0
  return nb_cli_apply_changes(vty, NULL);
234
0
}
235
236
int pim_process_no_keepalivetimer_cmd(struct vty *vty)
237
0
{
238
0
  const char *vrfname;
239
0
  char ka_timer_xpath[XPATH_MAXLEN];
240
241
0
  vrfname = pim_cli_get_vrf_name(vty);
242
0
  if (vrfname == NULL)
243
0
    return CMD_WARNING_CONFIG_FAILED;
244
245
0
  snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
246
0
     "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
247
0
  strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
248
249
0
  nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
250
251
0
  return nb_cli_apply_changes(vty, NULL);
252
0
}
253
254
int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
255
0
{
256
0
  const char *vrfname;
257
0
  char rp_ka_timer_xpath[XPATH_MAXLEN];
258
259
0
  vrfname = pim_cli_get_vrf_name(vty);
260
0
  if (vrfname == NULL)
261
0
    return CMD_WARNING_CONFIG_FAILED;
262
263
0
  snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
264
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
265
0
     FRR_PIM_AF_XPATH_VAL);
266
0
  strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
267
0
    sizeof(rp_ka_timer_xpath));
268
269
0
  nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
270
0
            rpkat);
271
272
0
  return nb_cli_apply_changes(vty, NULL);
273
0
}
274
275
int pim_process_no_rp_kat_cmd(struct vty *vty)
276
0
{
277
0
  const char *vrfname;
278
0
  char rp_ka_timer[6];
279
0
  char rp_ka_timer_xpath[XPATH_MAXLEN];
280
0
  uint v;
281
0
  char rs_timer_xpath[XPATH_MAXLEN];
282
283
0
  snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
284
0
     FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
285
0
  strlcat(rs_timer_xpath, "/register-suppress-time",
286
0
    sizeof(rs_timer_xpath));
287
288
  /* RFC4601 */
289
0
  v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
290
0
          rs_timer_xpath);
291
0
  v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
292
0
  if (v > UINT16_MAX)
293
0
    v = UINT16_MAX;
294
0
  snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
295
296
0
  vrfname = pim_cli_get_vrf_name(vty);
297
0
  if (vrfname == NULL)
298
0
    return CMD_WARNING_CONFIG_FAILED;
299
300
0
  snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
301
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
302
0
     FRR_PIM_AF_XPATH_VAL);
303
0
  strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
304
0
    sizeof(rp_ka_timer_xpath));
305
306
0
  nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
307
0
            rp_ka_timer);
308
309
0
  return nb_cli_apply_changes(vty, NULL);
310
0
}
311
312
int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
313
0
{
314
0
  char xpath[XPATH_MAXLEN];
315
316
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
317
0
     FRR_PIM_AF_XPATH_VAL);
318
0
  strlcat(xpath, "/register-suppress-time", sizeof(xpath));
319
320
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
321
322
0
  return nb_cli_apply_changes(vty, NULL);
323
0
}
324
325
int pim_process_no_register_suppress_cmd(struct vty *vty)
326
0
{
327
0
  char xpath[XPATH_MAXLEN];
328
329
0
  snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
330
0
     FRR_PIM_AF_XPATH_VAL);
331
0
  strlcat(xpath, "/register-suppress-time", sizeof(xpath));
332
333
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
334
335
0
  return nb_cli_apply_changes(vty, NULL);
336
0
}
337
338
int pim_process_ip_pim_cmd(struct vty *vty)
339
0
{
340
0
  nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
341
342
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
343
0
            FRR_PIM_AF_XPATH_VAL);
344
0
}
345
346
int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable)
347
0
{
348
0
  if (enable)
349
0
    nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
350
0
              "true");
351
0
  else
352
0
    nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
353
0
              "false");
354
355
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
356
0
            FRR_PIM_AF_XPATH_VAL);
357
0
}
358
359
int pim_process_no_ip_pim_cmd(struct vty *vty)
360
0
{
361
0
  const struct lyd_node *mld_enable_dnode;
362
0
  char mld_if_xpath[XPATH_MAXLEN];
363
364
0
  int printed =
365
0
    snprintf(mld_if_xpath, sizeof(mld_if_xpath),
366
0
       "%s/frr-gmp:gmp/address-family[address-family='%s']",
367
0
       VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
368
369
0
  if (printed >= (int)(sizeof(mld_if_xpath))) {
370
0
    vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
371
0
      XPATH_MAXLEN);
372
0
    return CMD_WARNING_CONFIG_FAILED;
373
0
  }
374
375
0
  mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
376
0
             FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
377
0
             FRR_PIM_AF_XPATH_VAL);
378
379
0
  if (!mld_enable_dnode) {
380
0
    nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
381
0
    nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
382
0
  } else {
383
0
    if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
384
0
      nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
385
0
                NULL);
386
0
      nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
387
0
    } else
388
0
      nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
389
0
                "false");
390
0
  }
391
392
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
393
0
            FRR_PIM_AF_XPATH_VAL);
394
0
}
395
396
int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
397
0
{
398
0
  nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
399
0
            drpriority_str);
400
401
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
402
0
            FRR_PIM_AF_XPATH_VAL);
403
0
}
404
405
int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
406
0
{
407
0
  nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
408
409
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
410
0
            FRR_PIM_AF_XPATH_VAL);
411
0
}
412
413
int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
414
         const char *hold_str)
415
0
{
416
0
  const struct lyd_node *mld_enable_dnode;
417
418
0
  mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
419
0
             FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
420
0
             FRR_PIM_AF_XPATH_VAL);
421
422
0
  if (!mld_enable_dnode) {
423
0
    nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
424
0
              "true");
425
0
  } else {
426
0
    if (!yang_dnode_get_bool(mld_enable_dnode, "."))
427
0
      nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
428
0
                "true");
429
0
  }
430
431
0
  nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
432
433
0
  if (hold_str)
434
0
    nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
435
0
              hold_str);
436
437
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
438
0
            FRR_PIM_AF_XPATH_VAL);
439
0
}
440
441
int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
442
0
{
443
0
  nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
444
0
  nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
445
446
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
447
0
            FRR_PIM_AF_XPATH_VAL);
448
0
}
449
450
int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
451
0
{
452
0
  if (no)
453
0
    nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
454
0
              "false");
455
0
  else {
456
0
    nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
457
0
              "true");
458
459
0
    nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
460
0
              "true");
461
0
  }
462
463
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
464
0
            FRR_PIM_AF_XPATH_VAL);
465
0
}
466
467
int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
468
0
{
469
0
  nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
470
0
            oil);
471
472
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
473
0
            FRR_PIM_AF_XPATH_VAL);
474
0
}
475
476
int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
477
0
{
478
0
  nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
479
0
            NULL);
480
481
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
482
0
            FRR_PIM_AF_XPATH_VAL);
483
0
}
484
485
int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
486
            const char *group_str, const char *source_str)
487
0
{
488
0
  nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
489
490
0
  if (!source_str) {
491
0
    char buf[SRCDEST2STR_BUFFER];
492
493
0
    inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
494
0
    return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
495
0
              FRR_PIM_AF_XPATH_VAL, buf,
496
0
              group_str);
497
0
  }
498
499
0
  return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
500
0
            FRR_PIM_AF_XPATH_VAL, source_str,
501
0
            group_str);
502
0
}
503
504
int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
505
         const char *group_str, const char *source_str)
506
0
{
507
0
  nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
508
509
0
  if (!source_str) {
510
0
    char buf[SRCDEST2STR_BUFFER];
511
512
0
    inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
513
0
    return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
514
0
              FRR_PIM_AF_XPATH_VAL, buf,
515
0
              group_str);
516
0
  }
517
518
0
  return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
519
0
            FRR_PIM_AF_XPATH_VAL, source_str,
520
0
            group_str);
521
0
}
522
523
int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
524
           const char *group_str)
525
0
{
526
0
  const char *vrfname;
527
0
  char rp_group_xpath[XPATH_MAXLEN];
528
0
  int result = 0;
529
0
  struct prefix group;
530
0
  pim_addr rp_addr;
531
532
0
  result = str2prefix(group_str, &group);
533
0
  if (result) {
534
0
    struct prefix temp;
535
536
0
    prefix_copy(&temp, &group);
537
0
    apply_mask(&temp);
538
0
    if (!prefix_same(&group, &temp)) {
539
0
      vty_out(vty, "%% Inconsistent address and mask: %s\n",
540
0
        group_str);
541
0
      return CMD_WARNING_CONFIG_FAILED;
542
0
    }
543
0
  }
544
545
0
  if (!result) {
546
0
    vty_out(vty, "%% Bad group address specified: %s\n", group_str);
547
0
    return CMD_WARNING_CONFIG_FAILED;
548
0
  }
549
550
0
  result = inet_pton(PIM_AF, rp_str, &rp_addr);
551
0
  if (result <= 0) {
552
0
    vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
553
0
    return CMD_WARNING_CONFIG_FAILED;
554
0
  }
555
556
0
  if (pim_addr_is_any(rp_addr) || pim_addr_is_multicast(rp_addr)) {
557
0
    vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
558
0
    return CMD_WARNING_CONFIG_FAILED;
559
0
  }
560
561
#if PIM_IPV == 6
562
  if (IN6_IS_ADDR_LINKLOCAL(&rp_addr)) {
563
    vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
564
    return CMD_WARNING_CONFIG_FAILED;
565
  }
566
#endif
567
568
0
  vrfname = pim_cli_get_vrf_name(vty);
569
0
  if (vrfname == NULL)
570
0
    return CMD_WARNING_CONFIG_FAILED;
571
572
0
  snprintf(rp_group_xpath, sizeof(rp_group_xpath),
573
0
     FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
574
0
     FRR_PIM_AF_XPATH_VAL, rp_str);
575
0
  strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
576
577
0
  nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
578
579
0
  return nb_cli_apply_changes(vty, NULL);
580
0
}
581
582
int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
583
        const char *group_str)
584
0
{
585
0
  char group_list_xpath[XPATH_MAXLEN];
586
0
  char group_xpath[XPATH_MAXLEN];
587
0
  char rp_xpath[XPATH_MAXLEN];
588
0
  int printed;
589
0
  const char *vrfname;
590
0
  const struct lyd_node *group_dnode;
591
592
0
  vrfname = pim_cli_get_vrf_name(vty);
593
0
  if (vrfname == NULL)
594
0
    return CMD_WARNING_CONFIG_FAILED;
595
596
0
  snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
597
0
     "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
598
599
0
  printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
600
0
         "%s/group-list", rp_xpath);
601
602
0
  if (printed >= (int)(sizeof(group_list_xpath))) {
603
0
    vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
604
0
      XPATH_MAXLEN);
605
0
    return CMD_WARNING_CONFIG_FAILED;
606
0
  }
607
608
0
  printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
609
0
         group_list_xpath, group_str);
610
611
0
  if (printed >= (int)(sizeof(group_xpath))) {
612
0
    vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
613
0
      XPATH_MAXLEN);
614
0
    return CMD_WARNING_CONFIG_FAILED;
615
0
  }
616
617
0
  group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
618
0
  if (!group_dnode) {
619
0
    vty_out(vty, "%% Unable to find specified RP\n");
620
0
    return NB_OK;
621
0
  }
622
623
0
  if (yang_is_last_list_dnode(group_dnode))
624
0
    nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
625
0
  else
626
0
    nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
627
0
              group_str);
628
629
0
  return nb_cli_apply_changes(vty, NULL);
630
0
}
631
632
int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
633
           const char *prefix_list)
634
0
{
635
0
  const char *vrfname;
636
0
  char rp_plist_xpath[XPATH_MAXLEN];
637
638
0
  vrfname = pim_cli_get_vrf_name(vty);
639
0
  if (vrfname == NULL)
640
0
    return CMD_WARNING_CONFIG_FAILED;
641
642
0
  snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
643
0
     FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
644
0
     FRR_PIM_AF_XPATH_VAL, rp_str);
645
0
  strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
646
647
0
  nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
648
649
0
  return nb_cli_apply_changes(vty, NULL);
650
0
}
651
652
int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
653
        const char *prefix_list)
654
0
{
655
0
  char rp_xpath[XPATH_MAXLEN];
656
0
  char plist_xpath[XPATH_MAXLEN];
657
0
  const char *vrfname;
658
0
  const struct lyd_node *plist_dnode;
659
0
  const char *plist;
660
661
0
  vrfname = pim_cli_get_vrf_name(vty);
662
0
  if (vrfname == NULL)
663
0
    return CMD_WARNING_CONFIG_FAILED;
664
665
0
  snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
666
0
     "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
667
668
0
  snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
669
0
     "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
670
0
  strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
671
672
0
  plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
673
0
  if (!plist_dnode) {
674
0
    vty_out(vty, "%% Unable to find specified RP\n");
675
0
    return NB_OK;
676
0
  }
677
678
0
  plist = yang_dnode_get_string(plist_dnode, "%s", plist_xpath);
679
0
  if (strcmp(prefix_list, plist)) {
680
0
    vty_out(vty, "%% Unable to find specified RP\n");
681
0
    return NB_OK;
682
0
  }
683
684
0
  nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
685
686
0
  return nb_cli_apply_changes(vty, NULL);
687
0
}
688
689
bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
690
0
{
691
0
  return (pim_addr_is_any(match.grp) ||
692
0
    !pim_addr_cmp(match.grp, item.grp)) &&
693
0
         (pim_addr_is_any(match.src) ||
694
0
    !pim_addr_cmp(match.src, item.src));
695
0
}
696
697
void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
698
0
{
699
0
  struct pim_interface *pim_ifp;
700
701
0
  pim_ifp = ifp->info;
702
0
  json_object_string_add(json, "name", ifp->name);
703
0
  json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
704
0
  json_object_string_addf(json, "address", "%pPA",
705
0
        &pim_ifp->primary_address);
706
0
  json_object_int_add(json, "index", ifp->ifindex);
707
708
0
  if (if_is_multicast(ifp))
709
0
    json_object_boolean_true_add(json, "flagMulticast");
710
711
0
  if (if_is_broadcast(ifp))
712
0
    json_object_boolean_true_add(json, "flagBroadcast");
713
714
0
  if (ifp->flags & IFF_ALLMULTI)
715
0
    json_object_boolean_true_add(json, "flagAllMulticast");
716
717
0
  if (ifp->flags & IFF_PROMISC)
718
0
    json_object_boolean_true_add(json, "flagPromiscuous");
719
720
0
  if (PIM_IF_IS_DELETED(ifp))
721
0
    json_object_boolean_true_add(json, "flagDeleted");
722
723
0
  if (pim_if_lan_delay_enabled(ifp))
724
0
    json_object_boolean_true_add(json, "lanDelayEnabled");
725
0
}
726
727
void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
728
0
{
729
0
  vty_out(vty, "Flags\n");
730
0
  vty_out(vty, "-----\n");
731
0
  vty_out(vty, "All Multicast   : %s\n",
732
0
    (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
733
0
  vty_out(vty, "Broadcast       : %s\n",
734
0
    if_is_broadcast(ifp) ? "yes" : "no");
735
0
  vty_out(vty, "Deleted         : %s\n",
736
0
    PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
737
0
  vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
738
0
  vty_out(vty, "Multicast       : %s\n",
739
0
    if_is_multicast(ifp) ? "yes" : "no");
740
0
  vty_out(vty, "Promiscuous     : %s\n",
741
0
    (ifp->flags & IFF_PROMISC) ? "yes" : "no");
742
0
  vty_out(vty, "\n");
743
0
  vty_out(vty, "\n");
744
0
}
745
746
void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
747
0
{
748
0
  json_object_boolean_add(
749
0
    json, "drJoinDesired",
750
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED));
751
0
  json_object_boolean_add(
752
0
    json, "drJoinDesiredUpdated",
753
0
    CHECK_FLAG(up->flags,
754
0
         PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED));
755
0
  json_object_boolean_add(
756
0
    json, "firstHopRouter",
757
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR));
758
0
  json_object_boolean_add(
759
0
    json, "sourceIgmp",
760
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP));
761
0
  json_object_boolean_add(
762
0
    json, "sourcePim",
763
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM));
764
0
  json_object_boolean_add(
765
0
    json, "sourceStream",
766
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM));
767
  /* XXX: need to print ths flag in the plain text display as well */
768
0
  json_object_boolean_add(
769
0
    json, "sourceMsdp",
770
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP));
771
0
  json_object_boolean_add(
772
0
    json, "sendSGRptPrune",
773
0
    CHECK_FLAG(up->flags,
774
0
         PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE));
775
0
  json_object_boolean_add(
776
0
    json, "lastHopRouter",
777
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR));
778
0
  json_object_boolean_add(
779
0
    json, "disableKATExpiry",
780
0
    CHECK_FLAG(up->flags,
781
0
         PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY));
782
0
  json_object_boolean_add(
783
0
    json, "staticIncomingInterface",
784
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF));
785
0
  json_object_boolean_add(
786
0
    json, "allowIncomingInterfaceinOil",
787
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL));
788
0
  json_object_boolean_add(
789
0
    json, "noPimRegistrationData",
790
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA));
791
0
  json_object_boolean_add(
792
0
    json, "forcePimRegistration",
793
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG));
794
0
  json_object_boolean_add(
795
0
    json, "sourceVxlanOrigination",
796
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG));
797
0
  json_object_boolean_add(
798
0
    json, "sourceVxlanTermination",
799
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM));
800
0
  json_object_boolean_add(
801
0
    json, "mlagVxlan",
802
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN));
803
0
  json_object_boolean_add(
804
0
    json, "mlagNonDesignatedForwarder",
805
0
    CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF));
806
0
}
807
808
static const char *
809
pim_upstream_state2brief_str(enum pim_upstream_state join_state,
810
           char *state_str, size_t state_str_len)
811
0
{
812
0
  switch (join_state) {
813
0
  case PIM_UPSTREAM_NOTJOINED:
814
0
    strlcpy(state_str, "NotJ", state_str_len);
815
0
    break;
816
0
  case PIM_UPSTREAM_JOINED:
817
0
    strlcpy(state_str, "J", state_str_len);
818
0
    break;
819
0
  default:
820
0
    strlcpy(state_str, "Unk", state_str_len);
821
0
  }
822
0
  return state_str;
823
0
}
824
825
static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
826
             char *state_str,
827
             size_t state_str_len)
828
0
{
829
0
  switch (reg_state) {
830
0
  case PIM_REG_NOINFO:
831
0
    strlcpy(state_str, "RegNI", state_str_len);
832
0
    break;
833
0
  case PIM_REG_JOIN:
834
0
    strlcpy(state_str, "RegJ", state_str_len);
835
0
    break;
836
0
  case PIM_REG_JOIN_PENDING:
837
0
  case PIM_REG_PRUNE:
838
0
    strlcpy(state_str, "RegP", state_str_len);
839
0
    break;
840
0
  }
841
0
  return state_str;
842
0
}
843
844
void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
845
        time_t now, json_object *json)
846
0
{
847
0
  char refresh_uptime[10];
848
849
0
  pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
850
0
            pim->rpf_cache_refresh_last);
851
852
0
  if (json) {
853
0
    json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
854
0
            router->rpf_cache_refresh_delay_msec);
855
0
    json_object_int_add(
856
0
      json, "rpfCacheRefreshTimer",
857
0
      pim_time_timer_remain_msec(pim->rpf_cache_refresher));
858
0
    json_object_int_add(json, "rpfCacheRefreshRequests",
859
0
            pim->rpf_cache_refresh_requests);
860
0
    json_object_int_add(json, "rpfCacheRefreshEvents",
861
0
            pim->rpf_cache_refresh_events);
862
0
    json_object_string_add(json, "rpfCacheRefreshLast",
863
0
               refresh_uptime);
864
0
    json_object_int_add(json, "nexthopLookups",
865
0
            pim->nexthop_lookups);
866
0
    json_object_int_add(json, "nexthopLookupsAvoided",
867
0
            pim->nexthop_lookups_avoided);
868
0
  } else {
869
0
    vty_out(vty,
870
0
      "RPF Cache Refresh Delay:    %ld msecs\n"
871
0
      "RPF Cache Refresh Timer:    %ld msecs\n"
872
0
      "RPF Cache Refresh Requests: %lld\n"
873
0
      "RPF Cache Refresh Events:   %lld\n"
874
0
      "RPF Cache Refresh Last:     %s\n"
875
0
      "Nexthop Lookups:            %lld\n"
876
0
      "Nexthop Lookups Avoided:    %lld\n",
877
0
      router->rpf_cache_refresh_delay_msec,
878
0
      pim_time_timer_remain_msec(pim->rpf_cache_refresher),
879
0
      (long long)pim->rpf_cache_refresh_requests,
880
0
      (long long)pim->rpf_cache_refresh_events,
881
0
      refresh_uptime, (long long)pim->nexthop_lookups,
882
0
      (long long)pim->nexthop_lookups_avoided);
883
0
  }
884
0
}
885
886
void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
887
0
{
888
0
  struct pim_upstream *up;
889
0
  time_t now = pim_time_monotonic_sec();
890
0
  struct ttable *tt = NULL;
891
0
  char *table = NULL;
892
0
  json_object *json_group = NULL;
893
0
  json_object *json_row = NULL;
894
895
0
  pim_show_rpf_refresh_stats(vty, pim, now, json);
896
897
0
  if (!json) {
898
0
    vty_out(vty, "\n");
899
900
    /* Prepare table. */
901
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
902
0
    ttable_add_row(
903
0
      tt,
904
0
      "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
905
0
    tt->style.cell.rpad = 2;
906
0
    tt->style.corner = '+';
907
0
    ttable_restyle(tt);
908
0
  }
909
910
0
  frr_each (rb_pim_upstream, &pim->upstream_head, up) {
911
0
    const char *rpf_ifname;
912
0
    struct pim_rpf *rpf = &up->rpf;
913
914
0
    rpf_ifname =
915
0
      rpf->source_nexthop.interface ? rpf->source_nexthop
916
0
                .interface->name
917
0
                  : "<ifname?>";
918
919
0
    if (json) {
920
0
      char grp_str[PIM_ADDRSTRLEN];
921
0
      char src_str[PIM_ADDRSTRLEN];
922
923
0
      snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
924
0
           &up->sg.grp);
925
0
      snprintfrr(src_str, sizeof(src_str), "%pPAs",
926
0
           &up->sg.src);
927
928
0
      json_object_object_get_ex(json, grp_str, &json_group);
929
930
0
      if (!json_group) {
931
0
        json_group = json_object_new_object();
932
0
        json_object_object_add(json, grp_str,
933
0
                   json_group);
934
0
      }
935
936
0
      json_row = json_object_new_object();
937
0
      json_object_string_add(json_row, "source", src_str);
938
0
      json_object_string_add(json_row, "group", grp_str);
939
0
      json_object_string_add(json_row, "rpfInterface",
940
0
                 rpf_ifname);
941
0
      json_object_string_addf(json_row, "rpfAddress", "%pPA",
942
0
            &rpf->rpf_addr);
943
0
      json_object_string_addf(
944
0
        json_row, "ribNexthop", "%pPAs",
945
0
        &rpf->source_nexthop.mrib_nexthop_addr);
946
0
      json_object_int_add(
947
0
        json_row, "routeMetric",
948
0
        rpf->source_nexthop.mrib_route_metric);
949
0
      json_object_int_add(
950
0
        json_row, "routePreference",
951
0
        rpf->source_nexthop.mrib_metric_preference);
952
0
      json_object_object_add(json_group, src_str, json_row);
953
954
0
    } else {
955
0
      ttable_add_row(
956
0
        tt, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
957
0
        &up->sg.src, &up->sg.grp, rpf_ifname,
958
0
        &rpf->rpf_addr,
959
0
        &rpf->source_nexthop.mrib_nexthop_addr,
960
0
        rpf->source_nexthop.mrib_route_metric,
961
0
        rpf->source_nexthop.mrib_metric_preference);
962
0
    }
963
0
  }
964
  /* Dump the generated table. */
965
0
  if (!json) {
966
0
    table = ttable_dump(tt, "\n");
967
0
    vty_out(vty, "%s\n", table);
968
0
    XFREE(MTYPE_TMP, table);
969
0
    ttable_del(tt);
970
0
  }
971
0
}
972
973
void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
974
0
{
975
0
  struct interface *ifp;
976
0
  struct ttable *tt = NULL;
977
0
  char *table = NULL;
978
979
  /* Prepare table. */
980
0
  tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
981
0
  ttable_add_row(tt, "Interface|Address|Neighbor|Secondary");
982
0
  tt->style.cell.rpad = 2;
983
0
  tt->style.corner = '+';
984
0
  ttable_restyle(tt);
985
986
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
987
0
    struct pim_interface *pim_ifp;
988
0
    pim_addr ifaddr;
989
0
    struct listnode *neighnode;
990
0
    struct pim_neighbor *neigh;
991
992
0
    pim_ifp = ifp->info;
993
994
0
    if (!pim_ifp)
995
0
      continue;
996
997
0
    if (pim_ifp->pim_sock_fd < 0)
998
0
      continue;
999
1000
0
    ifaddr = pim_ifp->primary_address;
1001
1002
0
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1003
0
            neigh)) {
1004
0
      struct listnode *prefix_node;
1005
0
      struct prefix *p;
1006
1007
0
      if (!neigh->prefix_list)
1008
0
        continue;
1009
1010
0
      for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
1011
0
              prefix_node, p))
1012
0
        ttable_add_row(tt, "%s|%pPAs|%pPAs|%pFX",
1013
0
                 ifp->name, &ifaddr,
1014
0
                 &neigh->source_addr, p);
1015
0
    }
1016
0
  }
1017
  /* Dump the generated table. */
1018
0
  table = ttable_dump(tt, "\n");
1019
0
  vty_out(vty, "%s\n", table);
1020
0
  XFREE(MTYPE_TMP, table);
1021
0
  ttable_del(tt);
1022
0
}
1023
1024
void pim_show_state(struct pim_instance *pim, struct vty *vty,
1025
        const char *src_or_group, const char *group,
1026
        json_object *json)
1027
0
{
1028
0
  struct channel_oil *c_oil;
1029
#if PIM_IPV != 4
1030
  struct ttable *tt = NULL;
1031
  char *table = NULL;
1032
#endif
1033
0
  char flag[50];
1034
0
  json_object *json_group = NULL;
1035
0
  json_object *json_ifp_in = NULL;
1036
0
  json_object *json_ifp_out = NULL;
1037
0
  json_object *json_source = NULL;
1038
0
  time_t now;
1039
0
  int first_oif;
1040
1041
0
  now = pim_time_monotonic_sec();
1042
1043
0
  if (!json) {
1044
0
    vty_out(vty,
1045
0
      "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
1046
0
#if PIM_IPV == 4
1047
0
    vty_out(vty,
1048
0
      "Active Source           Group            RPT  IIF               OIL\n");
1049
#else
1050
    /* Prepare table. */
1051
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1052
    ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL");
1053
    tt->style.cell.rpad = 2;
1054
    tt->style.corner = '+';
1055
    ttable_restyle(tt);
1056
#endif
1057
0
  }
1058
1059
0
  frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
1060
0
    char src_str[PIM_ADDRSTRLEN];
1061
0
    char grp_str[PIM_ADDRSTRLEN];
1062
0
    char in_ifname[INTERFACE_NAMSIZ + 1];
1063
0
    char out_ifname[INTERFACE_NAMSIZ + 1];
1064
0
    int oif_vif_index;
1065
0
    struct interface *ifp_in;
1066
0
    bool isRpt;
1067
1068
0
    first_oif = 1;
1069
1070
0
    if ((c_oil->up &&
1071
0
         PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
1072
0
        pim_addr_is_any(*oil_origin(c_oil)))
1073
0
      isRpt = true;
1074
0
    else
1075
0
      isRpt = false;
1076
1077
0
    snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1078
0
         oil_mcastgrp(c_oil));
1079
0
    snprintfrr(src_str, sizeof(src_str), "%pPAs",
1080
0
         oil_origin(c_oil));
1081
0
    ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
1082
1083
0
    if (ifp_in)
1084
0
      strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
1085
0
    else
1086
0
      strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
1087
1088
0
    if (src_or_group) {
1089
0
      if (strcmp(src_or_group, src_str) &&
1090
0
          strcmp(src_or_group, grp_str))
1091
0
        continue;
1092
1093
0
      if (group && strcmp(group, grp_str))
1094
0
        continue;
1095
0
    }
1096
1097
0
    if (json) {
1098
1099
      /* Find the group, create it if it doesn't exist */
1100
0
      json_object_object_get_ex(json, grp_str, &json_group);
1101
1102
0
      if (!json_group) {
1103
0
        json_group = json_object_new_object();
1104
0
        json_object_object_add(json, grp_str,
1105
0
                   json_group);
1106
0
      }
1107
1108
      /* Find the source nested under the group, create it if
1109
       * it doesn't exist
1110
       */
1111
0
      json_object_object_get_ex(json_group, src_str,
1112
0
              &json_source);
1113
1114
0
      if (!json_source) {
1115
0
        json_source = json_object_new_object();
1116
0
        json_object_object_add(json_group, src_str,
1117
0
                   json_source);
1118
0
      }
1119
1120
      /* Find the inbound interface nested under the source,
1121
       * create it if it doesn't exist
1122
       */
1123
0
      json_object_object_get_ex(json_source, in_ifname,
1124
0
              &json_ifp_in);
1125
1126
0
      if (!json_ifp_in) {
1127
0
        json_ifp_in = json_object_new_object();
1128
0
        json_object_object_add(json_source, in_ifname,
1129
0
                   json_ifp_in);
1130
0
        json_object_int_add(json_source, "installed",
1131
0
                c_oil->installed);
1132
0
        json_object_boolean_add(json_source, "isRpt",
1133
0
              isRpt);
1134
0
        json_object_int_add(json_source, "refCount",
1135
0
                c_oil->oil_ref_count);
1136
0
        json_object_int_add(json_source, "oilListSize",
1137
0
                c_oil->oil_size);
1138
0
        json_object_int_add(
1139
0
          json_source, "oilRescan",
1140
0
          c_oil->oil_inherited_rescan);
1141
0
        json_object_int_add(json_source, "lastUsed",
1142
0
                c_oil->cc.lastused);
1143
0
        json_object_int_add(json_source, "packetCount",
1144
0
                c_oil->cc.pktcnt);
1145
0
        json_object_int_add(json_source, "byteCount",
1146
0
                c_oil->cc.bytecnt);
1147
0
        json_object_int_add(json_source,
1148
0
                "wrongInterface",
1149
0
                c_oil->cc.wrong_if);
1150
0
      }
1151
0
    }
1152
0
#if PIM_IPV == 4
1153
0
    else
1154
0
      vty_out(vty, "%-6d %-15pPAs  %-15pPAs  %-3s  %-16s  ",
1155
0
        c_oil->installed, oil_origin(c_oil),
1156
0
        oil_mcastgrp(c_oil), isRpt ? "y" : "n",
1157
0
        in_ifname);
1158
0
#endif
1159
1160
0
    for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
1161
0
         ++oif_vif_index) {
1162
0
      struct interface *ifp_out;
1163
0
      char oif_uptime[10];
1164
0
      int ttl;
1165
1166
0
      ttl = oil_if_has(c_oil, oif_vif_index);
1167
0
      if (ttl < 1)
1168
0
        continue;
1169
1170
0
      ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
1171
0
      pim_time_uptime(
1172
0
        oif_uptime, sizeof(oif_uptime),
1173
0
        now - c_oil->oif_creation[oif_vif_index]);
1174
1175
0
      if (ifp_out)
1176
0
        strlcpy(out_ifname, ifp_out->name,
1177
0
          sizeof(out_ifname));
1178
0
      else
1179
0
        strlcpy(out_ifname, "<oif?>",
1180
0
          sizeof(out_ifname));
1181
1182
0
      if (json) {
1183
0
        json_ifp_out = json_object_new_object();
1184
0
        json_object_string_add(json_ifp_out, "source",
1185
0
                   src_str);
1186
0
        json_object_string_add(json_ifp_out, "group",
1187
0
                   grp_str);
1188
0
        json_object_string_add(json_ifp_out,
1189
0
                   "inboundInterface",
1190
0
                   in_ifname);
1191
0
        json_object_string_add(json_ifp_out,
1192
0
                   "outboundInterface",
1193
0
                   out_ifname);
1194
0
        json_object_int_add(json_ifp_out, "installed",
1195
0
                c_oil->installed);
1196
1197
0
        json_object_object_add(json_ifp_in, out_ifname,
1198
0
                   json_ifp_out);
1199
0
      } else {
1200
0
        flag[0] = '\0';
1201
0
        snprintf(flag, sizeof(flag), "(%c%c%c%c%c)",
1202
0
           (c_oil->oif_flags[oif_vif_index] &
1203
0
            PIM_OIF_FLAG_PROTO_GM)
1204
0
             ? 'I'
1205
0
             : ' ',
1206
0
           (c_oil->oif_flags[oif_vif_index] &
1207
0
            PIM_OIF_FLAG_PROTO_PIM)
1208
0
             ? 'J'
1209
0
             : ' ',
1210
0
           (c_oil->oif_flags[oif_vif_index] &
1211
0
            PIM_OIF_FLAG_PROTO_VXLAN)
1212
0
             ? 'V'
1213
0
             : ' ',
1214
0
           (c_oil->oif_flags[oif_vif_index] &
1215
0
            PIM_OIF_FLAG_PROTO_STAR)
1216
0
             ? '*'
1217
0
             : ' ',
1218
0
           (c_oil->oif_flags[oif_vif_index] &
1219
0
            PIM_OIF_FLAG_MUTE)
1220
0
             ? 'M'
1221
0
             : ' ');
1222
1223
0
        if (first_oif) {
1224
0
          first_oif = 0;
1225
0
#if PIM_IPV == 4
1226
0
          vty_out(vty, "%s%s", out_ifname, flag);
1227
#else
1228
          ttable_add_row(
1229
            tt, "%d|%pPAs|%pPAs|%s|%s|%s%s",
1230
            c_oil->installed,
1231
            oil_origin(c_oil),
1232
            oil_mcastgrp(c_oil),
1233
            isRpt ? "y" : "n", in_ifname,
1234
            out_ifname, flag);
1235
#endif
1236
0
        } else {
1237
0
#if PIM_IPV == 4
1238
0
          vty_out(vty, ", %s%s", out_ifname,
1239
0
            flag);
1240
#else
1241
          ttable_add_row(tt,
1242
                   "%c|%c|%c|%c|%c|%s%s",
1243
                   ' ', ' ', ' ', ' ', ' ',
1244
                   out_ifname, flag);
1245
#endif
1246
0
        }
1247
0
      }
1248
0
    }
1249
0
#if PIM_IPV == 4
1250
0
    if (!json)
1251
0
      vty_out(vty, "\n");
1252
0
#endif
1253
0
  }
1254
1255
  /* Dump the generated table. */
1256
0
  if (!json) {
1257
0
#if PIM_IPV == 4
1258
0
    vty_out(vty, "\n");
1259
#else
1260
    table = ttable_dump(tt, "\n");
1261
    vty_out(vty, "%s\n", table);
1262
    XFREE(MTYPE_TMP, table);
1263
    ttable_del(tt);
1264
#endif
1265
0
  }
1266
0
}
1267
1268
/* pim statistics - just adding only bsm related now.
1269
 * We can continue to add all pim related stats here.
1270
 */
1271
void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
1272
       const char *ifname, bool uj)
1273
0
{
1274
0
  json_object *json = NULL;
1275
0
  struct interface *ifp;
1276
1277
0
  if (uj) {
1278
0
    json = json_object_new_object();
1279
0
    json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
1280
0
    json_object_int_add(json, "bsmTx", pim->bsm_sent);
1281
0
    json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
1282
0
  } else {
1283
0
    vty_out(vty, "BSM Statistics :\n");
1284
0
    vty_out(vty, "----------------\n");
1285
0
    vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
1286
0
      pim->bsm_rcvd);
1287
0
    vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
1288
0
      pim->bsm_sent);
1289
0
    vty_out(vty, "Number of Dropped BSMs  : %" PRIu64 "\n",
1290
0
      pim->bsm_dropped);
1291
0
  }
1292
1293
0
  vty_out(vty, "\n");
1294
1295
  /* scan interfaces */
1296
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
1297
0
    struct pim_interface *pim_ifp = ifp->info;
1298
1299
0
    if (ifname && strcmp(ifname, ifp->name))
1300
0
      continue;
1301
1302
0
    if (!pim_ifp)
1303
0
      continue;
1304
1305
0
    if (!uj) {
1306
0
      vty_out(vty, "Interface : %s\n", ifp->name);
1307
0
      vty_out(vty, "-------------------\n");
1308
0
      vty_out(vty,
1309
0
        "Number of BSMs dropped due to config miss : %u\n",
1310
0
        pim_ifp->pim_ifstat_bsm_cfg_miss);
1311
0
      vty_out(vty, "Number of unicast BSMs dropped : %u\n",
1312
0
        pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1313
0
      vty_out(vty,
1314
0
        "Number of BSMs dropped due to invalid scope zone : %u\n",
1315
0
        pim_ifp->pim_ifstat_bsm_invalid_sz);
1316
0
    } else {
1317
1318
0
      json_object *json_row = NULL;
1319
1320
0
      json_row = json_object_new_object();
1321
1322
0
      json_object_string_add(json_row, "If Name", ifp->name);
1323
0
      json_object_int_add(json_row, "bsmDroppedConfig",
1324
0
              pim_ifp->pim_ifstat_bsm_cfg_miss);
1325
0
      json_object_int_add(
1326
0
        json_row, "bsmDroppedUnicast",
1327
0
        pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1328
0
      json_object_int_add(json_row,
1329
0
              "bsmDroppedInvalidScopeZone",
1330
0
              pim_ifp->pim_ifstat_bsm_invalid_sz);
1331
0
      json_object_object_add(json, ifp->name, json_row);
1332
0
    }
1333
0
    vty_out(vty, "\n");
1334
0
  }
1335
1336
0
  if (uj)
1337
0
    vty_json(vty, json);
1338
0
}
1339
1340
void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
1341
           pim_sgaddr *sg, json_object *json)
1342
0
{
1343
0
  struct pim_upstream *up;
1344
0
  struct ttable *tt = NULL;
1345
0
  char *table = NULL;
1346
0
  time_t now;
1347
0
  json_object *json_group = NULL;
1348
0
  json_object *json_row = NULL;
1349
1350
0
  now = pim_time_monotonic_sec();
1351
1352
0
  if (!json) {
1353
    /* Prepare table. */
1354
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1355
0
    ttable_add_row(
1356
0
      tt,
1357
0
      "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
1358
0
    tt->style.cell.rpad = 2;
1359
0
    tt->style.corner = '+';
1360
0
    ttable_restyle(tt);
1361
0
  }
1362
1363
0
  frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1364
0
    char uptime[10];
1365
0
    char join_timer[10];
1366
0
    char rs_timer[10];
1367
0
    char ka_timer[10];
1368
0
    char msdp_reg_timer[10];
1369
0
    char state_str[PIM_REG_STATE_STR_LEN];
1370
1371
0
    if (!pim_sgaddr_match(up->sg, *sg))
1372
0
      continue;
1373
1374
0
    pim_time_uptime(uptime, sizeof(uptime),
1375
0
        now - up->state_transition);
1376
0
    pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
1377
0
           up->t_join_timer);
1378
1379
    /*
1380
     * If the upstream is not dummy and it has a J/P timer for the
1381
     * neighbor display that
1382
     */
1383
0
    if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
1384
0
      struct pim_neighbor *nbr;
1385
1386
0
      nbr = pim_neighbor_find(
1387
0
        up->rpf.source_nexthop.interface,
1388
0
        up->rpf.rpf_addr, false);
1389
0
      if (nbr)
1390
0
        pim_time_timer_to_hhmmss(join_timer,
1391
0
               sizeof(join_timer),
1392
0
               nbr->jp_timer);
1393
0
    }
1394
1395
0
    pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
1396
0
           up->t_rs_timer);
1397
0
    pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
1398
0
           up->t_ka_timer);
1399
0
    pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
1400
0
           up->t_msdp_reg_timer);
1401
1402
0
    pim_upstream_state2brief_str(up->join_state, state_str,
1403
0
               sizeof(state_str));
1404
0
    if (up->reg_state != PIM_REG_NOINFO) {
1405
0
      char tmp_str[PIM_REG_STATE_STR_LEN];
1406
0
      char tmp[sizeof(state_str) + 1];
1407
1408
0
      snprintf(tmp, sizeof(tmp), ",%s",
1409
0
         pim_reg_state2brief_str(up->reg_state, tmp_str,
1410
0
               sizeof(tmp_str)));
1411
0
      strlcat(state_str, tmp, sizeof(state_str));
1412
0
    }
1413
1414
0
    if (json) {
1415
0
      char grp_str[PIM_ADDRSTRLEN];
1416
0
      char src_str[PIM_ADDRSTRLEN];
1417
1418
0
      snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1419
0
           &up->sg.grp);
1420
0
      snprintfrr(src_str, sizeof(src_str), "%pPAs",
1421
0
           &up->sg.src);
1422
1423
0
      json_object_object_get_ex(json, grp_str, &json_group);
1424
1425
0
      if (!json_group) {
1426
0
        json_group = json_object_new_object();
1427
0
        json_object_object_add(json, grp_str,
1428
0
                   json_group);
1429
0
      }
1430
1431
0
      json_row = json_object_new_object();
1432
0
      json_object_pim_upstream_add(json_row, up);
1433
0
      json_object_string_add(
1434
0
        json_row, "inboundInterface",
1435
0
        up->rpf.source_nexthop.interface
1436
0
        ? up->rpf.source_nexthop.interface->name
1437
0
        : "Unknown");
1438
1439
      /*
1440
       * The RPF address we use is slightly different
1441
       * based upon what we are looking up.
1442
       * If we have a S, list that unless
1443
       * we are the FHR, else we just put
1444
       * the RP as the rpfAddress
1445
       */
1446
0
      if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
1447
0
          pim_addr_is_any(up->sg.src)) {
1448
0
        struct pim_rpf *rpg;
1449
1450
0
        rpg = RP(pim, up->sg.grp);
1451
0
        json_object_string_addf(json_row, "rpfAddress",
1452
0
              "%pPA", &rpg->rpf_addr);
1453
0
      } else {
1454
0
        json_object_string_add(json_row, "rpfAddress",
1455
0
                   src_str);
1456
0
      }
1457
1458
0
      json_object_string_add(json_row, "source", src_str);
1459
0
      json_object_string_add(json_row, "group", grp_str);
1460
0
      json_object_string_add(json_row, "state", state_str);
1461
0
      json_object_string_add(
1462
0
        json_row, "joinState",
1463
0
        pim_upstream_state2str(up->join_state));
1464
0
      json_object_string_add(
1465
0
        json_row, "regState",
1466
0
        pim_reg_state2str(up->reg_state, state_str,
1467
0
              sizeof(state_str)));
1468
0
      json_object_string_add(json_row, "upTime", uptime);
1469
0
      json_object_string_add(json_row, "joinTimer",
1470
0
                 join_timer);
1471
0
      json_object_string_add(json_row, "resetTimer",
1472
0
                 rs_timer);
1473
0
      json_object_string_add(json_row, "keepaliveTimer",
1474
0
                 ka_timer);
1475
0
      json_object_string_add(json_row, "msdpRegTimer",
1476
0
                 msdp_reg_timer);
1477
0
      json_object_int_add(json_row, "refCount",
1478
0
              up->ref_count);
1479
0
      json_object_int_add(json_row, "sptBit", up->sptbit);
1480
0
      json_object_object_add(json_group, src_str, json_row);
1481
0
    } else {
1482
0
      ttable_add_row(tt,
1483
0
        "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
1484
0
        up->rpf.source_nexthop.interface
1485
0
        ? up->rpf.source_nexthop.interface->name
1486
0
        : "Unknown",
1487
0
        &up->sg.src, &up->sg.grp, state_str, uptime,
1488
0
        join_timer, rs_timer, ka_timer, up->ref_count);
1489
0
    }
1490
0
  }
1491
  /* Dump the generated table. */
1492
0
  if (!json) {
1493
0
    table = ttable_dump(tt, "\n");
1494
0
    vty_out(vty, "%s\n", table);
1495
0
    XFREE(MTYPE_TMP, table);
1496
0
    ttable_del(tt);
1497
0
  }
1498
0
}
1499
1500
static void pim_show_join_desired_helper(struct pim_instance *pim,
1501
           struct vty *vty,
1502
           struct pim_upstream *up,
1503
           json_object *json, bool uj,
1504
           struct ttable *tt)
1505
0
{
1506
0
  json_object *json_group = NULL;
1507
0
  json_object *json_row = NULL;
1508
1509
0
  if (uj) {
1510
0
    char grp_str[PIM_ADDRSTRLEN];
1511
0
    char src_str[PIM_ADDRSTRLEN];
1512
1513
0
    snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
1514
0
    snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
1515
1516
0
    json_object_object_get_ex(json, grp_str, &json_group);
1517
1518
0
    if (!json_group) {
1519
0
      json_group = json_object_new_object();
1520
0
      json_object_object_add(json, grp_str, json_group);
1521
0
    }
1522
1523
0
    json_row = json_object_new_object();
1524
0
    json_object_pim_upstream_add(json_row, up);
1525
0
    json_object_string_add(json_row, "source", src_str);
1526
0
    json_object_string_add(json_row, "group", grp_str);
1527
1528
0
    if (pim_upstream_evaluate_join_desired(pim, up))
1529
0
      json_object_boolean_true_add(json_row,
1530
0
                 "evaluateJoinDesired");
1531
1532
0
    json_object_object_add(json_group, src_str, json_row);
1533
1534
0
  } else {
1535
0
    ttable_add_row(tt, "%pPAs|%pPAs|%s", &up->sg.src, &up->sg.grp,
1536
0
             pim_upstream_evaluate_join_desired(pim, up)
1537
0
               ? "yes"
1538
0
               : "no");
1539
0
  }
1540
0
}
1541
1542
void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
1543
0
{
1544
0
  struct pim_upstream *up;
1545
0
  struct ttable *tt = NULL;
1546
0
  char *table = NULL;
1547
1548
0
  json_object *json = NULL;
1549
1550
0
  if (uj)
1551
0
    json = json_object_new_object();
1552
0
  else {
1553
    /* Prepare table. */
1554
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1555
0
    ttable_add_row(tt, "Source|Group|EvalJD");
1556
0
    tt->style.cell.rpad = 2;
1557
0
    tt->style.corner = '+';
1558
0
    ttable_restyle(tt);
1559
0
  }
1560
1561
0
  frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1562
    /* scan all interfaces */
1563
0
    pim_show_join_desired_helper(pim, vty, up, json, uj, tt);
1564
0
  }
1565
1566
0
  if (uj)
1567
0
    vty_json(vty, json);
1568
0
  else {
1569
    /* Dump the generated table. */
1570
0
    table = ttable_dump(tt, "\n");
1571
0
    vty_out(vty, "%s\n", table);
1572
0
    XFREE(MTYPE_TMP, table);
1573
0
    ttable_del(tt);
1574
0
  }
1575
0
}
1576
1577
void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
1578
0
{
1579
0
  struct pim_upstream *up;
1580
0
  struct ttable *tt = NULL;
1581
0
  char *table = NULL;
1582
0
  json_object *json = NULL;
1583
0
  json_object *json_group = NULL;
1584
0
  json_object *json_row = NULL;
1585
1586
0
  if (uj)
1587
0
    json = json_object_new_object();
1588
0
  else {
1589
    /* Prepare table. */
1590
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1591
0
    ttable_add_row(tt,
1592
0
             "Source|Group|RpfIface|RibNextHop|RpfAddress");
1593
0
    tt->style.cell.rpad = 2;
1594
0
    tt->style.corner = '+';
1595
0
    ttable_restyle(tt);
1596
0
  }
1597
1598
0
  frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1599
0
    struct pim_rpf *rpf;
1600
0
    const char *rpf_ifname;
1601
1602
0
    rpf = &up->rpf;
1603
1604
0
    rpf_ifname =
1605
0
      rpf->source_nexthop.interface ? rpf->source_nexthop
1606
0
                .interface->name
1607
0
                  : "<ifname?>";
1608
1609
0
    if (uj) {
1610
0
      char grp_str[PIM_ADDRSTRLEN];
1611
0
      char src_str[PIM_ADDRSTRLEN];
1612
1613
0
      snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1614
0
           &up->sg.grp);
1615
0
      snprintfrr(src_str, sizeof(src_str), "%pPAs",
1616
0
           &up->sg.src);
1617
0
      json_object_object_get_ex(json, grp_str, &json_group);
1618
1619
0
      if (!json_group) {
1620
0
        json_group = json_object_new_object();
1621
0
        json_object_object_add(json, grp_str,
1622
0
                   json_group);
1623
0
      }
1624
1625
0
      json_row = json_object_new_object();
1626
0
      json_object_pim_upstream_add(json_row, up);
1627
0
      json_object_string_add(json_row, "source", src_str);
1628
0
      json_object_string_add(json_row, "group", grp_str);
1629
0
      json_object_string_add(json_row, "rpfInterface",
1630
0
                 rpf_ifname);
1631
0
      json_object_string_addf(
1632
0
        json_row, "ribNexthop", "%pPAs",
1633
0
        &rpf->source_nexthop.mrib_nexthop_addr);
1634
0
      json_object_string_addf(json_row, "rpfAddress", "%pPA",
1635
0
            &rpf->rpf_addr);
1636
0
      json_object_object_add(json_group, src_str, json_row);
1637
0
    } else {
1638
0
      ttable_add_row(tt, "%pPAs|%pPAs|%s|%pPA|%pPA",
1639
0
               &up->sg.src, &up->sg.grp, rpf_ifname,
1640
0
               &rpf->source_nexthop.mrib_nexthop_addr,
1641
0
               &rpf->rpf_addr);
1642
0
    }
1643
0
  }
1644
1645
0
  if (uj)
1646
0
    vty_json(vty, json);
1647
0
  else {
1648
    /* Dump the generated table. */
1649
0
    table = ttable_dump(tt, "\n");
1650
0
    vty_out(vty, "%s\n", table);
1651
0
    XFREE(MTYPE_TMP, table);
1652
0
    ttable_del(tt);
1653
0
  }
1654
0
}
1655
1656
static void pim_show_join_helper(struct pim_interface *pim_ifp,
1657
         struct pim_ifchannel *ch, json_object *json,
1658
         time_t now, struct ttable *tt)
1659
0
{
1660
0
  json_object *json_iface = NULL;
1661
0
  json_object *json_row = NULL;
1662
0
  json_object *json_grp = NULL;
1663
0
  pim_addr ifaddr;
1664
0
  char uptime[10];
1665
0
  char expire[10];
1666
0
  char prune[10];
1667
1668
0
  ifaddr = pim_ifp->primary_address;
1669
1670
0
  pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1671
0
  pim_time_timer_to_mmss(expire, sizeof(expire),
1672
0
             ch->t_ifjoin_expiry_timer);
1673
0
  pim_time_timer_to_mmss(prune, sizeof(prune),
1674
0
             ch->t_ifjoin_prune_pending_timer);
1675
1676
0
  if (json) {
1677
0
    char ch_grp_str[PIM_ADDRSTRLEN];
1678
1679
0
    json_object_object_get_ex(json, ch->interface->name,
1680
0
            &json_iface);
1681
1682
0
    if (!json_iface) {
1683
0
      json_iface = json_object_new_object();
1684
0
      json_object_pim_ifp_add(json_iface, ch->interface);
1685
0
      json_object_object_add(json, ch->interface->name,
1686
0
                 json_iface);
1687
0
    }
1688
1689
0
    json_row = json_object_new_object();
1690
0
    json_object_string_addf(json_row, "source", "%pPAs",
1691
0
          &ch->sg.src);
1692
0
    json_object_string_addf(json_row, "group", "%pPAs",
1693
0
          &ch->sg.grp);
1694
0
    json_object_string_add(json_row, "upTime", uptime);
1695
0
    json_object_string_add(json_row, "expire", expire);
1696
0
    json_object_string_add(json_row, "prune", prune);
1697
0
    json_object_string_add(
1698
0
      json_row, "channelJoinName",
1699
0
      pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
1700
0
    if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
1701
0
      json_object_int_add(json_row, "sgRpt", 1);
1702
0
    if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
1703
0
      json_object_int_add(json_row, "protocolPim", 1);
1704
0
    if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
1705
0
      json_object_int_add(json_row, "protocolIgmp", 1);
1706
0
    snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
1707
0
         &ch->sg.grp);
1708
0
    json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
1709
0
    if (!json_grp) {
1710
0
      json_grp = json_object_new_object();
1711
0
      json_object_object_addf(json_grp, json_row, "%pPAs",
1712
0
            &ch->sg.src);
1713
0
      json_object_object_addf(json_iface, json_grp, "%pPAs",
1714
0
            &ch->sg.grp);
1715
0
    } else
1716
0
      json_object_object_addf(json_grp, json_row, "%pPAs",
1717
0
            &ch->sg.src);
1718
0
  } else {
1719
0
    ttable_add_row(
1720
0
      tt, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
1721
0
      ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
1722
0
      pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
1723
0
      uptime, expire, prune);
1724
0
  }
1725
0
}
1726
1727
int pim_show_join_cmd_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
1728
           pim_addr g, const char *json)
1729
0
{
1730
0
  pim_sgaddr sg = {};
1731
0
  struct vrf *v;
1732
0
  struct pim_instance *pim;
1733
0
  json_object *json_parent = NULL;
1734
1735
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1736
1737
0
  if (!v) {
1738
0
    vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
1739
0
    return CMD_WARNING;
1740
0
  }
1741
0
  pim = v->info;
1742
1743
0
  if (!pim) {
1744
0
    vty_out(vty, "%% Unable to find pim instance\n");
1745
0
    return CMD_WARNING;
1746
0
  }
1747
1748
0
  if (!pim_addr_is_any(s_or_g)) {
1749
0
    if (!pim_addr_is_any(g)) {
1750
0
      sg.src = s_or_g;
1751
0
      sg.grp = g;
1752
0
    } else
1753
0
      sg.grp = s_or_g;
1754
0
  }
1755
1756
0
  if (json)
1757
0
    json_parent = json_object_new_object();
1758
1759
0
  pim_show_join(pim, vty, &sg, json_parent);
1760
1761
0
  if (json)
1762
0
    vty_json(vty, json_parent);
1763
1764
0
  return CMD_SUCCESS;
1765
0
}
1766
1767
int pim_show_join_vrf_all_cmd_helper(struct vty *vty, const char *json)
1768
0
{
1769
0
  pim_sgaddr sg = {0};
1770
0
  struct vrf *vrf_struct;
1771
0
  json_object *json_parent = NULL;
1772
0
  json_object *json_vrf = NULL;
1773
1774
0
  if (json)
1775
0
    json_parent = json_object_new_object();
1776
1777
0
  RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) {
1778
0
    if (!json_parent)
1779
0
      vty_out(vty, "VRF: %s\n", vrf_struct->name);
1780
0
    else
1781
0
      json_vrf = json_object_new_object();
1782
0
    pim_show_join(vrf_struct->info, vty, &sg, json_vrf);
1783
1784
0
    if (json)
1785
0
      json_object_object_add(json_parent, vrf_struct->name,
1786
0
                 json_vrf);
1787
0
  }
1788
0
  if (json)
1789
0
    vty_json(vty, json_parent);
1790
1791
0
  return CMD_WARNING;
1792
0
}
1793
1794
void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
1795
       json_object *json)
1796
0
{
1797
0
  struct pim_interface *pim_ifp;
1798
0
  struct pim_ifchannel *ch;
1799
0
  struct interface *ifp;
1800
0
  time_t now;
1801
0
  struct ttable *tt = NULL;
1802
0
  char *table = NULL;
1803
1804
0
  now = pim_time_monotonic_sec();
1805
1806
0
  if (!json) {
1807
    /* Prepare table. */
1808
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1809
0
    ttable_add_row(
1810
0
      tt,
1811
0
      "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
1812
0
    tt->style.cell.rpad = 2;
1813
0
    tt->style.corner = '+';
1814
0
    ttable_restyle(tt);
1815
0
  }
1816
1817
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
1818
0
    pim_ifp = ifp->info;
1819
0
    if (!pim_ifp)
1820
0
      continue;
1821
1822
0
    RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1823
0
      if (!pim_sgaddr_match(ch->sg, *sg))
1824
0
        continue;
1825
1826
0
      pim_show_join_helper(pim_ifp, ch, json, now, tt);
1827
0
    } /* scan interface channels */
1828
0
  }
1829
  /* Dump the generated table. */
1830
0
  if (!json) {
1831
0
    table = ttable_dump(tt, "\n");
1832
0
    vty_out(vty, "%s\n", table);
1833
0
    XFREE(MTYPE_TMP, table);
1834
0
    ttable_del(tt);
1835
0
  }
1836
0
}
1837
1838
static void pim_show_jp_agg_helper(struct interface *ifp,
1839
           struct pim_neighbor *neigh,
1840
           struct pim_upstream *up, int is_join,
1841
           struct ttable *tt)
1842
0
{
1843
0
  ttable_add_row(tt, "%s|%pPAs|%pPAs|%pPAs|%s", ifp->name,
1844
0
           &neigh->source_addr, &up->sg.src, &up->sg.grp,
1845
0
           is_join ? "J" : "P");
1846
0
}
1847
1848
int pim_show_jp_agg_list_cmd_helper(const char *vrf, struct vty *vty)
1849
0
{
1850
0
  struct vrf *v;
1851
0
  struct pim_instance *pim;
1852
1853
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1854
1855
0
  if (!v) {
1856
0
    vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
1857
0
    return CMD_WARNING;
1858
0
  }
1859
0
  pim = v->info;
1860
1861
0
  if (!pim) {
1862
0
    vty_out(vty, "%% Unable to find pim instance\n");
1863
0
    return CMD_WARNING;
1864
0
  }
1865
1866
0
  pim_show_jp_agg_list(pim, vty);
1867
1868
0
  return CMD_SUCCESS;
1869
0
}
1870
1871
void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
1872
0
{
1873
0
  struct interface *ifp;
1874
0
  struct pim_interface *pim_ifp;
1875
0
  struct listnode *n_node;
1876
0
  struct pim_neighbor *neigh;
1877
0
  struct listnode *jag_node;
1878
0
  struct pim_jp_agg_group *jag;
1879
0
  struct listnode *js_node;
1880
0
  struct pim_jp_sources *js;
1881
0
  struct ttable *tt;
1882
0
  char *table;
1883
1884
  /* Prepare table. */
1885
0
  tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1886
0
  ttable_add_row(tt, "Interface|RPF Nbr|Source|Group|State");
1887
0
  tt->style.cell.rpad = 2;
1888
0
  tt->style.corner = '+';
1889
0
  ttable_restyle(tt);
1890
1891
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
1892
0
    pim_ifp = ifp->info;
1893
0
    if (!pim_ifp)
1894
0
      continue;
1895
1896
0
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
1897
0
            neigh)) {
1898
0
      for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
1899
0
              jag_node, jag)) {
1900
0
        for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
1901
0
                js)) {
1902
0
          pim_show_jp_agg_helper(ifp, neigh,
1903
0
                     js->up,
1904
0
                     js->is_join, tt);
1905
0
        }
1906
0
      }
1907
0
    }
1908
0
  }
1909
1910
  /* Dump the generated table. */
1911
0
  table = ttable_dump(tt, "\n");
1912
0
  vty_out(vty, "%s\n", table);
1913
0
  XFREE(MTYPE_TMP, table);
1914
0
  ttable_del(tt);
1915
0
}
1916
1917
int pim_show_membership_cmd_helper(const char *vrf, struct vty *vty, bool uj)
1918
0
{
1919
0
  struct vrf *v;
1920
1921
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1922
1923
0
  if (!v)
1924
0
    return CMD_WARNING;
1925
1926
0
  pim_show_membership(v->info, vty, uj);
1927
1928
0
  return CMD_SUCCESS;
1929
0
}
1930
1931
static void pim_show_membership_helper(struct vty *vty,
1932
               struct pim_interface *pim_ifp,
1933
               struct pim_ifchannel *ch,
1934
               struct json_object *json)
1935
0
{
1936
0
  json_object *json_iface = NULL;
1937
0
  json_object *json_row = NULL;
1938
1939
0
  json_object_object_get_ex(json, ch->interface->name, &json_iface);
1940
0
  if (!json_iface) {
1941
0
    json_iface = json_object_new_object();
1942
0
    json_object_pim_ifp_add(json_iface, ch->interface);
1943
0
    json_object_object_add(json, ch->interface->name, json_iface);
1944
0
  }
1945
1946
0
  json_row = json_object_new_object();
1947
0
  json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
1948
0
  json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
1949
0
  json_object_string_add(json_row, "localMembership",
1950
0
             ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
1951
0
               ? "NOINFO"
1952
0
               : "INCLUDE");
1953
0
  json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
1954
0
}
1955
1956
void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
1957
0
{
1958
0
  struct pim_interface *pim_ifp;
1959
0
  struct pim_ifchannel *ch;
1960
0
  struct interface *ifp;
1961
0
  enum json_type type;
1962
0
  json_object *json = NULL;
1963
0
  json_object *json_tmp = NULL;
1964
0
  struct ttable *tt = NULL;
1965
0
  char *table = NULL;
1966
1967
0
  json = json_object_new_object();
1968
1969
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
1970
0
    pim_ifp = ifp->info;
1971
0
    if (!pim_ifp)
1972
0
      continue;
1973
1974
0
    RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1975
0
      pim_show_membership_helper(vty, pim_ifp, ch, json);
1976
0
    } /* scan interface channels */
1977
0
  }
1978
1979
0
  if (uj) {
1980
0
    vty_json(vty, json);
1981
0
  } else {
1982
    /* Prepare table. */
1983
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1984
0
    ttable_add_row(tt, "Interface|Address|Source|Group|Membership");
1985
0
    tt->style.cell.rpad = 2;
1986
0
    tt->style.corner = '+';
1987
0
    ttable_restyle(tt);
1988
1989
    /*
1990
     * Example of the json data we are traversing
1991
     *
1992
     * {
1993
     *   "swp3":{
1994
     *     "name":"swp3",
1995
     *     "state":"up",
1996
     *     "address":"10.1.20.1",
1997
     *     "index":5,
1998
     *     "flagMulticast":true,
1999
     *     "flagBroadcast":true,
2000
     *     "lanDelayEnabled":true,
2001
     *     "226.10.10.10":{
2002
     *       "source":"*",
2003
     *       "group":"226.10.10.10",
2004
     *       "localMembership":"INCLUDE"
2005
     *     }
2006
     *   }
2007
     * }
2008
     */
2009
2010
    /* foreach interface */
2011
0
    json_object_object_foreach(json, key, val)
2012
0
    {
2013
2014
      /* Find all of the keys where the val is an object. In
2015
       * the example
2016
       * above the only one is 226.10.10.10
2017
       */
2018
0
      json_object_object_foreach(val, if_field_key,
2019
0
               if_field_val)
2020
0
      {
2021
0
        type = json_object_get_type(if_field_val);
2022
2023
0
        if (type == json_type_object) {
2024
0
          const char *address, *source,
2025
0
            *localMembership;
2026
2027
0
          json_object_object_get_ex(
2028
0
            val, "address", &json_tmp);
2029
0
          address = json_object_get_string(
2030
0
            json_tmp);
2031
2032
0
          json_object_object_get_ex(if_field_val,
2033
0
                  "source",
2034
0
                  &json_tmp);
2035
0
          source = json_object_get_string(
2036
0
            json_tmp);
2037
2038
0
          json_object_object_get_ex(
2039
0
            if_field_val, "localMembership",
2040
0
            &json_tmp);
2041
0
          localMembership =
2042
0
            json_object_get_string(
2043
0
              json_tmp);
2044
2045
0
          ttable_add_row(tt, "%s|%s|%s|%s|%s",
2046
0
                   key, address, source,
2047
0
                   if_field_key,
2048
0
                   localMembership);
2049
0
        }
2050
0
      }
2051
0
    }
2052
0
    json_object_free(json);
2053
    /* Dump the generated table. */
2054
0
    table = ttable_dump(tt, "\n");
2055
0
    vty_out(vty, "%s\n", table);
2056
0
    XFREE(MTYPE_TMP, table);
2057
0
    ttable_del(tt);
2058
0
  }
2059
0
}
2060
2061
static void pim_show_channel_helper(struct pim_instance *pim,
2062
            struct pim_interface *pim_ifp,
2063
            struct pim_ifchannel *ch, json_object *json,
2064
            bool uj, struct ttable *tt)
2065
0
{
2066
0
  struct pim_upstream *up = ch->upstream;
2067
0
  json_object *json_group = NULL;
2068
0
  json_object *json_row = NULL;
2069
2070
0
  if (uj) {
2071
0
    char grp_str[PIM_ADDRSTRLEN];
2072
2073
0
    snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
2074
0
    json_object_object_get_ex(json, grp_str, &json_group);
2075
2076
0
    if (!json_group) {
2077
0
      json_group = json_object_new_object();
2078
0
      json_object_object_add(json, grp_str, json_group);
2079
0
    }
2080
2081
0
    json_row = json_object_new_object();
2082
0
    json_object_pim_upstream_add(json_row, up);
2083
0
    json_object_string_add(json_row, "interface",
2084
0
               ch->interface->name);
2085
0
    json_object_string_addf(json_row, "source", "%pPAs",
2086
0
          &up->sg.src);
2087
0
    json_object_string_addf(json_row, "group", "%pPAs",
2088
0
          &up->sg.grp);
2089
2090
0
    if (pim_macro_ch_lost_assert(ch))
2091
0
      json_object_boolean_true_add(json_row, "lostAssert");
2092
2093
0
    if (pim_macro_chisin_joins(ch))
2094
0
      json_object_boolean_true_add(json_row, "joins");
2095
2096
0
    if (pim_macro_chisin_pim_include(ch))
2097
0
      json_object_boolean_true_add(json_row, "pimInclude");
2098
2099
0
    if (pim_upstream_evaluate_join_desired(pim, up))
2100
0
      json_object_boolean_true_add(json_row,
2101
0
                 "evaluateJoinDesired");
2102
2103
0
    json_object_object_addf(json_group, json_row, "%pPAs",
2104
0
          &up->sg.src);
2105
2106
0
  } else {
2107
0
    ttable_add_row(tt, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
2108
0
             ch->interface->name, &up->sg.src, &up->sg.grp,
2109
0
             pim_macro_ch_lost_assert(ch) ? "yes" : "no",
2110
0
             pim_macro_chisin_joins(ch) ? "yes" : "no",
2111
0
             pim_macro_chisin_pim_include(ch) ? "yes" : "no",
2112
0
             PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
2113
0
               ? "yes"
2114
0
               : "no",
2115
0
             pim_upstream_evaluate_join_desired(pim, up)
2116
0
               ? "yes"
2117
0
               : "no");
2118
0
  }
2119
0
}
2120
2121
void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
2122
0
{
2123
0
  struct pim_interface *pim_ifp;
2124
0
  struct pim_ifchannel *ch;
2125
0
  struct interface *ifp;
2126
0
  struct ttable *tt = NULL;
2127
0
  json_object *json = NULL;
2128
0
  char *table = NULL;
2129
2130
0
  if (uj)
2131
0
    json = json_object_new_object();
2132
0
  else {
2133
    /* Prepare table. */
2134
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2135
0
    ttable_add_row(
2136
0
      tt,
2137
0
      "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
2138
0
    tt->style.cell.rpad = 2;
2139
0
    tt->style.corner = '+';
2140
0
    ttable_restyle(tt);
2141
0
  }
2142
2143
  /* scan per-interface (S,G) state */
2144
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
2145
0
    pim_ifp = ifp->info;
2146
0
    if (!pim_ifp)
2147
0
      continue;
2148
2149
0
    RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
2150
      /* scan all interfaces */
2151
0
      pim_show_channel_helper(pim, pim_ifp, ch, json, uj, tt);
2152
0
    }
2153
0
  }
2154
2155
0
  if (uj)
2156
0
    vty_json(vty, json);
2157
0
  else {
2158
    /* Dump the generated table. */
2159
0
    table = ttable_dump(tt, "\n");
2160
0
    vty_out(vty, "%s\n", table);
2161
0
    XFREE(MTYPE_TMP, table);
2162
0
    ttable_del(tt);
2163
0
  }
2164
0
}
2165
2166
int pim_show_channel_cmd_helper(const char *vrf, struct vty *vty, bool uj)
2167
0
{
2168
0
  struct vrf *v;
2169
2170
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2171
2172
0
  if (!v)
2173
0
    return CMD_WARNING;
2174
2175
0
  pim_show_channel(v->info, vty, uj);
2176
2177
0
  return CMD_SUCCESS;
2178
0
}
2179
2180
int pim_show_interface_cmd_helper(const char *vrf, struct vty *vty, bool uj,
2181
          bool mlag, const char *interface)
2182
0
{
2183
0
  struct vrf *v;
2184
0
  json_object *json_parent = NULL;
2185
2186
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2187
2188
0
  if (!v)
2189
0
    return CMD_WARNING;
2190
2191
0
  if (uj)
2192
0
    json_parent = json_object_new_object();
2193
2194
0
  if (interface)
2195
0
    pim_show_interfaces_single(v->info, vty, interface, mlag,
2196
0
             json_parent);
2197
0
  else
2198
0
    pim_show_interfaces(v->info, vty, mlag, json_parent);
2199
2200
0
  if (uj)
2201
0
    vty_json(vty, json_parent);
2202
2203
0
  return CMD_SUCCESS;
2204
0
}
2205
2206
int pim_show_interface_vrf_all_cmd_helper(struct vty *vty, bool uj, bool mlag,
2207
            const char *interface)
2208
0
{
2209
0
  struct vrf *v;
2210
0
  json_object *json_parent = NULL;
2211
0
  json_object *json_vrf = NULL;
2212
2213
0
  if (uj)
2214
0
    json_parent = json_object_new_object();
2215
2216
0
  RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
2217
0
    if (!uj)
2218
0
      vty_out(vty, "VRF: %s\n", v->name);
2219
0
    else
2220
0
      json_vrf = json_object_new_object();
2221
2222
0
    if (interface)
2223
0
      pim_show_interfaces_single(v->info, vty, interface,
2224
0
               mlag, json_vrf);
2225
0
    else
2226
0
      pim_show_interfaces(v->info, vty, mlag, json_vrf);
2227
2228
0
    if (uj)
2229
0
      json_object_object_add(json_parent, v->name, json_vrf);
2230
0
  }
2231
0
  if (uj)
2232
0
    vty_json(vty, json_parent);
2233
2234
0
  return CMD_SUCCESS;
2235
0
}
2236
2237
void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
2238
       json_object *json)
2239
0
{
2240
0
  struct interface *ifp;
2241
0
  struct pim_interface *pim_ifp;
2242
0
  struct pim_upstream *up;
2243
0
  int fhr = 0;
2244
0
  int pim_nbrs = 0;
2245
0
  int pim_ifchannels = 0;
2246
0
  bool uj = true;
2247
0
  struct ttable *tt = NULL;
2248
0
  char *table = NULL;
2249
0
  json_object *json_row = NULL;
2250
0
  json_object *json_tmp;
2251
2252
0
  if (!json) {
2253
0
    uj = false;
2254
0
    json = json_object_new_object();
2255
0
  }
2256
2257
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
2258
0
    pim_ifp = ifp->info;
2259
2260
0
    if (!pim_ifp)
2261
0
      continue;
2262
2263
0
    if (mlag == true && pim_ifp->activeactive == false)
2264
0
      continue;
2265
2266
0
    pim_nbrs = pim_ifp->pim_neighbor_list->count;
2267
0
    pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
2268
0
    fhr = 0;
2269
2270
0
    frr_each (rb_pim_upstream, &pim->upstream_head, up)
2271
0
      if (ifp == up->rpf.source_nexthop.interface)
2272
0
        if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
2273
0
          fhr++;
2274
2275
0
    json_row = json_object_new_object();
2276
0
    json_object_pim_ifp_add(json_row, ifp);
2277
0
    json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
2278
0
    json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
2279
0
    json_object_int_add(json_row, "firstHopRouterCount", fhr);
2280
0
    json_object_string_addf(json_row, "pimDesignatedRouter",
2281
0
          "%pPAs", &pim_ifp->pim_dr_addr);
2282
2283
0
    if (!pim_addr_cmp(pim_ifp->pim_dr_addr,
2284
0
          pim_ifp->primary_address))
2285
0
      json_object_boolean_true_add(
2286
0
        json_row, "pimDesignatedRouterLocal");
2287
2288
0
    json_object_object_add(json, ifp->name, json_row);
2289
0
  }
2290
2291
0
  if (!uj) {
2292
2293
    /* Prepare table. */
2294
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2295
0
    ttable_add_row(
2296
0
      tt,
2297
0
      "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
2298
0
    tt->style.cell.rpad = 2;
2299
0
    tt->style.corner = '+';
2300
0
    ttable_restyle(tt);
2301
2302
0
    json_object_object_foreach(json, key, val)
2303
0
    {
2304
0
      const char *state, *address, *pimdr;
2305
0
      int neighbors, firsthpr, pimifchnl;
2306
2307
0
      json_object_object_get_ex(val, "state", &json_tmp);
2308
0
      state = json_object_get_string(json_tmp);
2309
2310
0
      json_object_object_get_ex(val, "address", &json_tmp);
2311
0
      address = json_object_get_string(json_tmp);
2312
2313
0
      json_object_object_get_ex(val, "pimNeighbors",
2314
0
              &json_tmp);
2315
0
      neighbors = json_object_get_int(json_tmp);
2316
2317
0
      if (json_object_object_get_ex(
2318
0
            val, "pimDesignatedRouterLocal",
2319
0
            &json_tmp)) {
2320
0
        pimdr = "local";
2321
0
      } else {
2322
0
        json_object_object_get_ex(
2323
0
          val, "pimDesignatedRouter", &json_tmp);
2324
0
        pimdr = json_object_get_string(json_tmp);
2325
0
      }
2326
2327
0
      json_object_object_get_ex(val, "firstHopRouter",
2328
0
              &json_tmp);
2329
0
      firsthpr = json_object_get_int(json_tmp);
2330
2331
0
      json_object_object_get_ex(val, "pimIfChannels",
2332
0
              &json_tmp);
2333
0
      pimifchnl = json_object_get_int(json_tmp);
2334
2335
0
      ttable_add_row(tt, "%s|%s|%s|%d|%s|%d|%d", key, state,
2336
0
               address, neighbors, pimdr, firsthpr,
2337
0
               pimifchnl);
2338
0
    }
2339
0
    json_object_free(json);
2340
2341
    /* Dump the generated table. */
2342
0
    table = ttable_dump(tt, "\n");
2343
0
    vty_out(vty, "%s\n", table);
2344
0
    XFREE(MTYPE_TMP, table);
2345
2346
0
    ttable_del(tt);
2347
0
  }
2348
0
}
2349
2350
void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
2351
        const char *ifname, bool mlag,
2352
        json_object *json)
2353
0
{
2354
0
  pim_addr ifaddr;
2355
0
  struct interface *ifp;
2356
0
  struct listnode *neighnode;
2357
0
  struct pim_interface *pim_ifp;
2358
0
  struct pim_neighbor *neigh;
2359
0
  struct pim_upstream *up;
2360
0
  time_t now;
2361
0
  char dr_str[PIM_ADDRSTRLEN];
2362
0
  char dr_uptime[10];
2363
0
  char expire[10];
2364
0
  char grp_str[PIM_ADDRSTRLEN];
2365
0
  char hello_period[10];
2366
0
  char hello_timer[10];
2367
0
  char neigh_src_str[PIM_ADDRSTRLEN];
2368
0
  char src_str[PIM_ADDRSTRLEN];
2369
0
  char stat_uptime[10];
2370
0
  char uptime[10];
2371
0
  int found_ifname = 0;
2372
0
  int print_header;
2373
0
  json_object *json_row = NULL;
2374
0
  json_object *json_pim_neighbor = NULL;
2375
0
  json_object *json_pim_neighbors = NULL;
2376
0
  json_object *json_group = NULL;
2377
0
  json_object *json_group_source = NULL;
2378
0
  json_object *json_fhr_sources = NULL;
2379
0
  struct pim_secondary_addr *sec_addr;
2380
0
  struct listnode *sec_node;
2381
2382
0
  now = pim_time_monotonic_sec();
2383
2384
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
2385
0
    pim_ifp = ifp->info;
2386
2387
0
    if (!pim_ifp)
2388
0
      continue;
2389
2390
0
    if (mlag == true && pim_ifp->activeactive == false)
2391
0
      continue;
2392
2393
0
    if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
2394
0
      continue;
2395
2396
0
    found_ifname = 1;
2397
0
    ifaddr = pim_ifp->primary_address;
2398
0
    snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
2399
0
         &pim_ifp->pim_dr_addr);
2400
0
    pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
2401
0
              pim_ifp->pim_dr_election_last);
2402
0
    pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
2403
0
           pim_ifp->t_pim_hello_timer);
2404
0
    pim_time_mmss(hello_period, sizeof(hello_period),
2405
0
            pim_ifp->pim_hello_period);
2406
0
    pim_time_uptime(stat_uptime, sizeof(stat_uptime),
2407
0
        now - pim_ifp->pim_ifstat_start);
2408
2409
0
    if (json) {
2410
0
      json_row = json_object_new_object();
2411
0
      json_object_pim_ifp_add(json_row, ifp);
2412
2413
0
      if (!pim_addr_is_any(pim_ifp->update_source)) {
2414
0
        json_object_string_addf(
2415
0
          json_row, "useSource", "%pPAs",
2416
0
          &pim_ifp->update_source);
2417
0
      }
2418
0
      if (pim_ifp->sec_addr_list) {
2419
0
        json_object *sec_list = NULL;
2420
2421
0
        sec_list = json_object_new_array();
2422
0
        for (ALL_LIST_ELEMENTS_RO(
2423
0
               pim_ifp->sec_addr_list, sec_node,
2424
0
               sec_addr)) {
2425
0
          json_object_array_add(
2426
0
            sec_list,
2427
0
            json_object_new_stringf(
2428
0
              "%pFXh",
2429
0
              &sec_addr->addr));
2430
0
        }
2431
0
        json_object_object_add(json_row,
2432
0
                   "secondaryAddressList",
2433
0
                   sec_list);
2434
0
      }
2435
2436
0
      if (pim_ifp->pim_passive_enable)
2437
0
        json_object_boolean_true_add(json_row,
2438
0
                   "passive");
2439
2440
      /* PIM neighbors */
2441
0
      if (pim_ifp->pim_neighbor_list->count) {
2442
0
        json_pim_neighbors = json_object_new_object();
2443
2444
0
        for (ALL_LIST_ELEMENTS_RO(
2445
0
               pim_ifp->pim_neighbor_list,
2446
0
               neighnode, neigh)) {
2447
0
          json_pim_neighbor =
2448
0
            json_object_new_object();
2449
0
          snprintfrr(neigh_src_str,
2450
0
               sizeof(neigh_src_str),
2451
0
               "%pPAs",
2452
0
               &neigh->source_addr);
2453
0
          pim_time_uptime(uptime, sizeof(uptime),
2454
0
              now - neigh->creation);
2455
0
          pim_time_timer_to_hhmmss(
2456
0
            expire, sizeof(expire),
2457
0
            neigh->t_expire_timer);
2458
2459
0
          json_object_string_add(
2460
0
            json_pim_neighbor, "address",
2461
0
            neigh_src_str);
2462
0
          json_object_string_add(
2463
0
            json_pim_neighbor, "upTime",
2464
0
            uptime);
2465
0
          json_object_string_add(
2466
0
            json_pim_neighbor, "holdtime",
2467
0
            expire);
2468
2469
0
          json_object_object_add(
2470
0
            json_pim_neighbors,
2471
0
            neigh_src_str,
2472
0
            json_pim_neighbor);
2473
0
        }
2474
2475
0
        json_object_object_add(json_row, "neighbors",
2476
0
                   json_pim_neighbors);
2477
0
      }
2478
2479
0
      json_object_string_add(json_row, "drAddress", dr_str);
2480
0
      json_object_int_add(json_row, "drPriority",
2481
0
              pim_ifp->pim_dr_priority);
2482
0
      json_object_string_add(json_row, "drUptime", dr_uptime);
2483
0
      json_object_int_add(json_row, "drElections",
2484
0
              pim_ifp->pim_dr_election_count);
2485
0
      json_object_int_add(json_row, "drChanges",
2486
0
              pim_ifp->pim_dr_election_changes);
2487
2488
      /* FHR */
2489
0
      frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2490
0
        if (ifp != up->rpf.source_nexthop.interface)
2491
0
          continue;
2492
2493
0
        if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2494
0
          continue;
2495
2496
0
        if (!json_fhr_sources)
2497
0
          json_fhr_sources =
2498
0
            json_object_new_object();
2499
2500
0
        snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
2501
0
             &up->sg.grp);
2502
0
        snprintfrr(src_str, sizeof(src_str), "%pPAs",
2503
0
             &up->sg.src);
2504
0
        pim_time_uptime(uptime, sizeof(uptime),
2505
0
            now - up->state_transition);
2506
2507
        /*
2508
         * Does this group live in json_fhr_sources?
2509
         * If not create it.
2510
         */
2511
0
        json_object_object_get_ex(json_fhr_sources,
2512
0
                grp_str, &json_group);
2513
2514
0
        if (!json_group) {
2515
0
          json_group = json_object_new_object();
2516
0
          json_object_object_add(json_fhr_sources,
2517
0
                     grp_str,
2518
0
                     json_group);
2519
0
        }
2520
2521
0
        json_group_source = json_object_new_object();
2522
0
        json_object_string_add(json_group_source,
2523
0
                   "source", src_str);
2524
0
        json_object_string_add(json_group_source,
2525
0
                   "group", grp_str);
2526
0
        json_object_string_add(json_group_source,
2527
0
                   "upTime", uptime);
2528
0
        json_object_object_add(json_group, src_str,
2529
0
                   json_group_source);
2530
0
      }
2531
2532
0
      if (json_fhr_sources) {
2533
0
        json_object_object_add(json_row,
2534
0
                   "firstHopRouter",
2535
0
                   json_fhr_sources);
2536
0
      }
2537
2538
0
      json_object_int_add(json_row, "helloPeriod",
2539
0
              pim_ifp->pim_hello_period);
2540
0
      json_object_int_add(json_row, "holdTime",
2541
0
              PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2542
0
      json_object_string_add(json_row, "helloTimer",
2543
0
                 hello_timer);
2544
0
      json_object_string_add(json_row, "helloStatStart",
2545
0
                 stat_uptime);
2546
0
      json_object_int_add(json_row, "helloReceived",
2547
0
              pim_ifp->pim_ifstat_hello_recv);
2548
0
      json_object_int_add(json_row, "helloReceivedFailed",
2549
0
              pim_ifp->pim_ifstat_hello_recvfail);
2550
0
      json_object_int_add(json_row, "helloSend",
2551
0
              pim_ifp->pim_ifstat_hello_sent);
2552
0
      json_object_int_add(json_row, "hellosendFailed",
2553
0
              pim_ifp->pim_ifstat_hello_sendfail);
2554
0
      json_object_int_add(json_row, "helloGenerationId",
2555
0
              pim_ifp->pim_generation_id);
2556
2557
0
      json_object_int_add(
2558
0
        json_row, "effectivePropagationDelay",
2559
0
        pim_if_effective_propagation_delay_msec(ifp));
2560
0
      json_object_int_add(
2561
0
        json_row, "effectiveOverrideInterval",
2562
0
        pim_if_effective_override_interval_msec(ifp));
2563
0
      json_object_int_add(
2564
0
        json_row, "joinPruneOverrideInterval",
2565
0
        pim_if_jp_override_interval_msec(ifp));
2566
2567
0
      json_object_int_add(
2568
0
        json_row, "propagationDelay",
2569
0
        pim_ifp->pim_propagation_delay_msec);
2570
0
      json_object_int_add(
2571
0
        json_row, "propagationDelayHighest",
2572
0
        pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2573
0
      json_object_int_add(
2574
0
        json_row, "overrideInterval",
2575
0
        pim_ifp->pim_override_interval_msec);
2576
0
      json_object_int_add(
2577
0
        json_row, "overrideIntervalHighest",
2578
0
        pim_ifp->pim_neighbors_highest_override_interval_msec);
2579
0
      if (pim_ifp->bsm_enable)
2580
0
        json_object_boolean_true_add(json_row,
2581
0
                   "bsmEnabled");
2582
0
      if (pim_ifp->ucast_bsm_accept)
2583
0
        json_object_boolean_true_add(json_row,
2584
0
                   "ucastBsmEnabled");
2585
0
      json_object_object_add(json, ifp->name, json_row);
2586
2587
0
    } else {
2588
0
      vty_out(vty, "Interface  : %s\n", ifp->name);
2589
0
      vty_out(vty, "State      : %s\n",
2590
0
        if_is_up(ifp) ? "up" : "down");
2591
0
      if (!pim_addr_is_any(pim_ifp->update_source)) {
2592
0
        vty_out(vty, "Use Source : %pPAs\n",
2593
0
          &pim_ifp->update_source);
2594
0
      }
2595
0
      if (pim_ifp->sec_addr_list) {
2596
0
        vty_out(vty, "Address    : %pPAs (primary)\n",
2597
0
          &ifaddr);
2598
0
        for (ALL_LIST_ELEMENTS_RO(
2599
0
               pim_ifp->sec_addr_list, sec_node,
2600
0
               sec_addr))
2601
0
          vty_out(vty, "             %pFX\n",
2602
0
            &sec_addr->addr);
2603
0
      } else {
2604
0
        vty_out(vty, "Address    : %pPAs\n", &ifaddr);
2605
0
      }
2606
2607
0
      if (pim_ifp->pim_passive_enable)
2608
0
        vty_out(vty, "Passive    : %s\n",
2609
0
          (pim_ifp->pim_passive_enable) ? "yes"
2610
0
                      : "no");
2611
2612
0
      vty_out(vty, "\n");
2613
2614
      /* PIM neighbors */
2615
0
      print_header = 1;
2616
2617
0
      for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
2618
0
              neighnode, neigh)) {
2619
2620
0
        if (print_header) {
2621
0
          vty_out(vty, "PIM Neighbors\n");
2622
0
          vty_out(vty, "-------------\n");
2623
0
          print_header = 0;
2624
0
        }
2625
2626
0
        snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2627
0
             "%pPAs", &neigh->source_addr);
2628
0
        pim_time_uptime(uptime, sizeof(uptime),
2629
0
            now - neigh->creation);
2630
0
        pim_time_timer_to_hhmmss(expire, sizeof(expire),
2631
0
               neigh->t_expire_timer);
2632
0
        vty_out(vty,
2633
0
          "%-15s : up for %s, holdtime expires in %s\n",
2634
0
          neigh_src_str, uptime, expire);
2635
0
      }
2636
2637
0
      if (!print_header) {
2638
0
        vty_out(vty, "\n");
2639
0
        vty_out(vty, "\n");
2640
0
      }
2641
2642
0
      vty_out(vty, "Designated Router\n");
2643
0
      vty_out(vty, "-----------------\n");
2644
0
      vty_out(vty, "Address   : %s\n", dr_str);
2645
0
      vty_out(vty, "Priority  : %u(%d)\n",
2646
0
        pim_ifp->pim_dr_priority,
2647
0
        pim_ifp->pim_dr_num_nondrpri_neighbors);
2648
0
      vty_out(vty, "Uptime    : %s\n", dr_uptime);
2649
0
      vty_out(vty, "Elections : %d\n",
2650
0
        pim_ifp->pim_dr_election_count);
2651
0
      vty_out(vty, "Changes   : %d\n",
2652
0
        pim_ifp->pim_dr_election_changes);
2653
0
      vty_out(vty, "\n");
2654
0
      vty_out(vty, "\n");
2655
2656
      /* FHR */
2657
0
      print_header = 1;
2658
0
      frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2659
0
        if (!up->rpf.source_nexthop.interface)
2660
0
          continue;
2661
2662
0
        if (strcmp(ifp->name,
2663
0
             up->rpf.source_nexthop
2664
0
               .interface->name) != 0)
2665
0
          continue;
2666
2667
0
        if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2668
0
          continue;
2669
2670
0
        if (print_header) {
2671
0
          vty_out(vty,
2672
0
            "FHR - First Hop Router\n");
2673
0
          vty_out(vty,
2674
0
            "----------------------\n");
2675
0
          print_header = 0;
2676
0
        }
2677
2678
0
        pim_time_uptime(uptime, sizeof(uptime),
2679
0
            now - up->state_transition);
2680
0
        vty_out(vty,
2681
0
          "%pPAs : %pPAs is a source, uptime is %s\n",
2682
0
          &up->sg.grp, &up->sg.src, uptime);
2683
0
      }
2684
2685
0
      if (!print_header) {
2686
0
        vty_out(vty, "\n");
2687
0
        vty_out(vty, "\n");
2688
0
      }
2689
2690
0
      vty_out(vty, "Hellos\n");
2691
0
      vty_out(vty, "------\n");
2692
0
      vty_out(vty, "Period         : %d\n",
2693
0
        pim_ifp->pim_hello_period);
2694
0
      vty_out(vty, "HoldTime       : %d\n",
2695
0
        PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2696
0
      vty_out(vty, "Timer          : %s\n", hello_timer);
2697
0
      vty_out(vty, "StatStart      : %s\n", stat_uptime);
2698
0
      vty_out(vty, "Receive        : %d\n",
2699
0
        pim_ifp->pim_ifstat_hello_recv);
2700
0
      vty_out(vty, "Receive Failed : %d\n",
2701
0
        pim_ifp->pim_ifstat_hello_recvfail);
2702
0
      vty_out(vty, "Send           : %d\n",
2703
0
        pim_ifp->pim_ifstat_hello_sent);
2704
0
      vty_out(vty, "Send Failed    : %d\n",
2705
0
        pim_ifp->pim_ifstat_hello_sendfail);
2706
0
      vty_out(vty, "Generation ID  : %08x\n",
2707
0
        pim_ifp->pim_generation_id);
2708
0
      vty_out(vty, "\n");
2709
0
      vty_out(vty, "\n");
2710
2711
0
      pim_print_ifp_flags(vty, ifp);
2712
2713
0
      vty_out(vty, "Join Prune Interval\n");
2714
0
      vty_out(vty, "-------------------\n");
2715
0
      vty_out(vty, "LAN Delay                    : %s\n",
2716
0
        pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
2717
0
      vty_out(vty, "Effective Propagation Delay  : %d msec\n",
2718
0
        pim_if_effective_propagation_delay_msec(ifp));
2719
0
      vty_out(vty, "Effective Override Interval  : %d msec\n",
2720
0
        pim_if_effective_override_interval_msec(ifp));
2721
0
      vty_out(vty, "Join Prune Override Interval : %d msec\n",
2722
0
        pim_if_jp_override_interval_msec(ifp));
2723
0
      vty_out(vty, "\n");
2724
0
      vty_out(vty, "\n");
2725
2726
0
      vty_out(vty, "LAN Prune Delay\n");
2727
0
      vty_out(vty, "---------------\n");
2728
0
      vty_out(vty, "Propagation Delay           : %d msec\n",
2729
0
        pim_ifp->pim_propagation_delay_msec);
2730
0
      vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
2731
0
        pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2732
0
      vty_out(vty, "Override Interval           : %d msec\n",
2733
0
        pim_ifp->pim_override_interval_msec);
2734
0
      vty_out(vty, "Override Interval (Highest) : %d msec\n",
2735
0
        pim_ifp->pim_neighbors_highest_override_interval_msec);
2736
0
      vty_out(vty, "\n");
2737
0
      vty_out(vty, "\n");
2738
2739
0
      vty_out(vty, "BSM Status\n");
2740
0
      vty_out(vty, "----------\n");
2741
0
      vty_out(vty, "Bsm Enabled          : %s\n",
2742
0
        pim_ifp->bsm_enable ? "yes" : "no");
2743
0
      vty_out(vty, "Unicast Bsm Enabled  : %s\n",
2744
0
        pim_ifp->ucast_bsm_accept ? "yes" : "no");
2745
0
      vty_out(vty, "\n");
2746
0
      vty_out(vty, "\n");
2747
0
    }
2748
0
  }
2749
2750
0
  if (!found_ifname && !json)
2751
0
    vty_out(vty, "%% No such interface\n");
2752
0
}
2753
2754
void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
2755
         bool uj)
2756
0
{
2757
0
  struct pim_ssm *ssm = pim->ssm_info;
2758
0
  const char *range_str =
2759
0
    ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
2760
2761
0
  if (uj) {
2762
0
    json_object *json;
2763
2764
0
    json = json_object_new_object();
2765
0
    json_object_string_add(json, "ssmGroups", range_str);
2766
0
    vty_json(vty, json);
2767
0
  } else
2768
0
    vty_out(vty, "SSM group range : %s\n", range_str);
2769
0
}
2770
2771
struct vty_pnc_cache_walk_data {
2772
  struct vty *vty;
2773
  struct pim_instance *pim;
2774
};
2775
2776
struct json_pnc_cache_walk_data {
2777
  json_object *json_obj;
2778
  struct pim_instance *pim;
2779
};
2780
2781
static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
2782
0
{
2783
0
  struct pim_nexthop_cache *pnc = bucket->data;
2784
0
  struct vty_pnc_cache_walk_data *cwd = arg;
2785
0
  struct vty *vty = cwd->vty;
2786
0
  struct pim_instance *pim = cwd->pim;
2787
0
  struct nexthop *nh_node = NULL;
2788
0
  ifindex_t first_ifindex;
2789
0
  struct interface *ifp = NULL;
2790
0
  struct ttable *tt = NULL;
2791
0
  char *table = NULL;
2792
2793
  /* Prepare table. */
2794
0
  tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2795
0
  ttable_add_row(tt, "Address|Interface|Nexthop");
2796
0
  tt->style.cell.rpad = 2;
2797
0
  tt->style.corner = '+';
2798
0
  ttable_restyle(tt);
2799
2800
0
  for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2801
0
    first_ifindex = nh_node->ifindex;
2802
2803
0
    ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2804
2805
0
#if PIM_IPV == 4
2806
0
    ttable_add_row(tt, "%pPA|%s|%pI4", &pnc->rpf.rpf_addr,
2807
0
             ifp ? ifp->name : "NULL", &nh_node->gate.ipv4);
2808
#else
2809
    ttable_add_row(tt, "%pPA|%s|%pI6", &pnc->rpf.rpf_addr,
2810
             ifp ? ifp->name : "NULL", &nh_node->gate.ipv6);
2811
#endif
2812
0
  }
2813
  /* Dump the generated table. */
2814
0
  table = ttable_dump(tt, "\n");
2815
0
  vty_out(vty, "%s\n", table);
2816
0
  XFREE(MTYPE_TMP, table);
2817
0
  ttable_del(tt);
2818
2819
0
  return CMD_SUCCESS;
2820
0
}
2821
2822
static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
2823
             void *arg)
2824
0
{
2825
0
  struct pim_nexthop_cache *pnc = backet->data;
2826
0
  struct json_pnc_cache_walk_data *cwd = arg;
2827
0
  struct pim_instance *pim = cwd->pim;
2828
0
  struct nexthop *nh_node = NULL;
2829
0
  ifindex_t first_ifindex;
2830
0
  struct interface *ifp = NULL;
2831
0
  char addr_str[PIM_ADDRSTRLEN];
2832
0
  json_object *json_row = NULL;
2833
0
  json_object *json_ifp = NULL;
2834
0
  json_object *json_arr = NULL;
2835
2836
0
  for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2837
0
    first_ifindex = nh_node->ifindex;
2838
0
    ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2839
0
    snprintfrr(addr_str, sizeof(addr_str), "%pPA",
2840
0
         &pnc->rpf.rpf_addr);
2841
0
    json_object_object_get_ex(cwd->json_obj, addr_str, &json_row);
2842
0
    if (!json_row) {
2843
0
      json_row = json_object_new_object();
2844
0
      json_object_string_addf(json_row, "address", "%pPA",
2845
0
            &pnc->rpf.rpf_addr);
2846
0
      json_object_object_addf(cwd->json_obj, json_row, "%pPA",
2847
0
            &pnc->rpf.rpf_addr);
2848
0
      json_arr = json_object_new_array();
2849
0
      json_object_object_add(json_row, "nexthops", json_arr);
2850
0
    }
2851
0
    json_ifp = json_object_new_object();
2852
0
    json_object_string_add(json_ifp, "interface",
2853
0
               ifp ? ifp->name : "NULL");
2854
0
#if PIM_IPV == 4
2855
0
    json_object_string_addf(json_ifp, "nexthop", "%pI4",
2856
0
          &nh_node->gate.ipv4);
2857
#else
2858
    json_object_string_addf(json_ifp, "nexthop", "%pI6",
2859
          &nh_node->gate.ipv6);
2860
#endif
2861
0
    json_object_array_add(json_arr, json_ifp);
2862
0
  }
2863
0
  return CMD_SUCCESS;
2864
0
}
2865
2866
int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
2867
               pim_addr source, pim_addr group)
2868
0
{
2869
0
  int result = 0;
2870
0
  pim_addr vif_source;
2871
0
  struct prefix grp;
2872
0
  struct pim_nexthop nexthop;
2873
0
  struct vrf *v;
2874
0
  char grp_str[PREFIX_STRLEN];
2875
2876
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2877
2878
0
  if (!v)
2879
0
    return CMD_WARNING;
2880
2881
0
#if PIM_IPV == 4
2882
0
  if (pim_is_group_224_4(source)) {
2883
0
    vty_out(vty,
2884
0
      "Invalid argument. Expected Valid Source Address.\n");
2885
0
    return CMD_WARNING;
2886
0
  }
2887
2888
0
  if (!pim_is_group_224_4(group)) {
2889
0
    vty_out(vty,
2890
0
      "Invalid argument. Expected Valid Multicast Group Address.\n");
2891
0
    return CMD_WARNING;
2892
0
  }
2893
0
#endif
2894
2895
0
  if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group))
2896
0
    return CMD_SUCCESS;
2897
2898
0
  pim_addr_to_prefix(&grp, group);
2899
0
  memset(&nexthop, 0, sizeof(nexthop));
2900
2901
0
  result =
2902
0
    pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
2903
2904
0
  if (!result) {
2905
0
    vty_out(vty,
2906
0
      "Nexthop Lookup failed, no usable routes returned.\n");
2907
0
    return CMD_SUCCESS;
2908
0
  }
2909
2910
0
  pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
2911
2912
0
  vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str,
2913
0
    &nexthop.mrib_nexthop_addr, nexthop.interface->name);
2914
2915
0
  return CMD_SUCCESS;
2916
0
}
2917
2918
int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj)
2919
0
{
2920
0
  struct vrf *v;
2921
2922
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2923
2924
0
  if (!v)
2925
0
    return CMD_WARNING;
2926
2927
0
  pim_show_nexthop(v->info, vty, uj);
2928
2929
0
  return CMD_SUCCESS;
2930
0
}
2931
2932
void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj)
2933
0
{
2934
0
  struct vty_pnc_cache_walk_data cwd;
2935
0
  struct json_pnc_cache_walk_data jcwd;
2936
2937
0
  cwd.vty = vty;
2938
0
  cwd.pim = pim;
2939
0
  jcwd.pim = pim;
2940
2941
0
  if (uj) {
2942
0
    jcwd.json_obj = json_object_new_object();
2943
0
  } else {
2944
0
    vty_out(vty, "Number of registered addresses: %lu\n",
2945
0
      pim->rpf_hash->count);
2946
0
  }
2947
2948
0
  if (uj) {
2949
0
    hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb,
2950
0
        &jcwd);
2951
0
    vty_json(vty, jcwd.json_obj);
2952
0
  } else
2953
0
    hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
2954
0
}
2955
2956
int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
2957
          const char *json, const char *interface)
2958
0
{
2959
0
  struct vrf *v;
2960
0
  json_object *json_parent = NULL;
2961
2962
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2963
2964
0
  if (!v)
2965
0
    return CMD_WARNING;
2966
2967
0
  if (json)
2968
0
    json_parent = json_object_new_object();
2969
2970
0
  if (interface)
2971
0
    pim_show_neighbors_single(v->info, vty, interface, json_parent);
2972
0
  else
2973
0
    pim_show_neighbors(v->info, vty, json_parent);
2974
2975
0
  if (json)
2976
0
    vty_json(vty, json_parent);
2977
2978
0
  return CMD_SUCCESS;
2979
0
}
2980
2981
int pim_show_neighbors_vrf_all_cmd_helper(struct vty *vty, const char *json,
2982
            const char *interface)
2983
0
{
2984
0
  struct vrf *v;
2985
0
  json_object *json_parent = NULL;
2986
0
  json_object *json_vrf = NULL;
2987
2988
0
  if (json)
2989
0
    json_parent = json_object_new_object();
2990
0
  RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
2991
0
    if (!json)
2992
0
      vty_out(vty, "VRF: %s\n", v->name);
2993
0
    else
2994
0
      json_vrf = json_object_new_object();
2995
2996
0
    if (interface)
2997
0
      pim_show_neighbors_single(v->info, vty, interface,
2998
0
              json_vrf);
2999
0
    else
3000
0
      pim_show_neighbors(v->info, vty, json_vrf);
3001
3002
0
    if (json)
3003
0
      json_object_object_add(json_parent, v->name, json_vrf);
3004
0
  }
3005
0
  if (json)
3006
0
    vty_json(vty, json_parent);
3007
3008
0
  return CMD_SUCCESS;
3009
0
}
3010
3011
void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
3012
             const char *neighbor, json_object *json)
3013
0
{
3014
0
  struct listnode *neighnode;
3015
0
  struct interface *ifp;
3016
0
  struct pim_interface *pim_ifp;
3017
0
  struct pim_neighbor *neigh;
3018
0
  time_t now;
3019
0
  int found_neighbor = 0;
3020
0
  int option_address_list;
3021
0
  int option_dr_priority;
3022
0
  int option_generation_id;
3023
0
  int option_holdtime;
3024
0
  int option_lan_prune_delay;
3025
0
  int option_t_bit;
3026
0
  char uptime[10];
3027
0
  char expire[10];
3028
0
  char neigh_src_str[PIM_ADDRSTRLEN];
3029
3030
0
  json_object *json_ifp = NULL;
3031
0
  json_object *json_row = NULL;
3032
3033
0
  now = pim_time_monotonic_sec();
3034
3035
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
3036
0
    pim_ifp = ifp->info;
3037
3038
0
    if (!pim_ifp)
3039
0
      continue;
3040
3041
0
    if (pim_ifp->pim_sock_fd < 0)
3042
0
      continue;
3043
3044
0
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
3045
0
            neigh)) {
3046
0
      snprintfrr(neigh_src_str, sizeof(neigh_src_str),
3047
0
           "%pPAs", &neigh->source_addr);
3048
3049
      /*
3050
       * The user can specify either the interface name or the
3051
       * PIM neighbor IP.
3052
       * If this pim_ifp matches neither then skip.
3053
       */
3054
0
      if (strcmp(neighbor, "detail") &&
3055
0
          strcmp(neighbor, ifp->name) &&
3056
0
          strcmp(neighbor, neigh_src_str))
3057
0
        continue;
3058
3059
0
      found_neighbor = 1;
3060
0
      pim_time_uptime(uptime, sizeof(uptime),
3061
0
          now - neigh->creation);
3062
0
      pim_time_timer_to_hhmmss(expire, sizeof(expire),
3063
0
             neigh->t_expire_timer);
3064
3065
0
      option_address_list = 0;
3066
0
      option_dr_priority = 0;
3067
0
      option_generation_id = 0;
3068
0
      option_holdtime = 0;
3069
0
      option_lan_prune_delay = 0;
3070
0
      option_t_bit = 0;
3071
3072
0
      if (PIM_OPTION_IS_SET(neigh->hello_options,
3073
0
                PIM_OPTION_MASK_ADDRESS_LIST))
3074
0
        option_address_list = 1;
3075
3076
0
      if (PIM_OPTION_IS_SET(neigh->hello_options,
3077
0
                PIM_OPTION_MASK_DR_PRIORITY))
3078
0
        option_dr_priority = 1;
3079
3080
0
      if (PIM_OPTION_IS_SET(neigh->hello_options,
3081
0
                PIM_OPTION_MASK_GENERATION_ID))
3082
0
        option_generation_id = 1;
3083
3084
0
      if (PIM_OPTION_IS_SET(neigh->hello_options,
3085
0
                PIM_OPTION_MASK_HOLDTIME))
3086
0
        option_holdtime = 1;
3087
3088
0
      if (PIM_OPTION_IS_SET(neigh->hello_options,
3089
0
                PIM_OPTION_MASK_LAN_PRUNE_DELAY))
3090
0
        option_lan_prune_delay = 1;
3091
3092
0
      if (PIM_OPTION_IS_SET(
3093
0
            neigh->hello_options,
3094
0
            PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
3095
0
        option_t_bit = 1;
3096
3097
0
      if (json) {
3098
3099
        /* Does this ifp live in json? If not create it
3100
         */
3101
0
        json_object_object_get_ex(json, ifp->name,
3102
0
                &json_ifp);
3103
3104
0
        if (!json_ifp) {
3105
0
          json_ifp = json_object_new_object();
3106
0
          json_object_pim_ifp_add(json_ifp, ifp);
3107
0
          json_object_object_add(json, ifp->name,
3108
0
                     json_ifp);
3109
0
        }
3110
3111
0
        json_row = json_object_new_object();
3112
0
        json_object_string_add(json_row, "interface",
3113
0
                   ifp->name);
3114
0
        json_object_string_add(json_row, "address",
3115
0
                   neigh_src_str);
3116
0
        json_object_string_add(json_row, "upTime",
3117
0
                   uptime);
3118
0
        json_object_string_add(json_row, "holdtime",
3119
0
                   expire);
3120
0
        json_object_int_add(json_row, "drPriority",
3121
0
                neigh->dr_priority);
3122
0
        json_object_int_add(json_row, "generationId",
3123
0
                neigh->generation_id);
3124
3125
0
        if (option_address_list)
3126
0
          json_object_boolean_true_add(
3127
0
            json_row,
3128
0
            "helloOptionAddressList");
3129
3130
0
        if (option_dr_priority)
3131
0
          json_object_boolean_true_add(
3132
0
            json_row,
3133
0
            "helloOptionDrPriority");
3134
3135
0
        if (option_generation_id)
3136
0
          json_object_boolean_true_add(
3137
0
            json_row,
3138
0
            "helloOptionGenerationId");
3139
3140
0
        if (option_holdtime)
3141
0
          json_object_boolean_true_add(
3142
0
            json_row,
3143
0
            "helloOptionHoldtime");
3144
3145
0
        if (option_lan_prune_delay)
3146
0
          json_object_boolean_true_add(
3147
0
            json_row,
3148
0
            "helloOptionLanPruneDelay");
3149
3150
0
        if (option_t_bit)
3151
0
          json_object_boolean_true_add(
3152
0
            json_row, "helloOptionTBit");
3153
3154
0
        json_object_object_add(json_ifp, neigh_src_str,
3155
0
                   json_row);
3156
3157
0
      } else {
3158
0
        vty_out(vty, "Interface : %s\n", ifp->name);
3159
0
        vty_out(vty, "Neighbor  : %s\n", neigh_src_str);
3160
0
        vty_out(vty,
3161
0
          "    Uptime                         : %s\n",
3162
0
          uptime);
3163
0
        vty_out(vty,
3164
0
          "    Holdtime                       : %s\n",
3165
0
          expire);
3166
0
        vty_out(vty,
3167
0
          "    DR Priority                    : %d\n",
3168
0
          neigh->dr_priority);
3169
0
        vty_out(vty,
3170
0
          "    Generation ID                  : %08x\n",
3171
0
          neigh->generation_id);
3172
0
        vty_out(vty,
3173
0
          "    Override Interval (msec)       : %d\n",
3174
0
          neigh->override_interval_msec);
3175
0
        vty_out(vty,
3176
0
          "    Propagation Delay (msec)       : %d\n",
3177
0
          neigh->propagation_delay_msec);
3178
0
        vty_out(vty,
3179
0
          "    Hello Option - Address List    : %s\n",
3180
0
          option_address_list ? "yes" : "no");
3181
0
        vty_out(vty,
3182
0
          "    Hello Option - DR Priority     : %s\n",
3183
0
          option_dr_priority ? "yes" : "no");
3184
0
        vty_out(vty,
3185
0
          "    Hello Option - Generation ID   : %s\n",
3186
0
          option_generation_id ? "yes" : "no");
3187
0
        vty_out(vty,
3188
0
          "    Hello Option - Holdtime        : %s\n",
3189
0
          option_holdtime ? "yes" : "no");
3190
0
        vty_out(vty,
3191
0
          "    Hello Option - LAN Prune Delay : %s\n",
3192
0
          option_lan_prune_delay ? "yes" : "no");
3193
0
        vty_out(vty,
3194
0
          "    Hello Option - T-bit           : %s\n",
3195
0
          option_t_bit ? "yes" : "no");
3196
0
        bfd_sess_show(vty, json_ifp,
3197
0
                neigh->bfd_session);
3198
0
        vty_out(vty, "\n");
3199
0
      }
3200
0
    }
3201
0
  }
3202
3203
0
  if (!found_neighbor && !json)
3204
0
    vty_out(vty, "%% No such interface or neighbor\n");
3205
0
}
3206
3207
void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
3208
      json_object *json)
3209
0
{
3210
0
  struct listnode *neighnode;
3211
0
  struct interface *ifp;
3212
0
  struct pim_interface *pim_ifp;
3213
0
  struct pim_neighbor *neigh;
3214
0
  struct ttable *tt = NULL;
3215
0
  char *table = NULL;
3216
0
  time_t now;
3217
0
  char uptime[10];
3218
0
  char expire[10];
3219
0
  char neigh_src_str[PIM_ADDRSTRLEN];
3220
0
  json_object *json_ifp_rows = NULL;
3221
0
  json_object *json_row = NULL;
3222
3223
0
  now = pim_time_monotonic_sec();
3224
3225
0
  if (!json) {
3226
    /* Prepare table. */
3227
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3228
0
    ttable_add_row(tt, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
3229
0
    tt->style.cell.rpad = 2;
3230
0
    tt->style.corner = '+';
3231
0
    ttable_restyle(tt);
3232
0
  }
3233
3234
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
3235
0
    pim_ifp = ifp->info;
3236
3237
0
    if (!pim_ifp)
3238
0
      continue;
3239
3240
0
    if (pim_ifp->pim_sock_fd < 0)
3241
0
      continue;
3242
3243
0
    if (json)
3244
0
      json_ifp_rows = json_object_new_object();
3245
3246
0
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
3247
0
            neigh)) {
3248
0
      snprintfrr(neigh_src_str, sizeof(neigh_src_str),
3249
0
           "%pPAs", &neigh->source_addr);
3250
0
      pim_time_uptime(uptime, sizeof(uptime),
3251
0
          now - neigh->creation);
3252
0
      pim_time_timer_to_hhmmss(expire, sizeof(expire),
3253
0
             neigh->t_expire_timer);
3254
3255
0
      if (json) {
3256
0
        json_row = json_object_new_object();
3257
0
        json_object_string_add(json_row, "interface",
3258
0
                   ifp->name);
3259
0
        json_object_string_add(json_row, "neighbor",
3260
0
                   neigh_src_str);
3261
0
        json_object_string_add(json_row, "upTime",
3262
0
                   uptime);
3263
0
        json_object_string_add(json_row, "holdTime",
3264
0
                   expire);
3265
0
        json_object_int_add(json_row, "holdTimeMax",
3266
0
                neigh->holdtime);
3267
0
        json_object_int_add(json_row, "drPriority",
3268
0
                neigh->dr_priority);
3269
0
        json_object_object_add(json_ifp_rows,
3270
0
                   neigh_src_str, json_row);
3271
3272
0
      } else {
3273
0
        ttable_add_row(tt, "%s|%pPAs|%s|%s|%d",
3274
0
                 ifp->name, &neigh->source_addr,
3275
0
                 uptime, expire,
3276
0
                 neigh->dr_priority);
3277
0
      }
3278
0
    }
3279
3280
0
    if (json) {
3281
0
      json_object_object_add(json, ifp->name, json_ifp_rows);
3282
0
      json_ifp_rows = NULL;
3283
0
    }
3284
0
  }
3285
  /* Dump the generated table. */
3286
0
  if (!json) {
3287
0
    table = ttable_dump(tt, "\n");
3288
0
    vty_out(vty, "%s\n", table);
3289
0
    XFREE(MTYPE_TMP, table);
3290
0
    ttable_del(tt);
3291
0
  }
3292
0
}
3293
3294
int gm_process_query_max_response_time_cmd(struct vty *vty,
3295
             const char *qmrt_str)
3296
0
{
3297
0
  const struct lyd_node *pim_enable_dnode;
3298
3299
0
  pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3300
0
             FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3301
0
             FRR_PIM_AF_XPATH_VAL);
3302
3303
0
  if (!pim_enable_dnode) {
3304
0
    nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3305
0
  } else {
3306
0
    if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3307
0
      nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3308
0
                "true");
3309
0
  }
3310
3311
0
  nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
3312
0
            qmrt_str);
3313
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3314
0
            FRR_PIM_AF_XPATH_VAL);
3315
0
}
3316
3317
int gm_process_no_query_max_response_time_cmd(struct vty *vty)
3318
0
{
3319
0
  nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
3320
0
            NULL);
3321
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3322
0
            FRR_PIM_AF_XPATH_VAL);
3323
0
}
3324
3325
int gm_process_last_member_query_count_cmd(struct vty *vty,
3326
             const char *lmqc_str)
3327
0
{
3328
0
  const struct lyd_node *pim_enable_dnode;
3329
3330
0
  pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3331
0
             FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3332
0
             FRR_PIM_AF_XPATH_VAL);
3333
0
  if (!pim_enable_dnode) {
3334
0
    nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3335
0
  } else {
3336
0
    if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3337
0
      nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3338
0
                "true");
3339
0
  }
3340
3341
0
  nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
3342
0
            lmqc_str);
3343
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3344
0
            FRR_PIM_AF_XPATH_VAL);
3345
0
}
3346
3347
int gm_process_no_last_member_query_count_cmd(struct vty *vty)
3348
0
{
3349
0
  nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
3350
0
            NULL);
3351
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3352
0
            FRR_PIM_AF_XPATH_VAL);
3353
0
}
3354
3355
int gm_process_last_member_query_interval_cmd(struct vty *vty,
3356
                const char *lmqi_str)
3357
0
{
3358
0
  const struct lyd_node *pim_enable_dnode;
3359
3360
0
  pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3361
0
             FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3362
0
             FRR_PIM_AF_XPATH_VAL);
3363
0
  if (!pim_enable_dnode) {
3364
0
    nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3365
0
  } else {
3366
0
    if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3367
0
      nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3368
0
                "true");
3369
0
  }
3370
3371
0
  nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
3372
0
            lmqi_str);
3373
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3374
0
            FRR_PIM_AF_XPATH_VAL);
3375
0
}
3376
3377
int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
3378
0
{
3379
0
  nb_cli_enqueue_change(vty, "./last-member-query-interval",
3380
0
            NB_OP_DESTROY, NULL);
3381
0
  return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3382
0
            FRR_PIM_AF_XPATH_VAL);
3383
0
}
3384
3385
int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
3386
           const char *src_str)
3387
0
{
3388
0
  const char *vrfname;
3389
0
  char ssmpingd_ip_xpath[XPATH_MAXLEN];
3390
3391
0
  vrfname = pim_cli_get_vrf_name(vty);
3392
0
  if (vrfname == NULL)
3393
0
    return CMD_WARNING_CONFIG_FAILED;
3394
3395
0
  snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
3396
0
     FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
3397
0
     FRR_PIM_AF_XPATH_VAL);
3398
0
  strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
3399
0
    sizeof(ssmpingd_ip_xpath));
3400
3401
0
  nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
3402
3403
0
  return nb_cli_apply_changes(vty, NULL);
3404
0
}
3405
3406
int pim_process_bsm_cmd(struct vty *vty)
3407
0
{
3408
0
  const struct lyd_node *gm_enable_dnode;
3409
3410
0
  gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3411
0
            FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
3412
0
            FRR_PIM_AF_XPATH_VAL);
3413
0
  if (!gm_enable_dnode)
3414
0
    nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3415
0
              "true");
3416
0
  else {
3417
0
    if (!yang_dnode_get_bool(gm_enable_dnode, "."))
3418
0
      nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3419
0
                "true");
3420
0
  }
3421
3422
0
  nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
3423
3424
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3425
0
            FRR_PIM_AF_XPATH_VAL);
3426
0
}
3427
3428
int pim_process_no_bsm_cmd(struct vty *vty)
3429
0
{
3430
0
  nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
3431
3432
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3433
0
            FRR_PIM_AF_XPATH_VAL);
3434
0
}
3435
3436
int pim_process_unicast_bsm_cmd(struct vty *vty)
3437
0
{
3438
0
  const struct lyd_node *gm_enable_dnode;
3439
3440
0
  gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3441
0
            FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
3442
0
            FRR_PIM_AF_XPATH_VAL);
3443
0
  if (!gm_enable_dnode)
3444
0
    nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3445
0
              "true");
3446
0
  else {
3447
0
    if (!yang_dnode_get_bool(gm_enable_dnode, "."))
3448
0
      nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3449
0
                "true");
3450
0
  }
3451
3452
0
  nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
3453
3454
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3455
0
            FRR_PIM_AF_XPATH_VAL);
3456
0
}
3457
3458
int pim_process_no_unicast_bsm_cmd(struct vty *vty)
3459
0
{
3460
0
  nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
3461
3462
0
  return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3463
0
            FRR_PIM_AF_XPATH_VAL);
3464
0
}
3465
3466
static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
3467
        time_t now)
3468
0
{
3469
0
  char uptime_scan_oil[10];
3470
0
  char uptime_mroute_add[10];
3471
0
  char uptime_mroute_del[10];
3472
3473
0
  pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
3474
0
            pim->scan_oil_last);
3475
0
  pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
3476
0
            pim->mroute_add_last);
3477
0
  pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
3478
0
            pim->mroute_del_last);
3479
3480
0
  vty_out(vty,
3481
0
    "Scan OIL - Last: %s  Events: %lld\n"
3482
0
    "MFC Add  - Last: %s  Events: %lld\n"
3483
0
    "MFC Del  - Last: %s  Events: %lld\n",
3484
0
    uptime_scan_oil, (long long)pim->scan_oil_events,
3485
0
    uptime_mroute_add, (long long)pim->mroute_add_events,
3486
0
    uptime_mroute_del, (long long)pim->mroute_del_events);
3487
0
}
3488
3489
void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
3490
             json_object *json)
3491
0
{
3492
0
  struct interface *ifp;
3493
0
  struct ttable *tt = NULL;
3494
0
  char *table = NULL;
3495
0
  json_object *json_row = NULL;
3496
3497
0
  vty_out(vty, "\n");
3498
3499
0
  if (!json) {
3500
    /* Prepare table. */
3501
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3502
0
    ttable_add_row(
3503
0
      tt,
3504
0
      "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
3505
0
    tt->style.cell.rpad = 2;
3506
0
    tt->style.corner = '+';
3507
0
    ttable_restyle(tt);
3508
0
  }
3509
3510
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
3511
0
    struct pim_interface *pim_ifp;
3512
0
#if PIM_IPV == 4
3513
0
    struct sioc_vif_req vreq;
3514
#else
3515
    struct sioc_mif_req6 vreq;
3516
#endif
3517
3518
0
    pim_ifp = ifp->info;
3519
3520
0
    if (!pim_ifp)
3521
0
      continue;
3522
3523
0
    memset(&vreq, 0, sizeof(vreq));
3524
0
#if PIM_IPV == 4
3525
0
    vreq.vifi = pim_ifp->mroute_vif_index;
3526
0
    if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
3527
0
      zlog_warn(
3528
0
        "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3529
0
        (unsigned long)SIOCGETVIFCNT, ifp->name,
3530
0
        pim_ifp->mroute_vif_index, errno,
3531
0
        safe_strerror(errno));
3532
0
    }
3533
#else
3534
    vreq.mifi = pim_ifp->mroute_vif_index;
3535
    if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
3536
      zlog_warn(
3537
        "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3538
        (unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
3539
        pim_ifp->mroute_vif_index, errno,
3540
        safe_strerror(errno));
3541
    }
3542
#endif
3543
3544
0
    if (json) {
3545
0
      json_row = json_object_new_object();
3546
0
      json_object_string_add(json_row, "name", ifp->name);
3547
0
      json_object_string_add(json_row, "state",
3548
0
                 if_is_up(ifp) ? "up" : "down");
3549
0
      json_object_string_addf(json_row, "address", "%pPA",
3550
0
            &pim_ifp->primary_address);
3551
0
      json_object_int_add(json_row, "ifIndex", ifp->ifindex);
3552
0
      json_object_int_add(json_row, "vif",
3553
0
              pim_ifp->mroute_vif_index);
3554
0
      json_object_int_add(json_row, "pktsIn",
3555
0
              (unsigned long)vreq.icount);
3556
0
      json_object_int_add(json_row, "pktsOut",
3557
0
              (unsigned long)vreq.ocount);
3558
0
      json_object_int_add(json_row, "bytesIn",
3559
0
              (unsigned long)vreq.ibytes);
3560
0
      json_object_int_add(json_row, "bytesOut",
3561
0
              (unsigned long)vreq.obytes);
3562
0
      json_object_object_add(json, ifp->name, json_row);
3563
0
    } else {
3564
0
      ttable_add_row(tt, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
3565
0
               ifp->name, &pim_ifp->primary_address,
3566
0
               ifp->ifindex, pim_ifp->mroute_vif_index,
3567
0
               (unsigned long)vreq.icount,
3568
0
               (unsigned long)vreq.ocount,
3569
0
               (unsigned long)vreq.ibytes,
3570
0
               (unsigned long)vreq.obytes);
3571
0
    }
3572
0
  }
3573
  /* Dump the generated table. */
3574
0
  if (!json) {
3575
0
    table = ttable_dump(tt, "\n");
3576
0
    vty_out(vty, "%s\n", table);
3577
0
    XFREE(MTYPE_TMP, table);
3578
0
    ttable_del(tt);
3579
0
  }
3580
0
}
3581
3582
void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
3583
0
{
3584
0
  struct vrf *vrf = pim->vrf;
3585
0
  time_t now = pim_time_monotonic_sec();
3586
0
  char uptime[10];
3587
0
  char mlag_role[80];
3588
3589
0
  pim = vrf->info;
3590
3591
0
  vty_out(vty, "Router MLAG Role: %s\n",
3592
0
    mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
3593
0
  vty_out(vty, "Mroute socket descriptor:");
3594
3595
0
  vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
3596
0
  vty_out(vty, "PIM Register socket descriptor:");
3597
0
  vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name);
3598
3599
0
  pim_time_uptime(uptime, sizeof(uptime),
3600
0
      now - pim->mroute_socket_creation);
3601
0
  vty_out(vty, "Mroute socket uptime: %s\n", uptime);
3602
3603
0
  vty_out(vty, "\n");
3604
3605
0
  pim_zebra_zclient_update(vty);
3606
0
  pim_zlookup_show_ip_multicast(vty);
3607
3608
0
  vty_out(vty, "\n");
3609
0
  vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
3610
3611
0
  vty_out(vty, "\n");
3612
0
  vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
3613
0
  vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
3614
0
  vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
3615
0
  vty_out(vty, "PIM ECMP Rebalance: %s\n",
3616
0
    pim->ecmp_rebalance_enable ? "Enable" : "Disable");
3617
3618
0
  vty_out(vty, "\n");
3619
3620
0
  pim_show_rpf_refresh_stats(vty, pim, now, NULL);
3621
3622
0
  vty_out(vty, "\n");
3623
3624
0
  show_scan_oil_stats(pim, vty, now);
3625
3626
0
  show_multicast_interfaces(pim, vty, NULL);
3627
0
}
3628
3629
void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
3630
     bool fill, json_object *json)
3631
0
{
3632
0
  struct listnode *node;
3633
0
  struct channel_oil *c_oil;
3634
0
  struct static_route *s_route;
3635
0
  struct ttable *tt = NULL;
3636
0
  char *table = NULL;
3637
0
  time_t now;
3638
0
  json_object *json_group = NULL;
3639
0
  json_object *json_source = NULL;
3640
0
  json_object *json_oil = NULL;
3641
0
  json_object *json_ifp_out = NULL;
3642
0
  int found_oif;
3643
0
  int first;
3644
0
  char grp_str[PIM_ADDRSTRLEN];
3645
0
  char src_str[PIM_ADDRSTRLEN];
3646
0
  char in_ifname[INTERFACE_NAMSIZ + 1];
3647
0
  char out_ifname[INTERFACE_NAMSIZ + 1];
3648
0
  int oif_vif_index;
3649
0
  struct interface *ifp_in;
3650
0
  char proto[100];
3651
0
  char state_str[PIM_REG_STATE_STR_LEN];
3652
0
  char mroute_uptime[10];
3653
3654
0
  if (!json) {
3655
0
    vty_out(vty, "IP Multicast Routing Table\n");
3656
0
    vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3657
0
    vty_out(vty,
3658
0
      "       R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3659
3660
    /* Prepare table. */
3661
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3662
0
    ttable_add_row(
3663
0
      tt, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
3664
0
    tt->style.cell.rpad = 2;
3665
0
    tt->style.corner = '+';
3666
0
    ttable_restyle(tt);
3667
0
  }
3668
3669
0
  now = pim_time_monotonic_sec();
3670
3671
  /* print list of PIM and IGMP routes */
3672
0
  frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
3673
0
    found_oif = 0;
3674
0
    first = 1;
3675
0
    if (!c_oil->installed)
3676
0
      continue;
3677
3678
0
    if (!pim_addr_is_any(sg->grp) &&
3679
0
        pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil)))
3680
0
      continue;
3681
0
    if (!pim_addr_is_any(sg->src) &&
3682
0
        pim_addr_cmp(sg->src, *oil_origin(c_oil)))
3683
0
      continue;
3684
3685
0
    snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
3686
0
         oil_mcastgrp(c_oil));
3687
0
    snprintfrr(src_str, sizeof(src_str), "%pPAs",
3688
0
         oil_origin(c_oil));
3689
3690
0
    strlcpy(state_str, "S", sizeof(state_str));
3691
    /* When a non DR receives a igmp join, it creates a (*,G)
3692
     * channel_oil without any upstream creation
3693
     */
3694
0
    if (c_oil->up) {
3695
0
      if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
3696
0
        strlcat(state_str, "C", sizeof(state_str));
3697
0
      if (pim_upstream_is_sg_rpt(c_oil->up))
3698
0
        strlcat(state_str, "R", sizeof(state_str));
3699
0
      if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
3700
0
        strlcat(state_str, "F", sizeof(state_str));
3701
0
      if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
3702
0
        strlcat(state_str, "T", sizeof(state_str));
3703
0
    }
3704
0
    if (pim_channel_oil_empty(c_oil))
3705
0
      strlcat(state_str, "P", sizeof(state_str));
3706
3707
0
    ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
3708
3709
0
    if (ifp_in)
3710
0
      strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3711
0
    else
3712
0
      strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3713
3714
3715
0
    pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
3716
0
        now - c_oil->mroute_creation);
3717
3718
0
    if (json) {
3719
3720
      /* Find the group, create it if it doesn't exist */
3721
0
      json_object_object_get_ex(json, grp_str, &json_group);
3722
3723
0
      if (!json_group) {
3724
0
        json_group = json_object_new_object();
3725
0
        json_object_object_add(json, grp_str,
3726
0
                   json_group);
3727
0
      }
3728
3729
      /* Find the source nested under the group, create it if
3730
       * it doesn't exist
3731
       */
3732
0
      json_object_object_get_ex(json_group, src_str,
3733
0
              &json_source);
3734
3735
0
      if (!json_source) {
3736
0
        json_source = json_object_new_object();
3737
0
        json_object_object_add(json_group, src_str,
3738
0
                   json_source);
3739
0
      }
3740
3741
      /* Find the inbound interface nested under the source,
3742
       * create it if it doesn't exist
3743
       */
3744
0
      json_object_string_add(json_source, "source", src_str);
3745
0
      json_object_string_add(json_source, "group", grp_str);
3746
0
      json_object_int_add(json_source, "installed",
3747
0
              c_oil->installed);
3748
0
      json_object_int_add(json_source, "refCount",
3749
0
              c_oil->oil_ref_count);
3750
0
      json_object_int_add(json_source, "oilSize",
3751
0
              c_oil->oil_size);
3752
0
      json_object_int_add(json_source, "oilInheritedRescan",
3753
0
              c_oil->oil_inherited_rescan);
3754
0
      json_object_string_add(json_source, "iif", in_ifname);
3755
0
      json_object_string_add(json_source, "upTime",
3756
0
                 mroute_uptime);
3757
0
      json_oil = NULL;
3758
0
    }
3759
3760
0
    for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3761
0
         ++oif_vif_index) {
3762
0
      struct interface *ifp_out;
3763
0
      int ttl;
3764
3765
0
      ttl = oil_if_has(c_oil, oif_vif_index);
3766
0
      if (ttl < 1)
3767
0
        continue;
3768
3769
      /* do not display muted OIFs */
3770
0
      if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE)
3771
0
        continue;
3772
3773
0
      if (*oil_parent(c_oil) == oif_vif_index &&
3774
0
          !pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index))
3775
0
        continue;
3776
3777
0
      ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3778
0
      found_oif = 1;
3779
3780
0
      if (ifp_out)
3781
0
        strlcpy(out_ifname, ifp_out->name,
3782
0
          sizeof(out_ifname));
3783
0
      else
3784
0
        strlcpy(out_ifname, "<oif?>",
3785
0
          sizeof(out_ifname));
3786
3787
0
      if (json) {
3788
0
        json_ifp_out = json_object_new_object();
3789
0
        json_object_string_add(json_ifp_out, "source",
3790
0
                   src_str);
3791
0
        json_object_string_add(json_ifp_out, "group",
3792
0
                   grp_str);
3793
3794
0
        if (c_oil->oif_flags[oif_vif_index] &
3795
0
            PIM_OIF_FLAG_PROTO_PIM)
3796
0
          json_object_boolean_true_add(
3797
0
            json_ifp_out, "protocolPim");
3798
3799
0
        if (c_oil->oif_flags[oif_vif_index] &
3800
0
            PIM_OIF_FLAG_PROTO_GM)
3801
0
#if PIM_IPV == 4
3802
0
          json_object_boolean_true_add(
3803
0
            json_ifp_out, "protocolIgmp");
3804
#else
3805
          json_object_boolean_true_add(
3806
            json_ifp_out, "protocolMld");
3807
#endif
3808
3809
0
        if (c_oil->oif_flags[oif_vif_index] &
3810
0
            PIM_OIF_FLAG_PROTO_VXLAN)
3811
0
          json_object_boolean_true_add(
3812
0
            json_ifp_out, "protocolVxlan");
3813
3814
0
        if (c_oil->oif_flags[oif_vif_index] &
3815
0
            PIM_OIF_FLAG_PROTO_STAR)
3816
0
          json_object_boolean_true_add(
3817
0
            json_ifp_out,
3818
0
            "protocolInherited");
3819
3820
0
        json_object_string_add(json_ifp_out,
3821
0
                   "inboundInterface",
3822
0
                   in_ifname);
3823
0
        json_object_int_add(json_ifp_out, "iVifI",
3824
0
                *oil_parent(c_oil));
3825
0
        json_object_string_add(json_ifp_out,
3826
0
                   "outboundInterface",
3827
0
                   out_ifname);
3828
0
        json_object_int_add(json_ifp_out, "oVifI",
3829
0
                oif_vif_index);
3830
0
        json_object_int_add(json_ifp_out, "ttl", ttl);
3831
0
        json_object_string_add(json_ifp_out, "upTime",
3832
0
                   mroute_uptime);
3833
0
        json_object_string_add(json_source, "flags",
3834
0
                   state_str);
3835
0
        if (!json_oil) {
3836
0
          json_oil = json_object_new_object();
3837
0
          json_object_object_add(json_source,
3838
0
                     "oil", json_oil);
3839
0
        }
3840
0
        json_object_object_add(json_oil, out_ifname,
3841
0
                   json_ifp_out);
3842
0
      } else {
3843
0
        proto[0] = '\0';
3844
0
        if (c_oil->oif_flags[oif_vif_index] &
3845
0
            PIM_OIF_FLAG_PROTO_PIM) {
3846
0
          strlcpy(proto, "PIM", sizeof(proto));
3847
0
        }
3848
3849
0
        if (c_oil->oif_flags[oif_vif_index] &
3850
0
            PIM_OIF_FLAG_PROTO_GM) {
3851
0
#if PIM_IPV == 4
3852
0
          strlcpy(proto, "IGMP", sizeof(proto));
3853
#else
3854
          strlcpy(proto, "MLD", sizeof(proto));
3855
#endif
3856
0
        }
3857
3858
0
        if (c_oil->oif_flags[oif_vif_index] &
3859
0
            PIM_OIF_FLAG_PROTO_VXLAN) {
3860
0
          strlcpy(proto, "VxLAN", sizeof(proto));
3861
0
        }
3862
3863
0
        if (c_oil->oif_flags[oif_vif_index] &
3864
0
            PIM_OIF_FLAG_PROTO_STAR) {
3865
0
          strlcpy(proto, "STAR", sizeof(proto));
3866
0
        }
3867
3868
0
        ttable_add_row(tt, "%s|%s|%s|%s|%s|%s|%d|%s",
3869
0
                 src_str, grp_str, state_str,
3870
0
                 proto, in_ifname, out_ifname,
3871
0
                 ttl, mroute_uptime);
3872
3873
0
        if (first) {
3874
0
          src_str[0] = '\0';
3875
0
          grp_str[0] = '\0';
3876
0
          in_ifname[0] = '\0';
3877
0
          state_str[0] = '\0';
3878
0
          mroute_uptime[0] = '\0';
3879
0
          first = 0;
3880
0
        }
3881
0
      }
3882
0
    }
3883
3884
0
    if (!json && !found_oif) {
3885
0
      ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3886
0
               oil_origin(c_oil), oil_mcastgrp(c_oil),
3887
0
               state_str, "none", in_ifname, "none", 0,
3888
0
               "--:--:--");
3889
0
    }
3890
0
  }
3891
3892
  /* Print list of static routes */
3893
0
  for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
3894
0
    first = 1;
3895
3896
0
    if (!s_route->c_oil.installed)
3897
0
      continue;
3898
3899
0
    snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group);
3900
0
    snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source);
3901
0
    ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
3902
0
    found_oif = 0;
3903
3904
0
    if (ifp_in)
3905
0
      strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3906
0
    else
3907
0
      strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3908
3909
0
    if (json) {
3910
3911
      /* Find the group, create it if it doesn't exist */
3912
0
      json_object_object_get_ex(json, grp_str, &json_group);
3913
3914
0
      if (!json_group) {
3915
0
        json_group = json_object_new_object();
3916
0
        json_object_object_add(json, grp_str,
3917
0
                   json_group);
3918
0
      }
3919
3920
      /* Find the source nested under the group, create it if
3921
       * it doesn't exist
3922
       */
3923
0
      json_object_object_get_ex(json_group, src_str,
3924
0
              &json_source);
3925
3926
0
      if (!json_source) {
3927
0
        json_source = json_object_new_object();
3928
0
        json_object_object_add(json_group, src_str,
3929
0
                   json_source);
3930
0
      }
3931
3932
0
      json_object_string_add(json_source, "iif", in_ifname);
3933
0
      json_oil = NULL;
3934
0
    } else {
3935
0
      strlcpy(proto, "STATIC", sizeof(proto));
3936
0
    }
3937
3938
0
    for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3939
0
         ++oif_vif_index) {
3940
0
      struct interface *ifp_out;
3941
0
      char oif_uptime[10];
3942
0
      int ttl;
3943
3944
0
      ttl = s_route->oif_ttls[oif_vif_index];
3945
0
      if (ttl < 1)
3946
0
        continue;
3947
3948
0
      ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3949
0
      pim_time_uptime(
3950
0
        oif_uptime, sizeof(oif_uptime),
3951
0
        now - s_route->c_oil
3952
0
            .oif_creation[oif_vif_index]);
3953
0
      found_oif = 1;
3954
3955
0
      if (ifp_out)
3956
0
        strlcpy(out_ifname, ifp_out->name,
3957
0
          sizeof(out_ifname));
3958
0
      else
3959
0
        strlcpy(out_ifname, "<oif?>",
3960
0
          sizeof(out_ifname));
3961
3962
0
      if (json) {
3963
0
        json_ifp_out = json_object_new_object();
3964
0
        json_object_string_add(json_ifp_out, "source",
3965
0
                   src_str);
3966
0
        json_object_string_add(json_ifp_out, "group",
3967
0
                   grp_str);
3968
0
        json_object_boolean_true_add(json_ifp_out,
3969
0
                   "protocolStatic");
3970
0
        json_object_string_add(json_ifp_out,
3971
0
                   "inboundInterface",
3972
0
                   in_ifname);
3973
0
        json_object_int_add(
3974
0
          json_ifp_out, "iVifI",
3975
0
          *oil_parent(&s_route->c_oil));
3976
0
        json_object_string_add(json_ifp_out,
3977
0
                   "outboundInterface",
3978
0
                   out_ifname);
3979
0
        json_object_int_add(json_ifp_out, "oVifI",
3980
0
                oif_vif_index);
3981
0
        json_object_int_add(json_ifp_out, "ttl", ttl);
3982
0
        json_object_string_add(json_ifp_out, "upTime",
3983
0
                   oif_uptime);
3984
0
        if (!json_oil) {
3985
0
          json_oil = json_object_new_object();
3986
0
          json_object_object_add(json_source,
3987
0
                     "oil", json_oil);
3988
0
        }
3989
0
        json_object_object_add(json_oil, out_ifname,
3990
0
                   json_ifp_out);
3991
0
      } else {
3992
0
        ttable_add_row(
3993
0
          tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3994
0
          &s_route->source, &s_route->group, "-",
3995
0
          proto, in_ifname, out_ifname, ttl,
3996
0
          oif_uptime);
3997
0
        if (first && !fill) {
3998
0
          src_str[0] = '\0';
3999
0
          grp_str[0] = '\0';
4000
0
          in_ifname[0] = '\0';
4001
0
          first = 0;
4002
0
        }
4003
0
      }
4004
0
    }
4005
4006
0
    if (!json && !found_oif) {
4007
0
      ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4008
0
               &s_route->source, &s_route->group, "-",
4009
0
               proto, in_ifname, "none", 0, "--:--:--");
4010
0
    }
4011
0
  }
4012
  /* Dump the generated table. */
4013
0
  if (!json) {
4014
0
    table = ttable_dump(tt, "\n");
4015
0
    vty_out(vty, "%s\n", table);
4016
0
    XFREE(MTYPE_TMP, table);
4017
0
    ttable_del(tt);
4018
0
  }
4019
0
}
4020
4021
static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
4022
                json_object *json,
4023
                struct ttable *tt)
4024
0
{
4025
0
  json_object *json_group = NULL;
4026
0
  json_object *json_source = NULL;
4027
4028
0
  if (!c_oil->installed)
4029
0
    return;
4030
4031
0
  pim_mroute_update_counters(c_oil);
4032
4033
0
  if (json) {
4034
0
    char group_str[PIM_ADDRSTRLEN];
4035
0
    char source_str[PIM_ADDRSTRLEN];
4036
4037
0
    snprintfrr(group_str, sizeof(group_str), "%pPAs",
4038
0
         oil_mcastgrp(c_oil));
4039
0
    snprintfrr(source_str, sizeof(source_str), "%pPAs",
4040
0
         oil_origin(c_oil));
4041
4042
0
    json_object_object_get_ex(json, group_str, &json_group);
4043
4044
0
    if (!json_group) {
4045
0
      json_group = json_object_new_object();
4046
0
      json_object_object_add(json, group_str, json_group);
4047
0
    }
4048
4049
0
    json_source = json_object_new_object();
4050
0
    json_object_object_add(json_group, source_str, json_source);
4051
0
    json_object_int_add(json_source, "lastUsed",
4052
0
            c_oil->cc.lastused / 100);
4053
0
    json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
4054
0
    json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
4055
0
    json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
4056
4057
0
  } else {
4058
0
    ttable_add_row(tt, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
4059
0
             oil_origin(c_oil), oil_mcastgrp(c_oil),
4060
0
             c_oil->cc.lastused / 100,
4061
0
             c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
4062
0
             c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
4063
0
             c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
4064
0
  }
4065
0
}
4066
4067
void show_mroute_count(struct pim_instance *pim, struct vty *vty,
4068
           json_object *json)
4069
0
{
4070
0
  struct listnode *node;
4071
0
  struct channel_oil *c_oil;
4072
0
  struct static_route *sr;
4073
0
  struct ttable *tt = NULL;
4074
0
  char *table = NULL;
4075
4076
0
  if (!json) {
4077
0
    vty_out(vty, "\n");
4078
4079
    /* Prepare table. */
4080
0
    tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
4081
0
    ttable_add_row(tt,
4082
0
             "Source|Group|LastUsed|Packets|Bytes|WrongIf");
4083
0
    tt->style.cell.rpad = 2;
4084
0
    tt->style.corner = '+';
4085
0
    ttable_restyle(tt);
4086
0
  }
4087
4088
  /* Print PIM and IGMP route counts */
4089
0
  frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
4090
0
    show_mroute_count_per_channel_oil(c_oil, json, tt);
4091
4092
0
  for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
4093
0
    show_mroute_count_per_channel_oil(&sr->c_oil, json, tt);
4094
4095
  /* Dump the generated table. */
4096
0
  if (!json) {
4097
0
    table = ttable_dump(tt, "\n");
4098
0
    vty_out(vty, "%s\n", table);
4099
0
    XFREE(MTYPE_TMP, table);
4100
0
    ttable_del(tt);
4101
0
  }
4102
0
}
4103
4104
void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
4105
       json_object *json)
4106
0
{
4107
0
  struct listnode *node;
4108
0
  struct channel_oil *c_oil;
4109
0
  struct static_route *s_route;
4110
0
  uint32_t starg_sw_mroute_cnt = 0;
4111
0
  uint32_t sg_sw_mroute_cnt = 0;
4112
0
  uint32_t starg_hw_mroute_cnt = 0;
4113
0
  uint32_t sg_hw_mroute_cnt = 0;
4114
0
  json_object *json_starg = NULL;
4115
0
  json_object *json_sg = NULL;
4116
4117
0
  if (!json)
4118
0
    vty_out(vty, "Mroute Type    Installed/Total\n");
4119
4120
0
  frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
4121
0
    if (!c_oil->installed) {
4122
0
      if (pim_addr_is_any(*oil_origin(c_oil)))
4123
0
        starg_sw_mroute_cnt++;
4124
0
      else
4125
0
        sg_sw_mroute_cnt++;
4126
0
    } else {
4127
0
      if (pim_addr_is_any(*oil_origin(c_oil)))
4128
0
        starg_hw_mroute_cnt++;
4129
0
      else
4130
0
        sg_hw_mroute_cnt++;
4131
0
    }
4132
0
  }
4133
4134
0
  for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
4135
0
    if (!s_route->c_oil.installed) {
4136
0
      if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
4137
0
        starg_sw_mroute_cnt++;
4138
0
      else
4139
0
        sg_sw_mroute_cnt++;
4140
0
    } else {
4141
0
      if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
4142
0
        starg_hw_mroute_cnt++;
4143
0
      else
4144
0
        sg_hw_mroute_cnt++;
4145
0
    }
4146
0
  }
4147
4148
0
  if (!json) {
4149
0
    vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
4150
0
      starg_sw_mroute_cnt + starg_hw_mroute_cnt);
4151
0
    vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
4152
0
      sg_sw_mroute_cnt + sg_hw_mroute_cnt);
4153
0
    vty_out(vty, "------\n");
4154
0
    vty_out(vty, "%-20s %u/%u\n", "Total",
4155
0
      (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
4156
0
      (starg_sw_mroute_cnt + starg_hw_mroute_cnt +
4157
0
       sg_sw_mroute_cnt + sg_hw_mroute_cnt));
4158
0
  } else {
4159
    /* (*,G) route details */
4160
0
    json_starg = json_object_new_object();
4161
0
    json_object_object_add(json, "wildcardGroup", json_starg);
4162
4163
0
    json_object_int_add(json_starg, "installed",
4164
0
            starg_hw_mroute_cnt);
4165
0
    json_object_int_add(json_starg, "total",
4166
0
            starg_sw_mroute_cnt + starg_hw_mroute_cnt);
4167
4168
    /* (S, G) route details */
4169
0
    json_sg = json_object_new_object();
4170
0
    json_object_object_add(json, "sourceGroup", json_sg);
4171
4172
0
    json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
4173
0
    json_object_int_add(json_sg, "total",
4174
0
            sg_sw_mroute_cnt + sg_hw_mroute_cnt);
4175
4176
0
    json_object_int_add(json, "totalNumOfInstalledMroutes",
4177
0
            starg_hw_mroute_cnt + sg_hw_mroute_cnt);
4178
0
    json_object_int_add(json, "totalNumOfMroutes",
4179
0
            starg_sw_mroute_cnt + starg_hw_mroute_cnt +
4180
0
              sg_sw_mroute_cnt +
4181
0
              sg_hw_mroute_cnt);
4182
0
  }
4183
0
}
4184
4185
int clear_ip_mroute_count_command(struct vty *vty, const char *name)
4186
0
{
4187
0
  struct listnode *node;
4188
0
  struct channel_oil *c_oil;
4189
0
  struct static_route *sr;
4190
0
  struct vrf *v = pim_cmd_lookup(vty, name);
4191
0
  struct pim_instance *pim;
4192
4193
0
  if (!v)
4194
0
    return CMD_WARNING;
4195
4196
0
  pim = v->info;
4197
0
  frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
4198
0
    if (!c_oil->installed)
4199
0
      continue;
4200
4201
0
    pim_mroute_update_counters(c_oil);
4202
0
    c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
4203
0
    c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
4204
0
    c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
4205
0
  }
4206
4207
0
  for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
4208
0
    if (!sr->c_oil.installed)
4209
0
      continue;
4210
4211
0
    pim_mroute_update_counters(&sr->c_oil);
4212
4213
0
    sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
4214
0
    sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
4215
0
    sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
4216
0
  }
4217
0
  return CMD_SUCCESS;
4218
0
}
4219
4220
struct vrf *pim_cmd_lookup(struct vty *vty, const char *name)
4221
0
{
4222
0
  struct vrf *vrf;
4223
4224
0
  if (name)
4225
0
    vrf = vrf_lookup_by_name(name);
4226
0
  else
4227
0
    vrf = vrf_lookup_by_id(VRF_DEFAULT);
4228
4229
0
  if (!vrf)
4230
0
    vty_out(vty, "Specified VRF: %s does not exist\n", name);
4231
4232
0
  return vrf;
4233
0
}
4234
4235
void clear_mroute(struct pim_instance *pim)
4236
0
{
4237
0
  struct pim_upstream *up;
4238
0
  struct interface *ifp;
4239
4240
  /* scan interfaces */
4241
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
4242
0
    struct pim_interface *pim_ifp = ifp->info;
4243
0
    struct pim_ifchannel *ch;
4244
4245
0
    if (!pim_ifp)
4246
0
      continue;
4247
4248
    /* deleting all ifchannels */
4249
0
    while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
4250
0
      ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
4251
4252
0
      pim_ifchannel_delete(ch);
4253
0
    }
4254
4255
0
#if PIM_IPV == 4
4256
    /* clean up all igmp groups */
4257
0
    struct gm_group *grp;
4258
4259
0
    if (pim_ifp->gm_group_list) {
4260
0
      while (pim_ifp->gm_group_list->count) {
4261
0
        grp = listnode_head(pim_ifp->gm_group_list);
4262
0
        igmp_group_delete(grp);
4263
0
      }
4264
0
    }
4265
#else
4266
    struct gm_if *gm_ifp;
4267
4268
    gm_ifp = pim_ifp->mld;
4269
    if (gm_ifp)
4270
      gm_group_delete(gm_ifp);
4271
#endif
4272
0
  }
4273
4274
  /* clean up all upstreams*/
4275
0
  while ((up = rb_pim_upstream_first(&pim->upstream_head)))
4276
0
    pim_upstream_del(pim, up, __func__);
4277
0
}
4278
4279
void clear_pim_statistics(struct pim_instance *pim)
4280
0
{
4281
0
  struct interface *ifp;
4282
4283
0
  pim->bsm_rcvd = 0;
4284
0
  pim->bsm_sent = 0;
4285
0
  pim->bsm_dropped = 0;
4286
4287
  /* scan interfaces */
4288
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
4289
0
    struct pim_interface *pim_ifp = ifp->info;
4290
4291
0
    if (!pim_ifp)
4292
0
      continue;
4293
4294
0
    pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
4295
0
    pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
4296
0
    pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
4297
0
  }
4298
0
}
4299
4300
int clear_pim_interface_traffic(const char *vrf, struct vty *vty)
4301
0
{
4302
0
  struct interface *ifp = NULL;
4303
0
  struct pim_interface *pim_ifp = NULL;
4304
4305
0
  struct vrf *v = pim_cmd_lookup(vty, vrf);
4306
4307
0
  if (!v)
4308
0
    return CMD_WARNING;
4309
4310
0
  FOR_ALL_INTERFACES (v, ifp) {
4311
0
    pim_ifp = ifp->info;
4312
4313
0
    if (!pim_ifp)
4314
0
      continue;
4315
4316
0
    pim_ifp->pim_ifstat_hello_recv = 0;
4317
0
    pim_ifp->pim_ifstat_hello_sent = 0;
4318
0
    pim_ifp->pim_ifstat_join_recv = 0;
4319
0
    pim_ifp->pim_ifstat_join_send = 0;
4320
0
    pim_ifp->pim_ifstat_prune_recv = 0;
4321
0
    pim_ifp->pim_ifstat_prune_send = 0;
4322
0
    pim_ifp->pim_ifstat_reg_recv = 0;
4323
0
    pim_ifp->pim_ifstat_reg_send = 0;
4324
0
    pim_ifp->pim_ifstat_reg_stop_recv = 0;
4325
0
    pim_ifp->pim_ifstat_reg_stop_send = 0;
4326
0
    pim_ifp->pim_ifstat_assert_recv = 0;
4327
0
    pim_ifp->pim_ifstat_assert_send = 0;
4328
0
    pim_ifp->pim_ifstat_bsm_rx = 0;
4329
0
    pim_ifp->pim_ifstat_bsm_tx = 0;
4330
0
#if PIM_IPV == 4
4331
0
    pim_ifp->igmp_ifstat_joins_sent = 0;
4332
0
    pim_ifp->igmp_ifstat_joins_failed = 0;
4333
0
    pim_ifp->igmp_peak_group_count = 0;
4334
0
#endif
4335
0
  }
4336
4337
0
  return CMD_SUCCESS;
4338
0
}
4339
4340
int pim_debug_pim_cmd(void)
4341
0
{
4342
0
  PIM_DO_DEBUG_PIM_EVENTS;
4343
0
  PIM_DO_DEBUG_PIM_PACKETS;
4344
0
  PIM_DO_DEBUG_PIM_TRACE;
4345
0
  PIM_DO_DEBUG_MSDP_EVENTS;
4346
0
  PIM_DO_DEBUG_MSDP_PACKETS;
4347
0
  PIM_DO_DEBUG_BSM;
4348
0
  PIM_DO_DEBUG_VXLAN;
4349
0
  return CMD_SUCCESS;
4350
0
}
4351
4352
int pim_no_debug_pim_cmd(void)
4353
0
{
4354
0
  PIM_DONT_DEBUG_PIM_EVENTS;
4355
0
  PIM_DONT_DEBUG_PIM_PACKETS;
4356
0
  PIM_DONT_DEBUG_PIM_TRACE;
4357
0
  PIM_DONT_DEBUG_MSDP_EVENTS;
4358
0
  PIM_DONT_DEBUG_MSDP_PACKETS;
4359
4360
0
  PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
4361
0
  PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
4362
0
  PIM_DONT_DEBUG_BSM;
4363
0
  PIM_DONT_DEBUG_VXLAN;
4364
0
  return CMD_SUCCESS;
4365
0
}
4366
4367
int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
4368
            const char *registers, struct vty *vty)
4369
0
{
4370
0
  if (hello) {
4371
0
    PIM_DO_DEBUG_PIM_HELLO;
4372
0
    vty_out(vty, "PIM Hello debugging is on\n");
4373
0
  } else if (joins) {
4374
0
    PIM_DO_DEBUG_PIM_J_P;
4375
0
    vty_out(vty, "PIM Join/Prune debugging is on\n");
4376
0
  } else if (registers) {
4377
0
    PIM_DO_DEBUG_PIM_REG;
4378
0
    vty_out(vty, "PIM Register debugging is on\n");
4379
0
  } else {
4380
0
    PIM_DO_DEBUG_PIM_PACKETS;
4381
0
    vty_out(vty, "PIM Packet debugging is on\n");
4382
0
  }
4383
0
  return CMD_SUCCESS;
4384
0
}
4385
4386
int pim_no_debug_pim_packets_cmd(const char *hello, const char *joins,
4387
         const char *registers, struct vty *vty)
4388
0
{
4389
0
  if (hello) {
4390
0
    PIM_DONT_DEBUG_PIM_HELLO;
4391
0
    vty_out(vty, "PIM Hello debugging is off\n");
4392
0
  } else if (joins) {
4393
0
    PIM_DONT_DEBUG_PIM_J_P;
4394
0
    vty_out(vty, "PIM Join/Prune debugging is off\n");
4395
0
  } else if (registers) {
4396
0
    PIM_DONT_DEBUG_PIM_REG;
4397
0
    vty_out(vty, "PIM Register debugging is off\n");
4398
0
  } else {
4399
0
    PIM_DONT_DEBUG_PIM_PACKETS;
4400
0
    vty_out(vty, "PIM Packet debugging is off\n");
4401
0
  }
4402
4403
0
  return CMD_SUCCESS;
4404
0
}
4405
4406
int pim_show_rpf_helper(const char *vrf, struct vty *vty, bool json)
4407
0
{
4408
0
  struct pim_instance *pim;
4409
0
  struct vrf *v;
4410
0
  json_object *json_parent = NULL;
4411
4412
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4413
4414
0
  if (!v)
4415
0
    return CMD_WARNING;
4416
4417
0
  pim = v->info;
4418
4419
0
  if (!pim) {
4420
0
    vty_out(vty, "%% Unable to find pim instance\n");
4421
0
    return CMD_WARNING;
4422
0
  }
4423
4424
0
  if (json)
4425
0
    json_parent = json_object_new_object();
4426
4427
0
  pim_show_rpf(pim, vty, json_parent);
4428
4429
0
  if (json)
4430
0
    vty_json(vty, json_parent);
4431
4432
0
  return CMD_SUCCESS;
4433
0
}
4434
4435
int pim_show_rpf_vrf_all_helper(struct vty *vty, bool json)
4436
0
{
4437
0
  struct vrf *vrf;
4438
0
  json_object *json_parent = NULL;
4439
0
  json_object *json_vrf = NULL;
4440
4441
0
  if (json)
4442
0
    json_parent = json_object_new_object();
4443
4444
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4445
0
    if (!json)
4446
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4447
0
    else
4448
0
      json_vrf = json_object_new_object();
4449
0
    pim_show_rpf(vrf->info, vty, json_vrf);
4450
0
    if (json)
4451
0
      json_object_object_add(json_parent, vrf->name,
4452
0
                 json_vrf);
4453
0
  }
4454
0
  if (json)
4455
0
    vty_json(vty, json_parent);
4456
4457
0
  return CMD_SUCCESS;
4458
0
}
4459
4460
int pim_show_rp_helper(const char *vrf, struct vty *vty, const char *group_str,
4461
           const struct prefix *group, bool json)
4462
0
{
4463
0
  struct pim_instance *pim;
4464
0
  struct vrf *v;
4465
0
  json_object *json_parent = NULL;
4466
0
  struct prefix *range = NULL;
4467
4468
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4469
4470
0
  if (!v)
4471
0
    return CMD_WARNING;
4472
4473
0
  pim = v->info;
4474
4475
0
  if (!pim) {
4476
0
    vty_out(vty, "%% Unable to find pim instance\n");
4477
0
    return CMD_WARNING;
4478
0
  }
4479
4480
0
  if (group_str) {
4481
0
    range = prefix_new();
4482
0
    prefix_copy(range, group);
4483
0
    apply_mask(range);
4484
0
  }
4485
4486
0
  if (json)
4487
0
    json_parent = json_object_new_object();
4488
4489
0
  pim_rp_show_information(pim, range, vty, json_parent);
4490
4491
0
  if (json)
4492
0
    vty_json(vty, json_parent);
4493
4494
0
  prefix_free(&range);
4495
4496
0
  return CMD_SUCCESS;
4497
0
}
4498
4499
int pim_show_rp_vrf_all_helper(struct vty *vty, const char *group_str,
4500
             const struct prefix *group, bool json)
4501
0
{
4502
0
  struct vrf *vrf;
4503
0
  json_object *json_parent = NULL;
4504
0
  json_object *json_vrf = NULL;
4505
0
  struct prefix *range = NULL;
4506
4507
0
  if (group_str) {
4508
0
    range = prefix_new();
4509
0
    prefix_copy(range, group);
4510
0
    apply_mask(range);
4511
0
  }
4512
4513
0
  if (json)
4514
0
    json_parent = json_object_new_object();
4515
4516
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4517
0
    if (!json)
4518
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4519
0
    else
4520
0
      json_vrf = json_object_new_object();
4521
0
    pim_rp_show_information(vrf->info, range, vty, json_vrf);
4522
0
    if (json)
4523
0
      json_object_object_add(json_parent, vrf->name,
4524
0
                 json_vrf);
4525
0
  }
4526
0
  if (json)
4527
0
    vty_json(vty, json_parent);
4528
4529
0
  prefix_free(&range);
4530
4531
0
  return CMD_SUCCESS;
4532
0
}
4533
4534
int pim_show_secondary_helper(const char *vrf, struct vty *vty)
4535
0
{
4536
0
  struct pim_instance *pim;
4537
0
  struct vrf *v;
4538
4539
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4540
4541
0
  if (!v)
4542
0
    return CMD_WARNING;
4543
4544
0
  pim = v->info;
4545
4546
0
  if (!pim) {
4547
0
    vty_out(vty, "%% Unable to find pim instance\n");
4548
0
    return CMD_WARNING;
4549
0
  }
4550
4551
0
  pim_show_neighbors_secondary(pim, vty);
4552
4553
0
  return CMD_SUCCESS;
4554
0
}
4555
4556
int pim_show_statistics_helper(const char *vrf, struct vty *vty,
4557
             const char *word, bool uj)
4558
0
{
4559
0
  struct pim_instance *pim;
4560
0
  struct vrf *v;
4561
4562
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4563
4564
0
  if (!v)
4565
0
    return CMD_WARNING;
4566
4567
0
  pim = v->info;
4568
4569
0
  if (!pim) {
4570
0
    vty_out(vty, "%% Unable to find pim instance\n");
4571
0
    return CMD_WARNING;
4572
0
  }
4573
4574
0
  if (word)
4575
0
    pim_show_statistics(pim, vty, word, uj);
4576
0
  else
4577
0
    pim_show_statistics(pim, vty, NULL, uj);
4578
4579
0
  return CMD_SUCCESS;
4580
0
}
4581
4582
int pim_show_upstream_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
4583
           pim_addr g, bool json)
4584
0
{
4585
0
  pim_sgaddr sg = {0};
4586
0
  struct vrf *v;
4587
0
  struct pim_instance *pim;
4588
0
  json_object *json_parent = NULL;
4589
4590
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4591
4592
0
  if (!v) {
4593
0
    vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
4594
0
    return CMD_WARNING;
4595
0
  }
4596
0
  pim = v->info;
4597
4598
0
  if (!pim) {
4599
0
    vty_out(vty, "%% Unable to find pim instance\n");
4600
0
    return CMD_WARNING;
4601
0
  }
4602
4603
0
  if (json)
4604
0
    json_parent = json_object_new_object();
4605
4606
0
  if (!pim_addr_is_any(s_or_g)) {
4607
0
    if (!pim_addr_is_any(g)) {
4608
0
      sg.src = s_or_g;
4609
0
      sg.grp = g;
4610
0
    } else
4611
0
      sg.grp = s_or_g;
4612
0
  }
4613
4614
0
  pim_show_upstream(pim, vty, &sg, json_parent);
4615
4616
0
  if (json)
4617
0
    vty_json(vty, json_parent);
4618
4619
0
  return CMD_SUCCESS;
4620
0
}
4621
4622
int pim_show_upstream_vrf_all_helper(struct vty *vty, bool json)
4623
0
{
4624
0
  pim_sgaddr sg = {0};
4625
0
  struct vrf *vrf;
4626
0
  json_object *json_parent = NULL;
4627
0
  json_object *json_vrf = NULL;
4628
4629
0
  if (json)
4630
0
    json_parent = json_object_new_object();
4631
4632
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4633
0
    if (!json)
4634
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4635
0
    else
4636
0
      json_vrf = json_object_new_object();
4637
0
    pim_show_upstream(vrf->info, vty, &sg, json_vrf);
4638
0
    if (json)
4639
0
      json_object_object_add(json_parent, vrf->name,
4640
0
                 json_vrf);
4641
0
  }
4642
4643
0
  if (json)
4644
0
    vty_json(vty, json_parent);
4645
4646
0
  return CMD_SUCCESS;
4647
0
}
4648
4649
int pim_show_upstream_join_desired_helper(const char *vrf, struct vty *vty,
4650
            bool uj)
4651
0
{
4652
0
  struct pim_instance *pim;
4653
0
  struct vrf *v;
4654
4655
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4656
4657
0
  if (!v)
4658
0
    return CMD_WARNING;
4659
4660
0
  pim = v->info;
4661
4662
0
  if (!pim) {
4663
0
    vty_out(vty, "%% Unable to find pim instance\n");
4664
0
    return CMD_WARNING;
4665
0
  }
4666
4667
0
  pim_show_join_desired(pim, vty, uj);
4668
4669
0
  return CMD_SUCCESS;
4670
0
}
4671
4672
int pim_show_upstream_rpf_helper(const char *vrf, struct vty *vty, bool uj)
4673
0
{
4674
0
  struct pim_instance *pim;
4675
0
  struct vrf *v;
4676
4677
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4678
4679
0
  if (!v)
4680
0
    return CMD_WARNING;
4681
4682
0
  pim = v->info;
4683
4684
0
  if (!pim) {
4685
0
    vty_out(vty, "%% Unable to find pim instance\n");
4686
0
    return CMD_WARNING;
4687
0
  }
4688
4689
0
  pim_show_upstream_rpf(pim, vty, uj);
4690
4691
0
  return CMD_SUCCESS;
4692
0
}
4693
4694
int pim_show_state_helper(const char *vrf, struct vty *vty,
4695
        const char *s_or_g_str, const char *g_str, bool json)
4696
0
{
4697
0
  struct pim_instance *pim;
4698
0
  struct vrf *v;
4699
0
  json_object *json_parent = NULL;
4700
4701
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4702
4703
0
  if (!v)
4704
0
    return CMD_WARNING;
4705
4706
0
  pim = v->info;
4707
4708
0
  if (!pim) {
4709
0
    vty_out(vty, "%% Unable to find pim instance\n");
4710
0
    return CMD_WARNING;
4711
0
  }
4712
4713
0
  if (json)
4714
0
    json_parent = json_object_new_object();
4715
4716
0
  pim_show_state(pim, vty, s_or_g_str, g_str, json_parent);
4717
4718
0
  if (json)
4719
0
    vty_json(vty, json_parent);
4720
4721
0
  return CMD_SUCCESS;
4722
0
}
4723
4724
int pim_show_state_vrf_all_helper(struct vty *vty, const char *s_or_g_str,
4725
          const char *g_str, bool json)
4726
0
{
4727
0
  struct vrf *vrf;
4728
0
  json_object *json_parent = NULL;
4729
0
  json_object *json_vrf = NULL;
4730
4731
0
  if (json)
4732
0
    json_parent = json_object_new_object();
4733
4734
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4735
0
    if (!json)
4736
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4737
0
    else
4738
0
      json_vrf = json_object_new_object();
4739
0
    pim_show_state(vrf->info, vty, s_or_g_str, g_str, json_vrf);
4740
0
    if (json)
4741
0
      json_object_object_add(json_parent, vrf->name,
4742
0
                 json_vrf);
4743
0
  }
4744
0
  if (json)
4745
0
    vty_json(vty, json_parent);
4746
4747
0
  return CMD_SUCCESS;
4748
0
}
4749
4750
int pim_show_multicast_helper(const char *vrf, struct vty *vty)
4751
0
{
4752
0
  struct vrf *v;
4753
0
  struct pim_instance *pim;
4754
4755
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4756
4757
0
  if (!v)
4758
0
    return CMD_WARNING;
4759
4760
0
  pim = v->info;
4761
4762
0
  if (!pim) {
4763
0
    vty_out(vty, "%% Unable to find pim instance\n");
4764
0
    return CMD_WARNING;
4765
0
  }
4766
4767
0
  pim_cmd_show_ip_multicast_helper(pim, vty);
4768
4769
0
  return CMD_SUCCESS;
4770
0
}
4771
4772
int pim_show_multicast_vrf_all_helper(struct vty *vty)
4773
0
{
4774
0
  struct vrf *vrf;
4775
4776
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4777
0
    vty_out(vty, "VRF: %s\n", vrf->name);
4778
0
    pim_cmd_show_ip_multicast_helper(vrf->info, vty);
4779
0
  }
4780
4781
0
  return CMD_SUCCESS;
4782
0
}
4783
4784
int pim_show_multicast_count_helper(const char *vrf, struct vty *vty, bool json)
4785
0
{
4786
0
  struct pim_instance *pim;
4787
0
  struct vrf *v;
4788
0
  json_object *json_parent = NULL;
4789
4790
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4791
4792
0
  if (!v)
4793
0
    return CMD_WARNING;
4794
4795
0
  pim = v->info;
4796
4797
0
  if (!pim) {
4798
0
    vty_out(vty, "%% Unable to find pim instance\n");
4799
0
    return CMD_WARNING;
4800
0
  }
4801
4802
0
  if (json)
4803
0
    json_parent = json_object_new_object();
4804
4805
0
  show_multicast_interfaces(pim, vty, json_parent);
4806
4807
0
  if (json)
4808
0
    vty_json(vty, json_parent);
4809
4810
0
  return CMD_SUCCESS;
4811
0
}
4812
4813
int pim_show_multicast_count_vrf_all_helper(struct vty *vty, bool json)
4814
0
{
4815
0
  struct vrf *vrf;
4816
0
  json_object *json_parent = NULL;
4817
0
  json_object *json_vrf = NULL;
4818
4819
0
  if (json)
4820
0
    json_parent = json_object_new_object();
4821
4822
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4823
0
    if (!json)
4824
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4825
0
    else
4826
0
      json_vrf = json_object_new_object();
4827
4828
0
    show_multicast_interfaces(vrf->info, vty, json_vrf);
4829
0
    if (json)
4830
0
      json_object_object_add(json_parent, vrf->name,
4831
0
                 json_vrf);
4832
0
  }
4833
0
  if (json)
4834
0
    vty_json(vty, json_parent);
4835
4836
0
  return CMD_SUCCESS;
4837
0
}
4838
4839
int pim_show_mroute_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
4840
         pim_addr g, bool fill, bool json)
4841
0
{
4842
0
  pim_sgaddr sg = {0};
4843
0
  struct pim_instance *pim;
4844
0
  struct vrf *v;
4845
0
  json_object *json_parent = NULL;
4846
4847
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4848
4849
0
  if (!v)
4850
0
    return CMD_WARNING;
4851
4852
0
  pim = v->info;
4853
4854
0
  if (!pim) {
4855
0
    vty_out(vty, "%% Unable to find pim instance\n");
4856
0
    return CMD_WARNING;
4857
0
  }
4858
4859
0
  if (json)
4860
0
    json_parent = json_object_new_object();
4861
4862
0
  if (!pim_addr_is_any(s_or_g)) {
4863
0
    if (!pim_addr_is_any(g)) {
4864
0
      sg.src = s_or_g;
4865
0
      sg.grp = g;
4866
0
    } else
4867
0
      sg.grp = s_or_g;
4868
0
  }
4869
4870
0
  show_mroute(pim, vty, &sg, fill, json_parent);
4871
4872
0
  if (json)
4873
0
    vty_json(vty, json_parent);
4874
4875
0
  return CMD_SUCCESS;
4876
0
}
4877
4878
int pim_show_mroute_vrf_all_helper(struct vty *vty, bool fill, bool json)
4879
0
{
4880
0
  pim_sgaddr sg = {0};
4881
0
  struct vrf *vrf;
4882
0
  json_object *json_parent = NULL;
4883
0
  json_object *json_vrf = NULL;
4884
4885
0
  if (json)
4886
0
    json_parent = json_object_new_object();
4887
4888
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4889
0
    if (!json)
4890
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4891
0
    else
4892
0
      json_vrf = json_object_new_object();
4893
0
    show_mroute(vrf->info, vty, &sg, fill, json_vrf);
4894
0
    if (json)
4895
0
      json_object_object_add(json_parent, vrf->name,
4896
0
                 json_vrf);
4897
0
  }
4898
0
  if (json)
4899
0
    vty_json(vty, json_parent);
4900
4901
0
  return CMD_SUCCESS;
4902
0
}
4903
4904
int pim_show_mroute_count_helper(const char *vrf, struct vty *vty, bool json)
4905
0
{
4906
0
  struct pim_instance *pim;
4907
0
  struct vrf *v;
4908
0
  json_object *json_parent = NULL;
4909
4910
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4911
4912
0
  if (!v)
4913
0
    return CMD_WARNING;
4914
4915
0
  pim = v->info;
4916
4917
0
  if (!pim) {
4918
0
    vty_out(vty, "%% Unable to find pim instance\n");
4919
0
    return CMD_WARNING;
4920
0
  }
4921
4922
0
  if (json)
4923
0
    json_parent = json_object_new_object();
4924
4925
0
  show_mroute_count(pim, vty, json_parent);
4926
4927
0
  if (json)
4928
0
    vty_json(vty, json_parent);
4929
4930
0
  return CMD_SUCCESS;
4931
0
}
4932
4933
int pim_show_mroute_count_vrf_all_helper(struct vty *vty, bool json)
4934
0
{
4935
0
  struct vrf *vrf;
4936
0
  json_object *json_parent = NULL;
4937
0
  json_object *json_vrf = NULL;
4938
4939
0
  if (json)
4940
0
    json_parent = json_object_new_object();
4941
4942
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4943
0
    if (!json)
4944
0
      vty_out(vty, "VRF: %s\n", vrf->name);
4945
0
    else
4946
0
      json_vrf = json_object_new_object();
4947
4948
0
    show_mroute_count(vrf->info, vty, json_vrf);
4949
4950
0
    if (json)
4951
0
      json_object_object_add(json_parent, vrf->name,
4952
0
                 json_vrf);
4953
0
  }
4954
0
  if (json)
4955
0
    vty_json(vty, json_parent);
4956
4957
0
  return CMD_SUCCESS;
4958
0
}
4959
4960
int pim_show_mroute_summary_helper(const char *vrf, struct vty *vty, bool json)
4961
0
{
4962
0
  struct pim_instance *pim;
4963
0
  struct vrf *v;
4964
0
  json_object *json_parent = NULL;
4965
4966
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4967
4968
0
  if (!v)
4969
0
    return CMD_WARNING;
4970
4971
0
  pim = v->info;
4972
4973
0
  if (!pim) {
4974
0
    vty_out(vty, "%% Unable to find pim instance\n");
4975
0
    return CMD_WARNING;
4976
0
  }
4977
4978
0
  if (json)
4979
0
    json_parent = json_object_new_object();
4980
4981
0
  show_mroute_summary(pim, vty, json_parent);
4982
4983
0
  if (json)
4984
0
    vty_json(vty, json_parent);
4985
4986
0
  return CMD_SUCCESS;
4987
0
}
4988
4989
int pim_show_mroute_summary_vrf_all_helper(struct vty *vty, bool json)
4990
0
{
4991
0
  struct vrf *vrf;
4992
0
  json_object *json_parent = NULL;
4993
0
  json_object *json_vrf = NULL;
4994
4995
0
  if (json)
4996
0
    json_parent = json_object_new_object();
4997
4998
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4999
0
    if (!json)
5000
0
      vty_out(vty, "VRF: %s\n", vrf->name);
5001
0
    else
5002
0
      json_vrf = json_object_new_object();
5003
5004
0
    show_mroute_summary(vrf->info, vty, json_vrf);
5005
5006
0
    if (json)
5007
0
      json_object_object_add(json_parent, vrf->name,
5008
0
                 json_vrf);
5009
0
  }
5010
5011
0
  if (json)
5012
0
    vty_json(vty, json_parent);
5013
5014
0
  return CMD_SUCCESS;
5015
0
}
5016
5017
void pim_show_interface_traffic(struct pim_instance *pim, struct vty *vty,
5018
        bool uj)
5019
0
{
5020
0
  struct interface *ifp = NULL;
5021
0
  struct pim_interface *pim_ifp = NULL;
5022
0
  json_object *json = NULL;
5023
0
  json_object *json_row = NULL;
5024
5025
0
  if (uj)
5026
0
    json = json_object_new_object();
5027
0
  else {
5028
0
    vty_out(vty, "\n");
5029
0
    vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5030
0
      "Interface", "       HELLO", "       JOIN",
5031
0
      "      PRUNE", "   REGISTER", "REGISTER-STOP",
5032
0
      "  ASSERT", "  BSM");
5033
0
    vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5034
0
      "       Rx/Tx", "       Rx/Tx", "      Rx/Tx",
5035
0
      "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "   Rx/Tx");
5036
0
    vty_out(vty,
5037
0
      "---------------------------------------------------------------------------------------------------------------\n");
5038
0
  }
5039
5040
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
5041
0
    pim_ifp = ifp->info;
5042
5043
0
    if (!pim_ifp)
5044
0
      continue;
5045
5046
0
    if (uj) {
5047
0
      json_row = json_object_new_object();
5048
0
      json_object_pim_ifp_add(json_row, ifp);
5049
0
      json_object_int_add(json_row, "helloRx",
5050
0
              pim_ifp->pim_ifstat_hello_recv);
5051
0
      json_object_int_add(json_row, "helloTx",
5052
0
              pim_ifp->pim_ifstat_hello_sent);
5053
0
      json_object_int_add(json_row, "joinRx",
5054
0
              pim_ifp->pim_ifstat_join_recv);
5055
0
      json_object_int_add(json_row, "joinTx",
5056
0
              pim_ifp->pim_ifstat_join_send);
5057
0
      json_object_int_add(json_row, "pruneRx",
5058
0
              pim_ifp->pim_ifstat_prune_recv);
5059
0
      json_object_int_add(json_row, "pruneTx",
5060
0
              pim_ifp->pim_ifstat_prune_send);
5061
0
      json_object_int_add(json_row, "registerRx",
5062
0
              pim_ifp->pim_ifstat_reg_recv);
5063
0
      json_object_int_add(json_row, "registerTx",
5064
0
              pim_ifp->pim_ifstat_reg_send);
5065
0
      json_object_int_add(json_row, "registerStopRx",
5066
0
              pim_ifp->pim_ifstat_reg_stop_recv);
5067
0
      json_object_int_add(json_row, "registerStopTx",
5068
0
              pim_ifp->pim_ifstat_reg_stop_send);
5069
0
      json_object_int_add(json_row, "assertRx",
5070
0
              pim_ifp->pim_ifstat_assert_recv);
5071
0
      json_object_int_add(json_row, "assertTx",
5072
0
              pim_ifp->pim_ifstat_assert_send);
5073
0
      json_object_int_add(json_row, "bsmRx",
5074
0
              pim_ifp->pim_ifstat_bsm_rx);
5075
0
      json_object_int_add(json_row, "bsmTx",
5076
0
              pim_ifp->pim_ifstat_bsm_tx);
5077
0
      json_object_object_add(json, ifp->name, json_row);
5078
0
    } else {
5079
0
      vty_out(vty,
5080
0
        "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5081
0
        "/%-7" PRIu64 "\n",
5082
0
        ifp->name, pim_ifp->pim_ifstat_hello_recv,
5083
0
        pim_ifp->pim_ifstat_hello_sent,
5084
0
        pim_ifp->pim_ifstat_join_recv,
5085
0
        pim_ifp->pim_ifstat_join_send,
5086
0
        pim_ifp->pim_ifstat_prune_recv,
5087
0
        pim_ifp->pim_ifstat_prune_send,
5088
0
        pim_ifp->pim_ifstat_reg_recv,
5089
0
        pim_ifp->pim_ifstat_reg_send,
5090
0
        pim_ifp->pim_ifstat_reg_stop_recv,
5091
0
        pim_ifp->pim_ifstat_reg_stop_send,
5092
0
        pim_ifp->pim_ifstat_assert_recv,
5093
0
        pim_ifp->pim_ifstat_assert_send,
5094
0
        pim_ifp->pim_ifstat_bsm_rx,
5095
0
        pim_ifp->pim_ifstat_bsm_tx);
5096
0
    }
5097
0
  }
5098
0
  if (uj)
5099
0
    vty_json(vty, json);
5100
0
}
5101
5102
void pim_show_interface_traffic_single(struct pim_instance *pim,
5103
               struct vty *vty, const char *ifname,
5104
               bool uj)
5105
0
{
5106
0
  struct interface *ifp = NULL;
5107
0
  struct pim_interface *pim_ifp = NULL;
5108
0
  json_object *json = NULL;
5109
0
  json_object *json_row = NULL;
5110
0
  uint8_t found_ifname = 0;
5111
5112
0
  if (uj)
5113
0
    json = json_object_new_object();
5114
0
  else {
5115
0
    vty_out(vty, "\n");
5116
0
    vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5117
0
      "Interface", "    HELLO", "    JOIN", "   PRUNE",
5118
0
      "   REGISTER", "  REGISTER-STOP", "  ASSERT",
5119
0
      "    BSM");
5120
0
    vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5121
0
      "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
5122
0
      "     Rx/Tx", "    Rx/Tx", "    Rx/Tx");
5123
0
    vty_out(vty,
5124
0
      "-------------------------------------------------------------------------------------------------------------------------------\n");
5125
0
  }
5126
5127
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
5128
0
    if (strcmp(ifname, ifp->name))
5129
0
      continue;
5130
5131
0
    pim_ifp = ifp->info;
5132
5133
0
    if (!pim_ifp)
5134
0
      continue;
5135
5136
0
    found_ifname = 1;
5137
0
    if (uj) {
5138
0
      json_row = json_object_new_object();
5139
0
      json_object_pim_ifp_add(json_row, ifp);
5140
0
      json_object_int_add(json_row, "helloRx",
5141
0
              pim_ifp->pim_ifstat_hello_recv);
5142
0
      json_object_int_add(json_row, "helloTx",
5143
0
              pim_ifp->pim_ifstat_hello_sent);
5144
0
      json_object_int_add(json_row, "joinRx",
5145
0
              pim_ifp->pim_ifstat_join_recv);
5146
0
      json_object_int_add(json_row, "joinTx",
5147
0
              pim_ifp->pim_ifstat_join_send);
5148
0
      json_object_int_add(json_row, "pruneRx",
5149
0
              pim_ifp->pim_ifstat_prune_recv);
5150
0
      json_object_int_add(json_row, "pruneTx",
5151
0
              pim_ifp->pim_ifstat_prune_send);
5152
0
      json_object_int_add(json_row, "registerRx",
5153
0
              pim_ifp->pim_ifstat_reg_recv);
5154
0
      json_object_int_add(json_row, "registerTx",
5155
0
              pim_ifp->pim_ifstat_reg_send);
5156
0
      json_object_int_add(json_row, "registerStopRx",
5157
0
              pim_ifp->pim_ifstat_reg_stop_recv);
5158
0
      json_object_int_add(json_row, "registerStopTx",
5159
0
              pim_ifp->pim_ifstat_reg_stop_send);
5160
0
      json_object_int_add(json_row, "assertRx",
5161
0
              pim_ifp->pim_ifstat_assert_recv);
5162
0
      json_object_int_add(json_row, "assertTx",
5163
0
              pim_ifp->pim_ifstat_assert_send);
5164
0
      json_object_int_add(json_row, "bsmRx",
5165
0
              pim_ifp->pim_ifstat_bsm_rx);
5166
0
      json_object_int_add(json_row, "bsmTx",
5167
0
              pim_ifp->pim_ifstat_bsm_tx);
5168
5169
0
      json_object_object_add(json, ifp->name, json_row);
5170
0
    } else {
5171
0
      vty_out(vty,
5172
0
        "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5173
0
        "/%-7" PRIu64 "\n",
5174
0
        ifp->name, pim_ifp->pim_ifstat_hello_recv,
5175
0
        pim_ifp->pim_ifstat_hello_sent,
5176
0
        pim_ifp->pim_ifstat_join_recv,
5177
0
        pim_ifp->pim_ifstat_join_send,
5178
0
        pim_ifp->pim_ifstat_prune_recv,
5179
0
        pim_ifp->pim_ifstat_prune_send,
5180
0
        pim_ifp->pim_ifstat_reg_recv,
5181
0
        pim_ifp->pim_ifstat_reg_send,
5182
0
        pim_ifp->pim_ifstat_reg_stop_recv,
5183
0
        pim_ifp->pim_ifstat_reg_stop_send,
5184
0
        pim_ifp->pim_ifstat_assert_recv,
5185
0
        pim_ifp->pim_ifstat_assert_send,
5186
0
        pim_ifp->pim_ifstat_bsm_rx,
5187
0
        pim_ifp->pim_ifstat_bsm_tx);
5188
0
    }
5189
0
  }
5190
0
  if (uj)
5191
0
    vty_json(vty, json);
5192
0
  else if (!found_ifname)
5193
0
    vty_out(vty, "%% No such interface\n");
5194
0
}
5195
5196
int pim_show_interface_traffic_helper(const char *vrf, const char *if_name,
5197
              struct vty *vty, bool uj)
5198
0
{
5199
0
  struct pim_instance *pim;
5200
0
  struct vrf *v;
5201
5202
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5203
5204
0
  if (!v)
5205
0
    return CMD_WARNING;
5206
5207
0
  pim = v->info;
5208
5209
0
  if (!pim) {
5210
0
    vty_out(vty, "%% Unable to find pim instance\n");
5211
0
    return CMD_WARNING;
5212
0
  }
5213
5214
0
  if (if_name)
5215
0
    pim_show_interface_traffic_single(v->info, vty, if_name, uj);
5216
0
  else
5217
0
    pim_show_interface_traffic(v->info, vty, uj);
5218
5219
0
  return CMD_SUCCESS;
5220
0
}
5221
5222
void clear_pim_interfaces(struct pim_instance *pim)
5223
0
{
5224
0
  struct interface *ifp;
5225
5226
0
  FOR_ALL_INTERFACES (pim->vrf, ifp) {
5227
0
    if (ifp->info)
5228
0
      pim_neighbor_delete_all(ifp, "interface cleared");
5229
0
  }
5230
0
}
5231
5232
void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj)
5233
0
{
5234
0
  char uptime[10];
5235
0
  char last_bsm_seen[10];
5236
0
  time_t now;
5237
0
  char bsr_state[20];
5238
0
  json_object *json = NULL;
5239
5240
0
  if (pim_addr_is_any(pim->global_scope.current_bsr)) {
5241
0
    pim_time_uptime(uptime, sizeof(uptime),
5242
0
        pim->global_scope.current_bsr_first_ts);
5243
0
    pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
5244
0
        pim->global_scope.current_bsr_last_ts);
5245
0
  }
5246
5247
0
  else {
5248
0
    now = pim_time_monotonic_sec();
5249
0
    pim_time_uptime(uptime, sizeof(uptime),
5250
0
        (now - pim->global_scope.current_bsr_first_ts));
5251
0
    pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
5252
0
        now - pim->global_scope.current_bsr_last_ts);
5253
0
  }
5254
5255
0
  switch (pim->global_scope.state) {
5256
0
  case NO_INFO:
5257
0
    strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state));
5258
0
    break;
5259
0
  case ACCEPT_ANY:
5260
0
    strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state));
5261
0
    break;
5262
0
  case ACCEPT_PREFERRED:
5263
0
    strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state));
5264
0
    break;
5265
0
  default:
5266
0
    strlcpy(bsr_state, "", sizeof(bsr_state));
5267
0
  }
5268
5269
5270
0
  if (uj) {
5271
0
    json = json_object_new_object();
5272
0
    json_object_string_addf(json, "bsr", "%pPA",
5273
0
          &pim->global_scope.current_bsr);
5274
0
    json_object_int_add(json, "priority",
5275
0
            pim->global_scope.current_bsr_prio);
5276
0
    json_object_int_add(json, "fragmentTag",
5277
0
            pim->global_scope.bsm_frag_tag);
5278
0
    json_object_string_add(json, "state", bsr_state);
5279
0
    json_object_string_add(json, "upTime", uptime);
5280
0
    json_object_string_add(json, "lastBsmSeen", last_bsm_seen);
5281
0
  }
5282
5283
0
  else {
5284
0
    vty_out(vty, "PIMv2 Bootstrap information\n");
5285
0
    vty_out(vty, "Current preferred BSR address: %pPA\n",
5286
0
      &pim->global_scope.current_bsr);
5287
0
    vty_out(vty,
5288
0
      "Priority        Fragment-Tag       State           UpTime\n");
5289
0
    vty_out(vty, "  %-12d    %-12d    %-13s    %7s\n",
5290
0
      pim->global_scope.current_bsr_prio,
5291
0
      pim->global_scope.bsm_frag_tag, bsr_state, uptime);
5292
0
    vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen);
5293
0
  }
5294
5295
0
  if (uj)
5296
0
    vty_json(vty, json);
5297
0
}
5298
5299
int pim_show_bsr_helper(const char *vrf, struct vty *vty, bool uj)
5300
0
{
5301
0
  struct pim_instance *pim;
5302
0
  struct vrf *v;
5303
5304
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5305
5306
0
  if (!v)
5307
0
    return CMD_WARNING;
5308
5309
0
  pim = pim_get_pim_instance(v->vrf_id);
5310
5311
0
  if (!pim) {
5312
0
    vty_out(vty, "%% Unable to find pim instance\n");
5313
0
    return CMD_WARNING;
5314
0
  }
5315
5316
0
  pim_show_bsr(v->info, vty, uj);
5317
5318
0
  return CMD_SUCCESS;
5319
0
}
5320
5321
/*Display the group-rp mappings */
5322
static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
5323
              struct vty *vty, bool uj)
5324
0
{
5325
0
  struct bsgrp_node *bsgrp;
5326
0
  struct bsm_rpinfo *bsm_rp;
5327
0
  struct route_node *rn;
5328
0
  json_object *json = NULL;
5329
0
  json_object *json_group = NULL;
5330
0
  json_object *json_row = NULL;
5331
0
  struct ttable *tt = NULL;
5332
5333
0
  if (uj) {
5334
0
    json = json_object_new_object();
5335
0
    json_object_string_addf(json, "BSR Address", "%pPA",
5336
0
          &pim->global_scope.current_bsr);
5337
0
  } else
5338
0
    vty_out(vty, "BSR Address  %pPA\n",
5339
0
      &pim->global_scope.current_bsr);
5340
5341
0
  for (rn = route_top(pim->global_scope.bsrp_table); rn;
5342
0
       rn = route_next(rn)) {
5343
0
    bsgrp = (struct bsgrp_node *)rn->info;
5344
5345
0
    if (!bsgrp)
5346
0
      continue;
5347
5348
0
    char grp_str[PREFIX_STRLEN];
5349
5350
0
    prefix2str(&bsgrp->group, grp_str, sizeof(grp_str));
5351
5352
0
    if (uj) {
5353
0
      json_object_object_get_ex(json, grp_str, &json_group);
5354
0
      if (!json_group) {
5355
0
        json_group = json_object_new_object();
5356
0
        json_object_object_add(json, grp_str,
5357
0
                   json_group);
5358
0
      }
5359
0
    } else {
5360
0
      vty_out(vty, "Group Address %pFX\n", &bsgrp->group);
5361
0
      vty_out(vty, "--------------------------\n");
5362
      /* Prepare table. */
5363
0
      tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
5364
0
      ttable_add_row(tt, "Rp Address|priority|Holdtime|Hash");
5365
0
      tt->style.cell.rpad = 2;
5366
0
      tt->style.corner = '+';
5367
0
      ttable_restyle(tt);
5368
5369
0
      ttable_add_row(tt, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ',
5370
0
               ' ');
5371
0
    }
5372
5373
0
    frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) {
5374
0
      if (uj) {
5375
0
        json_row = json_object_new_object();
5376
0
        json_object_string_addf(json_row, "Rp Address",
5377
0
              "%pPA",
5378
0
              &bsm_rp->rp_address);
5379
0
        json_object_int_add(json_row, "Rp HoldTime",
5380
0
                bsm_rp->rp_holdtime);
5381
0
        json_object_int_add(json_row, "Rp Priority",
5382
0
                bsm_rp->rp_prio);
5383
0
        json_object_int_add(json_row, "Hash Val",
5384
0
                bsm_rp->hash);
5385
0
        json_object_object_addf(json_group, json_row,
5386
0
              "%pPA",
5387
0
              &bsm_rp->rp_address);
5388
5389
0
      } else {
5390
0
        ttable_add_row(
5391
0
          tt, "%pPA|%u|%u|%u",
5392
0
          &bsm_rp->rp_address, bsm_rp->rp_prio,
5393
0
          bsm_rp->rp_holdtime, bsm_rp->hash);
5394
0
      }
5395
0
    }
5396
    /* Dump the generated table. */
5397
0
    if (tt) {
5398
0
      char *table = NULL;
5399
5400
0
      table = ttable_dump(tt, "\n");
5401
0
      vty_out(vty, "%s\n", table);
5402
0
      XFREE(MTYPE_TMP, table);
5403
0
      ttable_del(tt);
5404
0
      tt = NULL;
5405
0
    }
5406
0
    if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj)
5407
0
      vty_out(vty, "Active List is empty.\n");
5408
5409
0
    if (uj) {
5410
0
      json_object_int_add(json_group, "Pending RP count",
5411
0
              bsgrp->pend_rp_cnt);
5412
0
    } else {
5413
0
      vty_out(vty, "(PENDING)\n");
5414
0
      vty_out(vty, "Pending RP count :%d\n",
5415
0
        bsgrp->pend_rp_cnt);
5416
0
      if (bsgrp->pend_rp_cnt) {
5417
        /* Prepare table. */
5418
0
        tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
5419
0
        ttable_add_row(
5420
0
          tt,
5421
0
          "Rp Address|priority|Holdtime|Hash");
5422
0
        tt->style.cell.rpad = 2;
5423
0
        tt->style.corner = '+';
5424
0
        ttable_restyle(tt);
5425
0
      }
5426
0
    }
5427
5428
0
    frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) {
5429
0
      if (uj) {
5430
0
        json_row = json_object_new_object();
5431
0
        json_object_string_addf(json_row, "Rp Address",
5432
0
              "%pPA",
5433
0
              &bsm_rp->rp_address);
5434
0
        json_object_int_add(json_row, "Rp HoldTime",
5435
0
                bsm_rp->rp_holdtime);
5436
0
        json_object_int_add(json_row, "Rp Priority",
5437
0
                bsm_rp->rp_prio);
5438
0
        json_object_int_add(json_row, "Hash Val",
5439
0
                bsm_rp->hash);
5440
0
        json_object_object_addf(json_group, json_row,
5441
0
              "%pPA",
5442
0
              &bsm_rp->rp_address);
5443
0
      } else {
5444
0
        ttable_add_row(
5445
0
          tt, "%pPA|%u|%u|%u",
5446
0
          &bsm_rp->rp_address, bsm_rp->rp_prio,
5447
0
          bsm_rp->rp_holdtime, bsm_rp->hash);
5448
0
      }
5449
0
    }
5450
    /* Dump the generated table. */
5451
0
    if (tt) {
5452
0
      char *table = NULL;
5453
5454
0
      table = ttable_dump(tt, "\n");
5455
0
      vty_out(vty, "%s\n", table);
5456
0
      XFREE(MTYPE_TMP, table);
5457
0
      ttable_del(tt);
5458
0
    }
5459
0
    if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj)
5460
0
      vty_out(vty, "Partial List is empty\n");
5461
5462
0
    if (!uj)
5463
0
      vty_out(vty, "\n");
5464
0
  }
5465
5466
0
  if (uj)
5467
0
    vty_json(vty, json);
5468
0
}
5469
5470
int pim_show_group_rp_mappings_info_helper(const char *vrf, struct vty *vty,
5471
             bool uj)
5472
0
{
5473
0
  struct pim_instance *pim;
5474
0
  struct vrf *v;
5475
5476
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5477
5478
0
  if (!v)
5479
0
    return CMD_WARNING;
5480
5481
0
  pim = v->info;
5482
5483
0
  if (!pim) {
5484
0
    vty_out(vty, "%% Unable to find pim instance\n");
5485
0
    return CMD_WARNING;
5486
0
  }
5487
5488
0
  pim_show_group_rp_mappings_info(v->info, vty, uj);
5489
5490
0
  return CMD_SUCCESS;
5491
0
}
5492
5493
/* Display the bsm database details */
5494
static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
5495
0
{
5496
0
  int count = 0;
5497
0
  int fragment = 1;
5498
0
  struct bsm_frag *bsfrag;
5499
0
  json_object *json = NULL;
5500
0
  json_object *json_group = NULL;
5501
0
  json_object *json_row = NULL;
5502
5503
0
  count = bsm_frags_count(pim->global_scope.bsm_frags);
5504
5505
0
  if (uj) {
5506
0
    json = json_object_new_object();
5507
0
    json_object_int_add(json, "Number of the fragments", count);
5508
0
  } else {
5509
0
    vty_out(vty, "Scope Zone: Global\n");
5510
0
    vty_out(vty, "Number of the fragments: %d\n", count);
5511
0
    vty_out(vty, "\n");
5512
0
  }
5513
5514
0
  frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) {
5515
0
    char grp_str[PREFIX_STRLEN];
5516
0
    struct bsmmsg_grpinfo *group;
5517
0
    struct bsmmsg_rpinfo *bsm_rpinfo;
5518
0
    struct prefix grp;
5519
0
    struct bsm_hdr *hdr;
5520
0
    pim_addr bsr_addr;
5521
0
    uint32_t offset = 0;
5522
0
    uint8_t *buf;
5523
0
    uint32_t len = 0;
5524
0
    uint32_t frag_rp_cnt = 0;
5525
5526
0
    buf = bsfrag->data;
5527
0
    len = bsfrag->size;
5528
5529
    /* skip pim header */
5530
0
    buf += PIM_MSG_HEADER_LEN;
5531
0
    len -= PIM_MSG_HEADER_LEN;
5532
5533
0
    hdr = (struct bsm_hdr *)buf;
5534
    /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
5535
0
    memcpy(&bsr_addr, &hdr->bsr_addr.addr, sizeof(bsr_addr));
5536
5537
    /* BSM starts with bsr header */
5538
0
    buf += sizeof(struct bsm_hdr);
5539
0
    len -= sizeof(struct bsm_hdr);
5540
5541
0
    if (uj) {
5542
0
      json_object_string_addf(json, "BSR address", "%pPA",
5543
0
            &bsr_addr);
5544
0
      json_object_int_add(json, "BSR priority",
5545
0
              hdr->bsr_prio);
5546
0
      json_object_int_add(json, "Hashmask Length",
5547
0
              hdr->hm_len);
5548
0
      json_object_int_add(json, "Fragment Tag",
5549
0
              ntohs(hdr->frag_tag));
5550
0
    } else {
5551
0
      vty_out(vty, "BSM Fragment : %d\n", fragment);
5552
0
      vty_out(vty, "------------------\n");
5553
0
      vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
5554
0
        "BSR-Priority", "Hashmask-len", "Fragment-Tag");
5555
0
      vty_out(vty, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr,
5556
0
        hdr->bsr_prio, hdr->hm_len,
5557
0
        ntohs(hdr->frag_tag));
5558
0
    }
5559
5560
0
    vty_out(vty, "\n");
5561
5562
0
    while (offset < len) {
5563
0
      group = (struct bsmmsg_grpinfo *)buf;
5564
5565
0
      if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4)
5566
0
        grp.family = AF_INET;
5567
0
      else if (group->group.family ==
5568
0
         PIM_MSG_ADDRESS_FAMILY_IPV6)
5569
0
        grp.family = AF_INET6;
5570
5571
0
      grp.prefixlen = group->group.mask;
5572
0
#if PIM_IPV == 4
5573
0
      grp.u.prefix4 = group->group.addr;
5574
#else
5575
      grp.u.prefix6 = group->group.addr;
5576
#endif
5577
5578
0
      prefix2str(&grp, grp_str, sizeof(grp_str));
5579
5580
0
      buf += sizeof(struct bsmmsg_grpinfo);
5581
0
      offset += sizeof(struct bsmmsg_grpinfo);
5582
5583
0
      if (uj) {
5584
0
        json_object_object_get_ex(json, grp_str,
5585
0
                &json_group);
5586
0
        if (!json_group) {
5587
0
          json_group = json_object_new_object();
5588
0
          json_object_int_add(json_group,
5589
0
                  "Rp Count",
5590
0
                  group->rp_count);
5591
0
          json_object_int_add(
5592
0
            json_group, "Fragment Rp count",
5593
0
            group->frag_rp_count);
5594
0
          json_object_object_add(json, grp_str,
5595
0
                     json_group);
5596
0
        }
5597
0
      } else {
5598
0
        vty_out(vty, "Group : %s\n", grp_str);
5599
0
        vty_out(vty, "-------------------\n");
5600
0
        vty_out(vty, "Rp Count:%d\n", group->rp_count);
5601
0
        vty_out(vty, "Fragment Rp Count : %d\n",
5602
0
          group->frag_rp_count);
5603
0
      }
5604
5605
0
      frag_rp_cnt = group->frag_rp_count;
5606
5607
0
      if (!frag_rp_cnt)
5608
0
        continue;
5609
5610
0
      if (!uj)
5611
0
        vty_out(vty,
5612
0
          "RpAddress     HoldTime     Priority\n");
5613
5614
0
      while (frag_rp_cnt--) {
5615
0
        pim_addr rp_addr;
5616
5617
0
        bsm_rpinfo = (struct bsmmsg_rpinfo *)buf;
5618
        /* unaligned, again */
5619
0
        memcpy(&rp_addr, &bsm_rpinfo->rpaddr.addr,
5620
0
               sizeof(rp_addr));
5621
5622
0
        buf += sizeof(struct bsmmsg_rpinfo);
5623
0
        offset += sizeof(struct bsmmsg_rpinfo);
5624
5625
0
        if (uj) {
5626
0
          json_row = json_object_new_object();
5627
0
          json_object_string_addf(
5628
0
            json_row, "Rp Address", "%pPA",
5629
0
            &rp_addr);
5630
0
          json_object_int_add(
5631
0
            json_row, "Rp HoldTime",
5632
0
            ntohs(bsm_rpinfo->rp_holdtime));
5633
0
          json_object_int_add(json_row,
5634
0
                  "Rp Priority",
5635
0
                  bsm_rpinfo->rp_pri);
5636
0
          json_object_object_addf(
5637
0
            json_group, json_row, "%pPA",
5638
0
            &rp_addr);
5639
0
        } else {
5640
0
          vty_out(vty, "%-15pPA %-12d %d\n",
5641
0
            &rp_addr,
5642
0
            ntohs(bsm_rpinfo->rp_holdtime),
5643
0
            bsm_rpinfo->rp_pri);
5644
0
        }
5645
0
      }
5646
0
      vty_out(vty, "\n");
5647
0
    }
5648
5649
0
    fragment++;
5650
0
  }
5651
5652
0
  if (uj)
5653
0
    vty_json(vty, json);
5654
0
}
5655
5656
int pim_show_bsm_db_helper(const char *vrf, struct vty *vty, bool uj)
5657
0
{
5658
0
  struct pim_instance *pim;
5659
0
  struct vrf *v;
5660
5661
0
  v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5662
5663
0
  if (!v)
5664
0
    return CMD_WARNING;
5665
5666
0
  pim = v->info;
5667
5668
0
  if (!pim) {
5669
0
    vty_out(vty, "%% Unable to find pim instance\n");
5670
0
    return CMD_WARNING;
5671
0
  }
5672
5673
0
  pim_show_bsm_db(v->info, vty, uj);
5674
5675
0
  return CMD_SUCCESS;
5676
0
}