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