]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_cmd_common.c
Merge pull request #11114 from opensourcerouting/vrf-declvar-macros
[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"
37#include "pim_vty.h"
38#include "lib/northbound_cli.h"
39#include "pim_errors.h"
40#include "pim_nb.h"
45e26aa0
A
41#include "pim_mroute.h"
42#include "pim_cmd.h"
43#include "pim6_cmd.h"
44#include "pim_cmd_common.h"
45#include "pim_time.h"
46#include "pim_zebra.h"
47#include "pim_zlookup.h"
48#include "pim_iface.h"
e2b601e8 49#include "pim_macro.h"
45e26aa0 50#include "pim_neighbor.h"
e2b601e8
SG
51#include "pim_nht.h"
52#include "pim_sock.h"
53#include "pim_ssm.h"
24de75a2 54#include "pim_addr.h"
26cd3d66 55
2328b7ef
MR
56/**
57 * Get current node VRF name.
58 *
59 * NOTE:
60 * In case of failure it will print error message to user.
61 *
62 * \returns name or NULL if failed to get VRF.
63 */
64const char *pim_cli_get_vrf_name(struct vty *vty)
65{
66 const struct lyd_node *vrf_node;
67
68 /* Not inside any VRF context. */
69 if (vty->xpath_index == 0)
70 return VRF_DEFAULT_NAME;
71
72 vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
73 if (vrf_node == NULL) {
74 vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
75 return NULL;
76 }
77
78 return yang_dnode_get_string(vrf_node, "./name");
79}
26cd3d66 80
c73113ea
MR
81int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
82{
83 char xpath[XPATH_MAXLEN];
84
85 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
86 FRR_PIM_AF_XPATH_VAL);
87 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
88
89 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
90
91 return nb_cli_apply_changes(vty, NULL);
92}
93
94int pim_process_no_join_prune_cmd(struct vty *vty)
95{
96 char xpath[XPATH_MAXLEN];
97
98 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
99 FRR_PIM_AF_XPATH_VAL);
100 strlcat(xpath, "/join-prune-interval", sizeof(xpath));
101
102 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
103
104 return nb_cli_apply_changes(vty, NULL);
105}
fb991ce9
MR
106
107int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
108{
109 const char *vrfname;
110 char spt_plist_xpath[XPATH_MAXLEN];
111 char spt_action_xpath[XPATH_MAXLEN];
112
113 vrfname = pim_cli_get_vrf_name(vty);
114 if (vrfname == NULL)
115 return CMD_WARNING_CONFIG_FAILED;
116
117 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
118 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
119 FRR_PIM_AF_XPATH_VAL);
120 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
121 sizeof(spt_plist_xpath));
122
123 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
124 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
125 FRR_PIM_AF_XPATH_VAL);
126 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
127 sizeof(spt_action_xpath));
128
129 if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
130 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
131 NULL);
132 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
133 "PIM_SPT_INFINITY");
134
135 return nb_cli_apply_changes(vty, NULL);
136}
137
138int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
139 const char *plist)
140{
141 const char *vrfname;
142 char spt_plist_xpath[XPATH_MAXLEN];
143 char spt_action_xpath[XPATH_MAXLEN];
144
145 vrfname = pim_cli_get_vrf_name(vty);
146 if (vrfname == NULL)
147 return CMD_WARNING_CONFIG_FAILED;
148
149 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
150 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
151 FRR_PIM_AF_XPATH_VAL);
152 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
153 sizeof(spt_plist_xpath));
154
155 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
156 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
157 FRR_PIM_AF_XPATH_VAL);
158 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
159 sizeof(spt_action_xpath));
160
161 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
162 "PIM_SPT_INFINITY");
163 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
164 plist);
165
166 return nb_cli_apply_changes(vty, NULL);
167}
168
169int pim_process_no_spt_switchover_cmd(struct vty *vty)
170{
171 const char *vrfname;
172 char spt_plist_xpath[XPATH_MAXLEN];
173 char spt_action_xpath[XPATH_MAXLEN];
174
175 vrfname = pim_cli_get_vrf_name(vty);
176 if (vrfname == NULL)
177 return CMD_WARNING_CONFIG_FAILED;
178
179 snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
180 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
181 FRR_PIM_AF_XPATH_VAL);
182 strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
183 sizeof(spt_plist_xpath));
184
185 snprintf(spt_action_xpath, sizeof(spt_action_xpath),
186 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
187 FRR_PIM_AF_XPATH_VAL);
188 strlcat(spt_action_xpath, "/spt-switchover/spt-action",
189 sizeof(spt_action_xpath));
190
191 nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
192 nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
193 "PIM_SPT_IMMEDIATE");
194
195 return nb_cli_apply_changes(vty, NULL);
196}
0da72f1f
MR
197
198int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
199{
200 char xpath[XPATH_MAXLEN];
201
202 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
203 FRR_PIM_AF_XPATH_VAL);
204 strlcat(xpath, "/packets", sizeof(xpath));
205
206 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
207
208 return nb_cli_apply_changes(vty, NULL);
209}
210
211int pim_process_no_pim_packet_cmd(struct vty *vty)
212{
213 char xpath[XPATH_MAXLEN];
214
215 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
216 FRR_PIM_AF_XPATH_VAL);
217 strlcat(xpath, "/packets", sizeof(xpath));
218
219 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
220
221 return nb_cli_apply_changes(vty, NULL);
222}
28e32366
MR
223
224int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
225{
226 const char *vrfname;
227 char ka_timer_xpath[XPATH_MAXLEN];
228
229 vrfname = pim_cli_get_vrf_name(vty);
230 if (vrfname == NULL)
231 return CMD_WARNING_CONFIG_FAILED;
232
233 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
234 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
235 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
236
237 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
238 kat);
239
240 return nb_cli_apply_changes(vty, NULL);
241}
242
243int pim_process_no_keepalivetimer_cmd(struct vty *vty)
244{
245 const char *vrfname;
246 char ka_timer_xpath[XPATH_MAXLEN];
247
248 vrfname = pim_cli_get_vrf_name(vty);
249 if (vrfname == NULL)
250 return CMD_WARNING_CONFIG_FAILED;
251
252 snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
253 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
254 strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
255
256 nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
257
258 return nb_cli_apply_changes(vty, NULL);
259}
2322b991
MR
260
261int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
262{
263 const char *vrfname;
264 char rp_ka_timer_xpath[XPATH_MAXLEN];
265
266 vrfname = pim_cli_get_vrf_name(vty);
267 if (vrfname == NULL)
268 return CMD_WARNING_CONFIG_FAILED;
269
270 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
271 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
272 FRR_PIM_AF_XPATH_VAL);
273 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
274 sizeof(rp_ka_timer_xpath));
275
276 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
277 rpkat);
278
279 return nb_cli_apply_changes(vty, NULL);
280}
281
282int pim_process_no_rp_kat_cmd(struct vty *vty)
283{
284 const char *vrfname;
285 char rp_ka_timer[6];
286 char rp_ka_timer_xpath[XPATH_MAXLEN];
287 uint v;
288 char rs_timer_xpath[XPATH_MAXLEN];
289
290 snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
291 FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
292 strlcat(rs_timer_xpath, "/register-suppress-time",
293 sizeof(rs_timer_xpath));
294
295 /* RFC4601 */
296 v = yang_dnode_get_uint16(vty->candidate_config->dnode,
297 rs_timer_xpath);
298 v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
299 if (v > UINT16_MAX)
300 v = UINT16_MAX;
301 snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
302
303 vrfname = pim_cli_get_vrf_name(vty);
304 if (vrfname == NULL)
305 return CMD_WARNING_CONFIG_FAILED;
306
307 snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
308 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
309 FRR_PIM_AF_XPATH_VAL);
310 strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
311 sizeof(rp_ka_timer_xpath));
312
313 nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
314 rp_ka_timer);
315
316 return nb_cli_apply_changes(vty, NULL);
317}
18ca7de5
MR
318
319int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
320{
321 char xpath[XPATH_MAXLEN];
322
323 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
324 FRR_PIM_AF_XPATH_VAL);
325 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
326
327 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
328
329 return nb_cli_apply_changes(vty, NULL);
330}
331
332int pim_process_no_register_suppress_cmd(struct vty *vty)
333{
334 char xpath[XPATH_MAXLEN];
335
336 snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
337 FRR_PIM_AF_XPATH_VAL);
338 strlcat(xpath, "/register-suppress-time", sizeof(xpath));
339
340 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
341
342 return nb_cli_apply_changes(vty, NULL);
343}
a1caf7a8 344
345int pim_process_ip_pim_cmd(struct vty *vty)
346{
347 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
348
349 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
350 FRR_PIM_AF_XPATH_VAL);
351}
352
353int pim_process_no_ip_pim_cmd(struct vty *vty)
354{
355 const struct lyd_node *mld_enable_dnode;
356 char mld_if_xpath[XPATH_MAXLEN];
357
358 int printed =
359 snprintf(mld_if_xpath, sizeof(mld_if_xpath),
360 "%s/frr-gmp:gmp/address-family[address-family='%s']",
361 VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
362
363 if (printed >= (int)(sizeof(mld_if_xpath))) {
364 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
365 XPATH_MAXLEN);
366 return CMD_WARNING_CONFIG_FAILED;
367 }
368
369 mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
370 FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
371 FRR_PIM_AF_XPATH_VAL);
372
373 if (!mld_enable_dnode) {
374 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
375 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
376 } else {
377 if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
378 nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
379 NULL);
380 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
381 } else
382 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
383 "false");
384 }
385
386 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
387 FRR_PIM_AF_XPATH_VAL);
388}
bb387611 389
390int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
391{
392 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
393 drpriority_str);
394
395 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
396 FRR_PIM_AF_XPATH_VAL);
397}
398
399int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
400{
401 nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
402
403 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
404 FRR_PIM_AF_XPATH_VAL);
405}
e6aab613 406
407int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
408 const char *hold_str)
409{
410 const struct lyd_node *mld_enable_dnode;
411
412 mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
413 FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
414 FRR_PIM_AF_XPATH_VAL);
415
416 if (!mld_enable_dnode) {
417 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
418 "true");
419 } else {
420 if (!yang_dnode_get_bool(mld_enable_dnode, "."))
421 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
422 "true");
423 }
424
425 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
426
427 if (hold_str)
428 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
429 hold_str);
430
431 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
432 FRR_PIM_AF_XPATH_VAL);
433}
434
435int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
436{
437 nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
438 nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
439
440 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
441 FRR_PIM_AF_XPATH_VAL);
442}
7e01b641 443
444int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
445{
446 if (no)
447 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
448 "false");
449 else {
450 nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
451 "true");
452
453 nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
454 "true");
455 }
456
457 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
458 FRR_PIM_AF_XPATH_VAL);
459}
52c52d78 460
461int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
462{
463 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
464 oil);
465
466 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
467 FRR_PIM_AF_XPATH_VAL);
468}
469
470int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
471{
472 nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
473 NULL);
474
475 return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
476 FRR_PIM_AF_XPATH_VAL);
477}
63ee25c0 478
479int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
480 const char *group_str, const char *source_str)
481{
482 nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
483
484 if (!source_str) {
485 char buf[SRCDEST2STR_BUFFER];
486
487 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
488 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
489 FRR_PIM_AF_XPATH_VAL, buf,
490 group_str);
491 }
492
493 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
494 FRR_PIM_AF_XPATH_VAL, source_str,
495 group_str);
496}
497
498int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
499 const char *group_str, const char *source_str)
500{
501 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
502
503 if (!source_str) {
504 char buf[SRCDEST2STR_BUFFER];
505
506 inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
507 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
508 FRR_PIM_AF_XPATH_VAL, buf,
509 group_str);
510 }
511
512 return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
513 FRR_PIM_AF_XPATH_VAL, source_str,
514 group_str);
515}
13ddf7cf
MR
516
517int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
518 const char *group_str)
519{
520 const char *vrfname;
521 char rp_group_xpath[XPATH_MAXLEN];
522 int result = 0;
523 struct prefix group;
a96942ca 524 pim_addr rp_addr;
13ddf7cf
MR
525
526 result = str2prefix(group_str, &group);
527 if (result) {
528 struct prefix temp;
529
530 prefix_copy(&temp, &group);
531 apply_mask(&temp);
532 if (!prefix_same(&group, &temp)) {
533 vty_out(vty, "%% Inconsistent address and mask: %s\n",
534 group_str);
535 return CMD_WARNING_CONFIG_FAILED;
536 }
537 }
538
539 if (!result) {
540 vty_out(vty, "%% Bad group address specified: %s\n", group_str);
541 return CMD_WARNING_CONFIG_FAILED;
542 }
543
a96942ca 544 result = inet_pton(PIM_AF, rp_str, &rp_addr);
13ddf7cf
MR
545 if (result <= 0) {
546 vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
547 return CMD_WARNING_CONFIG_FAILED;
548 }
549
550 vrfname = pim_cli_get_vrf_name(vty);
551 if (vrfname == NULL)
552 return CMD_WARNING_CONFIG_FAILED;
553
554 snprintf(rp_group_xpath, sizeof(rp_group_xpath),
a96942ca
MR
555 FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
556 FRR_PIM_AF_XPATH_VAL, rp_str);
13ddf7cf
MR
557 strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
558
559 nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
560
561 return nb_cli_apply_changes(vty, NULL);
562}
563
564int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
565 const char *group_str)
566{
567 char group_list_xpath[XPATH_MAXLEN];
568 char group_xpath[XPATH_MAXLEN];
569 char rp_xpath[XPATH_MAXLEN];
570 int printed;
571 const char *vrfname;
572 const struct lyd_node *group_dnode;
573
574 vrfname = pim_cli_get_vrf_name(vty);
575 if (vrfname == NULL)
576 return CMD_WARNING_CONFIG_FAILED;
577
578 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
a96942ca 579 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
13ddf7cf
MR
580
581 printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
582 "%s/group-list", rp_xpath);
583
584 if (printed >= (int)(sizeof(group_list_xpath))) {
585 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
586 XPATH_MAXLEN);
587 return CMD_WARNING_CONFIG_FAILED;
588 }
589
590 printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
591 group_list_xpath, group_str);
592
593 if (printed >= (int)(sizeof(group_xpath))) {
594 vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
595 XPATH_MAXLEN);
596 return CMD_WARNING_CONFIG_FAILED;
597 }
598
ea5f4c4c
MR
599 group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
600 if (!group_dnode) {
13ddf7cf
MR
601 vty_out(vty, "%% Unable to find specified RP\n");
602 return NB_OK;
603 }
604
13ddf7cf
MR
605 if (yang_is_last_list_dnode(group_dnode))
606 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
607 else
608 nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
609 group_str);
610
611 return nb_cli_apply_changes(vty, NULL);
612}
f39f3497
MR
613
614int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
615 const char *prefix_list)
616{
617 const char *vrfname;
618 char rp_plist_xpath[XPATH_MAXLEN];
619
620 vrfname = pim_cli_get_vrf_name(vty);
621 if (vrfname == NULL)
622 return CMD_WARNING_CONFIG_FAILED;
623
624 snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
625 FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
626 FRR_PIM_AF_XPATH_VAL, rp_str);
627 strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
628
629 nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
630
631 return nb_cli_apply_changes(vty, NULL);
632}
633
634int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
635 const char *prefix_list)
636{
637 char rp_xpath[XPATH_MAXLEN];
638 char plist_xpath[XPATH_MAXLEN];
639 const char *vrfname;
640 const struct lyd_node *plist_dnode;
641 const char *plist;
642
643 vrfname = pim_cli_get_vrf_name(vty);
644 if (vrfname == NULL)
645 return CMD_WARNING_CONFIG_FAILED;
646
647 snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
648 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
649
650 snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
651 "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
652 strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
653
654 plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
655 if (!plist_dnode) {
656 vty_out(vty, "%% Unable to find specified RP\n");
657 return NB_OK;
658 }
659
660 plist = yang_dnode_get_string(plist_dnode, plist_xpath);
661 if (strcmp(prefix_list, plist)) {
662 vty_out(vty, "%% Unable to find specified RP\n");
663 return NB_OK;
664 }
665
666 nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
667
668 return nb_cli_apply_changes(vty, NULL);
669}
45e26aa0 670
95023bd7
A
671bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
672{
673 return (pim_addr_is_any(match.grp) ||
674 !pim_addr_cmp(match.grp, item.grp)) &&
675 (pim_addr_is_any(match.src) ||
676 !pim_addr_cmp(match.src, item.src));
677}
678
e2b601e8
SG
679void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
680{
681 struct pim_interface *pim_ifp;
682
683 pim_ifp = ifp->info;
684 json_object_string_add(json, "name", ifp->name);
685 json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
686 json_object_string_addf(json, "address", "%pPA",
687 &pim_ifp->primary_address);
688 json_object_int_add(json, "index", ifp->ifindex);
689
690 if (if_is_multicast(ifp))
691 json_object_boolean_true_add(json, "flagMulticast");
692
693 if (if_is_broadcast(ifp))
694 json_object_boolean_true_add(json, "flagBroadcast");
695
696 if (ifp->flags & IFF_ALLMULTI)
697 json_object_boolean_true_add(json, "flagAllMulticast");
698
699 if (ifp->flags & IFF_PROMISC)
700 json_object_boolean_true_add(json, "flagPromiscuous");
701
702 if (PIM_IF_IS_DELETED(ifp))
703 json_object_boolean_true_add(json, "flagDeleted");
704
705 if (pim_if_lan_delay_enabled(ifp))
706 json_object_boolean_true_add(json, "lanDelayEnabled");
707}
708
709void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
710{
711 vty_out(vty, "Flags\n");
712 vty_out(vty, "-----\n");
713 vty_out(vty, "All Multicast : %s\n",
714 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
715 vty_out(vty, "Broadcast : %s\n",
716 if_is_broadcast(ifp) ? "yes" : "no");
717 vty_out(vty, "Deleted : %s\n",
718 PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
719 vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
720 vty_out(vty, "Multicast : %s\n",
721 if_is_multicast(ifp) ? "yes" : "no");
722 vty_out(vty, "Promiscuous : %s\n",
723 (ifp->flags & IFF_PROMISC) ? "yes" : "no");
724 vty_out(vty, "\n");
725 vty_out(vty, "\n");
726}
727
45e26aa0
A
728void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
729{
b1a419ba
A
730 json_object_boolean_add(
731 json, "drJoinDesired",
732 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED));
733 json_object_boolean_add(
734 json, "drJoinDesiredUpdated",
735 CHECK_FLAG(up->flags,
736 PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED));
737 json_object_boolean_add(
738 json, "firstHopRouter",
739 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR));
740 json_object_boolean_add(
741 json, "sourceIgmp",
742 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP));
743 json_object_boolean_add(
744 json, "sourcePim",
745 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM));
746 json_object_boolean_add(
747 json, "sourceStream",
748 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM));
45e26aa0 749 /* XXX: need to print ths flag in the plain text display as well */
b1a419ba
A
750 json_object_boolean_add(
751 json, "sourceMsdp",
752 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP));
753 json_object_boolean_add(
754 json, "sendSGRptPrune",
755 CHECK_FLAG(up->flags,
756 PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE));
757 json_object_boolean_add(
758 json, "lastHopRouter",
759 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR));
760 json_object_boolean_add(
761 json, "disableKATExpiry",
762 CHECK_FLAG(up->flags,
763 PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY));
764 json_object_boolean_add(
765 json, "staticIncomingInterface",
766 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF));
767 json_object_boolean_add(
768 json, "allowIncomingInterfaceinOil",
769 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL));
770 json_object_boolean_add(
771 json, "noPimRegistrationData",
772 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA));
773 json_object_boolean_add(
774 json, "forcePimRegistration",
775 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG));
776 json_object_boolean_add(
777 json, "sourceVxlanOrigination",
778 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG));
779 json_object_boolean_add(
780 json, "sourceVxlanTermination",
781 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM));
782 json_object_boolean_add(
783 json, "mlagVxlan",
784 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN));
785 json_object_boolean_add(
786 json, "mlagNonDesignatedForwarder",
787 CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF));
45e26aa0
A
788}
789
790static const char *
791pim_upstream_state2brief_str(enum pim_upstream_state join_state,
792 char *state_str, size_t state_str_len)
793{
794 switch (join_state) {
795 case PIM_UPSTREAM_NOTJOINED:
796 strlcpy(state_str, "NotJ", state_str_len);
797 break;
798 case PIM_UPSTREAM_JOINED:
799 strlcpy(state_str, "J", state_str_len);
800 break;
801 default:
802 strlcpy(state_str, "Unk", state_str_len);
803 }
804 return state_str;
805}
806
807static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
808 char *state_str,
809 size_t state_str_len)
810{
811 switch (reg_state) {
812 case PIM_REG_NOINFO:
813 strlcpy(state_str, "RegNI", state_str_len);
814 break;
815 case PIM_REG_JOIN:
816 strlcpy(state_str, "RegJ", state_str_len);
817 break;
818 case PIM_REG_JOIN_PENDING:
819 case PIM_REG_PRUNE:
820 strlcpy(state_str, "RegP", state_str_len);
821 break;
822 }
823 return state_str;
824}
825
1aa8de46
A
826void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
827 time_t now, json_object *json)
45e26aa0
A
828{
829 char refresh_uptime[10];
830
831 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
832 pim->rpf_cache_refresh_last);
833
834 if (json) {
835 json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
836 router->rpf_cache_refresh_delay_msec);
837 json_object_int_add(
838 json, "rpfCacheRefreshTimer",
839 pim_time_timer_remain_msec(pim->rpf_cache_refresher));
840 json_object_int_add(json, "rpfCacheRefreshRequests",
841 pim->rpf_cache_refresh_requests);
842 json_object_int_add(json, "rpfCacheRefreshEvents",
843 pim->rpf_cache_refresh_events);
844 json_object_string_add(json, "rpfCacheRefreshLast",
845 refresh_uptime);
846 json_object_int_add(json, "nexthopLookups",
847 pim->nexthop_lookups);
848 json_object_int_add(json, "nexthopLookupsAvoided",
849 pim->nexthop_lookups_avoided);
850 } else {
851 vty_out(vty,
852 "RPF Cache Refresh Delay: %ld msecs\n"
853 "RPF Cache Refresh Timer: %ld msecs\n"
854 "RPF Cache Refresh Requests: %lld\n"
855 "RPF Cache Refresh Events: %lld\n"
856 "RPF Cache Refresh Last: %s\n"
857 "Nexthop Lookups: %lld\n"
858 "Nexthop Lookups Avoided: %lld\n",
859 router->rpf_cache_refresh_delay_msec,
860 pim_time_timer_remain_msec(pim->rpf_cache_refresher),
861 (long long)pim->rpf_cache_refresh_requests,
862 (long long)pim->rpf_cache_refresh_events,
863 refresh_uptime, (long long)pim->nexthop_lookups,
864 (long long)pim->nexthop_lookups_avoided);
865 }
866}
867
1aa8de46 868void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
45e26aa0
A
869{
870 struct pim_upstream *up;
871 time_t now = pim_time_monotonic_sec();
45e26aa0
A
872 json_object *json_group = NULL;
873 json_object *json_row = NULL;
874
1aa8de46
A
875 pim_show_rpf_refresh_stats(vty, pim, now, json);
876
877 if (!json) {
45e26aa0
A
878 vty_out(vty, "\n");
879 vty_out(vty,
880 "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
881 }
882
883 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
884 char rpf_addr_str[PREFIX_STRLEN];
45e26aa0
A
885 const char *rpf_ifname;
886 struct pim_rpf *rpf = &up->rpf;
887
888 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
889 sizeof(rpf_addr_str));
45e26aa0 890
1aa8de46
A
891 rpf_ifname =
892 rpf->source_nexthop.interface ? rpf->source_nexthop
893 .interface->name
894 : "<ifname?>";
45e26aa0 895
1aa8de46 896 if (json) {
45e26aa0
A
897 char grp_str[PIM_ADDRSTRLEN];
898 char src_str[PIM_ADDRSTRLEN];
899
900 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
901 &up->sg.grp);
902 snprintfrr(src_str, sizeof(src_str), "%pPAs",
903 &up->sg.src);
904
905 json_object_object_get_ex(json, grp_str, &json_group);
906
907 if (!json_group) {
908 json_group = json_object_new_object();
909 json_object_object_add(json, grp_str,
910 json_group);
911 }
912
913 json_row = json_object_new_object();
914 json_object_string_add(json_row, "source", src_str);
915 json_object_string_add(json_row, "group", grp_str);
916 json_object_string_add(json_row, "rpfInterface",
917 rpf_ifname);
918 json_object_string_add(json_row, "rpfAddress",
919 rpf_addr_str);
641ac7c7 920 json_object_string_addf(
921 json_row, "ribNexthop", "%pPAs",
922 &rpf->source_nexthop.mrib_nexthop_addr);
45e26aa0
A
923 json_object_int_add(
924 json_row, "routeMetric",
925 rpf->source_nexthop.mrib_route_metric);
926 json_object_int_add(
927 json_row, "routePreference",
928 rpf->source_nexthop.mrib_metric_preference);
929 json_object_object_add(json_group, src_str, json_row);
930
931 } else {
1aa8de46 932 vty_out(vty,
641ac7c7 933 "%-15pPAs %-15pPAs %-16s %-15s %-15pPAs %6d %4d\n",
45e26aa0 934 &up->sg.src, &up->sg.grp, rpf_ifname,
641ac7c7 935 rpf_addr_str,
936 &rpf->source_nexthop.mrib_nexthop_addr,
45e26aa0
A
937 rpf->source_nexthop.mrib_route_metric,
938 rpf->source_nexthop.mrib_metric_preference);
939 }
940 }
45e26aa0
A
941}
942
943void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
944{
945 struct interface *ifp;
946
947 vty_out(vty,
948 "Interface Address Neighbor Secondary \n");
949
950 FOR_ALL_INTERFACES (pim->vrf, ifp) {
951 struct pim_interface *pim_ifp;
626dab7f 952 pim_addr ifaddr;
45e26aa0
A
953 struct listnode *neighnode;
954 struct pim_neighbor *neigh;
45e26aa0
A
955
956 pim_ifp = ifp->info;
957
958 if (!pim_ifp)
959 continue;
960
961 if (pim_ifp->pim_sock_fd < 0)
962 continue;
963
964 ifaddr = pim_ifp->primary_address;
965
966 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
967 neigh)) {
45e26aa0
A
968 struct listnode *prefix_node;
969 struct prefix *p;
970
971 if (!neigh->prefix_list)
972 continue;
973
45e26aa0
A
974 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
975 prefix_node, p))
626dab7f
A
976 vty_out(vty,
977 "%-16s %-15pPAs %-15pPAs %-15pFX\n",
978 ifp->name, &ifaddr, &neigh->source_addr,
979 p);
45e26aa0
A
980 }
981 }
982}
983
984void pim_show_state(struct pim_instance *pim, struct vty *vty,
2d85c671
A
985 const char *src_or_group, const char *group,
986 json_object *json)
45e26aa0
A
987{
988 struct channel_oil *c_oil;
45e26aa0
A
989 json_object *json_group = NULL;
990 json_object *json_ifp_in = NULL;
991 json_object *json_ifp_out = NULL;
992 json_object *json_source = NULL;
993 time_t now;
994 int first_oif;
995
996 now = pim_time_monotonic_sec();
997
2d85c671 998 if (!json) {
45e26aa0
A
999 vty_out(vty,
1000 "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
1001 vty_out(vty,
1002 "\nActive Source Group RPT IIF OIL\n");
1003 }
1004
1005 frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
2d85c671
A
1006 char src_str[PIM_ADDRSTRLEN];
1007 char grp_str[PIM_ADDRSTRLEN];
45e26aa0
A
1008 char in_ifname[INTERFACE_NAMSIZ + 1];
1009 char out_ifname[INTERFACE_NAMSIZ + 1];
1010 int oif_vif_index;
1011 struct interface *ifp_in;
1012 bool isRpt;
1013
1014 first_oif = 1;
1015
1016 if ((c_oil->up &&
1017 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
2d85c671 1018 pim_addr_is_any(*oil_origin(c_oil)))
45e26aa0
A
1019 isRpt = true;
1020 else
1021 isRpt = false;
1022
2d85c671
A
1023 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1024 oil_mcastgrp(c_oil));
1025 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1026 oil_origin(c_oil));
1027 ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
45e26aa0
A
1028
1029 if (ifp_in)
1030 strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
1031 else
1032 strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
1033
1034 if (src_or_group) {
1035 if (strcmp(src_or_group, src_str) &&
1036 strcmp(src_or_group, grp_str))
1037 continue;
1038
1039 if (group && strcmp(group, grp_str))
1040 continue;
1041 }
1042
2d85c671 1043 if (json) {
45e26aa0
A
1044
1045 /* Find the group, create it if it doesn't exist */
1046 json_object_object_get_ex(json, grp_str, &json_group);
1047
1048 if (!json_group) {
1049 json_group = json_object_new_object();
1050 json_object_object_add(json, grp_str,
1051 json_group);
1052 }
1053
1054 /* Find the source nested under the group, create it if
1055 * it doesn't exist
1056 */
1057 json_object_object_get_ex(json_group, src_str,
1058 &json_source);
1059
1060 if (!json_source) {
1061 json_source = json_object_new_object();
1062 json_object_object_add(json_group, src_str,
1063 json_source);
1064 }
1065
1066 /* Find the inbound interface nested under the source,
1067 * create it if it doesn't exist
1068 */
1069 json_object_object_get_ex(json_source, in_ifname,
1070 &json_ifp_in);
1071
1072 if (!json_ifp_in) {
1073 json_ifp_in = json_object_new_object();
1074 json_object_object_add(json_source, in_ifname,
1075 json_ifp_in);
1076 json_object_int_add(json_source, "Installed",
1077 c_oil->installed);
1078 json_object_int_add(json_source, "installed",
1079 c_oil->installed);
2d85c671
A
1080 json_object_boolean_add(json_source, "isRpt",
1081 isRpt);
45e26aa0
A
1082 json_object_int_add(json_source, "RefCount",
1083 c_oil->oil_ref_count);
1084 json_object_int_add(json_source, "refCount",
1085 c_oil->oil_ref_count);
1086 json_object_int_add(json_source, "OilListSize",
1087 c_oil->oil_size);
1088 json_object_int_add(json_source, "oilListSize",
1089 c_oil->oil_size);
1090 json_object_int_add(
1091 json_source, "OilRescan",
1092 c_oil->oil_inherited_rescan);
1093 json_object_int_add(
1094 json_source, "oilRescan",
1095 c_oil->oil_inherited_rescan);
1096 json_object_int_add(json_source, "LastUsed",
1097 c_oil->cc.lastused);
1098 json_object_int_add(json_source, "lastUsed",
1099 c_oil->cc.lastused);
1100 json_object_int_add(json_source, "PacketCount",
1101 c_oil->cc.pktcnt);
1102 json_object_int_add(json_source, "packetCount",
1103 c_oil->cc.pktcnt);
1104 json_object_int_add(json_source, "ByteCount",
1105 c_oil->cc.bytecnt);
1106 json_object_int_add(json_source, "byteCount",
1107 c_oil->cc.bytecnt);
1108 json_object_int_add(json_source,
1109 "WrongInterface",
1110 c_oil->cc.wrong_if);
1111 json_object_int_add(json_source,
1112 "wrongInterface",
1113 c_oil->cc.wrong_if);
1114 }
2d85c671
A
1115 } else
1116 vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1117 c_oil->installed, oil_origin(c_oil),
1118 oil_mcastgrp(c_oil), isRpt ? "y" : "n",
1119 in_ifname);
45e26aa0
A
1120
1121 for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
1122 ++oif_vif_index) {
1123 struct interface *ifp_out;
1124 char oif_uptime[10];
1125 int ttl;
1126
2d85c671 1127 ttl = oil_if_has(c_oil, oif_vif_index);
45e26aa0
A
1128 if (ttl < 1)
1129 continue;
1130
1131 ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
1132 pim_time_uptime(
1133 oif_uptime, sizeof(oif_uptime),
1134 now - c_oil->oif_creation[oif_vif_index]);
1135
1136 if (ifp_out)
1137 strlcpy(out_ifname, ifp_out->name,
1138 sizeof(out_ifname));
1139 else
1140 strlcpy(out_ifname, "<oif?>",
1141 sizeof(out_ifname));
1142
2d85c671 1143 if (json) {
45e26aa0
A
1144 json_ifp_out = json_object_new_object();
1145 json_object_string_add(json_ifp_out, "source",
1146 src_str);
1147 json_object_string_add(json_ifp_out, "group",
1148 grp_str);
1149 json_object_string_add(json_ifp_out,
1150 "inboundInterface",
1151 in_ifname);
1152 json_object_string_add(json_ifp_out,
1153 "outboundInterface",
1154 out_ifname);
1155 json_object_int_add(json_ifp_out, "installed",
1156 c_oil->installed);
1157
1158 json_object_object_add(json_ifp_in, out_ifname,
1159 json_ifp_out);
1160 } else {
1161 if (first_oif) {
1162 first_oif = 0;
1163 vty_out(vty, "%s(%c%c%c%c%c)",
1164 out_ifname,
1165 (c_oil->oif_flags
1166 [oif_vif_index] &
80a82b56 1167 PIM_OIF_FLAG_PROTO_GM)
45e26aa0
A
1168 ? 'I'
1169 : ' ',
1170 (c_oil->oif_flags
1171 [oif_vif_index] &
1172 PIM_OIF_FLAG_PROTO_PIM)
1173 ? 'J'
1174 : ' ',
1175 (c_oil->oif_flags
1176 [oif_vif_index] &
1177 PIM_OIF_FLAG_PROTO_VXLAN)
1178 ? 'V'
1179 : ' ',
1180 (c_oil->oif_flags
1181 [oif_vif_index] &
1182 PIM_OIF_FLAG_PROTO_STAR)
1183 ? '*'
1184 : ' ',
1185 (c_oil->oif_flags
1186 [oif_vif_index] &
1187 PIM_OIF_FLAG_MUTE)
1188 ? 'M'
1189 : ' ');
1190 } else
1191 vty_out(vty, ", %s(%c%c%c%c%c)",
1192 out_ifname,
1193 (c_oil->oif_flags
1194 [oif_vif_index] &
80a82b56 1195 PIM_OIF_FLAG_PROTO_GM)
45e26aa0
A
1196 ? 'I'
1197 : ' ',
1198 (c_oil->oif_flags
1199 [oif_vif_index] &
1200 PIM_OIF_FLAG_PROTO_PIM)
1201 ? 'J'
1202 : ' ',
1203 (c_oil->oif_flags
1204 [oif_vif_index] &
1205 PIM_OIF_FLAG_PROTO_VXLAN)
1206 ? 'V'
1207 : ' ',
1208 (c_oil->oif_flags
1209 [oif_vif_index] &
1210 PIM_OIF_FLAG_PROTO_STAR)
1211 ? '*'
1212 : ' ',
1213 (c_oil->oif_flags
1214 [oif_vif_index] &
1215 PIM_OIF_FLAG_MUTE)
1216 ? 'M'
1217 : ' ');
1218 }
1219 }
1220
2d85c671 1221 if (!json)
45e26aa0
A
1222 vty_out(vty, "\n");
1223 }
1224
2d85c671 1225 if (!json)
45e26aa0
A
1226 vty_out(vty, "\n");
1227}
1228
1229/* pim statistics - just adding only bsm related now.
1230 * We can continue to add all pim related stats here.
1231 */
1232void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
1233 const char *ifname, bool uj)
1234{
1235 json_object *json = NULL;
1236 struct interface *ifp;
1237
1238 if (uj) {
1239 json = json_object_new_object();
1240 json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
1241 json_object_int_add(json, "bsmTx", pim->bsm_sent);
1242 json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
1243 } else {
1244 vty_out(vty, "BSM Statistics :\n");
1245 vty_out(vty, "----------------\n");
1246 vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
1247 pim->bsm_rcvd);
1248 vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
1249 pim->bsm_sent);
1250 vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n",
1251 pim->bsm_dropped);
1252 }
1253
1254 vty_out(vty, "\n");
1255
1256 /* scan interfaces */
1257 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1258 struct pim_interface *pim_ifp = ifp->info;
1259
1260 if (ifname && strcmp(ifname, ifp->name))
1261 continue;
1262
1263 if (!pim_ifp)
1264 continue;
1265
1266 if (!uj) {
1267 vty_out(vty, "Interface : %s\n", ifp->name);
1268 vty_out(vty, "-------------------\n");
1269 vty_out(vty,
1270 "Number of BSMs dropped due to config miss : %u\n",
1271 pim_ifp->pim_ifstat_bsm_cfg_miss);
1272 vty_out(vty, "Number of unicast BSMs dropped : %u\n",
1273 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1274 vty_out(vty,
1275 "Number of BSMs dropped due to invalid scope zone : %u\n",
1276 pim_ifp->pim_ifstat_bsm_invalid_sz);
1277 } else {
1278
1279 json_object *json_row = NULL;
1280
1281 json_row = json_object_new_object();
1282
1283 json_object_string_add(json_row, "If Name", ifp->name);
1284 json_object_int_add(json_row, "bsmDroppedConfig",
1285 pim_ifp->pim_ifstat_bsm_cfg_miss);
1286 json_object_int_add(
1287 json_row, "bsmDroppedUnicast",
1288 pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1289 json_object_int_add(json_row,
1290 "bsmDroppedInvalidScopeZone",
1291 pim_ifp->pim_ifstat_bsm_invalid_sz);
1292 json_object_object_add(json, ifp->name, json_row);
1293 }
1294 vty_out(vty, "\n");
1295 }
1296
1297 if (uj)
1298 vty_json(vty, json);
1299}
1300
1301void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
95023bd7 1302 pim_sgaddr *sg, json_object *json)
45e26aa0
A
1303{
1304 struct pim_upstream *up;
1305 time_t now;
45e26aa0
A
1306 json_object *json_group = NULL;
1307 json_object *json_row = NULL;
1308
1309 now = pim_time_monotonic_sec();
1310
95023bd7 1311 if (!json)
45e26aa0
A
1312 vty_out(vty,
1313 "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
1314
1315 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
45e26aa0
A
1316 char uptime[10];
1317 char join_timer[10];
1318 char rs_timer[10];
1319 char ka_timer[10];
1320 char msdp_reg_timer[10];
1321 char state_str[PIM_REG_STATE_STR_LEN];
1322
95023bd7 1323 if (!pim_sgaddr_match(up->sg, *sg))
45e26aa0
A
1324 continue;
1325
45e26aa0
A
1326 pim_time_uptime(uptime, sizeof(uptime),
1327 now - up->state_transition);
1328 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
1329 up->t_join_timer);
1330
1331 /*
1332 * If the upstream is not dummy and it has a J/P timer for the
1333 * neighbor display that
1334 */
1335 if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
1336 struct pim_neighbor *nbr;
1337
95023bd7 1338 nbr = pim_neighbor_find_prefix(
45e26aa0 1339 up->rpf.source_nexthop.interface,
95023bd7 1340 &up->rpf.rpf_addr);
45e26aa0
A
1341 if (nbr)
1342 pim_time_timer_to_hhmmss(join_timer,
1343 sizeof(join_timer),
1344 nbr->jp_timer);
1345 }
1346
1347 pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
1348 up->t_rs_timer);
1349 pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
1350 up->t_ka_timer);
1351 pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
1352 up->t_msdp_reg_timer);
1353
1354 pim_upstream_state2brief_str(up->join_state, state_str,
1355 sizeof(state_str));
1356 if (up->reg_state != PIM_REG_NOINFO) {
1357 char tmp_str[PIM_REG_STATE_STR_LEN];
1358 char tmp[sizeof(state_str) + 1];
1359
1360 snprintf(tmp, sizeof(tmp), ",%s",
1361 pim_reg_state2brief_str(up->reg_state, tmp_str,
1362 sizeof(tmp_str)));
1363 strlcat(state_str, tmp, sizeof(state_str));
1364 }
1365
95023bd7
A
1366 if (json) {
1367 char grp_str[PIM_ADDRSTRLEN];
1368 char src_str[PIM_ADDRSTRLEN];
1369
1370 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1371 &up->sg.grp);
1372 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1373 &up->sg.src);
1374
45e26aa0
A
1375 json_object_object_get_ex(json, grp_str, &json_group);
1376
1377 if (!json_group) {
1378 json_group = json_object_new_object();
1379 json_object_object_add(json, grp_str,
1380 json_group);
1381 }
1382
1383 json_row = json_object_new_object();
1384 json_object_pim_upstream_add(json_row, up);
1385 json_object_string_add(
1386 json_row, "inboundInterface",
1387 up->rpf.source_nexthop.interface
1388 ? up->rpf.source_nexthop.interface->name
1389 : "Unknown");
1390
1391 /*
1392 * The RPF address we use is slightly different
1393 * based upon what we are looking up.
1394 * If we have a S, list that unless
1395 * we are the FHR, else we just put
1396 * the RP as the rpfAddress
1397 */
1398 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
95023bd7 1399 pim_addr_is_any(up->sg.src)) {
45e26aa0
A
1400 struct pim_rpf *rpg;
1401
1402 rpg = RP(pim, up->sg.grp);
95023bd7
A
1403 json_object_string_addf(json_row, "rpfAddress",
1404 "%pFX", &rpg->rpf_addr);
45e26aa0
A
1405 } else {
1406 json_object_string_add(json_row, "rpfAddress",
1407 src_str);
1408 }
1409
1410 json_object_string_add(json_row, "source", src_str);
1411 json_object_string_add(json_row, "group", grp_str);
1412 json_object_string_add(json_row, "state", state_str);
1413 json_object_string_add(
1414 json_row, "joinState",
1415 pim_upstream_state2str(up->join_state));
1416 json_object_string_add(
1417 json_row, "regState",
1418 pim_reg_state2str(up->reg_state, state_str,
1419 sizeof(state_str)));
1420 json_object_string_add(json_row, "upTime", uptime);
1421 json_object_string_add(json_row, "joinTimer",
1422 join_timer);
1423 json_object_string_add(json_row, "resetTimer",
1424 rs_timer);
1425 json_object_string_add(json_row, "keepaliveTimer",
1426 ka_timer);
1427 json_object_string_add(json_row, "msdpRegTimer",
1428 msdp_reg_timer);
1429 json_object_int_add(json_row, "refCount",
1430 up->ref_count);
1431 json_object_int_add(json_row, "sptBit", up->sptbit);
1432 json_object_object_add(json_group, src_str, json_row);
1433 } else {
1434 vty_out(vty,
95023bd7 1435 "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n",
45e26aa0
A
1436 up->rpf.source_nexthop.interface
1437 ? up->rpf.source_nexthop.interface->name
1438 : "Unknown",
95023bd7
A
1439 &up->sg.src, &up->sg.grp, state_str, uptime,
1440 join_timer, rs_timer, ka_timer, up->ref_count);
45e26aa0
A
1441 }
1442 }
45e26aa0
A
1443}
1444
1445static void pim_show_join_desired_helper(struct pim_instance *pim,
1446 struct vty *vty,
1447 struct pim_upstream *up,
1448 json_object *json, bool uj)
1449{
1450 json_object *json_group = NULL;
45e26aa0
A
1451 json_object *json_row = NULL;
1452
45e26aa0 1453 if (uj) {
e577f6e7
A
1454 char grp_str[PIM_ADDRSTRLEN];
1455 char src_str[PIM_ADDRSTRLEN];
1456
1457 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
1458 snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
1459
45e26aa0
A
1460 json_object_object_get_ex(json, grp_str, &json_group);
1461
1462 if (!json_group) {
1463 json_group = json_object_new_object();
1464 json_object_object_add(json, grp_str, json_group);
1465 }
1466
1467 json_row = json_object_new_object();
1468 json_object_pim_upstream_add(json_row, up);
1469 json_object_string_add(json_row, "source", src_str);
1470 json_object_string_add(json_row, "group", grp_str);
1471
1472 if (pim_upstream_evaluate_join_desired(pim, up))
1473 json_object_boolean_true_add(json_row,
1474 "evaluateJoinDesired");
1475
1476 json_object_object_add(json_group, src_str, json_row);
1477
1478 } else {
e577f6e7
A
1479 vty_out(vty, "%-15pPAs %-15pPAs %-6s\n", &up->sg.src,
1480 &up->sg.grp,
45e26aa0
A
1481 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
1482 : "no");
1483 }
1484}
1485
1486void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
1487{
1488 struct pim_upstream *up;
1489
1490 json_object *json = NULL;
1491
1492 if (uj)
1493 json = json_object_new_object();
1494 else
1495 vty_out(vty, "Source Group EvalJD\n");
1496
1497 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1498 /* scan all interfaces */
1499 pim_show_join_desired_helper(pim, vty, up, json, uj);
1500 }
1501
1502 if (uj)
1503 vty_json(vty, json);
1504}
1505
1506void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
1507{
1508 struct pim_upstream *up;
1509 json_object *json = NULL;
1510 json_object *json_group = NULL;
1511 json_object *json_row = NULL;
1512
1513 if (uj)
1514 json = json_object_new_object();
1515 else
1516 vty_out(vty,
1517 "Source Group RpfIface RibNextHop RpfAddress \n");
1518
1519 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
45e26aa0
A
1520 char rpf_addr_str[PREFIX_STRLEN];
1521 struct pim_rpf *rpf;
1522 const char *rpf_ifname;
1523
1524 rpf = &up->rpf;
1525
45e26aa0
A
1526 pim_addr_dump("<rpf?>", &rpf->rpf_addr, rpf_addr_str,
1527 sizeof(rpf_addr_str));
1528
1529 rpf_ifname =
1530 rpf->source_nexthop.interface ? rpf->source_nexthop
1531 .interface->name
1532 : "<ifname?>";
1533
1534 if (uj) {
b1a419ba
A
1535 char grp_str[PIM_ADDRSTRLEN];
1536 char src_str[PIM_ADDRSTRLEN];
1537
1538 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1539 &up->sg.grp);
1540 snprintfrr(src_str, sizeof(src_str), "%pPAs",
1541 &up->sg.src);
45e26aa0
A
1542 json_object_object_get_ex(json, grp_str, &json_group);
1543
1544 if (!json_group) {
1545 json_group = json_object_new_object();
1546 json_object_object_add(json, grp_str,
1547 json_group);
1548 }
1549
1550 json_row = json_object_new_object();
1551 json_object_pim_upstream_add(json_row, up);
1552 json_object_string_add(json_row, "source", src_str);
1553 json_object_string_add(json_row, "group", grp_str);
1554 json_object_string_add(json_row, "rpfInterface",
1555 rpf_ifname);
641ac7c7 1556 json_object_string_addf(
1557 json_row, "ribNexthop", "%pPAs",
1558 &rpf->source_nexthop.mrib_nexthop_addr);
45e26aa0
A
1559 json_object_string_add(json_row, "rpfAddress",
1560 rpf_addr_str);
1561 json_object_object_add(json_group, src_str, json_row);
1562 } else {
641ac7c7 1563 vty_out(vty, "%-15pPAs %-15pPAs %-16s %-15pPA %-15s\n",
b1a419ba 1564 &up->sg.src, &up->sg.grp, rpf_ifname,
641ac7c7 1565 &rpf->source_nexthop.mrib_nexthop_addr,
1566 rpf_addr_str);
45e26aa0
A
1567 }
1568 }
1569
1570 if (uj)
1571 vty_json(vty, json);
1572}
e2b601e8
SG
1573
1574static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
1575 struct pim_ifchannel *ch, json_object *json,
24de75a2 1576 time_t now)
e2b601e8
SG
1577{
1578 json_object *json_iface = NULL;
1579 json_object *json_row = NULL;
1580 json_object *json_grp = NULL;
1581 pim_addr ifaddr;
1582 char uptime[10];
1583 char expire[10];
1584 char prune[10];
e2b601e8
SG
1585
1586 ifaddr = pim_ifp->primary_address;
1587
1588 pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1589 pim_time_timer_to_mmss(expire, sizeof(expire),
1590 ch->t_ifjoin_expiry_timer);
1591 pim_time_timer_to_mmss(prune, sizeof(prune),
1592 ch->t_ifjoin_prune_pending_timer);
1593
24de75a2 1594 if (json) {
e2b601e8 1595 char ch_grp_str[PIM_ADDRSTRLEN];
e2b601e8
SG
1596
1597 json_object_object_get_ex(json, ch->interface->name,
1598 &json_iface);
1599
1600 if (!json_iface) {
1601 json_iface = json_object_new_object();
1602 json_object_pim_ifp_add(json_iface, ch->interface);
1603 json_object_object_add(json, ch->interface->name,
1604 json_iface);
1605 }
1606
1607 json_row = json_object_new_object();
24de75a2
SG
1608 json_object_string_addf(json_row, "source", "%pPAs",
1609 &ch->sg.src);
1610 json_object_string_addf(json_row, "group", "%pPAs",
1611 &ch->sg.grp);
e2b601e8
SG
1612 json_object_string_add(json_row, "upTime", uptime);
1613 json_object_string_add(json_row, "expire", expire);
1614 json_object_string_add(json_row, "prune", prune);
1615 json_object_string_add(
1616 json_row, "channelJoinName",
1617 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
1618 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) {
1619#if CONFDATE > 20230131
1620 CPP_NOTICE(
1621 "Remove JSON object commands with keys starting with capital")
1622#endif
1623 json_object_int_add(json_row, "SGRpt", 1);
1624 json_object_int_add(json_row, "sgRpt", 1);
1625 }
1626 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
1627 json_object_int_add(json_row, "protocolPim", 1);
1628 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
1629 json_object_int_add(json_row, "protocolIgmp", 1);
24de75a2
SG
1630 snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
1631 &ch->sg.grp);
e2b601e8
SG
1632 json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
1633 if (!json_grp) {
1634 json_grp = json_object_new_object();
24de75a2
SG
1635 json_object_object_addf(json_grp, json_row, "%pPAs",
1636 &ch->sg.src);
1637 json_object_object_addf(json_iface, json_grp, "%pPAs",
1638 &ch->sg.grp);
e2b601e8 1639 } else
24de75a2
SG
1640 json_object_object_addf(json_grp, json_row, "%pPAs",
1641 &ch->sg.src);
e2b601e8 1642 } else {
24de75a2
SG
1643 vty_out(vty,
1644 "%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
1645 ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
e2b601e8
SG
1646 pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
1647 uptime, expire, prune);
1648 }
1649}
1650
24de75a2
SG
1651void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
1652 json_object *json)
e2b601e8
SG
1653{
1654 struct pim_interface *pim_ifp;
1655 struct pim_ifchannel *ch;
1656 struct interface *ifp;
1657 time_t now;
e2b601e8
SG
1658
1659 now = pim_time_monotonic_sec();
1660
24de75a2 1661 if (!json)
e2b601e8
SG
1662 vty_out(vty,
1663 "Interface Address Source Group State Uptime Expire Prune\n");
1664
1665 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1666 pim_ifp = ifp->info;
1667 if (!pim_ifp)
1668 continue;
1669
1670 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1671 if (!pim_sgaddr_match(ch->sg, *sg))
1672 continue;
24de75a2
SG
1673
1674 pim_show_join_helper(vty, pim_ifp, ch, json, now);
e2b601e8
SG
1675 } /* scan interface channels */
1676 }
e2b601e8
SG
1677}
1678
1679static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp,
1680 struct pim_neighbor *neigh,
1681 struct pim_upstream *up, int is_join)
1682{
be223239
SG
1683 vty_out(vty, "%-16s %-15pPAs %-15pPAs %-15pPAs %5s\n", ifp->name,
1684 &neigh->source_addr, &up->sg.src, &up->sg.grp,
1685 is_join ? "J" : "P");
e2b601e8
SG
1686}
1687
1688void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
1689{
1690 struct interface *ifp;
1691 struct pim_interface *pim_ifp;
1692 struct listnode *n_node;
1693 struct pim_neighbor *neigh;
1694 struct listnode *jag_node;
1695 struct pim_jp_agg_group *jag;
1696 struct listnode *js_node;
1697 struct pim_jp_sources *js;
1698
1699 vty_out(vty,
1700 "Interface RPF Nbr Source Group State\n");
1701
1702 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1703 pim_ifp = ifp->info;
1704 if (!pim_ifp)
1705 continue;
1706
1707 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
1708 neigh)) {
1709 for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
1710 jag_node, jag)) {
1711 for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
1712 js)) {
1713 pim_show_jp_agg_helper(vty, ifp, neigh,
1714 js->up,
1715 js->is_join);
1716 }
1717 }
1718 }
1719 }
1720}
1721
1722static void pim_show_membership_helper(struct vty *vty,
1723 struct pim_interface *pim_ifp,
1724 struct pim_ifchannel *ch,
1725 struct json_object *json)
1726{
e2b601e8
SG
1727 json_object *json_iface = NULL;
1728 json_object *json_row = NULL;
1729
1730 json_object_object_get_ex(json, ch->interface->name, &json_iface);
1731 if (!json_iface) {
1732 json_iface = json_object_new_object();
1733 json_object_pim_ifp_add(json_iface, ch->interface);
1734 json_object_object_add(json, ch->interface->name, json_iface);
1735 }
1736
e2b601e8
SG
1737 json_row = json_object_new_object();
1738 json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
de11054e 1739 json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
e2b601e8
SG
1740 json_object_string_add(json_row, "localMembership",
1741 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
de11054e
SG
1742 ? "NOINFO"
1743 : "INCLUDE");
1744 json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
e2b601e8
SG
1745}
1746
1747void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
1748{
1749 struct pim_interface *pim_ifp;
1750 struct pim_ifchannel *ch;
1751 struct interface *ifp;
1752 enum json_type type;
1753 json_object *json = NULL;
1754 json_object *json_tmp = NULL;
1755
1756 json = json_object_new_object();
1757
1758 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1759 pim_ifp = ifp->info;
1760 if (!pim_ifp)
1761 continue;
1762
1763 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1764 pim_show_membership_helper(vty, pim_ifp, ch, json);
1765 } /* scan interface channels */
1766 }
1767
1768 if (uj) {
de11054e 1769 vty_json(vty, json);
e2b601e8
SG
1770 } else {
1771 vty_out(vty,
1772 "Interface Address Source Group Membership\n");
1773
1774 /*
1775 * Example of the json data we are traversing
1776 *
1777 * {
1778 * "swp3":{
1779 * "name":"swp3",
1780 * "state":"up",
1781 * "address":"10.1.20.1",
1782 * "index":5,
1783 * "flagMulticast":true,
1784 * "flagBroadcast":true,
1785 * "lanDelayEnabled":true,
1786 * "226.10.10.10":{
1787 * "source":"*",
1788 * "group":"226.10.10.10",
1789 * "localMembership":"INCLUDE"
1790 * }
1791 * }
1792 * }
1793 */
1794
1795 /* foreach interface */
1796 json_object_object_foreach(json, key, val)
1797 {
1798
1799 /* Find all of the keys where the val is an object. In
1800 * the example
1801 * above the only one is 226.10.10.10
1802 */
1803 json_object_object_foreach(val, if_field_key,
1804 if_field_val)
1805 {
1806 type = json_object_get_type(if_field_val);
1807
1808 if (type == json_type_object) {
1809 vty_out(vty, "%-16s ", key);
1810
1811 json_object_object_get_ex(
1812 val, "address", &json_tmp);
1813 vty_out(vty, "%-15s ",
1814 json_object_get_string(
1815 json_tmp));
1816
1817 json_object_object_get_ex(if_field_val,
1818 "source",
1819 &json_tmp);
1820 vty_out(vty, "%-15s ",
1821 json_object_get_string(
1822 json_tmp));
1823
1824 /* Group */
1825 vty_out(vty, "%-15s ", if_field_key);
1826
1827 json_object_object_get_ex(
1828 if_field_val, "localMembership",
1829 &json_tmp);
1830 vty_out(vty, "%-10s\n",
1831 json_object_get_string(
1832 json_tmp));
1833 }
1834 }
1835 }
de11054e 1836 json_object_free(json);
e2b601e8 1837 }
e2b601e8
SG
1838}
1839
1840static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
1841 struct pim_interface *pim_ifp,
1842 struct pim_ifchannel *ch, json_object *json,
1843 bool uj)
1844{
1845 struct pim_upstream *up = ch->upstream;
1846 json_object *json_group = NULL;
e2b601e8
SG
1847 json_object *json_row = NULL;
1848
e2b601e8 1849 if (uj) {
bf083b3a
SG
1850 char grp_str[PIM_ADDRSTRLEN];
1851
1852 snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
e2b601e8
SG
1853 json_object_object_get_ex(json, grp_str, &json_group);
1854
1855 if (!json_group) {
1856 json_group = json_object_new_object();
1857 json_object_object_add(json, grp_str, json_group);
1858 }
1859
1860 json_row = json_object_new_object();
1861 json_object_pim_upstream_add(json_row, up);
1862 json_object_string_add(json_row, "interface",
1863 ch->interface->name);
bf083b3a
SG
1864 json_object_string_addf(json_row, "source", "%pPAs",
1865 &up->sg.src);
1866 json_object_string_addf(json_row, "group", "%pPAs",
1867 &up->sg.grp);
e2b601e8
SG
1868
1869 if (pim_macro_ch_lost_assert(ch))
1870 json_object_boolean_true_add(json_row, "lostAssert");
1871
1872 if (pim_macro_chisin_joins(ch))
1873 json_object_boolean_true_add(json_row, "joins");
1874
1875 if (pim_macro_chisin_pim_include(ch))
1876 json_object_boolean_true_add(json_row, "pimInclude");
1877
1878 if (pim_upstream_evaluate_join_desired(pim, up))
1879 json_object_boolean_true_add(json_row,
1880 "evaluateJoinDesired");
1881
bf083b3a
SG
1882 json_object_object_addf(json_group, json_row, "%pPAs",
1883 &up->sg.src);
e2b601e8
SG
1884
1885 } else {
bf083b3a
SG
1886 vty_out(vty,
1887 "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n",
1888 ch->interface->name, &up->sg.src, &up->sg.grp,
e2b601e8
SG
1889 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
1890 pim_macro_chisin_joins(ch) ? "yes" : "no",
1891 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
1892 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
1893 ? "yes"
1894 : "no",
1895 pim_upstream_evaluate_join_desired(pim, up) ? "yes"
1896 : "no");
1897 }
1898}
1899
1900void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
1901{
1902 struct pim_interface *pim_ifp;
1903 struct pim_ifchannel *ch;
1904 struct interface *ifp;
1905
1906 json_object *json = NULL;
1907
1908 if (uj)
1909 json = json_object_new_object();
1910 else
1911 vty_out(vty,
1912 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
1913
1914 /* scan per-interface (S,G) state */
1915 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1916 pim_ifp = ifp->info;
1917 if (!pim_ifp)
1918 continue;
1919
1920
1921 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1922 /* scan all interfaces */
1923 pim_show_channel_helper(pim, vty, pim_ifp, ch, json,
1924 uj);
1925 }
1926 }
1927
1928 if (uj)
1929 vty_json(vty, json);
1930}
1931
1932void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
44f99d22 1933 json_object *json)
e2b601e8
SG
1934{
1935 struct interface *ifp;
1936 struct pim_interface *pim_ifp;
1937 struct pim_upstream *up;
1938 int fhr = 0;
1939 int pim_nbrs = 0;
1940 int pim_ifchannels = 0;
44f99d22 1941 bool uj = true;
e2b601e8
SG
1942 json_object *json_row = NULL;
1943 json_object *json_tmp;
1944
44f99d22
SG
1945 if (!json) {
1946 uj = false;
1947 json = json_object_new_object();
1948 }
e2b601e8
SG
1949
1950 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1951 pim_ifp = ifp->info;
1952
1953 if (!pim_ifp)
1954 continue;
1955
1956 if (mlag == true && pim_ifp->activeactive == false)
1957 continue;
1958
1959 pim_nbrs = pim_ifp->pim_neighbor_list->count;
1960 pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
1961 fhr = 0;
1962
1963 frr_each (rb_pim_upstream, &pim->upstream_head, up)
1964 if (ifp == up->rpf.source_nexthop.interface)
1965 if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
1966 fhr++;
1967
1968 json_row = json_object_new_object();
1969 json_object_pim_ifp_add(json_row, ifp);
1970 json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
1971 json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
1972 json_object_int_add(json_row, "firstHopRouterCount", fhr);
44f99d22
SG
1973 json_object_string_addf(json_row, "pimDesignatedRouter",
1974 "%pPAs", &pim_ifp->pim_dr_addr);
e2b601e8
SG
1975
1976 if (pim_addr_cmp(pim_ifp->pim_dr_addr,
44f99d22 1977 pim_ifp->primary_address))
e2b601e8
SG
1978 json_object_boolean_true_add(
1979 json_row, "pimDesignatedRouterLocal");
1980
1981 json_object_object_add(json, ifp->name, json_row);
1982 }
1983
44f99d22 1984 if (!uj) {
e2b601e8
SG
1985 vty_out(vty,
1986 "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
1987
1988 json_object_object_foreach(json, key, val)
1989 {
1990 vty_out(vty, "%-16s ", key);
1991
1992 json_object_object_get_ex(val, "state", &json_tmp);
1993 vty_out(vty, "%5s ", json_object_get_string(json_tmp));
1994
1995 json_object_object_get_ex(val, "address", &json_tmp);
1996 vty_out(vty, "%15s ",
1997 json_object_get_string(json_tmp));
1998
1999 json_object_object_get_ex(val, "pimNeighbors",
2000 &json_tmp);
2001 vty_out(vty, "%8d ", json_object_get_int(json_tmp));
2002
2003 if (json_object_object_get_ex(
2004 val, "pimDesignatedRouterLocal",
2005 &json_tmp)) {
2006 vty_out(vty, "%15s ", "local");
2007 } else {
2008 json_object_object_get_ex(
2009 val, "pimDesignatedRouter", &json_tmp);
2010 vty_out(vty, "%15s ",
2011 json_object_get_string(json_tmp));
2012 }
2013
2014 json_object_object_get_ex(val, "firstHopRouter",
2015 &json_tmp);
2016 vty_out(vty, "%3d ", json_object_get_int(json_tmp));
2017
2018 json_object_object_get_ex(val, "pimIfChannels",
2019 &json_tmp);
2020 vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
2021 }
2022 }
e2b601e8
SG
2023}
2024
44f99d22
SG
2025void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
2026 const char *ifname, bool mlag,
2027 json_object *json)
e2b601e8
SG
2028{
2029 pim_addr ifaddr;
2030 struct interface *ifp;
2031 struct listnode *neighnode;
2032 struct pim_interface *pim_ifp;
2033 struct pim_neighbor *neigh;
2034 struct pim_upstream *up;
2035 time_t now;
44f99d22 2036 char dr_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2037 char dr_uptime[10];
2038 char expire[10];
44f99d22 2039 char grp_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2040 char hello_period[10];
2041 char hello_timer[10];
44f99d22
SG
2042 char neigh_src_str[PIM_ADDRSTRLEN];
2043 char src_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2044 char stat_uptime[10];
2045 char uptime[10];
2046 int found_ifname = 0;
2047 int print_header;
e2b601e8
SG
2048 json_object *json_row = NULL;
2049 json_object *json_pim_neighbor = NULL;
2050 json_object *json_pim_neighbors = NULL;
2051 json_object *json_group = NULL;
2052 json_object *json_group_source = NULL;
2053 json_object *json_fhr_sources = NULL;
2054 struct pim_secondary_addr *sec_addr;
2055 struct listnode *sec_node;
2056
2057 now = pim_time_monotonic_sec();
2058
e2b601e8
SG
2059 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2060 pim_ifp = ifp->info;
2061
2062 if (!pim_ifp)
2063 continue;
2064
2065 if (mlag == true && pim_ifp->activeactive == false)
2066 continue;
2067
2068 if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
2069 continue;
2070
2071 found_ifname = 1;
2072 ifaddr = pim_ifp->primary_address;
44f99d22
SG
2073 snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
2074 &pim_ifp->pim_dr_addr);
e2b601e8
SG
2075 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
2076 pim_ifp->pim_dr_election_last);
2077 pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
2078 pim_ifp->t_pim_hello_timer);
2079 pim_time_mmss(hello_period, sizeof(hello_period),
2080 pim_ifp->pim_hello_period);
2081 pim_time_uptime(stat_uptime, sizeof(stat_uptime),
2082 now - pim_ifp->pim_ifstat_start);
2083
44f99d22 2084 if (json) {
e2b601e8
SG
2085 json_row = json_object_new_object();
2086 json_object_pim_ifp_add(json_row, ifp);
2087
44f99d22 2088 if (!pim_addr_is_any(pim_ifp->update_source)) {
e2b601e8 2089 json_object_string_addf(
44f99d22 2090 json_row, "useSource", "%pPAs",
e2b601e8
SG
2091 &pim_ifp->update_source);
2092 }
2093 if (pim_ifp->sec_addr_list) {
2094 json_object *sec_list = NULL;
2095
2096 sec_list = json_object_new_array();
2097 for (ALL_LIST_ELEMENTS_RO(
2098 pim_ifp->sec_addr_list, sec_node,
2099 sec_addr)) {
2100 json_object_array_add(
2101 sec_list,
44f99d22
SG
2102 json_object_new_stringf(
2103 "%pFXh",
2104 &sec_addr->addr));
e2b601e8
SG
2105 }
2106 json_object_object_add(json_row,
2107 "secondaryAddressList",
2108 sec_list);
2109 }
2110
2111 /* PIM neighbors */
2112 if (pim_ifp->pim_neighbor_list->count) {
2113 json_pim_neighbors = json_object_new_object();
2114
2115 for (ALL_LIST_ELEMENTS_RO(
2116 pim_ifp->pim_neighbor_list,
2117 neighnode, neigh)) {
2118 json_pim_neighbor =
2119 json_object_new_object();
44f99d22
SG
2120 snprintfrr(neigh_src_str,
2121 sizeof(neigh_src_str),
2122 "%pPAs",
2123 &neigh->source_addr);
e2b601e8
SG
2124 pim_time_uptime(uptime, sizeof(uptime),
2125 now - neigh->creation);
2126 pim_time_timer_to_hhmmss(
2127 expire, sizeof(expire),
2128 neigh->t_expire_timer);
2129
2130 json_object_string_add(
2131 json_pim_neighbor, "address",
2132 neigh_src_str);
2133 json_object_string_add(
2134 json_pim_neighbor, "upTime",
2135 uptime);
2136 json_object_string_add(
2137 json_pim_neighbor, "holdtime",
2138 expire);
2139
2140 json_object_object_add(
2141 json_pim_neighbors,
2142 neigh_src_str,
2143 json_pim_neighbor);
2144 }
2145
2146 json_object_object_add(json_row, "neighbors",
2147 json_pim_neighbors);
2148 }
2149
2150 json_object_string_add(json_row, "drAddress", dr_str);
2151 json_object_int_add(json_row, "drPriority",
2152 pim_ifp->pim_dr_priority);
2153 json_object_string_add(json_row, "drUptime", dr_uptime);
2154 json_object_int_add(json_row, "drElections",
2155 pim_ifp->pim_dr_election_count);
2156 json_object_int_add(json_row, "drChanges",
2157 pim_ifp->pim_dr_election_changes);
2158
2159 /* FHR */
2160 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2161 if (ifp != up->rpf.source_nexthop.interface)
2162 continue;
2163
2164 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2165 continue;
2166
2167 if (!json_fhr_sources)
2168 json_fhr_sources =
2169 json_object_new_object();
2170
2171 snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
2172 &up->sg.grp);
2173 snprintfrr(src_str, sizeof(src_str), "%pPAs",
2174 &up->sg.src);
2175 pim_time_uptime(uptime, sizeof(uptime),
2176 now - up->state_transition);
2177
2178 /*
2179 * Does this group live in json_fhr_sources?
2180 * If not create it.
2181 */
2182 json_object_object_get_ex(json_fhr_sources,
2183 grp_str, &json_group);
2184
2185 if (!json_group) {
2186 json_group = json_object_new_object();
2187 json_object_object_add(json_fhr_sources,
2188 grp_str,
2189 json_group);
2190 }
2191
2192 json_group_source = json_object_new_object();
2193 json_object_string_add(json_group_source,
2194 "source", src_str);
2195 json_object_string_add(json_group_source,
2196 "group", grp_str);
2197 json_object_string_add(json_group_source,
2198 "upTime", uptime);
2199 json_object_object_add(json_group, src_str,
2200 json_group_source);
2201 }
2202
2203 if (json_fhr_sources) {
2204 json_object_object_add(json_row,
2205 "firstHopRouter",
2206 json_fhr_sources);
2207 }
2208
2209 json_object_int_add(json_row, "helloPeriod",
2210 pim_ifp->pim_hello_period);
2211 json_object_int_add(json_row, "holdTime",
2212 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2213 json_object_string_add(json_row, "helloTimer",
2214 hello_timer);
2215 json_object_string_add(json_row, "helloStatStart",
2216 stat_uptime);
2217 json_object_int_add(json_row, "helloReceived",
2218 pim_ifp->pim_ifstat_hello_recv);
2219 json_object_int_add(json_row, "helloReceivedFailed",
2220 pim_ifp->pim_ifstat_hello_recvfail);
2221 json_object_int_add(json_row, "helloSend",
2222 pim_ifp->pim_ifstat_hello_sent);
2223 json_object_int_add(json_row, "hellosendFailed",
2224 pim_ifp->pim_ifstat_hello_sendfail);
2225 json_object_int_add(json_row, "helloGenerationId",
2226 pim_ifp->pim_generation_id);
2227
2228 json_object_int_add(
2229 json_row, "effectivePropagationDelay",
2230 pim_if_effective_propagation_delay_msec(ifp));
2231 json_object_int_add(
2232 json_row, "effectiveOverrideInterval",
2233 pim_if_effective_override_interval_msec(ifp));
2234 json_object_int_add(
2235 json_row, "joinPruneOverrideInterval",
2236 pim_if_jp_override_interval_msec(ifp));
2237
2238 json_object_int_add(
2239 json_row, "propagationDelay",
2240 pim_ifp->pim_propagation_delay_msec);
2241 json_object_int_add(
2242 json_row, "propagationDelayHighest",
2243 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2244 json_object_int_add(
2245 json_row, "overrideInterval",
2246 pim_ifp->pim_override_interval_msec);
2247 json_object_int_add(
2248 json_row, "overrideIntervalHighest",
2249 pim_ifp->pim_neighbors_highest_override_interval_msec);
2250 if (pim_ifp->bsm_enable)
2251 json_object_boolean_true_add(json_row,
2252 "bsmEnabled");
2253 if (pim_ifp->ucast_bsm_accept)
2254 json_object_boolean_true_add(json_row,
2255 "ucastBsmEnabled");
2256 json_object_object_add(json, ifp->name, json_row);
2257
2258 } else {
2259 vty_out(vty, "Interface : %s\n", ifp->name);
2260 vty_out(vty, "State : %s\n",
2261 if_is_up(ifp) ? "up" : "down");
44f99d22
SG
2262 if (!pim_addr_is_any(pim_ifp->update_source)) {
2263 vty_out(vty, "Use Source : %pPAs\n",
e2b601e8
SG
2264 &pim_ifp->update_source);
2265 }
2266 if (pim_ifp->sec_addr_list) {
44f99d22 2267 vty_out(vty, "Address : %pPAs (primary)\n",
e2b601e8
SG
2268 &ifaddr);
2269 for (ALL_LIST_ELEMENTS_RO(
2270 pim_ifp->sec_addr_list, sec_node,
2271 sec_addr))
2272 vty_out(vty, " %pFX\n",
2273 &sec_addr->addr);
2274 } else {
44f99d22 2275 vty_out(vty, "Address : %pPAs\n", &ifaddr);
e2b601e8
SG
2276 }
2277 vty_out(vty, "\n");
2278
2279 /* PIM neighbors */
2280 print_header = 1;
2281
2282 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
2283 neighnode, neigh)) {
2284
2285 if (print_header) {
2286 vty_out(vty, "PIM Neighbors\n");
2287 vty_out(vty, "-------------\n");
2288 print_header = 0;
2289 }
2290
44f99d22
SG
2291 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2292 "%pPAs", &neigh->source_addr);
e2b601e8
SG
2293 pim_time_uptime(uptime, sizeof(uptime),
2294 now - neigh->creation);
2295 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2296 neigh->t_expire_timer);
2297 vty_out(vty,
2298 "%-15s : up for %s, holdtime expires in %s\n",
2299 neigh_src_str, uptime, expire);
2300 }
2301
2302 if (!print_header) {
2303 vty_out(vty, "\n");
2304 vty_out(vty, "\n");
2305 }
2306
2307 vty_out(vty, "Designated Router\n");
2308 vty_out(vty, "-----------------\n");
2309 vty_out(vty, "Address : %s\n", dr_str);
2310 vty_out(vty, "Priority : %u(%d)\n",
2311 pim_ifp->pim_dr_priority,
2312 pim_ifp->pim_dr_num_nondrpri_neighbors);
2313 vty_out(vty, "Uptime : %s\n", dr_uptime);
2314 vty_out(vty, "Elections : %d\n",
2315 pim_ifp->pim_dr_election_count);
2316 vty_out(vty, "Changes : %d\n",
2317 pim_ifp->pim_dr_election_changes);
2318 vty_out(vty, "\n");
2319 vty_out(vty, "\n");
2320
2321 /* FHR */
2322 print_header = 1;
2323 frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2324 if (!up->rpf.source_nexthop.interface)
2325 continue;
2326
2327 if (strcmp(ifp->name,
2328 up->rpf.source_nexthop
44f99d22 2329 .interface->name) != 0)
e2b601e8
SG
2330 continue;
2331
2332 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2333 continue;
2334
2335 if (print_header) {
2336 vty_out(vty,
2337 "FHR - First Hop Router\n");
2338 vty_out(vty,
2339 "----------------------\n");
2340 print_header = 0;
2341 }
2342
2343 pim_time_uptime(uptime, sizeof(uptime),
2344 now - up->state_transition);
2345 vty_out(vty,
2346 "%pPAs : %pPAs is a source, uptime is %s\n",
2347 &up->sg.grp, &up->sg.src, uptime);
2348 }
2349
2350 if (!print_header) {
2351 vty_out(vty, "\n");
2352 vty_out(vty, "\n");
2353 }
2354
2355 vty_out(vty, "Hellos\n");
2356 vty_out(vty, "------\n");
2357 vty_out(vty, "Period : %d\n",
2358 pim_ifp->pim_hello_period);
2359 vty_out(vty, "HoldTime : %d\n",
2360 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2361 vty_out(vty, "Timer : %s\n", hello_timer);
2362 vty_out(vty, "StatStart : %s\n", stat_uptime);
2363 vty_out(vty, "Receive : %d\n",
2364 pim_ifp->pim_ifstat_hello_recv);
2365 vty_out(vty, "Receive Failed : %d\n",
2366 pim_ifp->pim_ifstat_hello_recvfail);
2367 vty_out(vty, "Send : %d\n",
2368 pim_ifp->pim_ifstat_hello_sent);
2369 vty_out(vty, "Send Failed : %d\n",
2370 pim_ifp->pim_ifstat_hello_sendfail);
2371 vty_out(vty, "Generation ID : %08x\n",
2372 pim_ifp->pim_generation_id);
2373 vty_out(vty, "\n");
2374 vty_out(vty, "\n");
2375
2376 pim_print_ifp_flags(vty, ifp);
2377
2378 vty_out(vty, "Join Prune Interval\n");
2379 vty_out(vty, "-------------------\n");
2380 vty_out(vty, "LAN Delay : %s\n",
2381 pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
2382 vty_out(vty, "Effective Propagation Delay : %d msec\n",
2383 pim_if_effective_propagation_delay_msec(ifp));
2384 vty_out(vty, "Effective Override Interval : %d msec\n",
2385 pim_if_effective_override_interval_msec(ifp));
2386 vty_out(vty, "Join Prune Override Interval : %d msec\n",
2387 pim_if_jp_override_interval_msec(ifp));
2388 vty_out(vty, "\n");
2389 vty_out(vty, "\n");
2390
2391 vty_out(vty, "LAN Prune Delay\n");
2392 vty_out(vty, "---------------\n");
2393 vty_out(vty, "Propagation Delay : %d msec\n",
2394 pim_ifp->pim_propagation_delay_msec);
2395 vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
2396 pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2397 vty_out(vty, "Override Interval : %d msec\n",
2398 pim_ifp->pim_override_interval_msec);
2399 vty_out(vty, "Override Interval (Highest) : %d msec\n",
2400 pim_ifp->pim_neighbors_highest_override_interval_msec);
2401 vty_out(vty, "\n");
2402 vty_out(vty, "\n");
2403
2404 vty_out(vty, "BSM Status\n");
2405 vty_out(vty, "----------\n");
2406 vty_out(vty, "Bsm Enabled : %s\n",
2407 pim_ifp->bsm_enable ? "yes" : "no");
2408 vty_out(vty, "Unicast Bsm Enabled : %s\n",
2409 pim_ifp->ucast_bsm_accept ? "yes" : "no");
2410 vty_out(vty, "\n");
2411 vty_out(vty, "\n");
2412 }
2413 }
2414
44f99d22 2415 if (!found_ifname)
e2b601e8
SG
2416 vty_out(vty, "%% No such interface\n");
2417}
2418
2419void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
2420 bool uj)
2421{
2422 struct pim_ssm *ssm = pim->ssm_info;
2423 const char *range_str =
2424 ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
2425
2426 if (uj) {
2427 json_object *json;
2428
2429 json = json_object_new_object();
2430 json_object_string_add(json, "ssmGroups", range_str);
2431 vty_json(vty, json);
2432 } else
2433 vty_out(vty, "SSM group range : %s\n", range_str);
2434}
2435
2436struct pnc_cache_walk_data {
2437 struct vty *vty;
2438 struct pim_instance *pim;
2439};
2440
2441static int pim_print_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
2442{
2443 struct pim_nexthop_cache *pnc = bucket->data;
2444 struct pnc_cache_walk_data *cwd = arg;
2445 struct vty *vty = cwd->vty;
2446 struct pim_instance *pim = cwd->pim;
2447 struct nexthop *nh_node = NULL;
2448 ifindex_t first_ifindex;
2449 struct interface *ifp = NULL;
2450 char buf[PREFIX_STRLEN];
2451
2452 for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2453 first_ifindex = nh_node->ifindex;
2454 ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2455
2456 vty_out(vty, "%-15s ",
2457 inet_ntop(AF_INET, &pnc->rpf.rpf_addr.u.prefix4, buf,
2458 sizeof(buf)));
2459 vty_out(vty, "%-16s ", ifp ? ifp->name : "NULL");
2460 vty_out(vty, "%pI4 ", &nh_node->gate.ipv4);
2461 vty_out(vty, "\n");
2462 }
2463 return CMD_SUCCESS;
2464}
2465
2466void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
2467{
2468 struct pnc_cache_walk_data cwd;
2469
2470 cwd.vty = vty;
2471 cwd.pim = pim;
2472 vty_out(vty, "Number of registered addresses: %lu\n",
2473 pim->rpf_hash->count);
2474 vty_out(vty, "Address Interface Nexthop\n");
2475 vty_out(vty, "---------------------------------------------\n");
2476
2477 hash_walk(pim->rpf_hash, pim_print_pnc_cache_walkcb, &cwd);
2478}
2479
2480void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
2481 const char *neighbor, json_object *json)
2482{
2483 struct listnode *neighnode;
2484 struct interface *ifp;
2485 struct pim_interface *pim_ifp;
2486 struct pim_neighbor *neigh;
2487 time_t now;
2488 int found_neighbor = 0;
2489 int option_address_list;
2490 int option_dr_priority;
2491 int option_generation_id;
2492 int option_holdtime;
2493 int option_lan_prune_delay;
2494 int option_t_bit;
2495 char uptime[10];
2496 char expire[10];
2497 char neigh_src_str[PIM_ADDRSTRLEN];
2498
2499 json_object *json_ifp = NULL;
2500 json_object *json_row = NULL;
2501
2502 now = pim_time_monotonic_sec();
2503
2504 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2505 pim_ifp = ifp->info;
2506
2507 if (!pim_ifp)
2508 continue;
2509
2510 if (pim_ifp->pim_sock_fd < 0)
2511 continue;
2512
2513 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2514 neigh)) {
2515 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2516 "%pPAs", &neigh->source_addr);
2517
2518 /*
2519 * The user can specify either the interface name or the
2520 * PIM neighbor IP.
2521 * If this pim_ifp matches neither then skip.
2522 */
2523 if (strcmp(neighbor, "detail") &&
2524 strcmp(neighbor, ifp->name) &&
2525 strcmp(neighbor, neigh_src_str))
2526 continue;
2527
2528 found_neighbor = 1;
2529 pim_time_uptime(uptime, sizeof(uptime),
2530 now - neigh->creation);
2531 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2532 neigh->t_expire_timer);
2533
2534 option_address_list = 0;
2535 option_dr_priority = 0;
2536 option_generation_id = 0;
2537 option_holdtime = 0;
2538 option_lan_prune_delay = 0;
2539 option_t_bit = 0;
2540
2541 if (PIM_OPTION_IS_SET(neigh->hello_options,
2542 PIM_OPTION_MASK_ADDRESS_LIST))
2543 option_address_list = 1;
2544
2545 if (PIM_OPTION_IS_SET(neigh->hello_options,
2546 PIM_OPTION_MASK_DR_PRIORITY))
2547 option_dr_priority = 1;
2548
2549 if (PIM_OPTION_IS_SET(neigh->hello_options,
2550 PIM_OPTION_MASK_GENERATION_ID))
2551 option_generation_id = 1;
2552
2553 if (PIM_OPTION_IS_SET(neigh->hello_options,
2554 PIM_OPTION_MASK_HOLDTIME))
2555 option_holdtime = 1;
2556
2557 if (PIM_OPTION_IS_SET(neigh->hello_options,
2558 PIM_OPTION_MASK_LAN_PRUNE_DELAY))
2559 option_lan_prune_delay = 1;
2560
2561 if (PIM_OPTION_IS_SET(
2562 neigh->hello_options,
2563 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
2564 option_t_bit = 1;
2565
2566 if (json) {
2567
2568 /* Does this ifp live in json? If not create it
2569 */
2570 json_object_object_get_ex(json, ifp->name,
2571 &json_ifp);
2572
2573 if (!json_ifp) {
2574 json_ifp = json_object_new_object();
2575 json_object_pim_ifp_add(json_ifp, ifp);
2576 json_object_object_add(json, ifp->name,
2577 json_ifp);
2578 }
2579
2580 json_row = json_object_new_object();
2581 json_object_string_add(json_row, "interface",
2582 ifp->name);
2583 json_object_string_add(json_row, "address",
2584 neigh_src_str);
2585 json_object_string_add(json_row, "upTime",
2586 uptime);
2587 json_object_string_add(json_row, "holdtime",
2588 expire);
2589 json_object_int_add(json_row, "drPriority",
2590 neigh->dr_priority);
2591 json_object_int_add(json_row, "generationId",
2592 neigh->generation_id);
2593
2594 if (option_address_list)
2595 json_object_boolean_true_add(
2596 json_row,
2597 "helloOptionAddressList");
2598
2599 if (option_dr_priority)
2600 json_object_boolean_true_add(
2601 json_row,
2602 "helloOptionDrPriority");
2603
2604 if (option_generation_id)
2605 json_object_boolean_true_add(
2606 json_row,
2607 "helloOptionGenerationId");
2608
2609 if (option_holdtime)
2610 json_object_boolean_true_add(
2611 json_row,
2612 "helloOptionHoldtime");
2613
2614 if (option_lan_prune_delay)
2615 json_object_boolean_true_add(
2616 json_row,
2617 "helloOptionLanPruneDelay");
2618
2619 if (option_t_bit)
2620 json_object_boolean_true_add(
2621 json_row, "helloOptionTBit");
2622
2623 json_object_object_add(json_ifp, neigh_src_str,
2624 json_row);
2625
2626 } else {
2627 vty_out(vty, "Interface : %s\n", ifp->name);
2628 vty_out(vty, "Neighbor : %s\n", neigh_src_str);
2629 vty_out(vty,
2630 " Uptime : %s\n",
2631 uptime);
2632 vty_out(vty,
2633 " Holdtime : %s\n",
2634 expire);
2635 vty_out(vty,
2636 " DR Priority : %d\n",
2637 neigh->dr_priority);
2638 vty_out(vty,
2639 " Generation ID : %08x\n",
2640 neigh->generation_id);
2641 vty_out(vty,
2642 " Override Interval (msec) : %d\n",
2643 neigh->override_interval_msec);
2644 vty_out(vty,
2645 " Propagation Delay (msec) : %d\n",
2646 neigh->propagation_delay_msec);
2647 vty_out(vty,
2648 " Hello Option - Address List : %s\n",
2649 option_address_list ? "yes" : "no");
2650 vty_out(vty,
2651 " Hello Option - DR Priority : %s\n",
2652 option_dr_priority ? "yes" : "no");
2653 vty_out(vty,
2654 " Hello Option - Generation ID : %s\n",
2655 option_generation_id ? "yes" : "no");
2656 vty_out(vty,
2657 " Hello Option - Holdtime : %s\n",
2658 option_holdtime ? "yes" : "no");
2659 vty_out(vty,
2660 " Hello Option - LAN Prune Delay : %s\n",
2661 option_lan_prune_delay ? "yes" : "no");
2662 vty_out(vty,
2663 " Hello Option - T-bit : %s\n",
2664 option_t_bit ? "yes" : "no");
2665 bfd_sess_show(vty, json_ifp,
2666 neigh->bfd_session);
2667 vty_out(vty, "\n");
2668 }
2669 }
2670 }
2671
2672 if (!found_neighbor)
2673 vty_out(vty, "%% No such interface or neighbor\n");
2674}
2675
1295dbeb
SG
2676void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
2677 json_object *json)
e2b601e8
SG
2678{
2679 struct listnode *neighnode;
2680 struct interface *ifp;
2681 struct pim_interface *pim_ifp;
2682 struct pim_neighbor *neigh;
2683 time_t now;
2684 char uptime[10];
2685 char expire[10];
1295dbeb 2686 char neigh_src_str[PIM_ADDRSTRLEN];
e2b601e8
SG
2687 json_object *json_ifp_rows = NULL;
2688 json_object *json_row = NULL;
2689
2690 now = pim_time_monotonic_sec();
2691
1295dbeb 2692 if (!json) {
e2b601e8
SG
2693 vty_out(vty,
2694 "Interface Neighbor Uptime Holdtime DR Pri\n");
2695 }
2696
2697 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2698 pim_ifp = ifp->info;
2699
2700 if (!pim_ifp)
2701 continue;
2702
2703 if (pim_ifp->pim_sock_fd < 0)
2704 continue;
2705
1295dbeb 2706 if (json)
e2b601e8
SG
2707 json_ifp_rows = json_object_new_object();
2708
2709 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
2710 neigh)) {
1295dbeb
SG
2711 snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2712 "%pPAs", &neigh->source_addr);
e2b601e8
SG
2713 pim_time_uptime(uptime, sizeof(uptime),
2714 now - neigh->creation);
2715 pim_time_timer_to_hhmmss(expire, sizeof(expire),
2716 neigh->t_expire_timer);
2717
1295dbeb 2718 if (json) {
e2b601e8
SG
2719 json_row = json_object_new_object();
2720 json_object_string_add(json_row, "interface",
2721 ifp->name);
2722 json_object_string_add(json_row, "neighbor",
2723 neigh_src_str);
2724 json_object_string_add(json_row, "upTime",
2725 uptime);
2726 json_object_string_add(json_row, "holdTime",
2727 expire);
2728 json_object_int_add(json_row, "holdTimeMax",
2729 neigh->holdtime);
2730 json_object_int_add(json_row, "drPriority",
2731 neigh->dr_priority);
2732 json_object_object_add(json_ifp_rows,
2733 neigh_src_str, json_row);
2734
2735 } else {
2736 vty_out(vty, "%-16s %15s %8s %8s %6d\n",
2737 ifp->name, neigh_src_str, uptime,
2738 expire, neigh->dr_priority);
2739 }
2740 }
2741
1295dbeb 2742 if (json) {
e2b601e8
SG
2743 json_object_object_add(json, ifp->name, json_ifp_rows);
2744 json_ifp_rows = NULL;
2745 }
2746 }
e2b601e8 2747}
c8b3d45d
SG
2748
2749int gm_process_query_max_response_time_cmd(struct vty *vty,
2750 const char *qmrt_str)
2751{
2752 const struct lyd_node *pim_enable_dnode;
2753
2754 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2755 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2756 FRR_PIM_AF_XPATH_VAL);
2757
2758 if (!pim_enable_dnode) {
2759 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2760 } else {
2761 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2762 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2763 "true");
2764 }
2765
2766 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
2767 qmrt_str);
2768 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2769 FRR_PIM_AF_XPATH_VAL);
2770}
2771
2772int gm_process_no_query_max_response_time_cmd(struct vty *vty)
2773{
2774 nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
2775 NULL);
2776 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2777 FRR_PIM_AF_XPATH_VAL);
2778}
c889adcb
SG
2779
2780int gm_process_last_member_query_count_cmd(struct vty *vty,
2781 const char *lmqc_str)
2782{
2783 const struct lyd_node *pim_enable_dnode;
2784
2785 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2786 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2787 FRR_PIM_AF_XPATH_VAL);
2788 if (!pim_enable_dnode) {
2789 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2790 } else {
2791 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2792 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2793 "true");
2794 }
2795
2796 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
2797 lmqc_str);
2798 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2799 FRR_PIM_AF_XPATH_VAL);
2800}
2801
2802int gm_process_no_last_member_query_count_cmd(struct vty *vty)
2803{
2804 nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
2805 NULL);
2806 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2807 FRR_PIM_AF_XPATH_VAL);
2808}
e7ec758d
SG
2809
2810int gm_process_last_member_query_interval_cmd(struct vty *vty,
2811 const char *lmqi_str)
2812{
2813 const struct lyd_node *pim_enable_dnode;
2814
2815 pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
2816 FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
2817 FRR_PIM_AF_XPATH_VAL);
2818 if (!pim_enable_dnode) {
2819 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
2820 } else {
2821 if (!yang_dnode_get_bool(pim_enable_dnode, "."))
2822 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
2823 "true");
2824 }
2825
2826 nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
2827 lmqi_str);
2828 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2829 FRR_PIM_AF_XPATH_VAL);
2830}
2831
2832int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
2833{
2834 nb_cli_enqueue_change(vty, "./last-member-query-interval",
2835 NB_OP_DESTROY, NULL);
2836 return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
2837 FRR_PIM_AF_XPATH_VAL);
2838}
a8caf78d 2839
a8caf78d
BG
2840int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
2841 const char *src_str)
2842{
2843 const char *vrfname;
2844 char ssmpingd_ip_xpath[XPATH_MAXLEN];
2845
2846 vrfname = pim_cli_get_vrf_name(vty);
2847 if (vrfname == NULL)
2848 return CMD_WARNING_CONFIG_FAILED;
2849
2850 snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
2851 FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
2852 FRR_PIM_AF_XPATH_VAL);
2853 strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
2854 sizeof(ssmpingd_ip_xpath));
2855
2856 nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
2857
2858 return nb_cli_apply_changes(vty, NULL);
2859}
be126d91 2860
be126d91
A
2861static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
2862 time_t now)
2863{
2864 char uptime_scan_oil[10];
2865 char uptime_mroute_add[10];
2866 char uptime_mroute_del[10];
2867
2868 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
2869 pim->scan_oil_last);
2870 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
2871 pim->mroute_add_last);
2872 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
2873 pim->mroute_del_last);
2874
2875 vty_out(vty,
2876 "Scan OIL - Last: %s Events: %lld\n"
2877 "MFC Add - Last: %s Events: %lld\n"
2878 "MFC Del - Last: %s Events: %lld\n",
2879 uptime_scan_oil, (long long)pim->scan_oil_events,
2880 uptime_mroute_add, (long long)pim->mroute_add_events,
2881 uptime_mroute_del, (long long)pim->mroute_del_events);
2882}
2883
2884void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
3e55b3b5 2885 json_object *json)
be126d91
A
2886{
2887 struct interface *ifp;
be126d91
A
2888 json_object *json_row = NULL;
2889
2890 vty_out(vty, "\n");
2891
3e55b3b5 2892 if (!json)
be126d91
A
2893 vty_out(vty,
2894 "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
2895
2896 FOR_ALL_INTERFACES (pim->vrf, ifp) {
2897 struct pim_interface *pim_ifp;
ca3b5906 2898#if PIM_IPV == 4
be126d91 2899 struct sioc_vif_req vreq;
ca3b5906
A
2900#else
2901 struct sioc_mif_req6 vreq;
2902#endif
be126d91
A
2903
2904 pim_ifp = ifp->info;
2905
2906 if (!pim_ifp)
2907 continue;
2908
2909 memset(&vreq, 0, sizeof(vreq));
ca3b5906 2910#if PIM_IPV == 4
be126d91 2911 vreq.vifi = pim_ifp->mroute_vif_index;
be126d91
A
2912 if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
2913 zlog_warn(
2914 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
2915 (unsigned long)SIOCGETVIFCNT, ifp->name,
2916 pim_ifp->mroute_vif_index, errno,
2917 safe_strerror(errno));
2918 }
ca3b5906
A
2919#else
2920 vreq.mifi = pim_ifp->mroute_vif_index;
2921 if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
2922 zlog_warn(
2923 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
2924 (unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
2925 pim_ifp->mroute_vif_index, errno,
2926 safe_strerror(errno));
2927 }
2928#endif
be126d91 2929
3e55b3b5 2930 if (json) {
be126d91
A
2931 json_row = json_object_new_object();
2932 json_object_string_add(json_row, "name", ifp->name);
2933 json_object_string_add(json_row, "state",
2934 if_is_up(ifp) ? "up" : "down");
ca3b5906 2935 json_object_string_addf(json_row, "address", "%pPA",
be126d91
A
2936 &pim_ifp->primary_address);
2937 json_object_int_add(json_row, "ifIndex", ifp->ifindex);
2938 json_object_int_add(json_row, "vif",
2939 pim_ifp->mroute_vif_index);
2940 json_object_int_add(json_row, "pktsIn",
2941 (unsigned long)vreq.icount);
2942 json_object_int_add(json_row, "pktsOut",
2943 (unsigned long)vreq.ocount);
2944 json_object_int_add(json_row, "bytesIn",
2945 (unsigned long)vreq.ibytes);
2946 json_object_int_add(json_row, "bytesOut",
2947 (unsigned long)vreq.obytes);
2948 json_object_object_add(json, ifp->name, json_row);
2949 } else {
2950 vty_out(vty,
ca3b5906
A
2951 "%-16s %-15pPAs %3d %3d %7lu %7lu %10lu %10lu\n",
2952 ifp->name, &pim_ifp->primary_address,
be126d91
A
2953 ifp->ifindex, pim_ifp->mroute_vif_index,
2954 (unsigned long)vreq.icount,
2955 (unsigned long)vreq.ocount,
2956 (unsigned long)vreq.ibytes,
2957 (unsigned long)vreq.obytes);
2958 }
2959 }
be126d91
A
2960}
2961
ca3b5906 2962void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
be126d91
A
2963{
2964 struct vrf *vrf = pim->vrf;
2965 time_t now = pim_time_monotonic_sec();
2966 char uptime[10];
2967 char mlag_role[80];
2968
2969 pim = vrf->info;
2970
2971 vty_out(vty, "Router MLAG Role: %s\n",
2972 mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
2973 vty_out(vty, "Mroute socket descriptor:");
2974
2975 vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
2976
2977 pim_time_uptime(uptime, sizeof(uptime),
2978 now - pim->mroute_socket_creation);
2979 vty_out(vty, "Mroute socket uptime: %s\n", uptime);
2980
2981 vty_out(vty, "\n");
2982
2983 pim_zebra_zclient_update(vty);
ca3b5906 2984#if PIM_IPV == 4
be126d91 2985 pim_zlookup_show_ip_multicast(vty);
ca3b5906
A
2986#else
2987 /* TBD */
2988#endif
be126d91
A
2989
2990 vty_out(vty, "\n");
2991 vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
2992
2993 vty_out(vty, "\n");
2994 vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
2995 vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
2996 vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
2997 vty_out(vty, "PIM ECMP Rebalance: %s\n",
2998 pim->ecmp_rebalance_enable ? "Enable" : "Disable");
2999
3000 vty_out(vty, "\n");
3001
3002 pim_show_rpf_refresh_stats(vty, pim, now, NULL);
3003
3004 vty_out(vty, "\n");
3005
3006 show_scan_oil_stats(pim, vty, now);
3007
3e55b3b5 3008 show_multicast_interfaces(pim, vty, NULL);
be126d91 3009}