]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_cmd_common.c
pim6d: Moving reusable code to common api for "show ip/ipv6 mroute count" command
[mirror_frr.git] / pimd / pim_cmd_common.c
CommitLineData
26cd3d66
MR
1/*
2 * PIM for IPv6 FRR
3 * Copyright (C) 2022 Vmware, Inc.
4 * Mobashshera Rasool <mrasool@vmware.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <zebra.h>
22
23#include "lib/json.h"
24#include "command.h"
25#include "if.h"
26#include "prefix.h"
27#include "zclient.h"
28#include "plist.h"
29#include "hash.h"
30#include "nexthop.h"
31#include "vrf.h"
32#include "ferr.h"
63ee25c0 33#include "lib/srcdest_table.h"
e2b601e8 34#include "lib/linklist.h"
26cd3d66
MR
35
36#include "pimd.h"
993e3d8e 37#include "pim_instance.h"
26cd3d66
MR
38#include "pim_vty.h"
39#include "lib/northbound_cli.h"
40#include "pim_errors.h"
41#include "pim_nb.h"
45e26aa0
A
42#include "pim_mroute.h"
43#include "pim_cmd.h"
44#include "pim6_cmd.h"
45#include "pim_cmd_common.h"
46#include "pim_time.h"
47#include "pim_zebra.h"
48#include "pim_zlookup.h"
49#include "pim_iface.h"
e2b601e8 50#include "pim_macro.h"
45e26aa0 51#include "pim_neighbor.h"
e2b601e8
SG
52#include "pim_nht.h"
53#include "pim_sock.h"
54#include "pim_ssm.h"
4e65109c 55#include "pim_static.h"
24de75a2 56#include "pim_addr.h"
3b767e4b 57#include "pim_static.h"
26cd3d66 58
2328b7ef
MR
59/**
60 * Get current node VRF name.
61 *
62 * NOTE:
63 * In case of failure it will print error message to user.
64 *
65 * \returns name or NULL if failed to get VRF.
66 */
67const char *pim_cli_get_vrf_name(struct vty *vty)
68{
69 const struct lyd_node *vrf_node;
70
71 /* Not inside any VRF context. */
72 if (vty->xpath_index == 0)
73 return VRF_DEFAULT_NAME;
74
75 vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
76 if (vrf_node == NULL) {
77 vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
78 return NULL;
79 }
80
81 return yang_dnode_get_string(vrf_node, "./name");
82}
26cd3d66 83
c73113ea
MR
84int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
85{
86 char xpath[XPATH_MAXLEN];
87
88 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
89 FRR_PIM_AF_XPATH_VAL);
90 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
91
92 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
93
94 return nb_cli_apply_changes(vty, NULL);
95}
96
97int pim_process_no_join_prune_cmd(struct vty *vty)
98{
99 char xpath[XPATH_MAXLEN];
100
101 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
102 FRR_PIM_AF_XPATH_VAL);
103 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
104
105 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
106
107 return nb_cli_apply_changes(vty, NULL);
108}
fb991ce9
MR
109
110int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
111{
112 const char *vrfname;
113 char spt_plist_xpath[XPATH_MAXLEN];
114 char spt_action_xpath[XPATH_MAXLEN];
115
116 vrfname = pim_cli_get_vrf_name(vty);
117 if (vrfname == NULL)
118 return CMD_WARNING_CONFIG_FAILED;
119
120 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
121 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
122 FRR_PIM_AF_XPATH_VAL);
123 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
124 sizeof(spt_plist_xpath));
125
126 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
127 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
128 FRR_PIM_AF_XPATH_VAL);
129 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
130 sizeof(spt_action_xpath));
131
132 if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
133 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
134 NULL);
135 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
136 "PIM_SPT_INFINITY");
137
138 return nb_cli_apply_changes(vty, NULL);
139}
140
141int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
142 const char *plist)
143{
144 const char *vrfname;
145 char spt_plist_xpath[XPATH_MAXLEN];
146 char spt_action_xpath[XPATH_MAXLEN];
147
148 vrfname = pim_cli_get_vrf_name(vty);
149 if (vrfname == NULL)
150 return CMD_WARNING_CONFIG_FAILED;
151
152 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
153 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
154 FRR_PIM_AF_XPATH_VAL);
155 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
156 sizeof(spt_plist_xpath));
157
158 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
159 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
160 FRR_PIM_AF_XPATH_VAL);
161 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
162 sizeof(spt_action_xpath));
163
164 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
165 "PIM_SPT_INFINITY");
166 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
167 plist);
168
169 return nb_cli_apply_changes(vty, NULL);
170}
171
172int pim_process_no_spt_switchover_cmd(struct vty *vty)
173{
174 const char *vrfname;
175 char spt_plist_xpath[XPATH_MAXLEN];
176 char spt_action_xpath[XPATH_MAXLEN];
177
178 vrfname = pim_cli_get_vrf_name(vty);
179 if (vrfname == NULL)
180 return CMD_WARNING_CONFIG_FAILED;
181
182 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
183 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
184 FRR_PIM_AF_XPATH_VAL);
185 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
186 sizeof(spt_plist_xpath));
187
188 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
189 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
190 FRR_PIM_AF_XPATH_VAL);
191 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
192 sizeof(spt_action_xpath));
193
194 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
195 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
196 "PIM_SPT_IMMEDIATE");
197
198 return nb_cli_apply_changes(vty, NULL);
199}
0da72f1f
MR
200
201int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
202{
203 char xpath[XPATH_MAXLEN];
204
205 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
206 FRR_PIM_AF_XPATH_VAL);
207 strlcat(xpath, "/packets", sizeof(xpath));
208
209 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
210
211 return nb_cli_apply_changes(vty, NULL);
212}
213
214int pim_process_no_pim_packet_cmd(struct vty *vty)
215{
216 char xpath[XPATH_MAXLEN];
217
218 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
219 FRR_PIM_AF_XPATH_VAL);
220 strlcat(xpath, "/packets", sizeof(xpath));
221
222 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
223
224 return nb_cli_apply_changes(vty, NULL);
225}
28e32366
MR
226
227int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
228{
229 const char *vrfname;
230 char ka_timer_xpath[XPATH_MAXLEN];
231
232 vrfname = pim_cli_get_vrf_name(vty);
233 if (vrfname == NULL)
234 return CMD_WARNING_CONFIG_FAILED;
235
236 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
237 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
238 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
239
240 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
241 kat);
242
243 return nb_cli_apply_changes(vty, NULL);
244}
245
246int pim_process_no_keepalivetimer_cmd(struct vty *vty)
247{
248 const char *vrfname;
249 char ka_timer_xpath[XPATH_MAXLEN];
250
251 vrfname = pim_cli_get_vrf_name(vty);
252 if (vrfname == NULL)
253 return CMD_WARNING_CONFIG_FAILED;
254
255 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
256 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
257 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
258
259 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
260
261 return nb_cli_apply_changes(vty, NULL);
262}
2322b991
MR
263
264int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
265{
266 const char *vrfname;
267 char rp_ka_timer_xpath[XPATH_MAXLEN];
268
269 vrfname = pim_cli_get_vrf_name(vty);
270 if (vrfname == NULL)
271 return CMD_WARNING_CONFIG_FAILED;
272
273 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
274 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
275 FRR_PIM_AF_XPATH_VAL);
276 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
277 sizeof(rp_ka_timer_xpath));
278
279 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
280 rpkat);
281
282 return nb_cli_apply_changes(vty, NULL);
283}
284
285int pim_process_no_rp_kat_cmd(struct vty *vty)
286{
287 const char *vrfname;
288 char rp_ka_timer[6];
289 char rp_ka_timer_xpath[XPATH_MAXLEN];
290 uint v;
291 char rs_timer_xpath[XPATH_MAXLEN];
292
293 snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
294 FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
295 strlcat(rs_timer_xpath, "/register-suppress-time",
296 sizeof(rs_timer_xpath));
297
298 /* RFC4601 */
299 v = yang_dnode_get_uint16(vty->candidate_config->dnode,
300 rs_timer_xpath);
301 v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
302 if (v > UINT16_MAX)
303 v = UINT16_MAX;
304 snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
305
306 vrfname = pim_cli_get_vrf_name(vty);
307 if (vrfname == NULL)
308 return CMD_WARNING_CONFIG_FAILED;
309
310 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
311 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
312 FRR_PIM_AF_XPATH_VAL);
313 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
314 sizeof(rp_ka_timer_xpath));
315
316 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
317 rp_ka_timer);
318
319 return nb_cli_apply_changes(vty, NULL);
320}
18ca7de5
MR
321
322int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
323{
324 char xpath[XPATH_MAXLEN];
325
326 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
327 FRR_PIM_AF_XPATH_VAL);
328 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
329
330 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
331
332 return nb_cli_apply_changes(vty, NULL);
333}
334
335int pim_process_no_register_suppress_cmd(struct vty *vty)
336{
337 char xpath[XPATH_MAXLEN];
338
339 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
340 FRR_PIM_AF_XPATH_VAL);
341 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
342
343 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
344
345 return nb_cli_apply_changes(vty, NULL);
346}
a1caf7a8 347
348int pim_process_ip_pim_cmd(struct vty *vty)
349{
350 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
351
352 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
353 FRR_PIM_AF_XPATH_VAL);
354}
355
9726536d 356int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable)
357{
358 if (enable)
359 nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
360 "true");
361 else
362 nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
363 "false");
364
365 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
366 FRR_PIM_AF_XPATH_VAL);
367}
368
a1caf7a8 369int pim_process_no_ip_pim_cmd(struct vty *vty)
370{
371 const struct lyd_node *mld_enable_dnode;
372 char mld_if_xpath[XPATH_MAXLEN];
373
374 int printed =
375 snprintf(mld_if_xpath, sizeof(mld_if_xpath),
376 "%s/frr-gmp:gmp/address-family[address-family='%s']",
377 VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
378
379 if (printed >= (int)(sizeof(mld_if_xpath))) {
380 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
381 XPATH_MAXLEN);
382 return CMD_WARNING_CONFIG_FAILED;
383 }
384
385 mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
386 FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
387 FRR_PIM_AF_XPATH_VAL);
388
389 if (!mld_enable_dnode) {
390 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
391 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
392 } else {
393 if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
394 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
395 NULL);
396 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
397 } else
398 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
399 "false");
400 }
401
402 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
403 FRR_PIM_AF_XPATH_VAL);
404}
bb387611 405
406int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
407{
408 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
409 drpriority_str);
410
411 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
412 FRR_PIM_AF_XPATH_VAL);
413}
414
415int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
416{
417 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
418
419 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
420 FRR_PIM_AF_XPATH_VAL);
421}
e6aab613 422
423int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
424 const char *hold_str)
425{
426 const struct lyd_node *mld_enable_dnode;
427
428 mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
429 FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
430 FRR_PIM_AF_XPATH_VAL);
431
432 if (!mld_enable_dnode) {
433 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
434 "true");
435 } else {
436 if (!yang_dnode_get_bool(mld_enable_dnode, "."))
437 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
438 "true");
439 }
440
441 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
442
443 if (hold_str)
444 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
445 hold_str);
446
447 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
448 FRR_PIM_AF_XPATH_VAL);
449}
450
451int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
452{
453 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
454 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
455
456 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
457 FRR_PIM_AF_XPATH_VAL);
458}
7e01b641 459
460int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
461{
462 if (no)
463 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
464 "false");
465 else {
466 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
467 "true");
468
469 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
470 "true");
471 }
472
473 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
474 FRR_PIM_AF_XPATH_VAL);
475}
52c52d78 476
477int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
478{
479 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
480 oil);
481
482 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
483 FRR_PIM_AF_XPATH_VAL);
484}
485
486int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
487{
488 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
489 NULL);
490
491 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
492 FRR_PIM_AF_XPATH_VAL);
493}
63ee25c0 494
495int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
496 const char *group_str, const char *source_str)
497{
498 nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
499
500 if (!source_str) {
501 char buf[SRCDEST2STR_BUFFER];
502
503 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
504 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
505 FRR_PIM_AF_XPATH_VAL, buf,
506 group_str);
507 }
508
509 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
510 FRR_PIM_AF_XPATH_VAL, source_str,
511 group_str);
512}
513
514int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
515 const char *group_str, const char *source_str)
516{
517 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
518
519 if (!source_str) {
520 char buf[SRCDEST2STR_BUFFER];
521
522 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
523 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
524 FRR_PIM_AF_XPATH_VAL, buf,
525 group_str);
526 }
527
528 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
529 FRR_PIM_AF_XPATH_VAL, source_str,
530 group_str);
531}
13ddf7cf
MR
532
533int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
534 const char *group_str)
535{
536 const char *vrfname;
537 char rp_group_xpath[XPATH_MAXLEN];
538 int result = 0;
539 struct prefix group;
a96942ca 540 pim_addr rp_addr;
13ddf7cf
MR
541
542 result = str2prefix(group_str, &group);
543 if (result) {
544 struct prefix temp;
545
546 prefix_copy(&temp, &group);
547 apply_mask(&temp);
548 if (!prefix_same(&group, &temp)) {
549 vty_out(vty, "%% Inconsistent address and mask: %s\n",
550 group_str);
551 return CMD_WARNING_CONFIG_FAILED;
552 }
553 }
554
555 if (!result) {
556 vty_out(vty, "%% Bad group address specified: %s\n", group_str);
557 return CMD_WARNING_CONFIG_FAILED;
558 }
559
a96942ca 560 result = inet_pton(PIM_AF, rp_str, &rp_addr);
13ddf7cf
MR
561 if (result <= 0) {
562 vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
563 return CMD_WARNING_CONFIG_FAILED;
564 }
565
566 vrfname = pim_cli_get_vrf_name(vty);
567 if (vrfname == NULL)
568 return CMD_WARNING_CONFIG_FAILED;
569
570 snprintf(rp_group_xpath, sizeof(rp_group_xpath),
a96942ca
MR
571 FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
572 FRR_PIM_AF_XPATH_VAL, rp_str);
13ddf7cf
MR
573 strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
574
575 nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
576
577 return nb_cli_apply_changes(vty, NULL);
578}
579
580int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
581 const char *group_str)
582{
583 char group_list_xpath[XPATH_MAXLEN];
584 char group_xpath[XPATH_MAXLEN];
585 char rp_xpath[XPATH_MAXLEN];
586 int printed;
587 const char *vrfname;
588 const struct lyd_node *group_dnode;
589
590 vrfname = pim_cli_get_vrf_name(vty);
591 if (vrfname == NULL)
592 return CMD_WARNING_CONFIG_FAILED;
593
594 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
a96942ca 595 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
13ddf7cf
MR
596
597 printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
598 "%s/group-list", rp_xpath);
599
600 if (printed >= (int)(sizeof(group_list_xpath))) {
601 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
602 XPATH_MAXLEN);
603 return CMD_WARNING_CONFIG_FAILED;
604 }
605
606 printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
607 group_list_xpath, group_str);
608
609 if (printed >= (int)(sizeof(group_xpath))) {
610 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
611 XPATH_MAXLEN);
612 return CMD_WARNING_CONFIG_FAILED;
613 }
614
ea5f4c4c
MR
615 group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
616 if (!group_dnode) {
13ddf7cf
MR
617 vty_out(vty, "%% Unable to find specified RP\n");
618 return NB_OK;
619 }
620
13ddf7cf
MR
621 if (yang_is_last_list_dnode(group_dnode))
622 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
623 else
624 nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
625 group_str);
626
627 return nb_cli_apply_changes(vty, NULL);
628}
f39f3497
MR
629
630int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
631 const char *prefix_list)
632{
633 const char *vrfname;
634 char rp_plist_xpath[XPATH_MAXLEN];
635
636 vrfname = pim_cli_get_vrf_name(vty);
637 if (vrfname == NULL)
638 return CMD_WARNING_CONFIG_FAILED;
639
640 snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
641 FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
642 FRR_PIM_AF_XPATH_VAL, rp_str);
643 strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
644
645 nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
646
647 return nb_cli_apply_changes(vty, NULL);
648}
649
650int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
651 const char *prefix_list)
652{
653 char rp_xpath[XPATH_MAXLEN];
654 char plist_xpath[XPATH_MAXLEN];
655 const char *vrfname;
656 const struct lyd_node *plist_dnode;
657 const char *plist;
658
659 vrfname = pim_cli_get_vrf_name(vty);
660 if (vrfname == NULL)
661 return CMD_WARNING_CONFIG_FAILED;
662
663 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
664 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
665
666 snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
667 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
668 strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
669
670 plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
671 if (!plist_dnode) {
672 vty_out(vty, "%% Unable to find specified RP\n");
673 return NB_OK;
674 }
675
676 plist = yang_dnode_get_string(plist_dnode, plist_xpath);
677 if (strcmp(prefix_list, plist)) {
678 vty_out(vty, "%% Unable to find specified RP\n");
679 return NB_OK;
680 }
681
682 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
683
684 return nb_cli_apply_changes(vty, NULL);
685}
45e26aa0 686
95023bd7
A
687bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
688{
689 return (pim_addr_is_any(match.grp) ||
690 !pim_addr_cmp(match.grp, item.grp)) &&
691 (pim_addr_is_any(match.src) ||
692 !pim_addr_cmp(match.src, item.src));
693}
694
e2b601e8
SG
695void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
696{
697 struct pim_interface *pim_ifp;
698
699 pim_ifp = ifp->info;
700 json_object_string_add(json, "name", ifp->name);
701 json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
702 json_object_string_addf(json, "address", "%pPA",
703 &pim_ifp->primary_address);
704 json_object_int_add(json, "index", ifp->ifindex);
705
706 if (if_is_multicast(ifp))
707 json_object_boolean_true_add(json, "flagMulticast");
708
709 if (if_is_broadcast(ifp))
710 json_object_boolean_true_add(json, "flagBroadcast");
711
712 if (ifp->flags & IFF_ALLMULTI)
713 json_object_boolean_true_add(json, "flagAllMulticast");
714
715 if (ifp->flags & IFF_PROMISC)
716 json_object_boolean_true_add(json, "flagPromiscuous");
717
718 if (PIM_IF_IS_DELETED(ifp))
719 json_object_boolean_true_add(json, "flagDeleted");
720
721 if (pim_if_lan_delay_enabled(ifp))
722 json_object_boolean_true_add(json, "lanDelayEnabled");
723}
724
725void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
726{
727 vty_out(vty, "Flags\n");
728 vty_out(vty, "-----\n");
729 vty_out(vty, "All Multicast : %s\n",
730 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
731 vty_out(vty, "Broadcast : %s\n",
732 if_is_broadcast(ifp) ? "yes" : "no");
733 vty_out(vty, "Deleted : %s\n",
734 PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
735 vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
736 vty_out(vty, "Multicast : %s\n",
737 if_is_multicast(ifp) ? "yes" : "no");
738 vty_out(vty, "Promiscuous : %s\n",
739 (ifp->flags & IFF_PROMISC) ? "yes" : "no");
740 vty_out(vty, "\n");
741 vty_out(vty, "\n");
742}
743
45e26aa0
A
744void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
745{
b1a419ba
A
746 json_object_boolean_add(
747 json, "drJoinDesired",
748 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED));
749 json_object_boolean_add(
750 json, "drJoinDesiredUpdated",
751 CHECK_FLAG(up->flags,
752 PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED));
753 json_object_boolean_add(
754 json, "firstHopRouter",
755 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR));
756 json_object_boolean_add(
757 json, "sourceIgmp",
758 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP));
759 json_object_boolean_add(
760 json, "sourcePim",
761 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM));
762 json_object_boolean_add(
763 json, "sourceStream",
764 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM));
45e26aa0 765 /* XXX: need to print ths flag in the plain text display as well */
b1a419ba
A
766 json_object_boolean_add(
767 json, "sourceMsdp",
768 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP));
769 json_object_boolean_add(
770 json, "sendSGRptPrune",
771 CHECK_FLAG(up->flags,
772 PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE));
773 json_object_boolean_add(
774 json, "lastHopRouter",
775 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR));
776 json_object_boolean_add(
777 json, "disableKATExpiry",
778 CHECK_FLAG(up->flags,
779 PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY));
780 json_object_boolean_add(
781 json, "staticIncomingInterface",
782 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF));
783 json_object_boolean_add(
784 json, "allowIncomingInterfaceinOil",
785 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL));
786 json_object_boolean_add(
787 json, "noPimRegistrationData",
788 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA));
789 json_object_boolean_add(
790 json, "forcePimRegistration",
791 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG));
792 json_object_boolean_add(
793 json, "sourceVxlanOrigination",
794 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG));
795 json_object_boolean_add(
796 json, "sourceVxlanTermination",
797 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM));
798 json_object_boolean_add(
799 json, "mlagVxlan",
800 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN));
801 json_object_boolean_add(
802 json, "mlagNonDesignatedForwarder",
803 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF));
45e26aa0
A
804}
805
806static const char *
807pim_upstream_state2brief_str(enum pim_upstream_state join_state,
808 char *state_str, size_t state_str_len)
809{
810 switch (join_state) {
811 case PIM_UPSTREAM_NOTJOINED:
812 strlcpy(state_str, "NotJ", state_str_len);
813 break;
814 case PIM_UPSTREAM_JOINED:
815 strlcpy(state_str, "J", state_str_len);
816 break;
817 default:
818 strlcpy(state_str, "Unk", state_str_len);
819 }
820 return state_str;
821}
822
823static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
824 char *state_str,
825 size_t state_str_len)
826{
827 switch (reg_state) {
828 case PIM_REG_NOINFO:
829 strlcpy(state_str, "RegNI", state_str_len);
830 break;
831 case PIM_REG_JOIN:
832 strlcpy(state_str, "RegJ", state_str_len);
833 break;
834 case PIM_REG_JOIN_PENDING:
835 case PIM_REG_PRUNE:
836 strlcpy(state_str, "RegP", state_str_len);
837 break;
838 }
839 return state_str;
840}
841
1aa8de46
A
842void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
843 time_t now, json_object *json)
45e26aa0
A
844{
845 char refresh_uptime[10];
846
847 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
848 pim->rpf_cache_refresh_last);
849
850 if (json) {
851 json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
852 router->rpf_cache_refresh_delay_msec);
853 json_object_int_add(
854 json, "rpfCacheRefreshTimer",
855 pim_time_timer_remain_msec(pim->rpf_cache_refresher));
856 json_object_int_add(json, "rpfCacheRefreshRequests",
857 pim->rpf_cache_refresh_requests);
858 json_object_int_add(json, "rpfCacheRefreshEvents",
859 pim->rpf_cache_refresh_events);
860 json_object_string_add(json, "rpfCacheRefreshLast",
861 refresh_uptime);
862 json_object_int_add(json, "nexthopLookups",
863 pim->nexthop_lookups);
864 json_object_int_add(json, "nexthopLookupsAvoided",
865 pim->nexthop_lookups_avoided);
866 } else {
867 vty_out(vty,
868 "RPF Cache Refresh Delay: %ld msecs\n"
869 "RPF Cache Refresh Timer: %ld msecs\n"
870 "RPF Cache Refresh Requests: %lld\n"
871 "RPF Cache Refresh Events: %lld\n"
872 "RPF Cache Refresh Last: %s\n"
873 "Nexthop Lookups: %lld\n"
874 "Nexthop Lookups Avoided: %lld\n",
875 router->rpf_cache_refresh_delay_msec,
876 pim_time_timer_remain_msec(pim->rpf_cache_refresher),
877 (long long)pim->rpf_cache_refresh_requests,
878 (long long)pim->rpf_cache_refresh_events,
879 refresh_uptime, (long long)pim->nexthop_lookups,
880 (long long)pim->nexthop_lookups_avoided);
881 }
882}
883
1aa8de46 884void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
45e26aa0
A
885{
886 struct pim_upstream *up;
887 time_t now = pim_time_monotonic_sec();
45e26aa0
A
888 json_object *json_group = NULL;
889 json_object *json_row = NULL;
890
1aa8de46
A
891 pim_show_rpf_refresh_stats(vty, pim, now, json);
892
893 if (!json) {
45e26aa0
A
894 vty_out(vty, "\n");
895 vty_out(vty,
896 "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
897 }
898
899 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
900 char rpf_addr_str[PREFIX_STRLEN];
45e26aa0
A
901 const char *rpf_ifname;
902 struct pim_rpf *rpf = &up->rpf;
903
904 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
905 sizeof(rpf_addr_str));
45e26aa0 906
1aa8de46
A
907 rpf_ifname =
908 rpf->source_nexthop.interface ? rpf->source_nexthop
909 .interface->name
910 : "<ifname?>";
45e26aa0 911
1aa8de46 912 if (json) {
45e26aa0
A
913 char grp_str[PIM_ADDRSTRLEN];
914 char src_str[PIM_ADDRSTRLEN];
915
916 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
917 &up->sg.grp);
918 snprintfrr(src_str, sizeof(src_str), "%pPAs",
919 &up->sg.src);
920
921 json_object_object_get_ex(json, grp_str, &json_group);
922
923 if (!json_group) {
924 json_group = json_object_new_object();
925 json_object_object_add(json, grp_str,
926 json_group);
927 }
928
929 json_row = json_object_new_object();
930 json_object_string_add(json_row, "source", src_str);
931 json_object_string_add(json_row, "group", grp_str);
932 json_object_string_add(json_row, "rpfInterface",
933 rpf_ifname);
934 json_object_string_add(json_row, "rpfAddress",
935 rpf_addr_str);
641ac7c7 936 json_object_string_addf(
937 json_row, "ribNexthop", "%pPAs",
938 &rpf->source_nexthop.mrib_nexthop_addr);
45e26aa0
A
939 json_object_int_add(
940 json_row, "routeMetric",
941 rpf->source_nexthop.mrib_route_metric);
942 json_object_int_add(
943 json_row, "routePreference",
944 rpf->source_nexthop.mrib_metric_preference);
945 json_object_object_add(json_group, src_str, json_row);
946
947 } else {
1aa8de46 948 vty_out(vty,
641ac7c7 949 "%-15pPAs %-15pPAs %-16s %-15s %-15pPAs %6d %4d\n",
45e26aa0 950 &up->sg.src, &up->sg.grp, rpf_ifname,
641ac7c7 951 rpf_addr_str,
952 &rpf->source_nexthop.mrib_nexthop_addr,
45e26aa0
A
953 rpf->source_nexthop.mrib_route_metric,
954 rpf->source_nexthop.mrib_metric_preference);
955 }
956 }
45e26aa0
A
957}
958
959void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
960{
961 struct interface *ifp;
962
963 vty_out(vty,
964 "Interface Address Neighbor Secondary \n");
965
966 FOR_ALL_INTERFACES (pim->vrf, ifp) {
967 struct pim_interface *pim_ifp;
626dab7f 968 pim_addr ifaddr;
45e26aa0
A
969 struct listnode *neighnode;
970 struct pim_neighbor *neigh;
45e26aa0
A
971
972 pim_ifp = ifp->info;
973
974 if (!pim_ifp)
975 continue;
976
977 if (pim_ifp->pim_sock_fd < 0)
978 continue;
979
980 ifaddr = pim_ifp->primary_address;
981
982 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
983 neigh)) {
45e26aa0
A
984 struct listnode *prefix_node;
985 struct prefix *p;
986
987 if (!neigh->prefix_list)
988 continue;
989
45e26aa0
A
990 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
991 prefix_node, p))
626dab7f
A
992 vty_out(vty,
993 "%-16s %-15pPAs %-15pPAs %-15pFX\n",
994 ifp->name, &ifaddr, &neigh->source_addr,
995 p);
45e26aa0
A
996 }
997 }
998}
999
1000void pim_show_state(struct pim_instance *pim, struct vty *vty,
2d85c671
A
1001 const char *src_or_group, const char *group,
1002 json_object *json)
45e26aa0
A
1003{
1004 struct channel_oil *c_oil;
45e26aa0
A
1005 json_object *json_group = NULL;
1006 json_object *json_ifp_in = NULL;
1007 json_object *json_ifp_out = NULL;
1008 json_object *json_source = NULL;
1009 time_t now;
1010 int first_oif;
1011
1012 now = pim_time_monotonic_sec();
1013
2d85c671 1014 if (!json) {
45e26aa0
A
1015 vty_out(vty,
1016 "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
1017 vty_out(vty,
1018 "\nActive Source Group RPT IIF OIL\n");
1019 }
1020
1021 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
2d85c671
A
1022 char src_str[PIM_ADDRSTRLEN];
1023 char grp_str[PIM_ADDRSTRLEN];
45e26aa0
A
1024 char in_ifname[INTERFACE_NAMSIZ + 1];
1025 char out_ifname[INTERFACE_NAMSIZ + 1];
1026 int oif_vif_index;
1027 struct interface *ifp_in;
1028 bool isRpt;
1029
1030 first_oif = 1;
1031
1032 if ((c_oil->up &&
1033 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
2d85c671 1034 pim_addr_is_any(*oil_origin(c_oil)))
45e26aa0
A
1035 isRpt = true;
1036 else
1037 isRpt = false;
1038
2d85c671
A
1039 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1040 oil_mcastgrp(c_oil));
1041 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1042 oil_origin(c_oil));
1043 ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
45e26aa0
A
1044
1045 if (ifp_in)
1046 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
1047 else
1048 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
1049
1050 if (src_or_group) {
1051 if (strcmp(src_or_group, src_str) &&
1052 strcmp(src_or_group, grp_str))
1053 continue;
1054
1055 if (group && strcmp(group, grp_str))
1056 continue;
1057 }
1058
2d85c671 1059 if (json) {
45e26aa0
A
1060
1061 /* Find the group, create it if it doesn't exist */
1062 json_object_object_get_ex(json, grp_str, &json_group);
1063
1064 if (!json_group) {
1065 json_group = json_object_new_object();
1066 json_object_object_add(json, grp_str,
1067 json_group);
1068 }
1069
1070 /* Find the source nested under the group, create it if
1071 * it doesn't exist
1072 */
1073 json_object_object_get_ex(json_group, src_str,
1074 &json_source);
1075
1076 if (!json_source) {
1077 json_source = json_object_new_object();
1078 json_object_object_add(json_group, src_str,
1079 json_source);
1080 }
1081
1082 /* Find the inbound interface nested under the source,
1083 * create it if it doesn't exist
1084 */
1085 json_object_object_get_ex(json_source, in_ifname,
1086 &json_ifp_in);
1087
1088 if (!json_ifp_in) {
1089 json_ifp_in = json_object_new_object();
1090 json_object_object_add(json_source, in_ifname,
1091 json_ifp_in);
1092 json_object_int_add(json_source, "Installed",
1093 c_oil->installed);
1094 json_object_int_add(json_source, "installed",
1095 c_oil->installed);
2d85c671
A
1096 json_object_boolean_add(json_source, "isRpt",
1097 isRpt);
45e26aa0
A
1098 json_object_int_add(json_source, "RefCount",
1099 c_oil->oil_ref_count);
1100 json_object_int_add(json_source, "refCount",
1101 c_oil->oil_ref_count);
1102 json_object_int_add(json_source, "OilListSize",
1103 c_oil->oil_size);
1104 json_object_int_add(json_source, "oilListSize",
1105 c_oil->oil_size);
1106 json_object_int_add(
1107 json_source, "OilRescan",
1108 c_oil->oil_inherited_rescan);
1109 json_object_int_add(
1110 json_source, "oilRescan",
1111 c_oil->oil_inherited_rescan);
1112 json_object_int_add(json_source, "LastUsed",
1113 c_oil->cc.lastused);
1114 json_object_int_add(json_source, "lastUsed",
1115 c_oil->cc.lastused);
1116 json_object_int_add(json_source, "PacketCount",
1117 c_oil->cc.pktcnt);
1118 json_object_int_add(json_source, "packetCount",
1119 c_oil->cc.pktcnt);
1120 json_object_int_add(json_source, "ByteCount",
1121 c_oil->cc.bytecnt);
1122 json_object_int_add(json_source, "byteCount",
1123 c_oil->cc.bytecnt);
1124 json_object_int_add(json_source,
1125 "WrongInterface",
1126 c_oil->cc.wrong_if);
1127 json_object_int_add(json_source,
1128 "wrongInterface",
1129 c_oil->cc.wrong_if);
1130 }
2d85c671
A
1131 } else
1132 vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1133 c_oil->installed, oil_origin(c_oil),
1134 oil_mcastgrp(c_oil), isRpt ? "y" : "n",
1135 in_ifname);
45e26aa0
A
1136
1137 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
1138 ++oif_vif_index) {
1139 struct interface *ifp_out;
1140 char oif_uptime[10];
1141 int ttl;
1142
2d85c671 1143 ttl = oil_if_has(c_oil, oif_vif_index);
45e26aa0
A
1144 if (ttl < 1)
1145 continue;
1146
1147 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
1148 pim_time_uptime(
1149 oif_uptime, sizeof(oif_uptime),
1150 now - c_oil->oif_creation[oif_vif_index]);
1151
1152 if (ifp_out)
1153 strlcpy(out_ifname, ifp_out->name,
1154 sizeof(out_ifname));
1155 else
1156 strlcpy(out_ifname, "<oif?>",
1157 sizeof(out_ifname));
1158
2d85c671 1159 if (json) {
45e26aa0
A
1160 json_ifp_out = json_object_new_object();
1161 json_object_string_add(json_ifp_out, "source",
1162 src_str);
1163 json_object_string_add(json_ifp_out, "group",
1164 grp_str);
1165 json_object_string_add(json_ifp_out,
1166 "inboundInterface",
1167 in_ifname);
1168 json_object_string_add(json_ifp_out,
1169 "outboundInterface",
1170 out_ifname);
1171 json_object_int_add(json_ifp_out, "installed",
1172 c_oil->installed);
1173
1174 json_object_object_add(json_ifp_in, out_ifname,
1175 json_ifp_out);
1176 } else {
1177 if (first_oif) {
1178 first_oif = 0;
1179 vty_out(vty, "%s(%c%c%c%c%c)",
1180 out_ifname,
1181 (c_oil->oif_flags
1182 [oif_vif_index] &
80a82b56 1183 PIM_OIF_FLAG_PROTO_GM)
45e26aa0
A
1184 ? 'I'
1185 : ' ',
1186 (c_oil->oif_flags
1187 [oif_vif_index] &
1188 PIM_OIF_FLAG_PROTO_PIM)
1189 ? 'J'
1190 : ' ',
1191 (c_oil->oif_flags
1192 [oif_vif_index] &
1193 PIM_OIF_FLAG_PROTO_VXLAN)
1194 ? 'V'
1195 : ' ',
1196 (c_oil->oif_flags
1197 [oif_vif_index] &
1198 PIM_OIF_FLAG_PROTO_STAR)
1199 ? '*'
1200 : ' ',
1201 (c_oil->oif_flags
1202 [oif_vif_index] &
1203 PIM_OIF_FLAG_MUTE)
1204 ? 'M'
1205 : ' ');
1206 } else
1207 vty_out(vty, ", %s(%c%c%c%c%c)",
1208 out_ifname,
1209 (c_oil->oif_flags
1210 [oif_vif_index] &
80a82b56 1211 PIM_OIF_FLAG_PROTO_GM)
45e26aa0
A
1212 ? 'I'
1213 : ' ',
1214 (c_oil->oif_flags
1215 [oif_vif_index] &
1216 PIM_OIF_FLAG_PROTO_PIM)
1217 ? 'J'
1218 : ' ',
1219 (c_oil->oif_flags
1220 [oif_vif_index] &
1221 PIM_OIF_FLAG_PROTO_VXLAN)
1222 ? 'V'
1223 : ' ',
1224 (c_oil->oif_flags
1225 [oif_vif_index] &
1226 PIM_OIF_FLAG_PROTO_STAR)
1227 ? '*'
1228 : ' ',
1229 (c_oil->oif_flags
1230 [oif_vif_index] &
1231 PIM_OIF_FLAG_MUTE)
1232 ? 'M'
1233 : ' ');
1234 }
1235 }
1236
2d85c671 1237 if (!json)
45e26aa0
A
1238 vty_out(vty, "\n");
1239 }
1240
2d85c671 1241 if (!json)
45e26aa0
A
1242 vty_out(vty, "\n");
1243}
1244
1245/* pim statistics - just adding only bsm related now.
1246 * We can continue to add all pim related stats here.
1247 */
1248void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
1249 const char *ifname, bool uj)
1250{
1251 json_object *json = NULL;
1252 struct interface *ifp;
1253
1254 if (uj) {
1255 json = json_object_new_object();
1256 json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
1257 json_object_int_add(json, "bsmTx", pim->bsm_sent);
1258 json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
1259 } else {
1260 vty_out(vty, "BSM Statistics :\n");
1261 vty_out(vty, "----------------\n");
1262 vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
1263 pim->bsm_rcvd);
1264 vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
1265 pim->bsm_sent);
1266 vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n",
1267 pim->bsm_dropped);
1268 }
1269
1270 vty_out(vty, "\n");
1271
1272 /* scan interfaces */
1273 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1274 struct pim_interface *pim_ifp = ifp->info;
1275
1276 if (ifname && strcmp(ifname, ifp->name))
1277 continue;
1278
1279 if (!pim_ifp)
1280 continue;
1281
1282 if (!uj) {
1283 vty_out(vty, "Interface : %s\n", ifp->name);
1284 vty_out(vty, "-------------------\n");
1285 vty_out(vty,
1286 "Number of BSMs dropped due to config miss : %u\n",
1287 pim_ifp->pim_ifstat_bsm_cfg_miss);
1288 vty_out(vty, "Number of unicast BSMs dropped : %u\n",
1289 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1290 vty_out(vty,
1291 "Number of BSMs dropped due to invalid scope zone : %u\n",
1292 pim_ifp->pim_ifstat_bsm_invalid_sz);
1293 } else {
1294
1295 json_object *json_row = NULL;
1296
1297 json_row = json_object_new_object();
1298
1299 json_object_string_add(json_row, "If Name", ifp->name);
1300 json_object_int_add(json_row, "bsmDroppedConfig",
1301 pim_ifp->pim_ifstat_bsm_cfg_miss);
1302 json_object_int_add(
1303 json_row, "bsmDroppedUnicast",
1304 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1305 json_object_int_add(json_row,
1306 "bsmDroppedInvalidScopeZone",
1307 pim_ifp->pim_ifstat_bsm_invalid_sz);
1308 json_object_object_add(json, ifp->name, json_row);
1309 }
1310 vty_out(vty, "\n");
1311 }
1312
1313 if (uj)
1314 vty_json(vty, json);
1315}
1316
1317void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
95023bd7 1318 pim_sgaddr *sg, json_object *json)
45e26aa0
A
1319{
1320 struct pim_upstream *up;
1321 time_t now;
45e26aa0
A
1322 json_object *json_group = NULL;
1323 json_object *json_row = NULL;
1324
1325 now = pim_time_monotonic_sec();
1326
95023bd7 1327 if (!json)
45e26aa0
A
1328 vty_out(vty,
1329 "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
1330
1331 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
45e26aa0
A
1332 char uptime[10];
1333 char join_timer[10];
1334 char rs_timer[10];
1335 char ka_timer[10];
1336 char msdp_reg_timer[10];
1337 char state_str[PIM_REG_STATE_STR_LEN];
1338
95023bd7 1339 if (!pim_sgaddr_match(up->sg, *sg))
45e26aa0
A
1340 continue;
1341
45e26aa0
A
1342 pim_time_uptime(uptime, sizeof(uptime),
1343 now - up->state_transition);
1344 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
1345 up->t_join_timer);
1346
1347 /*
1348 * If the upstream is not dummy and it has a J/P timer for the
1349 * neighbor display that
1350 */
1351 if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
1352 struct pim_neighbor *nbr;
1353
95023bd7 1354 nbr = pim_neighbor_find_prefix(
45e26aa0 1355 up->rpf.source_nexthop.interface,
95023bd7 1356 &up->rpf.rpf_addr);
45e26aa0
A
1357 if (nbr)
1358 pim_time_timer_to_hhmmss(join_timer,
1359 sizeof(join_timer),
1360 nbr->jp_timer);
1361 }
1362
1363 pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
1364 up->t_rs_timer);
1365 pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
1366 up->t_ka_timer);
1367 pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
1368 up->t_msdp_reg_timer);
1369
1370 pim_upstream_state2brief_str(up->join_state, state_str,
1371 sizeof(state_str));
1372 if (up->reg_state != PIM_REG_NOINFO) {
1373 char tmp_str[PIM_REG_STATE_STR_LEN];
1374 char tmp[sizeof(state_str) + 1];
1375
1376 snprintf(tmp, sizeof(tmp), ",%s",
1377 pim_reg_state2brief_str(up->reg_state, tmp_str,
1378 sizeof(tmp_str)));
1379 strlcat(state_str, tmp, sizeof(state_str));
1380 }
1381
95023bd7
A
1382 if (json) {
1383 char grp_str[PIM_ADDRSTRLEN];
1384 char src_str[PIM_ADDRSTRLEN];
1385
1386 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1387 &up->sg.grp);
1388 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1389 &up->sg.src);
1390
45e26aa0
A
1391 json_object_object_get_ex(json, grp_str, &json_group);
1392
1393 if (!json_group) {
1394 json_group = json_object_new_object();
1395 json_object_object_add(json, grp_str,
1396 json_group);
1397 }
1398
1399 json_row = json_object_new_object();
1400 json_object_pim_upstream_add(json_row, up);
1401 json_object_string_add(
1402 json_row, "inboundInterface",
1403 up->rpf.source_nexthop.interface
1404 ? up->rpf.source_nexthop.interface->name
1405 : "Unknown");
1406
1407 /*
1408 * The RPF address we use is slightly different
1409 * based upon what we are looking up.
1410 * If we have a S, list that unless
1411 * we are the FHR, else we just put
1412 * the RP as the rpfAddress
1413 */
1414 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
95023bd7 1415 pim_addr_is_any(up->sg.src)) {
45e26aa0
A
1416 struct pim_rpf *rpg;
1417
1418 rpg = RP(pim, up->sg.grp);
95023bd7
A
1419 json_object_string_addf(json_row, "rpfAddress",
1420 "%pFX", &rpg->rpf_addr);
45e26aa0
A
1421 } else {
1422 json_object_string_add(json_row, "rpfAddress",
1423 src_str);
1424 }
1425
1426 json_object_string_add(json_row, "source", src_str);
1427 json_object_string_add(json_row, "group", grp_str);
1428 json_object_string_add(json_row, "state", state_str);
1429 json_object_string_add(
1430 json_row, "joinState",
1431 pim_upstream_state2str(up->join_state));
1432 json_object_string_add(
1433 json_row, "regState",
1434 pim_reg_state2str(up->reg_state, state_str,
1435 sizeof(state_str)));
1436 json_object_string_add(json_row, "upTime", uptime);
1437 json_object_string_add(json_row, "joinTimer",
1438 join_timer);
1439 json_object_string_add(json_row, "resetTimer",
1440 rs_timer);
1441 json_object_string_add(json_row, "keepaliveTimer",
1442 ka_timer);
1443 json_object_string_add(json_row, "msdpRegTimer",
1444 msdp_reg_timer);
1445 json_object_int_add(json_row, "refCount",
1446 up->ref_count);
1447 json_object_int_add(json_row, "sptBit", up->sptbit);
1448 json_object_object_add(json_group, src_str, json_row);
1449 } else {
1450 vty_out(vty,
95023bd7 1451 "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n",
45e26aa0
A
1452 up->rpf.source_nexthop.interface
1453 ? up->rpf.source_nexthop.interface->name
1454 : "Unknown",
95023bd7
A
1455 &up->sg.src, &up->sg.grp, state_str, uptime,
1456 join_timer, rs_timer, ka_timer, up->ref_count);
45e26aa0
A
1457 }
1458 }
45e26aa0
A
1459}
1460
1461static void pim_show_join_desired_helper(struct pim_instance *pim,
1462 struct vty *vty,
1463 struct pim_upstream *up,
1464 json_object *json, bool uj)
1465{
1466 json_object *json_group = NULL;
45e26aa0
A
1467 json_object *json_row = NULL;
1468
45e26aa0 1469 if (uj) {
e577f6e7
A
1470 char grp_str[PIM_ADDRSTRLEN];
1471 char src_str[PIM_ADDRSTRLEN];
1472
1473 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
1474 snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
1475
45e26aa0
A
1476 json_object_object_get_ex(json, grp_str, &json_group);
1477
1478 if (!json_group) {
1479 json_group = json_object_new_object();
1480 json_object_object_add(json, grp_str, json_group);
1481 }
1482
1483 json_row = json_object_new_object();
1484 json_object_pim_upstream_add(json_row, up);
1485 json_object_string_add(json_row, "source", src_str);
1486 json_object_string_add(json_row, "group", grp_str);
1487
1488 if (pim_upstream_evaluate_join_desired(pim, up))
1489 json_object_boolean_true_add(json_row,
1490 "evaluateJoinDesired");
1491
1492 json_object_object_add(json_group, src_str, json_row);
1493
1494 } else {
e577f6e7
A
1495 vty_out(vty, "%-15pPAs %-15pPAs %-6s\n", &up->sg.src,
1496 &up->sg.grp,
45e26aa0
A
1497 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
1498 : "no");
1499 }
1500}
1501
1502void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
1503{
1504 struct pim_upstream *up;
1505
1506 json_object *json = NULL;
1507
1508 if (uj)
1509 json = json_object_new_object();
1510 else
1511 vty_out(vty, "Source Group EvalJD\n");
1512
1513 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1514 /* scan all interfaces */
1515 pim_show_join_desired_helper(pim, vty, up, json, uj);
1516 }
1517
1518 if (uj)
1519 vty_json(vty, json);
1520}
1521
1522void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
1523{
1524 struct pim_upstream *up;
1525 json_object *json = NULL;
1526 json_object *json_group = NULL;
1527 json_object *json_row = NULL;
1528
1529 if (uj)
1530 json = json_object_new_object();
1531 else
1532 vty_out(vty,
1533 "Source Group RpfIface RibNextHop RpfAddress \n");
1534
1535 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
45e26aa0
A
1536 char rpf_addr_str[PREFIX_STRLEN];
1537 struct pim_rpf *rpf;
1538 const char *rpf_ifname;
1539
1540 rpf = &up->rpf;
1541
45e26aa0
A
1542 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
1543 sizeof(rpf_addr_str));
1544
1545 rpf_ifname =
1546 rpf->source_nexthop.interface ? rpf->source_nexthop
1547 .interface->name
1548 : "<ifname?>";
1549
1550 if (uj) {
b1a419ba
A
1551 char grp_str[PIM_ADDRSTRLEN];
1552 char src_str[PIM_ADDRSTRLEN];
1553
1554 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1555 &up->sg.grp);
1556 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1557 &up->sg.src);
45e26aa0
A
1558 json_object_object_get_ex(json, grp_str, &json_group);
1559
1560 if (!json_group) {
1561 json_group = json_object_new_object();
1562 json_object_object_add(json, grp_str,
1563 json_group);
1564 }
1565
1566 json_row = json_object_new_object();
1567 json_object_pim_upstream_add(json_row, up);
1568 json_object_string_add(json_row, "source", src_str);
1569 json_object_string_add(json_row, "group", grp_str);
1570 json_object_string_add(json_row, "rpfInterface",
1571 rpf_ifname);
641ac7c7 1572 json_object_string_addf(
1573 json_row, "ribNexthop", "%pPAs",
1574 &rpf->source_nexthop.mrib_nexthop_addr);
45e26aa0
A
1575 json_object_string_add(json_row, "rpfAddress",
1576 rpf_addr_str);
1577 json_object_object_add(json_group, src_str, json_row);
1578 } else {
641ac7c7 1579 vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15pPA %-15s\n",
b1a419ba 1580 &up->sg.src, &up->sg.grp, rpf_ifname,
641ac7c7 1581 &rpf->source_nexthop.mrib_nexthop_addr,
1582 rpf_addr_str);
45e26aa0
A
1583 }
1584 }
1585
1586 if (uj)
1587 vty_json(vty, json);
1588}
e2b601e8
SG
1589
1590static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
1591 struct pim_ifchannel *ch, json_object *json,
24de75a2 1592 time_t now)
e2b601e8
SG
1593{
1594 json_object *json_iface = NULL;
1595 json_object *json_row = NULL;
1596 json_object *json_grp = NULL;
1597 pim_addr ifaddr;
1598 char uptime[10];
1599 char expire[10];
1600 char prune[10];
e2b601e8
SG
1601
1602 ifaddr = pim_ifp->primary_address;
1603
1604 pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1605 pim_time_timer_to_mmss(expire, sizeof(expire),
1606 ch->t_ifjoin_expiry_timer);
1607 pim_time_timer_to_mmss(prune, sizeof(prune),
1608 ch->t_ifjoin_prune_pending_timer);
1609
24de75a2 1610 if (json) {
e2b601e8 1611 char ch_grp_str[PIM_ADDRSTRLEN];
e2b601e8
SG
1612
1613 json_object_object_get_ex(json, ch->interface->name,
1614 &json_iface);
1615
1616 if (!json_iface) {
1617 json_iface = json_object_new_object();
1618 json_object_pim_ifp_add(json_iface, ch->interface);
1619 json_object_object_add(json, ch->interface->name,
1620 json_iface);
1621 }
1622
1623 json_row = json_object_new_object();
24de75a2
SG
1624 json_object_string_addf(json_row, "source", "%pPAs",
1625 &ch->sg.src);
1626 json_object_string_addf(json_row, "group", "%pPAs",
1627 &ch->sg.grp);
e2b601e8
SG
1628 json_object_string_add(json_row, "upTime", uptime);
1629 json_object_string_add(json_row, "expire", expire);
1630 json_object_string_add(json_row, "prune", prune);
1631 json_object_string_add(
1632 json_row, "channelJoinName",
1633 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
1634 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
1635#if CONFDATE > 20230131
1636 CPP_NOTICE(
1637 "Remove JSON object commands with keys starting with capital")
1638#endif
1639 json_object_int_add(json_row, "SGRpt", 1);
1640 json_object_int_add(json_row, "sgRpt", 1);
1641 }
1642 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
1643 json_object_int_add(json_row, "protocolPim", 1);
1644 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
1645 json_object_int_add(json_row, "protocolIgmp", 1);
24de75a2
SG
1646 snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
1647 &ch->sg.grp);
e2b601e8
SG
1648 json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
1649 if (!json_grp) {
1650 json_grp = json_object_new_object();
24de75a2
SG
1651 json_object_object_addf(json_grp, json_row, "%pPAs",
1652 &ch->sg.src);
1653 json_object_object_addf(json_iface, json_grp, "%pPAs",
1654 &ch->sg.grp);
e2b601e8 1655 } else
24de75a2
SG
1656 json_object_object_addf(json_grp, json_row, "%pPAs",
1657 &ch->sg.src);
e2b601e8 1658 } else {
24de75a2
SG
1659 vty_out(vty,
1660 "%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
1661 ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
e2b601e8
SG
1662 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
1663 uptime, expire, prune);
1664 }
1665}
1666
24de75a2
SG
1667void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
1668 json_object *json)
e2b601e8
SG
1669{
1670 struct pim_interface *pim_ifp;
1671 struct pim_ifchannel *ch;
1672 struct interface *ifp;
1673 time_t now;
e2b601e8
SG
1674
1675 now = pim_time_monotonic_sec();
1676
24de75a2 1677 if (!json)
e2b601e8
SG
1678 vty_out(vty,
1679 "Interface Address Source Group State Uptime Expire Prune\n");
1680
1681 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1682 pim_ifp = ifp->info;
1683 if (!pim_ifp)
1684 continue;
1685
1686 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1687 if (!pim_sgaddr_match(ch->sg, *sg))
1688 continue;
24de75a2
SG
1689
1690 pim_show_join_helper(vty, pim_ifp, ch, json, now);
e2b601e8
SG
1691 } /* scan interface channels */
1692 }
e2b601e8
SG
1693}
1694
1695static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp,
1696 struct pim_neighbor *neigh,
1697 struct pim_upstream *up, int is_join)
1698{
be223239
SG
1699 vty_out(vty, "%-16s %-15pPAs %-15pPAs %-15pPAs %5s\n", ifp->name,
1700 &neigh->source_addr, &up->sg.src, &up->sg.grp,
1701 is_join ? "J" : "P");
e2b601e8
SG
1702}
1703
1704void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
1705{
1706 struct interface *ifp;
1707 struct pim_interface *pim_ifp;
1708 struct listnode *n_node;
1709 struct pim_neighbor *neigh;
1710 struct listnode *jag_node;
1711 struct pim_jp_agg_group *jag;
1712 struct listnode *js_node;
1713 struct pim_jp_sources *js;
1714
1715 vty_out(vty,
1716 "Interface RPF Nbr Source Group State\n");
1717
1718 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1719 pim_ifp = ifp->info;
1720 if (!pim_ifp)
1721 continue;
1722
1723 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
1724 neigh)) {
1725 for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
1726 jag_node, jag)) {
1727 for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
1728 js)) {
1729 pim_show_jp_agg_helper(vty, ifp, neigh,
1730 js->up,
1731 js->is_join);
1732 }
1733 }
1734 }
1735 }
1736}
1737
1738static void pim_show_membership_helper(struct vty *vty,
1739 struct pim_interface *pim_ifp,
1740 struct pim_ifchannel *ch,
1741 struct json_object *json)
1742{
e2b601e8
SG
1743 json_object *json_iface = NULL;
1744 json_object *json_row = NULL;
1745
1746 json_object_object_get_ex(json, ch->interface->name, &json_iface);
1747 if (!json_iface) {
1748 json_iface = json_object_new_object();
1749 json_object_pim_ifp_add(json_iface, ch->interface);
1750 json_object_object_add(json, ch->interface->name, json_iface);
1751 }
1752
e2b601e8
SG
1753 json_row = json_object_new_object();
1754 json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
de11054e 1755 json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
e2b601e8
SG
1756 json_object_string_add(json_row, "localMembership",
1757 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
de11054e
SG
1758 ? "NOINFO"
1759 : "INCLUDE");
1760 json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
e2b601e8
SG
1761}
1762
1763void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
1764{
1765 struct pim_interface *pim_ifp;
1766 struct pim_ifchannel *ch;
1767 struct interface *ifp;
1768 enum json_type type;
1769 json_object *json = NULL;
1770 json_object *json_tmp = NULL;
1771
1772 json = json_object_new_object();
1773
1774 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1775 pim_ifp = ifp->info;
1776 if (!pim_ifp)
1777 continue;
1778
1779 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1780 pim_show_membership_helper(vty, pim_ifp, ch, json);
1781 } /* scan interface channels */
1782 }
1783
1784 if (uj) {
de11054e 1785 vty_json(vty, json);
e2b601e8
SG
1786 } else {
1787 vty_out(vty,
1788 "Interface Address Source Group Membership\n");
1789
1790 /*
1791 * Example of the json data we are traversing
1792 *
1793 * {
1794 * "swp3":{
1795 * "name":"swp3",
1796 * "state":"up",
1797 * "address":"10.1.20.1",
1798 * "index":5,
1799 * "flagMulticast":true,
1800 * "flagBroadcast":true,
1801 * "lanDelayEnabled":true,
1802 * "226.10.10.10":{
1803 * "source":"*",
1804 * "group":"226.10.10.10",
1805 * "localMembership":"INCLUDE"
1806 * }
1807 * }
1808 * }
1809 */
1810
1811 /* foreach interface */
1812 json_object_object_foreach(json, key, val)
1813 {
1814
1815 /* Find all of the keys where the val is an object. In
1816 * the example
1817 * above the only one is 226.10.10.10
1818 */
1819 json_object_object_foreach(val, if_field_key,
1820 if_field_val)
1821 {
1822 type = json_object_get_type(if_field_val);
1823
1824 if (type == json_type_object) {
1825 vty_out(vty, "%-16s ", key);
1826
1827 json_object_object_get_ex(
1828 val, "address", &json_tmp);
1829 vty_out(vty, "%-15s ",
1830 json_object_get_string(
1831 json_tmp));
1832
1833 json_object_object_get_ex(if_field_val,
1834 "source",
1835 &json_tmp);
1836 vty_out(vty, "%-15s ",
1837 json_object_get_string(
1838 json_tmp));
1839
1840 /* Group */
1841 vty_out(vty, "%-15s ", if_field_key);
1842
1843 json_object_object_get_ex(
1844 if_field_val, "localMembership",
1845 &json_tmp);
1846 vty_out(vty, "%-10s\n",
1847 json_object_get_string(
1848 json_tmp));
1849 }
1850 }
1851 }
de11054e 1852 json_object_free(json);
e2b601e8 1853 }
e2b601e8
SG
1854}
1855
1856static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
1857 struct pim_interface *pim_ifp,
1858 struct pim_ifchannel *ch, json_object *json,
1859 bool uj)
1860{
1861 struct pim_upstream *up = ch->upstream;
1862 json_object *json_group = NULL;
e2b601e8
SG
1863 json_object *json_row = NULL;
1864
e2b601e8 1865 if (uj) {
bf083b3a
SG
1866 char grp_str[PIM_ADDRSTRLEN];
1867
1868 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
e2b601e8
SG
1869 json_object_object_get_ex(json, grp_str, &json_group);
1870
1871 if (!json_group) {
1872 json_group = json_object_new_object();
1873 json_object_object_add(json, grp_str, json_group);
1874 }
1875
1876 json_row = json_object_new_object();
1877 json_object_pim_upstream_add(json_row, up);
1878 json_object_string_add(json_row, "interface",
1879 ch->interface->name);
bf083b3a
SG
1880 json_object_string_addf(json_row, "source", "%pPAs",
1881 &up->sg.src);
1882 json_object_string_addf(json_row, "group", "%pPAs",
1883 &up->sg.grp);
e2b601e8
SG
1884
1885 if (pim_macro_ch_lost_assert(ch))
1886 json_object_boolean_true_add(json_row, "lostAssert");
1887
1888 if (pim_macro_chisin_joins(ch))
1889 json_object_boolean_true_add(json_row, "joins");
1890
1891 if (pim_macro_chisin_pim_include(ch))
1892 json_object_boolean_true_add(json_row, "pimInclude");
1893
1894 if (pim_upstream_evaluate_join_desired(pim, up))
1895 json_object_boolean_true_add(json_row,
1896 "evaluateJoinDesired");
1897
bf083b3a
SG
1898 json_object_object_addf(json_group, json_row, "%pPAs",
1899 &up->sg.src);
e2b601e8
SG
1900
1901 } else {
bf083b3a
SG
1902 vty_out(vty,
1903 "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n",
1904 ch->interface->name, &up->sg.src, &up->sg.grp,
e2b601e8
SG
1905 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
1906 pim_macro_chisin_joins(ch) ? "yes" : "no",
1907 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
1908 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
1909 ? "yes"
1910 : "no",
1911 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
1912 : "no");
1913 }
1914}
1915
1916void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
1917{
1918 struct pim_interface *pim_ifp;
1919 struct pim_ifchannel *ch;
1920 struct interface *ifp;
1921
1922 json_object *json = NULL;
1923
1924 if (uj)
1925 json = json_object_new_object();
1926 else
1927 vty_out(vty,
1928 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
1929
1930 /* scan per-interface (S,G) state */
1931 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1932 pim_ifp = ifp->info;
1933 if (!pim_ifp)
1934 continue;
1935
1936
1937 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1938 /* scan all interfaces */
1939 pim_show_channel_helper(pim, vty, pim_ifp, ch, json,
1940 uj);
1941 }
1942 }
1943
1944 if (uj)
1945 vty_json(vty, json);
1946}
1947
1948void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
44f99d22 1949 json_object *json)
e2b601e8
SG
1950{
1951 struct interface *ifp;
1952 struct pim_interface *pim_ifp;
1953 struct pim_upstream *up;
1954 int fhr = 0;
1955 int pim_nbrs = 0;
1956 int pim_ifchannels = 0;
44f99d22 1957 bool uj = true;
e2b601e8
SG
1958 json_object *json_row = NULL;
1959 json_object *json_tmp;
1960
44f99d22
SG
1961 if (!json) {
1962 uj = false;
1963 json = json_object_new_object();
1964 }
e2b601e8
SG
1965
1966 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1967 pim_ifp = ifp->info;
1968
1969 if (!pim_ifp)
1970 continue;
1971
1972 if (mlag == true && pim_ifp->activeactive == false)
1973 continue;
1974
1975 pim_nbrs = pim_ifp->pim_neighbor_list->count;
1976 pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
1977 fhr = 0;
1978
1979 frr_each (rb_pim_upstream, &pim->upstream_head, up)
1980 if (ifp == up->rpf.source_nexthop.interface)
1981 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
1982 fhr++;
1983
1984 json_row = json_object_new_object();
1985 json_object_pim_ifp_add(json_row, ifp);
1986 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
1987 json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
1988 json_object_int_add(json_row, "firstHopRouterCount", fhr);
44f99d22
SG
1989 json_object_string_addf(json_row, "pimDesignatedRouter",
1990 "%pPAs", &pim_ifp->pim_dr_addr);
e2b601e8 1991
e0220703
DS
1992 if (!pim_addr_cmp(pim_ifp->pim_dr_addr,
1993 pim_ifp->primary_address))
e2b601e8
SG
1994 json_object_boolean_true_add(
1995 json_row, "pimDesignatedRouterLocal");
1996
1997 json_object_object_add(json, ifp->name, json_row);
1998 }
1999
44f99d22 2000 if (!uj) {
e2b601e8
SG
2001 vty_out(vty,
2002 "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
2003
2004 json_object_object_foreach(json, key, val)
2005 {
2006 vty_out(vty, "%-16s ", key);
2007
2008 json_object_object_get_ex(val, "state", &json_tmp);
2009 vty_out(vty, "%5s ", json_object_get_string(json_tmp));
2010
2011 json_object_object_get_ex(val, "address", &json_tmp);
2012 vty_out(vty, "%15s ",
2013 json_object_get_string(json_tmp));
2014
2015 json_object_object_get_ex(val, "pimNeighbors",
2016 &json_tmp);
2017 vty_out(vty, "%8d ", json_object_get_int(json_tmp));
2018
2019 if (json_object_object_get_ex(
2020 val, "pimDesignatedRouterLocal",
2021 &json_tmp)) {
2022 vty_out(vty, "%15s ", "local");
2023 } else {
2024 json_object_object_get_ex(
2025 val, "pimDesignatedRouter", &json_tmp);
2026 vty_out(vty, "%15s ",
2027 json_object_get_string(json_tmp));
2028 }
2029
2030 json_object_object_get_ex(val, "firstHopRouter",
2031 &json_tmp);
2032 vty_out(vty, "%3d ", json_object_get_int(json_tmp));
2033
2034 json_object_object_get_ex(val, "pimIfChannels",
2035 &json_tmp);
2036 vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
2037 }
2038 }
e2b601e8
SG
2039}
2040
44f99d22
SG
2041void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
2042 const char *ifname, bool mlag,
2043 json_object *json)
e2b601e8
SG
2044{
2045 pim_addr ifaddr;
2046 struct interface *ifp;
2047 struct listnode *neighnode;
2048 struct pim_interface *pim_ifp;
2049 struct pim_neighbor *neigh;
2050 struct pim_upstream *up;
2051 time_t now;
44f99d22 2052 char dr_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2053 char dr_uptime[10];
2054 char expire[10];
44f99d22 2055 char grp_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2056 char hello_period[10];
2057 char hello_timer[10];
44f99d22
SG
2058 char neigh_src_str[PIM_ADDRSTRLEN];
2059 char src_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2060 char stat_uptime[10];
2061 char uptime[10];
2062 int found_ifname = 0;
2063 int print_header;
e2b601e8
SG
2064 json_object *json_row = NULL;
2065 json_object *json_pim_neighbor = NULL;
2066 json_object *json_pim_neighbors = NULL;
2067 json_object *json_group = NULL;
2068 json_object *json_group_source = NULL;
2069 json_object *json_fhr_sources = NULL;
2070 struct pim_secondary_addr *sec_addr;
2071 struct listnode *sec_node;
2072
2073 now = pim_time_monotonic_sec();
2074
e2b601e8
SG
2075 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2076 pim_ifp = ifp->info;
2077
2078 if (!pim_ifp)
2079 continue;
2080
2081 if (mlag == true && pim_ifp->activeactive == false)
2082 continue;
2083
2084 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
2085 continue;
2086
2087 found_ifname = 1;
2088 ifaddr = pim_ifp->primary_address;
44f99d22
SG
2089 snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
2090 &pim_ifp->pim_dr_addr);
e2b601e8
SG
2091 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
2092 pim_ifp->pim_dr_election_last);
2093 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
2094 pim_ifp->t_pim_hello_timer);
2095 pim_time_mmss(hello_period, sizeof(hello_period),
2096 pim_ifp->pim_hello_period);
2097 pim_time_uptime(stat_uptime, sizeof(stat_uptime),
2098 now - pim_ifp->pim_ifstat_start);
2099
44f99d22 2100 if (json) {
e2b601e8
SG
2101 json_row = json_object_new_object();
2102 json_object_pim_ifp_add(json_row, ifp);
2103
44f99d22 2104 if (!pim_addr_is_any(pim_ifp->update_source)) {
e2b601e8 2105 json_object_string_addf(
44f99d22 2106 json_row, "useSource", "%pPAs",
e2b601e8
SG
2107 &pim_ifp->update_source);
2108 }
2109 if (pim_ifp->sec_addr_list) {
2110 json_object *sec_list = NULL;
2111
2112 sec_list = json_object_new_array();
2113 for (ALL_LIST_ELEMENTS_RO(
2114 pim_ifp->sec_addr_list, sec_node,
2115 sec_addr)) {
2116 json_object_array_add(
2117 sec_list,
44f99d22
SG
2118 json_object_new_stringf(
2119 "%pFXh",
2120 &sec_addr->addr));
e2b601e8
SG
2121 }
2122 json_object_object_add(json_row,
2123 "secondaryAddressList",
2124 sec_list);
2125 }
2126
7be33c5b 2127 if (pim_ifp->pim_passive_enable)
2128 json_object_boolean_true_add(json_row,
2129 "passive");
2130
e2b601e8
SG
2131 /* PIM neighbors */
2132 if (pim_ifp->pim_neighbor_list->count) {
2133 json_pim_neighbors = json_object_new_object();
2134
2135 for (ALL_LIST_ELEMENTS_RO(
2136 pim_ifp->pim_neighbor_list,
2137 neighnode, neigh)) {
2138 json_pim_neighbor =
2139 json_object_new_object();
44f99d22
SG
2140 snprintfrr(neigh_src_str,
2141 sizeof(neigh_src_str),
2142 "%pPAs",
2143 &neigh->source_addr);
e2b601e8
SG
2144 pim_time_uptime(uptime, sizeof(uptime),
2145 now - neigh->creation);
2146 pim_time_timer_to_hhmmss(
2147 expire, sizeof(expire),
2148 neigh->t_expire_timer);
2149
2150 json_object_string_add(
2151 json_pim_neighbor, "address",
2152 neigh_src_str);
2153 json_object_string_add(
2154 json_pim_neighbor, "upTime",
2155 uptime);
2156 json_object_string_add(
2157 json_pim_neighbor, "holdtime",
2158 expire);
2159
2160 json_object_object_add(
2161 json_pim_neighbors,
2162 neigh_src_str,
2163 json_pim_neighbor);
2164 }
2165
2166 json_object_object_add(json_row, "neighbors",
2167 json_pim_neighbors);
2168 }
2169
2170 json_object_string_add(json_row, "drAddress", dr_str);
2171 json_object_int_add(json_row, "drPriority",
2172 pim_ifp->pim_dr_priority);
2173 json_object_string_add(json_row, "drUptime", dr_uptime);
2174 json_object_int_add(json_row, "drElections",
2175 pim_ifp->pim_dr_election_count);
2176 json_object_int_add(json_row, "drChanges",
2177 pim_ifp->pim_dr_election_changes);
2178
2179 /* FHR */
2180 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2181 if (ifp != up->rpf.source_nexthop.interface)
2182 continue;
2183
2184 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2185 continue;
2186
2187 if (!json_fhr_sources)
2188 json_fhr_sources =
2189 json_object_new_object();
2190
2191 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
2192 &up->sg.grp);
2193 snprintfrr(src_str, sizeof(src_str), "%pPAs",
2194 &up->sg.src);
2195 pim_time_uptime(uptime, sizeof(uptime),
2196 now - up->state_transition);
2197
2198 /*
2199 * Does this group live in json_fhr_sources?
2200 * If not create it.
2201 */
2202 json_object_object_get_ex(json_fhr_sources,
2203 grp_str, &json_group);
2204
2205 if (!json_group) {
2206 json_group = json_object_new_object();
2207 json_object_object_add(json_fhr_sources,
2208 grp_str,
2209 json_group);
2210 }
2211
2212 json_group_source = json_object_new_object();
2213 json_object_string_add(json_group_source,
2214 "source", src_str);
2215 json_object_string_add(json_group_source,
2216 "group", grp_str);
2217 json_object_string_add(json_group_source,
2218 "upTime", uptime);
2219 json_object_object_add(json_group, src_str,
2220 json_group_source);
2221 }
2222
2223 if (json_fhr_sources) {
2224 json_object_object_add(json_row,
2225 "firstHopRouter",
2226 json_fhr_sources);
2227 }
2228
2229 json_object_int_add(json_row, "helloPeriod",
2230 pim_ifp->pim_hello_period);
2231 json_object_int_add(json_row, "holdTime",
2232 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2233 json_object_string_add(json_row, "helloTimer",
2234 hello_timer);
2235 json_object_string_add(json_row, "helloStatStart",
2236 stat_uptime);
2237 json_object_int_add(json_row, "helloReceived",
2238 pim_ifp->pim_ifstat_hello_recv);
2239 json_object_int_add(json_row, "helloReceivedFailed",
2240 pim_ifp->pim_ifstat_hello_recvfail);
2241 json_object_int_add(json_row, "helloSend",
2242 pim_ifp->pim_ifstat_hello_sent);
2243 json_object_int_add(json_row, "hellosendFailed",
2244 pim_ifp->pim_ifstat_hello_sendfail);
2245 json_object_int_add(json_row, "helloGenerationId",
2246 pim_ifp->pim_generation_id);
2247
2248 json_object_int_add(
2249 json_row, "effectivePropagationDelay",
2250 pim_if_effective_propagation_delay_msec(ifp));
2251 json_object_int_add(
2252 json_row, "effectiveOverrideInterval",
2253 pim_if_effective_override_interval_msec(ifp));
2254 json_object_int_add(
2255 json_row, "joinPruneOverrideInterval",
2256 pim_if_jp_override_interval_msec(ifp));
2257
2258 json_object_int_add(
2259 json_row, "propagationDelay",
2260 pim_ifp->pim_propagation_delay_msec);
2261 json_object_int_add(
2262 json_row, "propagationDelayHighest",
2263 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2264 json_object_int_add(
2265 json_row, "overrideInterval",
2266 pim_ifp->pim_override_interval_msec);
2267 json_object_int_add(
2268 json_row, "overrideIntervalHighest",
2269 pim_ifp->pim_neighbors_highest_override_interval_msec);
2270 if (pim_ifp->bsm_enable)
2271 json_object_boolean_true_add(json_row,
2272 "bsmEnabled");
2273 if (pim_ifp->ucast_bsm_accept)
2274 json_object_boolean_true_add(json_row,
2275 "ucastBsmEnabled");
2276 json_object_object_add(json, ifp->name, json_row);
2277
2278 } else {
2279 vty_out(vty, "Interface : %s\n", ifp->name);
2280 vty_out(vty, "State : %s\n",
2281 if_is_up(ifp) ? "up" : "down");
44f99d22
SG
2282 if (!pim_addr_is_any(pim_ifp->update_source)) {
2283 vty_out(vty, "Use Source : %pPAs\n",
e2b601e8
SG
2284 &pim_ifp->update_source);
2285 }
2286 if (pim_ifp->sec_addr_list) {
44f99d22 2287 vty_out(vty, "Address : %pPAs (primary)\n",
e2b601e8
SG
2288 &ifaddr);
2289 for (ALL_LIST_ELEMENTS_RO(
2290 pim_ifp->sec_addr_list, sec_node,
2291 sec_addr))
2292 vty_out(vty, " %pFX\n",
2293 &sec_addr->addr);
2294 } else {
44f99d22 2295 vty_out(vty, "Address : %pPAs\n", &ifaddr);
e2b601e8 2296 }
7be33c5b 2297
2298 if (pim_ifp->pim_passive_enable)
2299 vty_out(vty, "Passive : %s\n",
2300 (pim_ifp->pim_passive_enable) ? "yes"
2301 : "no");
2302
e2b601e8
SG
2303 vty_out(vty, "\n");
2304
2305 /* PIM neighbors */
2306 print_header = 1;
2307
2308 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
2309 neighnode, neigh)) {
2310
2311 if (print_header) {
2312 vty_out(vty, "PIM Neighbors\n");
2313 vty_out(vty, "-------------\n");
2314 print_header = 0;
2315 }
2316
44f99d22
SG
2317 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2318 "%pPAs", &neigh->source_addr);
e2b601e8
SG
2319 pim_time_uptime(uptime, sizeof(uptime),
2320 now - neigh->creation);
2321 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2322 neigh->t_expire_timer);
2323 vty_out(vty,
2324 "%-15s : up for %s, holdtime expires in %s\n",
2325 neigh_src_str, uptime, expire);
2326 }
2327
2328 if (!print_header) {
2329 vty_out(vty, "\n");
2330 vty_out(vty, "\n");
2331 }
2332
2333 vty_out(vty, "Designated Router\n");
2334 vty_out(vty, "-----------------\n");
2335 vty_out(vty, "Address : %s\n", dr_str);
2336 vty_out(vty, "Priority : %u(%d)\n",
2337 pim_ifp->pim_dr_priority,
2338 pim_ifp->pim_dr_num_nondrpri_neighbors);
2339 vty_out(vty, "Uptime : %s\n", dr_uptime);
2340 vty_out(vty, "Elections : %d\n",
2341 pim_ifp->pim_dr_election_count);
2342 vty_out(vty, "Changes : %d\n",
2343 pim_ifp->pim_dr_election_changes);
2344 vty_out(vty, "\n");
2345 vty_out(vty, "\n");
2346
2347 /* FHR */
2348 print_header = 1;
2349 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2350 if (!up->rpf.source_nexthop.interface)
2351 continue;
2352
2353 if (strcmp(ifp->name,
2354 up->rpf.source_nexthop
44f99d22 2355 .interface->name) != 0)
e2b601e8
SG
2356 continue;
2357
2358 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2359 continue;
2360
2361 if (print_header) {
2362 vty_out(vty,
2363 "FHR - First Hop Router\n");
2364 vty_out(vty,
2365 "----------------------\n");
2366 print_header = 0;
2367 }
2368
2369 pim_time_uptime(uptime, sizeof(uptime),
2370 now - up->state_transition);
2371 vty_out(vty,
2372 "%pPAs : %pPAs is a source, uptime is %s\n",
2373 &up->sg.grp, &up->sg.src, uptime);
2374 }
2375
2376 if (!print_header) {
2377 vty_out(vty, "\n");
2378 vty_out(vty, "\n");
2379 }
2380
2381 vty_out(vty, "Hellos\n");
2382 vty_out(vty, "------\n");
2383 vty_out(vty, "Period : %d\n",
2384 pim_ifp->pim_hello_period);
2385 vty_out(vty, "HoldTime : %d\n",
2386 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2387 vty_out(vty, "Timer : %s\n", hello_timer);
2388 vty_out(vty, "StatStart : %s\n", stat_uptime);
2389 vty_out(vty, "Receive : %d\n",
2390 pim_ifp->pim_ifstat_hello_recv);
2391 vty_out(vty, "Receive Failed : %d\n",
2392 pim_ifp->pim_ifstat_hello_recvfail);
2393 vty_out(vty, "Send : %d\n",
2394 pim_ifp->pim_ifstat_hello_sent);
2395 vty_out(vty, "Send Failed : %d\n",
2396 pim_ifp->pim_ifstat_hello_sendfail);
2397 vty_out(vty, "Generation ID : %08x\n",
2398 pim_ifp->pim_generation_id);
2399 vty_out(vty, "\n");
2400 vty_out(vty, "\n");
2401
2402 pim_print_ifp_flags(vty, ifp);
2403
2404 vty_out(vty, "Join Prune Interval\n");
2405 vty_out(vty, "-------------------\n");
2406 vty_out(vty, "LAN Delay : %s\n",
2407 pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
2408 vty_out(vty, "Effective Propagation Delay : %d msec\n",
2409 pim_if_effective_propagation_delay_msec(ifp));
2410 vty_out(vty, "Effective Override Interval : %d msec\n",
2411 pim_if_effective_override_interval_msec(ifp));
2412 vty_out(vty, "Join Prune Override Interval : %d msec\n",
2413 pim_if_jp_override_interval_msec(ifp));
2414 vty_out(vty, "\n");
2415 vty_out(vty, "\n");
2416
2417 vty_out(vty, "LAN Prune Delay\n");
2418 vty_out(vty, "---------------\n");
2419 vty_out(vty, "Propagation Delay : %d msec\n",
2420 pim_ifp->pim_propagation_delay_msec);
2421 vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
2422 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2423 vty_out(vty, "Override Interval : %d msec\n",
2424 pim_ifp->pim_override_interval_msec);
2425 vty_out(vty, "Override Interval (Highest) : %d msec\n",
2426 pim_ifp->pim_neighbors_highest_override_interval_msec);
2427 vty_out(vty, "\n");
2428 vty_out(vty, "\n");
2429
2430 vty_out(vty, "BSM Status\n");
2431 vty_out(vty, "----------\n");
2432 vty_out(vty, "Bsm Enabled : %s\n",
2433 pim_ifp->bsm_enable ? "yes" : "no");
2434 vty_out(vty, "Unicast Bsm Enabled : %s\n",
2435 pim_ifp->ucast_bsm_accept ? "yes" : "no");
2436 vty_out(vty, "\n");
2437 vty_out(vty, "\n");
2438 }
2439 }
2440
44f99d22 2441 if (!found_ifname)
e2b601e8
SG
2442 vty_out(vty, "%% No such interface\n");
2443}
2444
2445void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
2446 bool uj)
2447{
2448 struct pim_ssm *ssm = pim->ssm_info;
2449 const char *range_str =
2450 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
2451
2452 if (uj) {
2453 json_object *json;
2454
2455 json = json_object_new_object();
2456 json_object_string_add(json, "ssmGroups", range_str);
2457 vty_json(vty, json);
2458 } else
2459 vty_out(vty, "SSM group range : %s\n", range_str);
2460}
2461
2462struct pnc_cache_walk_data {
2463 struct vty *vty;
2464 struct pim_instance *pim;
2465};
2466
2467static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
2468{
2469 struct pim_nexthop_cache *pnc = bucket->data;
2470 struct pnc_cache_walk_data *cwd = arg;
2471 struct vty *vty = cwd->vty;
2472 struct pim_instance *pim = cwd->pim;
2473 struct nexthop *nh_node = NULL;
2474 ifindex_t first_ifindex;
2475 struct interface *ifp = NULL;
2476 char buf[PREFIX_STRLEN];
2477
2478 for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2479 first_ifindex = nh_node->ifindex;
2480 ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2481
2482 vty_out(vty, "%-15s ",
2483 inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, buf,
2484 sizeof(buf)));
2485 vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
2486 vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
2487 vty_out(vty, "\n");
2488 }
2489 return CMD_SUCCESS;
2490}
2491
2492void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
2493{
2494 struct pnc_cache_walk_data cwd;
2495
2496 cwd.vty = vty;
2497 cwd.pim = pim;
2498 vty_out(vty, "Number of registered addresses: %lu\n",
2499 pim->rpf_hash->count);
2500 vty_out(vty, "Address Interface Nexthop\n");
2501 vty_out(vty, "---------------------------------------------\n");
2502
2503 hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
2504}
2505
2506void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
2507 const char *neighbor, json_object *json)
2508{
2509 struct listnode *neighnode;
2510 struct interface *ifp;
2511 struct pim_interface *pim_ifp;
2512 struct pim_neighbor *neigh;
2513 time_t now;
2514 int found_neighbor = 0;
2515 int option_address_list;
2516 int option_dr_priority;
2517 int option_generation_id;
2518 int option_holdtime;
2519 int option_lan_prune_delay;
2520 int option_t_bit;
2521 char uptime[10];
2522 char expire[10];
2523 char neigh_src_str[PIM_ADDRSTRLEN];
2524
2525 json_object *json_ifp = NULL;
2526 json_object *json_row = NULL;
2527
2528 now = pim_time_monotonic_sec();
2529
2530 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2531 pim_ifp = ifp->info;
2532
2533 if (!pim_ifp)
2534 continue;
2535
2536 if (pim_ifp->pim_sock_fd < 0)
2537 continue;
2538
2539 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2540 neigh)) {
2541 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2542 "%pPAs", &neigh->source_addr);
2543
2544 /*
2545 * The user can specify either the interface name or the
2546 * PIM neighbor IP.
2547 * If this pim_ifp matches neither then skip.
2548 */
2549 if (strcmp(neighbor, "detail") &&
2550 strcmp(neighbor, ifp->name) &&
2551 strcmp(neighbor, neigh_src_str))
2552 continue;
2553
2554 found_neighbor = 1;
2555 pim_time_uptime(uptime, sizeof(uptime),
2556 now - neigh->creation);
2557 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2558 neigh->t_expire_timer);
2559
2560 option_address_list = 0;
2561 option_dr_priority = 0;
2562 option_generation_id = 0;
2563 option_holdtime = 0;
2564 option_lan_prune_delay = 0;
2565 option_t_bit = 0;
2566
2567 if (PIM_OPTION_IS_SET(neigh->hello_options,
2568 PIM_OPTION_MASK_ADDRESS_LIST))
2569 option_address_list = 1;
2570
2571 if (PIM_OPTION_IS_SET(neigh->hello_options,
2572 PIM_OPTION_MASK_DR_PRIORITY))
2573 option_dr_priority = 1;
2574
2575 if (PIM_OPTION_IS_SET(neigh->hello_options,
2576 PIM_OPTION_MASK_GENERATION_ID))
2577 option_generation_id = 1;
2578
2579 if (PIM_OPTION_IS_SET(neigh->hello_options,
2580 PIM_OPTION_MASK_HOLDTIME))
2581 option_holdtime = 1;
2582
2583 if (PIM_OPTION_IS_SET(neigh->hello_options,
2584 PIM_OPTION_MASK_LAN_PRUNE_DELAY))
2585 option_lan_prune_delay = 1;
2586
2587 if (PIM_OPTION_IS_SET(
2588 neigh->hello_options,
2589 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
2590 option_t_bit = 1;
2591
2592 if (json) {
2593
2594 /* Does this ifp live in json? If not create it
2595 */
2596 json_object_object_get_ex(json, ifp->name,
2597 &json_ifp);
2598
2599 if (!json_ifp) {
2600 json_ifp = json_object_new_object();
2601 json_object_pim_ifp_add(json_ifp, ifp);
2602 json_object_object_add(json, ifp->name,
2603 json_ifp);
2604 }
2605
2606 json_row = json_object_new_object();
2607 json_object_string_add(json_row, "interface",
2608 ifp->name);
2609 json_object_string_add(json_row, "address",
2610 neigh_src_str);
2611 json_object_string_add(json_row, "upTime",
2612 uptime);
2613 json_object_string_add(json_row, "holdtime",
2614 expire);
2615 json_object_int_add(json_row, "drPriority",
2616 neigh->dr_priority);
2617 json_object_int_add(json_row, "generationId",
2618 neigh->generation_id);
2619
2620 if (option_address_list)
2621 json_object_boolean_true_add(
2622 json_row,
2623 "helloOptionAddressList");
2624
2625 if (option_dr_priority)
2626 json_object_boolean_true_add(
2627 json_row,
2628 "helloOptionDrPriority");
2629
2630 if (option_generation_id)
2631 json_object_boolean_true_add(
2632 json_row,
2633 "helloOptionGenerationId");
2634
2635 if (option_holdtime)
2636 json_object_boolean_true_add(
2637 json_row,
2638 "helloOptionHoldtime");
2639
2640 if (option_lan_prune_delay)
2641 json_object_boolean_true_add(
2642 json_row,
2643 "helloOptionLanPruneDelay");
2644
2645 if (option_t_bit)
2646 json_object_boolean_true_add(
2647 json_row, "helloOptionTBit");
2648
2649 json_object_object_add(json_ifp, neigh_src_str,
2650 json_row);
2651
2652 } else {
2653 vty_out(vty, "Interface : %s\n", ifp->name);
2654 vty_out(vty, "Neighbor : %s\n", neigh_src_str);
2655 vty_out(vty,
2656 " Uptime : %s\n",
2657 uptime);
2658 vty_out(vty,
2659 " Holdtime : %s\n",
2660 expire);
2661 vty_out(vty,
2662 " DR Priority : %d\n",
2663 neigh->dr_priority);
2664 vty_out(vty,
2665 " Generation ID : %08x\n",
2666 neigh->generation_id);
2667 vty_out(vty,
2668 " Override Interval (msec) : %d\n",
2669 neigh->override_interval_msec);
2670 vty_out(vty,
2671 " Propagation Delay (msec) : %d\n",
2672 neigh->propagation_delay_msec);
2673 vty_out(vty,
2674 " Hello Option - Address List : %s\n",
2675 option_address_list ? "yes" : "no");
2676 vty_out(vty,
2677 " Hello Option - DR Priority : %s\n",
2678 option_dr_priority ? "yes" : "no");
2679 vty_out(vty,
2680 " Hello Option - Generation ID : %s\n",
2681 option_generation_id ? "yes" : "no");
2682 vty_out(vty,
2683 " Hello Option - Holdtime : %s\n",
2684 option_holdtime ? "yes" : "no");
2685 vty_out(vty,
2686 " Hello Option - LAN Prune Delay : %s\n",
2687 option_lan_prune_delay ? "yes" : "no");
2688 vty_out(vty,
2689 " Hello Option - T-bit : %s\n",
2690 option_t_bit ? "yes" : "no");
2691 bfd_sess_show(vty, json_ifp,
2692 neigh->bfd_session);
2693 vty_out(vty, "\n");
2694 }
2695 }
2696 }
2697
2698 if (!found_neighbor)
2699 vty_out(vty, "%% No such interface or neighbor\n");
2700}
2701
1295dbeb
SG
2702void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
2703 json_object *json)
e2b601e8
SG
2704{
2705 struct listnode *neighnode;
2706 struct interface *ifp;
2707 struct pim_interface *pim_ifp;
2708 struct pim_neighbor *neigh;
2709 time_t now;
2710 char uptime[10];
2711 char expire[10];
1295dbeb 2712 char neigh_src_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2713 json_object *json_ifp_rows = NULL;
2714 json_object *json_row = NULL;
2715
2716 now = pim_time_monotonic_sec();
2717
1295dbeb 2718 if (!json) {
e2b601e8
SG
2719 vty_out(vty,
2720 "Interface Neighbor Uptime Holdtime DR Pri\n");
2721 }
2722
2723 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2724 pim_ifp = ifp->info;
2725
2726 if (!pim_ifp)
2727 continue;
2728
2729 if (pim_ifp->pim_sock_fd < 0)
2730 continue;
2731
1295dbeb 2732 if (json)
e2b601e8
SG
2733 json_ifp_rows = json_object_new_object();
2734
2735 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2736 neigh)) {
1295dbeb
SG
2737 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2738 "%pPAs", &neigh->source_addr);
e2b601e8
SG
2739 pim_time_uptime(uptime, sizeof(uptime),
2740 now - neigh->creation);
2741 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2742 neigh->t_expire_timer);
2743
1295dbeb 2744 if (json) {
e2b601e8
SG
2745 json_row = json_object_new_object();
2746 json_object_string_add(json_row, "interface",
2747 ifp->name);
2748 json_object_string_add(json_row, "neighbor",
2749 neigh_src_str);
2750 json_object_string_add(json_row, "upTime",
2751 uptime);
2752 json_object_string_add(json_row, "holdTime",
2753 expire);
2754 json_object_int_add(json_row, "holdTimeMax",
2755 neigh->holdtime);
2756 json_object_int_add(json_row, "drPriority",
2757 neigh->dr_priority);
2758 json_object_object_add(json_ifp_rows,
2759 neigh_src_str, json_row);
2760
2761 } else {
2762 vty_out(vty, "%-16s %15s %8s %8s %6d\n",
2763 ifp->name, neigh_src_str, uptime,
2764 expire, neigh->dr_priority);
2765 }
2766 }
2767
1295dbeb 2768 if (json) {
e2b601e8
SG
2769 json_object_object_add(json, ifp->name, json_ifp_rows);
2770 json_ifp_rows = NULL;
2771 }
2772 }
e2b601e8 2773}
c8b3d45d
SG
2774
2775int gm_process_query_max_response_time_cmd(struct vty *vty,
2776 const char *qmrt_str)
2777{
2778 const struct lyd_node *pim_enable_dnode;
2779
2780 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2781 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2782 FRR_PIM_AF_XPATH_VAL);
2783
2784 if (!pim_enable_dnode) {
2785 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2786 } else {
2787 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2788 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2789 "true");
2790 }
2791
2792 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
2793 qmrt_str);
2794 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2795 FRR_PIM_AF_XPATH_VAL);
2796}
2797
2798int gm_process_no_query_max_response_time_cmd(struct vty *vty)
2799{
2800 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
2801 NULL);
2802 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2803 FRR_PIM_AF_XPATH_VAL);
2804}
c889adcb
SG
2805
2806int gm_process_last_member_query_count_cmd(struct vty *vty,
2807 const char *lmqc_str)
2808{
2809 const struct lyd_node *pim_enable_dnode;
2810
2811 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2812 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2813 FRR_PIM_AF_XPATH_VAL);
2814 if (!pim_enable_dnode) {
2815 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2816 } else {
2817 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2818 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2819 "true");
2820 }
2821
2822 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
2823 lmqc_str);
2824 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2825 FRR_PIM_AF_XPATH_VAL);
2826}
2827
2828int gm_process_no_last_member_query_count_cmd(struct vty *vty)
2829{
2830 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
2831 NULL);
2832 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2833 FRR_PIM_AF_XPATH_VAL);
2834}
e7ec758d
SG
2835
2836int gm_process_last_member_query_interval_cmd(struct vty *vty,
2837 const char *lmqi_str)
2838{
2839 const struct lyd_node *pim_enable_dnode;
2840
2841 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2842 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2843 FRR_PIM_AF_XPATH_VAL);
2844 if (!pim_enable_dnode) {
2845 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2846 } else {
2847 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2848 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2849 "true");
2850 }
2851
2852 nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
2853 lmqi_str);
2854 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2855 FRR_PIM_AF_XPATH_VAL);
2856}
2857
2858int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
2859{
2860 nb_cli_enqueue_change(vty, "./last-member-query-interval",
2861 NB_OP_DESTROY, NULL);
2862 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2863 FRR_PIM_AF_XPATH_VAL);
2864}
a8caf78d 2865
a8caf78d
BG
2866int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
2867 const char *src_str)
2868{
2869 const char *vrfname;
2870 char ssmpingd_ip_xpath[XPATH_MAXLEN];
2871
2872 vrfname = pim_cli_get_vrf_name(vty);
2873 if (vrfname == NULL)
2874 return CMD_WARNING_CONFIG_FAILED;
2875
2876 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
2877 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
2878 FRR_PIM_AF_XPATH_VAL);
2879 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
2880 sizeof(ssmpingd_ip_xpath));
2881
2882 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
2883
2884 return nb_cli_apply_changes(vty, NULL);
2885}
be126d91 2886
be126d91
A
2887static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
2888 time_t now)
2889{
2890 char uptime_scan_oil[10];
2891 char uptime_mroute_add[10];
2892 char uptime_mroute_del[10];
2893
2894 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
2895 pim->scan_oil_last);
2896 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
2897 pim->mroute_add_last);
2898 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
2899 pim->mroute_del_last);
2900
2901 vty_out(vty,
2902 "Scan OIL - Last: %s Events: %lld\n"
2903 "MFC Add - Last: %s Events: %lld\n"
2904 "MFC Del - Last: %s Events: %lld\n",
2905 uptime_scan_oil, (long long)pim->scan_oil_events,
2906 uptime_mroute_add, (long long)pim->mroute_add_events,
2907 uptime_mroute_del, (long long)pim->mroute_del_events);
2908}
2909
2910void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
3e55b3b5 2911 json_object *json)
be126d91
A
2912{
2913 struct interface *ifp;
be126d91
A
2914 json_object *json_row = NULL;
2915
2916 vty_out(vty, "\n");
2917
3e55b3b5 2918 if (!json)
be126d91
A
2919 vty_out(vty,
2920 "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
2921
2922 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2923 struct pim_interface *pim_ifp;
ca3b5906 2924#if PIM_IPV == 4
be126d91 2925 struct sioc_vif_req vreq;
ca3b5906
A
2926#else
2927 struct sioc_mif_req6 vreq;
2928#endif
be126d91
A
2929
2930 pim_ifp = ifp->info;
2931
2932 if (!pim_ifp)
2933 continue;
2934
2935 memset(&vreq, 0, sizeof(vreq));
ca3b5906 2936#if PIM_IPV == 4
be126d91 2937 vreq.vifi = pim_ifp->mroute_vif_index;
be126d91
A
2938 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
2939 zlog_warn(
2940 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
2941 (unsigned long)SIOCGETVIFCNT, ifp->name,
2942 pim_ifp->mroute_vif_index, errno,
2943 safe_strerror(errno));
2944 }
ca3b5906
A
2945#else
2946 vreq.mifi = pim_ifp->mroute_vif_index;
2947 if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
2948 zlog_warn(
2949 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
2950 (unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
2951 pim_ifp->mroute_vif_index, errno,
2952 safe_strerror(errno));
2953 }
2954#endif
be126d91 2955
3e55b3b5 2956 if (json) {
be126d91
A
2957 json_row = json_object_new_object();
2958 json_object_string_add(json_row, "name", ifp->name);
2959 json_object_string_add(json_row, "state",
2960 if_is_up(ifp) ? "up" : "down");
ca3b5906 2961 json_object_string_addf(json_row, "address", "%pPA",
be126d91
A
2962 &pim_ifp->primary_address);
2963 json_object_int_add(json_row, "ifIndex", ifp->ifindex);
2964 json_object_int_add(json_row, "vif",
2965 pim_ifp->mroute_vif_index);
2966 json_object_int_add(json_row, "pktsIn",
2967 (unsigned long)vreq.icount);
2968 json_object_int_add(json_row, "pktsOut",
2969 (unsigned long)vreq.ocount);
2970 json_object_int_add(json_row, "bytesIn",
2971 (unsigned long)vreq.ibytes);
2972 json_object_int_add(json_row, "bytesOut",
2973 (unsigned long)vreq.obytes);
2974 json_object_object_add(json, ifp->name, json_row);
2975 } else {
2976 vty_out(vty,
ca3b5906
A
2977 "%-16s %-15pPAs %3d %3d %7lu %7lu %10lu %10lu\n",
2978 ifp->name, &pim_ifp->primary_address,
be126d91
A
2979 ifp->ifindex, pim_ifp->mroute_vif_index,
2980 (unsigned long)vreq.icount,
2981 (unsigned long)vreq.ocount,
2982 (unsigned long)vreq.ibytes,
2983 (unsigned long)vreq.obytes);
2984 }
2985 }
be126d91
A
2986}
2987
ca3b5906 2988void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
be126d91
A
2989{
2990 struct vrf *vrf = pim->vrf;
2991 time_t now = pim_time_monotonic_sec();
2992 char uptime[10];
2993 char mlag_role[80];
2994
2995 pim = vrf->info;
2996
2997 vty_out(vty, "Router MLAG Role: %s\n",
2998 mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
2999 vty_out(vty, "Mroute socket descriptor:");
3000
3001 vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
3002
3003 pim_time_uptime(uptime, sizeof(uptime),
3004 now - pim->mroute_socket_creation);
3005 vty_out(vty, "Mroute socket uptime: %s\n", uptime);
3006
3007 vty_out(vty, "\n");
3008
3009 pim_zebra_zclient_update(vty);
ca3b5906 3010#if PIM_IPV == 4
be126d91 3011 pim_zlookup_show_ip_multicast(vty);
ca3b5906
A
3012#else
3013 /* TBD */
3014#endif
be126d91
A
3015
3016 vty_out(vty, "\n");
3017 vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
3018
3019 vty_out(vty, "\n");
3020 vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
3021 vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
3022 vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
3023 vty_out(vty, "PIM ECMP Rebalance: %s\n",
3024 pim->ecmp_rebalance_enable ? "Enable" : "Disable");
3025
3026 vty_out(vty, "\n");
3027
3028 pim_show_rpf_refresh_stats(vty, pim, now, NULL);
3029
3030 vty_out(vty, "\n");
3031
3032 show_scan_oil_stats(pim, vty, now);
3033
3e55b3b5 3034 show_multicast_interfaces(pim, vty, NULL);
be126d91 3035}
50ba39bf
A
3036
3037void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
3038 bool fill, json_object *json)
3b767e4b
A
3039{
3040 struct listnode *node;
3041 struct channel_oil *c_oil;
3042 struct static_route *s_route;
3043 time_t now;
3b767e4b
A
3044 json_object *json_group = NULL;
3045 json_object *json_source = NULL;
3046 json_object *json_oil = NULL;
3047 json_object *json_ifp_out = NULL;
3048 int found_oif;
3049 int first;
50ba39bf
A
3050 char grp_str[PIM_ADDRSTRLEN];
3051 char src_str[PIM_ADDRSTRLEN];
3b767e4b
A
3052 char in_ifname[INTERFACE_NAMSIZ + 1];
3053 char out_ifname[INTERFACE_NAMSIZ + 1];
3054 int oif_vif_index;
3055 struct interface *ifp_in;
3056 char proto[100];
3057 char state_str[PIM_REG_STATE_STR_LEN];
3058 char mroute_uptime[10];
3059
50ba39bf 3060 if (!json) {
3b767e4b
A
3061 vty_out(vty, "IP Multicast Routing Table\n");
3062 vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3063 vty_out(vty,
3064 " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3065 vty_out(vty,
3066 "\nSource Group Flags Proto Input Output TTL Uptime\n");
3067 }
3068
3069 now = pim_time_monotonic_sec();
3070
3071 /* print list of PIM and IGMP routes */
3072 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
3073 found_oif = 0;
3074 first = 1;
3075 if (!c_oil->installed)
3076 continue;
3077
3078 if (!pim_addr_is_any(sg->grp) &&
50ba39bf 3079 pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil)))
3b767e4b
A
3080 continue;
3081 if (!pim_addr_is_any(sg->src) &&
50ba39bf 3082 pim_addr_cmp(sg->src, *oil_origin(c_oil)))
3b767e4b
A
3083 continue;
3084
50ba39bf
A
3085 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
3086 oil_mcastgrp(c_oil));
3087 snprintfrr(src_str, sizeof(src_str), "%pPAs",
3088 oil_origin(c_oil));
3b767e4b
A
3089
3090 strlcpy(state_str, "S", sizeof(state_str));
3091 /* When a non DR receives a igmp join, it creates a (*,G)
50ba39bf
A
3092 * channel_oil without any upstream creation
3093 */
3b767e4b
A
3094 if (c_oil->up) {
3095 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
3096 strlcat(state_str, "C", sizeof(state_str));
3097 if (pim_upstream_is_sg_rpt(c_oil->up))
3098 strlcat(state_str, "R", sizeof(state_str));
3099 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
3100 strlcat(state_str, "F", sizeof(state_str));
3101 if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
3102 strlcat(state_str, "T", sizeof(state_str));
3103 }
3104 if (pim_channel_oil_empty(c_oil))
3105 strlcat(state_str, "P", sizeof(state_str));
3106
50ba39bf 3107 ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
3b767e4b
A
3108
3109 if (ifp_in)
3110 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3111 else
3112 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3113
3114
3115 pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
3116 now - c_oil->mroute_creation);
3117
50ba39bf 3118 if (json) {
3b767e4b
A
3119
3120 /* Find the group, create it if it doesn't exist */
3121 json_object_object_get_ex(json, grp_str, &json_group);
3122
3123 if (!json_group) {
3124 json_group = json_object_new_object();
3125 json_object_object_add(json, grp_str,
3126 json_group);
3127 }
3128
3129 /* Find the source nested under the group, create it if
3130 * it doesn't exist
3131 */
3132 json_object_object_get_ex(json_group, src_str,
3133 &json_source);
3134
3135 if (!json_source) {
3136 json_source = json_object_new_object();
3137 json_object_object_add(json_group, src_str,
3138 json_source);
3139 }
3140
3141 /* Find the inbound interface nested under the source,
50ba39bf
A
3142 * create it if it doesn't exist
3143 */
3144 json_object_string_add(json_source, "source", src_str);
3145 json_object_string_add(json_source, "group", grp_str);
3b767e4b
A
3146 json_object_int_add(json_source, "installed",
3147 c_oil->installed);
3148 json_object_int_add(json_source, "refCount",
3149 c_oil->oil_ref_count);
3150 json_object_int_add(json_source, "oilSize",
3151 c_oil->oil_size);
3152 json_object_int_add(json_source, "OilInheritedRescan",
3153 c_oil->oil_inherited_rescan);
3154 json_object_int_add(json_source, "oilInheritedRescan",
3155 c_oil->oil_inherited_rescan);
3156 json_object_string_add(json_source, "iif", in_ifname);
3157 json_object_string_add(json_source, "upTime",
3158 mroute_uptime);
3159 json_oil = NULL;
3160 }
3161
3162 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3163 ++oif_vif_index) {
3164 struct interface *ifp_out;
3165 int ttl;
3166
50ba39bf 3167 ttl = oil_if_has(c_oil, oif_vif_index);
3b767e4b
A
3168 if (ttl < 1)
3169 continue;
3170
3171 /* do not display muted OIFs */
50ba39bf 3172 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE)
3b767e4b
A
3173 continue;
3174
50ba39bf
A
3175 if (*oil_parent(c_oil) == oif_vif_index &&
3176 !pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index))
3b767e4b
A
3177 continue;
3178
3179 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3180 found_oif = 1;
3181
3182 if (ifp_out)
50ba39bf
A
3183 strlcpy(out_ifname, ifp_out->name,
3184 sizeof(out_ifname));
3b767e4b 3185 else
50ba39bf
A
3186 strlcpy(out_ifname, "<oif?>",
3187 sizeof(out_ifname));
3b767e4b 3188
50ba39bf 3189 if (json) {
3b767e4b
A
3190 json_ifp_out = json_object_new_object();
3191 json_object_string_add(json_ifp_out, "source",
3192 src_str);
3193 json_object_string_add(json_ifp_out, "group",
3194 grp_str);
3195
50ba39bf
A
3196 if (c_oil->oif_flags[oif_vif_index] &
3197 PIM_OIF_FLAG_PROTO_PIM)
3b767e4b
A
3198 json_object_boolean_true_add(
3199 json_ifp_out, "protocolPim");
3200
50ba39bf
A
3201 if (c_oil->oif_flags[oif_vif_index] &
3202 PIM_OIF_FLAG_PROTO_GM)
3203#if PIM_IPV == 4
3b767e4b
A
3204 json_object_boolean_true_add(
3205 json_ifp_out, "protocolIgmp");
50ba39bf
A
3206#else
3207 json_object_boolean_true_add(
3208 json_ifp_out, "protocolMld");
3209#endif
3b767e4b 3210
50ba39bf
A
3211 if (c_oil->oif_flags[oif_vif_index] &
3212 PIM_OIF_FLAG_PROTO_VXLAN)
3b767e4b
A
3213 json_object_boolean_true_add(
3214 json_ifp_out, "protocolVxlan");
3215
50ba39bf
A
3216 if (c_oil->oif_flags[oif_vif_index] &
3217 PIM_OIF_FLAG_PROTO_STAR)
3b767e4b
A
3218 json_object_boolean_true_add(
3219 json_ifp_out,
3220 "protocolInherited");
3221
3222 json_object_string_add(json_ifp_out,
3223 "inboundInterface",
3224 in_ifname);
3225 json_object_int_add(json_ifp_out, "iVifI",
50ba39bf 3226 *oil_parent(c_oil));
3b767e4b
A
3227 json_object_string_add(json_ifp_out,
3228 "outboundInterface",
3229 out_ifname);
3230 json_object_int_add(json_ifp_out, "oVifI",
3231 oif_vif_index);
3232 json_object_int_add(json_ifp_out, "ttl", ttl);
3233 json_object_string_add(json_ifp_out, "upTime",
3234 mroute_uptime);
3235 json_object_string_add(json_source, "flags",
3236 state_str);
3237 if (!json_oil) {
3238 json_oil = json_object_new_object();
3239 json_object_object_add(json_source,
3240 "oil", json_oil);
3241 }
3242 json_object_object_add(json_oil, out_ifname,
3243 json_ifp_out);
3244 } else {
3245 proto[0] = '\0';
50ba39bf
A
3246 if (c_oil->oif_flags[oif_vif_index] &
3247 PIM_OIF_FLAG_PROTO_PIM) {
3b767e4b
A
3248 strlcpy(proto, "PIM", sizeof(proto));
3249 }
3250
50ba39bf
A
3251 if (c_oil->oif_flags[oif_vif_index] &
3252 PIM_OIF_FLAG_PROTO_GM) {
3253#if PIM_IPV == 4
3b767e4b 3254 strlcpy(proto, "IGMP", sizeof(proto));
50ba39bf
A
3255#else
3256 strlcpy(proto, "MLD", sizeof(proto));
3257#endif
3b767e4b
A
3258 }
3259
50ba39bf
A
3260 if (c_oil->oif_flags[oif_vif_index] &
3261 PIM_OIF_FLAG_PROTO_VXLAN) {
3b767e4b
A
3262 strlcpy(proto, "VxLAN", sizeof(proto));
3263 }
3264
50ba39bf
A
3265 if (c_oil->oif_flags[oif_vif_index] &
3266 PIM_OIF_FLAG_PROTO_STAR) {
3b767e4b
A
3267 strlcpy(proto, "STAR", sizeof(proto));
3268 }
3269
3270 vty_out(vty,
50ba39bf
A
3271 "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
3272 oil_origin(c_oil), oil_mcastgrp(c_oil),
3273 state_str, proto, in_ifname, out_ifname,
3274 ttl, mroute_uptime);
3b767e4b
A
3275
3276 if (first) {
3277 src_str[0] = '\0';
3278 grp_str[0] = '\0';
3279 in_ifname[0] = '\0';
3280 state_str[0] = '\0';
3281 mroute_uptime[0] = '\0';
3282 first = 0;
3283 }
3284 }
3285 }
3286
50ba39bf 3287 if (!json && !found_oif) {
3b767e4b 3288 vty_out(vty,
50ba39bf
A
3289 "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
3290 oil_origin(c_oil), oil_mcastgrp(c_oil),
3291 state_str, "none", in_ifname, "none", 0,
3292 "--:--:--");
3b767e4b
A
3293 }
3294 }
3295
3296 /* Print list of static routes */
3297 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
3298 first = 1;
3299
3300 if (!s_route->c_oil.installed)
3301 continue;
3302
50ba39bf
A
3303 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group);
3304 snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source);
3b767e4b
A
3305 ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
3306 found_oif = 0;
3307
3308 if (ifp_in)
3309 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3310 else
3311 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3312
50ba39bf 3313 if (json) {
3b767e4b
A
3314
3315 /* Find the group, create it if it doesn't exist */
3316 json_object_object_get_ex(json, grp_str, &json_group);
3317
3318 if (!json_group) {
3319 json_group = json_object_new_object();
3320 json_object_object_add(json, grp_str,
3321 json_group);
3322 }
3323
3324 /* Find the source nested under the group, create it if
50ba39bf
A
3325 * it doesn't exist
3326 */
3b767e4b
A
3327 json_object_object_get_ex(json_group, src_str,
3328 &json_source);
3329
3330 if (!json_source) {
3331 json_source = json_object_new_object();
3332 json_object_object_add(json_group, src_str,
3333 json_source);
3334 }
3335
3336 json_object_string_add(json_source, "iif", in_ifname);
3337 json_oil = NULL;
3338 } else {
3339 strlcpy(proto, "STATIC", sizeof(proto));
3340 }
3341
3342 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3343 ++oif_vif_index) {
3344 struct interface *ifp_out;
3345 char oif_uptime[10];
3346 int ttl;
3347
3348 ttl = s_route->oif_ttls[oif_vif_index];
3349 if (ttl < 1)
3350 continue;
3351
3352 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3353 pim_time_uptime(
3354 oif_uptime, sizeof(oif_uptime),
50ba39bf
A
3355 now - s_route->c_oil
3356 .oif_creation[oif_vif_index]);
3b767e4b
A
3357 found_oif = 1;
3358
3359 if (ifp_out)
50ba39bf
A
3360 strlcpy(out_ifname, ifp_out->name,
3361 sizeof(out_ifname));
3b767e4b 3362 else
50ba39bf
A
3363 strlcpy(out_ifname, "<oif?>",
3364 sizeof(out_ifname));
3b767e4b 3365
50ba39bf 3366 if (json) {
3b767e4b
A
3367 json_ifp_out = json_object_new_object();
3368 json_object_string_add(json_ifp_out, "source",
3369 src_str);
3370 json_object_string_add(json_ifp_out, "group",
3371 grp_str);
3372 json_object_boolean_true_add(json_ifp_out,
3373 "protocolStatic");
3374 json_object_string_add(json_ifp_out,
3375 "inboundInterface",
3376 in_ifname);
3377 json_object_int_add(
3378 json_ifp_out, "iVifI",
50ba39bf 3379 *oil_parent(&s_route->c_oil));
3b767e4b
A
3380 json_object_string_add(json_ifp_out,
3381 "outboundInterface",
3382 out_ifname);
3383 json_object_int_add(json_ifp_out, "oVifI",
3384 oif_vif_index);
3385 json_object_int_add(json_ifp_out, "ttl", ttl);
3386 json_object_string_add(json_ifp_out, "upTime",
3387 oif_uptime);
3388 if (!json_oil) {
3389 json_oil = json_object_new_object();
3390 json_object_object_add(json_source,
3391 "oil", json_oil);
3392 }
3393 json_object_object_add(json_oil, out_ifname,
3394 json_ifp_out);
3395 } else {
3396 vty_out(vty,
50ba39bf
A
3397 "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
3398 &s_route->source, &s_route->group, "-",
3399 proto, in_ifname, out_ifname, ttl,
3400 oif_uptime);
3b767e4b
A
3401 if (first && !fill) {
3402 src_str[0] = '\0';
3403 grp_str[0] = '\0';
3404 in_ifname[0] = '\0';
3405 first = 0;
3406 }
3407 }
3408 }
3409
50ba39bf 3410 if (!json && !found_oif) {
3b767e4b 3411 vty_out(vty,
50ba39bf
A
3412 "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
3413 &s_route->source, &s_route->group, "-", proto,
3414 in_ifname, "none", 0, "--:--:--");
3b767e4b
A
3415 }
3416 }
3b767e4b
A
3417}
3418
3419static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
3420 json_object *json,
3421 struct vty *vty)
3422{
3b767e4b
A
3423 json_object *json_group = NULL;
3424 json_object *json_source = NULL;
3425
3426 if (!c_oil->installed)
3427 return;
3428
3429 pim_mroute_update_counters(c_oil);
3430
3b767e4b 3431 if (json) {
c41a9dcf
A
3432 char group_str[PIM_ADDRSTRLEN];
3433 char source_str[PIM_ADDRSTRLEN];
3434
3435 snprintfrr(group_str, sizeof(group_str), "%pPAs",
3436 oil_mcastgrp(c_oil));
3437 snprintfrr(source_str, sizeof(source_str), "%pPAs",
3438 oil_origin(c_oil));
3439
3b767e4b
A
3440 json_object_object_get_ex(json, group_str, &json_group);
3441
3442 if (!json_group) {
3443 json_group = json_object_new_object();
3444 json_object_object_add(json, group_str, json_group);
3445 }
3446
3447 json_source = json_object_new_object();
3448 json_object_object_add(json_group, source_str, json_source);
3449 json_object_int_add(json_source, "lastUsed",
3450 c_oil->cc.lastused / 100);
3451 json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
3452 json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
3453 json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
3454
3455 } else {
c41a9dcf
A
3456 vty_out(vty, "%-15pPAs %-15pPAs %-8llu %-7ld %-10ld %-7ld\n",
3457 oil_origin(c_oil), oil_mcastgrp(c_oil),
3458 c_oil->cc.lastused / 100,
3b767e4b
A
3459 c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
3460 c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
3461 c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
3462 }
3463}
3464
3465void show_mroute_count(struct pim_instance *pim, struct vty *vty,
c41a9dcf 3466 json_object *json)
3b767e4b
A
3467{
3468 struct listnode *node;
3469 struct channel_oil *c_oil;
3470 struct static_route *sr;
3b767e4b 3471
c41a9dcf 3472 if (!json) {
3b767e4b
A
3473 vty_out(vty, "\n");
3474
3475 vty_out(vty,
3476 "Source Group LastUsed Packets Bytes WrongIf \n");
3477 }
3478
3479 /* Print PIM and IGMP route counts */
3480 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
3481 show_mroute_count_per_channel_oil(c_oil, json, vty);
3482
3483 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
3484 show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
3b767e4b
A
3485}
3486
3487void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
74e8197b 3488 json_object *json)
3b767e4b
A
3489{
3490 struct listnode *node;
3491 struct channel_oil *c_oil;
3492 struct static_route *s_route;
3493 uint32_t starg_sw_mroute_cnt = 0;
3494 uint32_t sg_sw_mroute_cnt = 0;
3495 uint32_t starg_hw_mroute_cnt = 0;
3496 uint32_t sg_hw_mroute_cnt = 0;
3497 json_object *json_starg = NULL;
3498 json_object *json_sg = NULL;
3499
3500 if (!json)
3501 vty_out(vty, "Mroute Type Installed/Total\n");
3502
3503 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
3504 if (!c_oil->installed) {
74e8197b 3505 if (pim_addr_is_any(*oil_origin(c_oil)))
3b767e4b
A
3506 starg_sw_mroute_cnt++;
3507 else
3508 sg_sw_mroute_cnt++;
3509 } else {
74e8197b 3510 if (pim_addr_is_any(*oil_origin(c_oil)))
3b767e4b
A
3511 starg_hw_mroute_cnt++;
3512 else
3513 sg_hw_mroute_cnt++;
3514 }
3515 }
3516
3517 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
3518 if (!s_route->c_oil.installed) {
74e8197b 3519 if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
3b767e4b
A
3520 starg_sw_mroute_cnt++;
3521 else
3522 sg_sw_mroute_cnt++;
3523 } else {
74e8197b 3524 if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
3b767e4b
A
3525 starg_hw_mroute_cnt++;
3526 else
3527 sg_hw_mroute_cnt++;
3528 }
3529 }
3530
3531 if (!json) {
3532 vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
3533 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
3534 vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
3535 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
3536 vty_out(vty, "------\n");
3537 vty_out(vty, "%-20s %u/%u\n", "Total",
3538 (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
74e8197b
A
3539 (starg_sw_mroute_cnt + starg_hw_mroute_cnt +
3540 sg_sw_mroute_cnt + sg_hw_mroute_cnt));
3b767e4b
A
3541 } else {
3542 /* (*,G) route details */
3543 json_starg = json_object_new_object();
3544 json_object_object_add(json, "wildcardGroup", json_starg);
3545
3546 json_object_int_add(json_starg, "installed",
3547 starg_hw_mroute_cnt);
3548 json_object_int_add(json_starg, "total",
3549 starg_sw_mroute_cnt + starg_hw_mroute_cnt);
3550
3551 /* (S, G) route details */
3552 json_sg = json_object_new_object();
3553 json_object_object_add(json, "sourceGroup", json_sg);
3554
3555 json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
3556 json_object_int_add(json_sg, "total",
3557 sg_sw_mroute_cnt + sg_hw_mroute_cnt);
3558
3559 json_object_int_add(json, "totalNumOfInstalledMroutes",
3560 starg_hw_mroute_cnt + sg_hw_mroute_cnt);
3561 json_object_int_add(json, "totalNumOfMroutes",
74e8197b
A
3562 starg_sw_mroute_cnt + starg_hw_mroute_cnt +
3563 sg_sw_mroute_cnt +
3564 sg_hw_mroute_cnt);
3b767e4b
A
3565 }
3566}
58d57120 3567
4e65109c
SG
3568int clear_ip_mroute_count_command(struct vty *vty, const char *name)
3569{
3570 struct listnode *node;
3571 struct channel_oil *c_oil;
3572 struct static_route *sr;
3573 struct vrf *v = pim_cmd_lookup(vty, name);
3574 struct pim_instance *pim;
3575
3576 if (!v)
3577 return CMD_WARNING;
3578
3579 pim = v->info;
3580 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
3581 if (!c_oil->installed)
3582 continue;
3583
3584 pim_mroute_update_counters(c_oil);
3585 c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
3586 c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
3587 c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
3588 }
3589
3590 for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
3591 if (!sr->c_oil.installed)
3592 continue;
3593
3594 pim_mroute_update_counters(&sr->c_oil);
3595
3596 sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
3597 sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
3598 sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
3599 }
3600 return CMD_SUCCESS;
3601}
3602
fe0c6838
SG
3603struct vrf *pim_cmd_lookup(struct vty *vty, const char *name)
3604{
3605 struct vrf *vrf;
3606
3607 if (name)
3608 vrf = vrf_lookup_by_name(name);
3609 else
3610 vrf = vrf_lookup_by_id(VRF_DEFAULT);
3611
3612 if (!vrf)
3613 vty_out(vty, "Specified VRF: %s does not exist\n", name);
3614
3615 return vrf;
3616}
3617
58d57120
SG
3618void clear_mroute(struct pim_instance *pim)
3619{
3620 struct pim_upstream *up;
3621 struct interface *ifp;
3622
3623 /* scan interfaces */
3624 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3625 struct pim_interface *pim_ifp = ifp->info;
3626 struct pim_ifchannel *ch;
3627
3628 if (!pim_ifp)
3629 continue;
3630
3631 /* deleting all ifchannels */
3632 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
3633 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
3634
3635 pim_ifchannel_delete(ch);
3636 }
3637
3638#if PIM_IPV == 4
3639 /* clean up all igmp groups */
3640 struct gm_group *grp;
3641
3642 if (pim_ifp->gm_group_list) {
3643 while (pim_ifp->gm_group_list->count) {
3644 grp = listnode_head(pim_ifp->gm_group_list);
3645 igmp_group_delete(grp);
3646 }
3647 }
3648#endif
3649 }
3650
3651 /* clean up all upstreams*/
3652 while ((up = rb_pim_upstream_first(&pim->upstream_head)))
3653 pim_upstream_del(pim, up, __func__);
3654}
3655
3656void clear_pim_statistics(struct pim_instance *pim)
3657{
3658 struct interface *ifp;
3659
3660 pim->bsm_rcvd = 0;
3661 pim->bsm_sent = 0;
3662 pim->bsm_dropped = 0;
3663
3664 /* scan interfaces */
3665 FOR_ALL_INTERFACES (pim->vrf, ifp) {
3666 struct pim_interface *pim_ifp = ifp->info;
3667
3668 if (!pim_ifp)
3669 continue;
3670
3671 pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
3672 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
3673 pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
3674 }
3675}
bf385e26
SG
3676
3677int pim_debug_pim_cmd(void)
3678{
3679 PIM_DO_DEBUG_PIM_EVENTS;
3680 PIM_DO_DEBUG_PIM_PACKETS;
3681 PIM_DO_DEBUG_PIM_TRACE;
3682 PIM_DO_DEBUG_MSDP_EVENTS;
3683 PIM_DO_DEBUG_MSDP_PACKETS;
3684 PIM_DO_DEBUG_BSM;
3685 PIM_DO_DEBUG_VXLAN;
3686 return CMD_SUCCESS;
3687}
3688
3689int pim_no_debug_pim_cmd(void)
3690{
3691 PIM_DONT_DEBUG_PIM_EVENTS;
3692 PIM_DONT_DEBUG_PIM_PACKETS;
3693 PIM_DONT_DEBUG_PIM_TRACE;
3694 PIM_DONT_DEBUG_MSDP_EVENTS;
3695 PIM_DONT_DEBUG_MSDP_PACKETS;
3696
3697 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
3698 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
3699 return CMD_SUCCESS;
3700}
60940ee2
SG
3701
3702int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
3703 const char *registers, struct vty *vty)
3704{
3705 if (hello) {
3706 PIM_DO_DEBUG_PIM_HELLO;
3707 vty_out(vty, "PIM Hello debugging is on\n");
3708 } else if (joins) {
3709 PIM_DO_DEBUG_PIM_J_P;
3710 vty_out(vty, "PIM Join/Prune debugging is on\n");
3711 } else if (registers) {
3712 PIM_DO_DEBUG_PIM_REG;
3713 vty_out(vty, "PIM Register debugging is on\n");
3714 } else {
3715 PIM_DO_DEBUG_PIM_PACKETS;
3716 vty_out(vty, "PIM Packet debugging is on\n");
3717 }
3718 return CMD_SUCCESS;
3719}
3720
3721int pim_no_debug_pim_packets_cmd(const char *hello, const char *joins,
3722 const char *registers, struct vty *vty)
3723{
3724 if (hello) {
3725 PIM_DONT_DEBUG_PIM_HELLO;
3726 vty_out(vty, "PIM Hello debugging is off\n");
3727 } else if (joins) {
3728 PIM_DONT_DEBUG_PIM_J_P;
3729 vty_out(vty, "PIM Join/Prune debugging is off\n");
3730 } else if (registers) {
3731 PIM_DONT_DEBUG_PIM_REG;
3732 vty_out(vty, "PIM Register debugging is off\n");
3733 } else {
3734 PIM_DONT_DEBUG_PIM_PACKETS;
3735 vty_out(vty, "PIM Packet debugging is off\n");
3736 }
3737
3738 return CMD_SUCCESS;
3739}
6d1bd8c2
A
3740
3741int pim_show_rpf_helper(const char *vrf, struct vty *vty, bool json)
3742{
3743 struct pim_instance *pim;
3744 struct vrf *v;
3745 json_object *json_parent = NULL;
3746
3747 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3748
3749 if (!v)
3750 return CMD_WARNING;
3751
3752 pim = pim_get_pim_instance(v->vrf_id);
3753
3754 if (!pim) {
3755 vty_out(vty, "%% Unable to find pim instance\n");
3756 return CMD_WARNING;
3757 }
3758
3759 if (json)
3760 json_parent = json_object_new_object();
3761
3762 pim_show_rpf(pim, vty, json_parent);
3763
3764 if (json)
3765 vty_json(vty, json_parent);
3766
3767 return CMD_SUCCESS;
3768}
3769
3770int pim_show_rpf_vrf_all_helper(struct vty *vty, bool json)
3771{
3772 struct vrf *vrf;
3773 json_object *json_parent = NULL;
3774 json_object *json_vrf = NULL;
3775
3776 if (json)
3777 json_parent = json_object_new_object();
3778
3779 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3780 if (!json)
3781 vty_out(vty, "VRF: %s\n", vrf->name);
3782 else
3783 json_vrf = json_object_new_object();
3784 pim_show_rpf(vrf->info, vty, json_vrf);
3785 if (json)
3786 json_object_object_add(json_parent, vrf->name,
3787 json_vrf);
3788 }
3789 if (json)
3790 vty_json(vty, json_parent);
3791
3792 return CMD_SUCCESS;
3793}
e21c4e90
A
3794
3795int pim_show_rp_helper(const char *vrf, struct vty *vty, const char *group_str,
3796 const struct prefix *group, bool json)
3797{
3798 struct pim_instance *pim;
3799 struct vrf *v;
3800 json_object *json_parent = NULL;
3801 struct prefix *range = NULL;
3802
3803 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3804
3805 if (!v)
3806 return CMD_WARNING;
3807
3808 pim = pim_get_pim_instance(v->vrf_id);
3809
3810 if (!pim) {
3811 vty_out(vty, "%% Unable to find pim instance\n");
3812 return CMD_WARNING;
3813 }
3814
3815 if (group_str) {
3816 range = prefix_new();
3817 prefix_copy(range, group);
3818 apply_mask(range);
3819 }
3820
3821 if (json)
3822 json_parent = json_object_new_object();
3823
3824 pim_rp_show_information(pim, range, vty, json_parent);
3825
3826 if (json)
3827 vty_json(vty, json_parent);
3828
3829 prefix_free(&range);
3830
3831 return CMD_SUCCESS;
3832}
3833
3834int pim_show_rp_vrf_all_helper(struct vty *vty, const char *group_str,
3835 const struct prefix *group, bool json)
3836{
3837 struct vrf *vrf;
3838 json_object *json_parent = NULL;
3839 json_object *json_vrf = NULL;
3840 struct prefix *range = NULL;
3841
3842 if (group_str) {
3843 range = prefix_new();
3844 prefix_copy(range, group);
3845 apply_mask(range);
3846 }
3847
3848 if (json)
3849 json_parent = json_object_new_object();
3850
3851 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3852 if (!json)
3853 vty_out(vty, "VRF: %s\n", vrf->name);
3854 else
3855 json_vrf = json_object_new_object();
3856 pim_rp_show_information(vrf->info, range, vty, json_vrf);
3857 if (json)
3858 json_object_object_add(json_parent, vrf->name,
3859 json_vrf);
3860 }
3861 if (json)
3862 vty_json(vty, json_parent);
3863
3864 prefix_free(&range);
3865
3866 return CMD_SUCCESS;
3867}
5e52c8d5
A
3868
3869int pim_show_secondary_helper(const char *vrf, struct vty *vty)
3870{
3871 struct pim_instance *pim;
3872 struct vrf *v;
3873
3874 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3875
3876 if (!v)
3877 return CMD_WARNING;
3878
3879 pim = pim_get_pim_instance(v->vrf_id);
3880
3881 if (!pim) {
3882 vty_out(vty, "%% Unable to find pim instance\n");
3883 return CMD_WARNING;
3884 }
3885
3886 pim_show_neighbors_secondary(pim, vty);
3887
3888 return CMD_SUCCESS;
3889}
19296b58
A
3890
3891int pim_show_statistics_helper(const char *vrf, struct vty *vty,
3892 const char *word, bool uj)
3893{
3894 struct pim_instance *pim;
3895 struct vrf *v;
3896
3897 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3898
3899 if (!v)
3900 return CMD_WARNING;
3901
3902 pim = pim_get_pim_instance(v->vrf_id);
3903
3904 if (!pim) {
3905 vty_out(vty, "%% Unable to find pim instance\n");
3906 return CMD_WARNING;
3907 }
3908
3909 if (word)
3910 pim_show_statistics(pim, vty, word, uj);
3911 else
3912 pim_show_statistics(pim, vty, NULL, uj);
3913
3914 return CMD_SUCCESS;
3915}
9aa0569d
A
3916
3917int pim_show_upstream_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
3918 pim_addr g, bool json)
3919{
3920 pim_sgaddr sg = {0};
3921 struct vrf *v;
3922 struct pim_instance *pim;
3923 json_object *json_parent = NULL;
3924
3925 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3926
3927 if (!v) {
3928 vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
3929 return CMD_WARNING;
3930 }
3931 pim = pim_get_pim_instance(v->vrf_id);
3932
3933 if (!pim) {
3934 vty_out(vty, "%% Unable to find pim instance\n");
3935 return CMD_WARNING;
3936 }
3937
3938 if (json)
3939 json_parent = json_object_new_object();
3940
3941 if (!pim_addr_is_any(s_or_g)) {
3942 if (!pim_addr_is_any(g)) {
3943 sg.src = s_or_g;
3944 sg.grp = g;
3945 } else
3946 sg.grp = s_or_g;
3947 }
3948
3949 pim_show_upstream(pim, vty, &sg, json_parent);
3950
3951 if (json)
3952 vty_json(vty, json_parent);
3953
3954 return CMD_SUCCESS;
3955}
3956
3957int pim_show_upstream_vrf_all_helper(struct vty *vty, bool json)
3958{
3959 pim_sgaddr sg = {0};
3960 struct vrf *vrf;
3961 json_object *json_parent = NULL;
3962 json_object *json_vrf = NULL;
3963
3964 if (json)
3965 json_parent = json_object_new_object();
3966
3967 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3968 if (!json)
3969 vty_out(vty, "VRF: %s\n", vrf->name);
3970 else
3971 json_vrf = json_object_new_object();
3972 pim_show_upstream(vrf->info, vty, &sg, json_vrf);
3973 if (json)
3974 json_object_object_add(json_parent, vrf->name,
3975 json_vrf);
3976 }
3977
3978 if (json)
3979 vty_json(vty, json_parent);
3980
3981 return CMD_SUCCESS;
3982}
622da92f
A
3983
3984int pim_show_upstream_join_desired_helper(const char *vrf, struct vty *vty,
3985 bool uj)
3986{
3987 struct pim_instance *pim;
3988 struct vrf *v;
3989
3990 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
3991
3992 if (!v)
3993 return CMD_WARNING;
3994
3995 pim = pim_get_pim_instance(v->vrf_id);
3996
3997 if (!pim) {
3998 vty_out(vty, "%% Unable to find pim instance\n");
3999 return CMD_WARNING;
4000 }
4001
4002 pim_show_join_desired(pim, vty, uj);
4003
4004 return CMD_SUCCESS;
4005}
c6309708
A
4006
4007int pim_show_upstream_rpf_helper(const char *vrf, struct vty *vty, bool uj)
4008{
4009 struct pim_instance *pim;
4010 struct vrf *v;
4011
4012 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4013
4014 if (!v)
4015 return CMD_WARNING;
4016
4017 pim = pim_get_pim_instance(v->vrf_id);
4018
4019 if (!pim) {
4020 vty_out(vty, "%% Unable to find pim instance\n");
4021 return CMD_WARNING;
4022 }
4023
4024 pim_show_upstream_rpf(pim, vty, uj);
4025
4026 return CMD_SUCCESS;
4027}
e7c01c67
A
4028
4029int pim_show_state_helper(const char *vrf, struct vty *vty,
4030 const char *s_or_g_str, const char *g_str, bool json)
4031{
4032 struct pim_instance *pim;
4033 struct vrf *v;
4034 json_object *json_parent = NULL;
4035
4036 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4037
4038 if (!v)
4039 return CMD_WARNING;
4040
4041 pim = pim_get_pim_instance(v->vrf_id);
4042
4043 if (!pim) {
4044 vty_out(vty, "%% Unable to find pim instance\n");
4045 return CMD_WARNING;
4046 }
4047
4048 if (json)
4049 json_parent = json_object_new_object();
4050
4051 pim_show_state(pim, vty, s_or_g_str, g_str, json_parent);
4052
4053 if (json)
4054 vty_json(vty, json_parent);
4055
4056 return CMD_SUCCESS;
4057}
4058
4059int pim_show_state_vrf_all_helper(struct vty *vty, const char *s_or_g_str,
4060 const char *g_str, bool json)
4061{
4062 struct vrf *vrf;
4063 json_object *json_parent = NULL;
4064 json_object *json_vrf = NULL;
4065
4066 if (json)
4067 json_parent = json_object_new_object();
4068
4069 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4070 if (!json)
4071 vty_out(vty, "VRF: %s\n", vrf->name);
4072 else
4073 json_vrf = json_object_new_object();
4074 pim_show_state(vrf->info, vty, s_or_g_str, g_str, json_vrf);
4075 if (json)
4076 json_object_object_add(json_parent, vrf->name,
4077 json_vrf);
4078 }
4079 if (json)
4080 vty_json(vty, json_parent);
4081
4082 return CMD_SUCCESS;
4083}
8e15c9aa
A
4084
4085int pim_show_multicast_helper(const char *vrf, struct vty *vty)
4086{
4087 struct vrf *v;
4088 struct pim_instance *pim;
4089
4090 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4091
4092 if (!v)
4093 return CMD_WARNING;
4094
4095 pim = pim_get_pim_instance(v->vrf_id);
4096
4097 if (!pim) {
4098 vty_out(vty, "%% Unable to find pim instance\n");
4099 return CMD_WARNING;
4100 }
4101
4102 pim_cmd_show_ip_multicast_helper(pim, vty);
4103
4104 return CMD_SUCCESS;
4105}
4106
4107int pim_show_multicast_vrf_all_helper(struct vty *vty)
4108{
4109 struct vrf *vrf;
4110
4111 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4112 vty_out(vty, "VRF: %s\n", vrf->name);
4113 pim_cmd_show_ip_multicast_helper(vrf->info, vty);
4114 }
4115
4116 return CMD_SUCCESS;
4117}
334d2f8c
A
4118
4119int pim_show_multicast_count_helper(const char *vrf, struct vty *vty, bool json)
4120{
4121 struct pim_instance *pim;
4122 struct vrf *v;
4123 json_object *json_parent = NULL;
4124
4125 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4126
4127 if (!v)
4128 return CMD_WARNING;
4129
4130 pim = pim_get_pim_instance(v->vrf_id);
4131
4132 if (!pim) {
4133 vty_out(vty, "%% Unable to find pim instance\n");
4134 return CMD_WARNING;
4135 }
4136
4137 if (json)
4138 json_parent = json_object_new_object();
4139
4140 show_multicast_interfaces(pim, vty, json_parent);
4141
4142 if (json)
4143 vty_json(vty, json_parent);
4144
4145 return CMD_SUCCESS;
4146}
4147
4148int pim_show_multicast_count_vrf_all_helper(struct vty *vty, bool json)
4149{
4150 struct vrf *vrf;
4151 json_object *json_parent = NULL;
4152 json_object *json_vrf = NULL;
4153
4154 if (json)
4155 json_parent = json_object_new_object();
4156
4157 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4158 if (!json)
4159 vty_out(vty, "VRF: %s\n", vrf->name);
4160 else
4161 json_vrf = json_object_new_object();
4162
4163 show_multicast_interfaces(vrf->info, vty, json_vrf);
4164 if (json)
4165 json_object_object_add(json_parent, vrf->name,
4166 json_vrf);
4167 }
4168 if (json)
4169 vty_json(vty, json_parent);
4170
4171 return CMD_SUCCESS;
4172}
4f1f8ff9
A
4173
4174int pim_show_mroute_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
4175 pim_addr g, bool fill, bool json)
4176{
4177 pim_sgaddr sg = {0};
4178 struct pim_instance *pim;
4179 struct vrf *v;
4180 json_object *json_parent = NULL;
4181
4182 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4183
4184 if (!v)
4185 return CMD_WARNING;
4186
4187 pim = pim_get_pim_instance(v->vrf_id);
4188
4189 if (!pim) {
4190 vty_out(vty, "%% Unable to find pim instance\n");
4191 return CMD_WARNING;
4192 }
4193
4194 if (json)
4195 json_parent = json_object_new_object();
4196
4197 if (!pim_addr_is_any(s_or_g)) {
4198 if (!pim_addr_is_any(g)) {
4199 sg.src = s_or_g;
4200 sg.grp = g;
4201 } else
4202 sg.grp = s_or_g;
4203 }
4204
4205 show_mroute(pim, vty, &sg, fill, json_parent);
4206
4207 if (json)
4208 vty_json(vty, json_parent);
4209
4210 return CMD_SUCCESS;
4211}
4212
4213int pim_show_mroute_vrf_all_helper(struct vty *vty, bool fill, bool json)
4214{
4215 pim_sgaddr sg = {0};
4216 struct vrf *vrf;
4217 json_object *json_parent = NULL;
4218 json_object *json_vrf = NULL;
4219
4220 if (json)
4221 json_parent = json_object_new_object();
4222
4223 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4224 if (!json)
4225 vty_out(vty, "VRF: %s\n", vrf->name);
4226 else
4227 json_vrf = json_object_new_object();
4228 show_mroute(vrf->info, vty, &sg, fill, json_vrf);
4229 if (json)
4230 json_object_object_add(json_parent, vrf->name,
4231 json_vrf);
4232 }
4233 if (json)
4234 vty_json(vty, json_parent);
4235
4236 return CMD_SUCCESS;
4237}
1c1077c2
A
4238
4239int pim_show_mroute_count_helper(const char *vrf, struct vty *vty, bool json)
4240{
4241 struct pim_instance *pim;
4242 struct vrf *v;
4243 json_object *json_parent = NULL;
4244
4245 v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4246
4247 if (!v)
4248 return CMD_WARNING;
4249
4250 pim = pim_get_pim_instance(v->vrf_id);
4251
4252 if (!pim) {
4253 vty_out(vty, "%% Unable to find pim instance\n");
4254 return CMD_WARNING;
4255 }
4256
4257 if (json)
4258 json_parent = json_object_new_object();
4259
4260 show_mroute_count(pim, vty, json_parent);
4261
4262 if (json)
4263 vty_json(vty, json_parent);
4264
4265 return CMD_SUCCESS;
4266}
4267
4268int pim_show_mroute_count_vrf_all_helper(struct vty *vty, bool json)
4269{
4270 struct vrf *vrf;
4271 json_object *json_parent = NULL;
4272 json_object *json_vrf = NULL;
4273
4274 if (json)
4275 json_parent = json_object_new_object();
4276
4277 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4278 if (!json)
4279 vty_out(vty, "VRF: %s\n", vrf->name);
4280 else
4281 json_vrf = json_object_new_object();
4282
4283 show_mroute_count(vrf->info, vty, json_vrf);
4284
4285 if (json)
4286 json_object_object_add(json_parent, vrf->name,
4287 json_vrf);
4288 }
4289 if (json)
4290 vty_json(vty, json_parent);
4291
4292 return CMD_SUCCESS;
4293}