1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2022 Vmware, Inc.
5 * Mobashshera Rasool <mrasool@vmware.com>
20 #include "lib/srcdest_table.h"
21 #include "lib/linklist.h"
22 #include "termtable.h"
25 #include "pim_instance.h"
27 #include "lib/northbound_cli.h"
28 #include "pim_errors.h"
30 #include "pim_mroute.h"
33 #include "pim_cmd_common.h"
35 #include "pim_zebra.h"
36 #include "pim_zlookup.h"
37 #include "pim_iface.h"
38 #include "pim_macro.h"
39 #include "pim_neighbor.h"
43 #include "pim_static.h"
45 #include "pim_static.h"
50 * Get current node VRF name.
53 * In case of failure it will print error message to user.
55 * \returns name or NULL if failed to get VRF.
57 const char *pim_cli_get_vrf_name(struct vty
*vty
)
59 const struct lyd_node
*vrf_node
;
61 /* Not inside any VRF context. */
62 if (vty
->xpath_index
== 0)
63 return VRF_DEFAULT_NAME
;
65 vrf_node
= yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
66 if (vrf_node
== NULL
) {
67 vty_out(vty
, "%% Failed to get vrf dnode in configuration\n");
71 return yang_dnode_get_string(vrf_node
, "./name");
74 int pim_process_join_prune_cmd(struct vty
*vty
, const char *jpi_str
)
76 char xpath
[XPATH_MAXLEN
];
78 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
79 FRR_PIM_AF_XPATH_VAL
);
80 strlcat(xpath
, "/join-prune-interval", sizeof(xpath
));
82 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, jpi_str
);
84 return nb_cli_apply_changes(vty
, NULL
);
87 int pim_process_no_join_prune_cmd(struct vty
*vty
)
89 char xpath
[XPATH_MAXLEN
];
91 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
92 FRR_PIM_AF_XPATH_VAL
);
93 strlcat(xpath
, "/join-prune-interval", sizeof(xpath
));
95 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
97 return nb_cli_apply_changes(vty
, NULL
);
100 int pim_process_spt_switchover_infinity_cmd(struct vty
*vty
)
103 char spt_plist_xpath
[XPATH_MAXLEN
];
104 char spt_action_xpath
[XPATH_MAXLEN
];
106 vrfname
= pim_cli_get_vrf_name(vty
);
108 return CMD_WARNING_CONFIG_FAILED
;
110 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
111 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
112 FRR_PIM_AF_XPATH_VAL
);
113 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
114 sizeof(spt_plist_xpath
));
116 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
117 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
118 FRR_PIM_AF_XPATH_VAL
);
119 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
120 sizeof(spt_action_xpath
));
122 if (yang_dnode_exists(vty
->candidate_config
->dnode
, spt_plist_xpath
))
123 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
,
125 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
128 return nb_cli_apply_changes(vty
, NULL
);
131 int pim_process_spt_switchover_prefixlist_cmd(struct vty
*vty
,
135 char spt_plist_xpath
[XPATH_MAXLEN
];
136 char spt_action_xpath
[XPATH_MAXLEN
];
138 vrfname
= pim_cli_get_vrf_name(vty
);
140 return CMD_WARNING_CONFIG_FAILED
;
142 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
143 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
144 FRR_PIM_AF_XPATH_VAL
);
145 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
146 sizeof(spt_plist_xpath
));
148 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
149 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
150 FRR_PIM_AF_XPATH_VAL
);
151 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
152 sizeof(spt_action_xpath
));
154 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
156 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_MODIFY
,
159 return nb_cli_apply_changes(vty
, NULL
);
162 int pim_process_no_spt_switchover_cmd(struct vty
*vty
)
165 char spt_plist_xpath
[XPATH_MAXLEN
];
166 char spt_action_xpath
[XPATH_MAXLEN
];
168 vrfname
= pim_cli_get_vrf_name(vty
);
170 return CMD_WARNING_CONFIG_FAILED
;
172 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
173 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
174 FRR_PIM_AF_XPATH_VAL
);
175 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
176 sizeof(spt_plist_xpath
));
178 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
179 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
180 FRR_PIM_AF_XPATH_VAL
);
181 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
182 sizeof(spt_action_xpath
));
184 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
, NULL
);
185 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
186 "PIM_SPT_IMMEDIATE");
188 return nb_cli_apply_changes(vty
, NULL
);
191 int pim_process_pim_packet_cmd(struct vty
*vty
, const char *packet
)
193 char xpath
[XPATH_MAXLEN
];
195 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
196 FRR_PIM_AF_XPATH_VAL
);
197 strlcat(xpath
, "/packets", sizeof(xpath
));
199 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, packet
);
201 return nb_cli_apply_changes(vty
, NULL
);
204 int pim_process_no_pim_packet_cmd(struct vty
*vty
)
206 char xpath
[XPATH_MAXLEN
];
208 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
209 FRR_PIM_AF_XPATH_VAL
);
210 strlcat(xpath
, "/packets", sizeof(xpath
));
212 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
214 return nb_cli_apply_changes(vty
, NULL
);
217 int pim_process_keepalivetimer_cmd(struct vty
*vty
, const char *kat
)
220 char ka_timer_xpath
[XPATH_MAXLEN
];
222 vrfname
= pim_cli_get_vrf_name(vty
);
224 return CMD_WARNING_CONFIG_FAILED
;
226 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
227 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
228 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
230 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_MODIFY
,
233 return nb_cli_apply_changes(vty
, NULL
);
236 int pim_process_no_keepalivetimer_cmd(struct vty
*vty
)
239 char ka_timer_xpath
[XPATH_MAXLEN
];
241 vrfname
= pim_cli_get_vrf_name(vty
);
243 return CMD_WARNING_CONFIG_FAILED
;
245 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
246 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
247 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
249 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_DESTROY
, NULL
);
251 return nb_cli_apply_changes(vty
, NULL
);
254 int pim_process_rp_kat_cmd(struct vty
*vty
, const char *rpkat
)
257 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
259 vrfname
= pim_cli_get_vrf_name(vty
);
261 return CMD_WARNING_CONFIG_FAILED
;
263 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
264 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
265 FRR_PIM_AF_XPATH_VAL
);
266 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
267 sizeof(rp_ka_timer_xpath
));
269 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
272 return nb_cli_apply_changes(vty
, NULL
);
275 int pim_process_no_rp_kat_cmd(struct vty
*vty
)
279 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
281 char rs_timer_xpath
[XPATH_MAXLEN
];
283 snprintf(rs_timer_xpath
, sizeof(rs_timer_xpath
),
284 FRR_PIM_ROUTER_XPATH
, FRR_PIM_AF_XPATH_VAL
);
285 strlcat(rs_timer_xpath
, "/register-suppress-time",
286 sizeof(rs_timer_xpath
));
289 v
= yang_dnode_get_uint16(vty
->candidate_config
->dnode
, "%s",
291 v
= 3 * v
+ PIM_REGISTER_PROBE_TIME_DEFAULT
;
294 snprintf(rp_ka_timer
, sizeof(rp_ka_timer
), "%u", v
);
296 vrfname
= pim_cli_get_vrf_name(vty
);
298 return CMD_WARNING_CONFIG_FAILED
;
300 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
301 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
302 FRR_PIM_AF_XPATH_VAL
);
303 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
304 sizeof(rp_ka_timer_xpath
));
306 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
309 return nb_cli_apply_changes(vty
, NULL
);
312 int pim_process_register_suppress_cmd(struct vty
*vty
, const char *rst
)
314 char xpath
[XPATH_MAXLEN
];
316 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
317 FRR_PIM_AF_XPATH_VAL
);
318 strlcat(xpath
, "/register-suppress-time", sizeof(xpath
));
320 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, rst
);
322 return nb_cli_apply_changes(vty
, NULL
);
325 int pim_process_no_register_suppress_cmd(struct vty
*vty
)
327 char xpath
[XPATH_MAXLEN
];
329 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
330 FRR_PIM_AF_XPATH_VAL
);
331 strlcat(xpath
, "/register-suppress-time", sizeof(xpath
));
333 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
335 return nb_cli_apply_changes(vty
, NULL
);
338 int pim_process_ip_pim_cmd(struct vty
*vty
)
340 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
, "true");
342 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
343 FRR_PIM_AF_XPATH_VAL
);
346 int pim_process_ip_pim_passive_cmd(struct vty
*vty
, bool enable
)
349 nb_cli_enqueue_change(vty
, "./pim-passive-enable", NB_OP_MODIFY
,
352 nb_cli_enqueue_change(vty
, "./pim-passive-enable", NB_OP_MODIFY
,
355 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
356 FRR_PIM_AF_XPATH_VAL
);
359 int pim_process_no_ip_pim_cmd(struct vty
*vty
)
361 const struct lyd_node
*mld_enable_dnode
;
362 char mld_if_xpath
[XPATH_MAXLEN
];
365 snprintf(mld_if_xpath
, sizeof(mld_if_xpath
),
366 "%s/frr-gmp:gmp/address-family[address-family='%s']",
367 VTY_CURR_XPATH
, FRR_PIM_AF_XPATH_VAL
);
369 if (printed
>= (int)(sizeof(mld_if_xpath
))) {
370 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
372 return CMD_WARNING_CONFIG_FAILED
;
375 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
376 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
377 FRR_PIM_AF_XPATH_VAL
);
379 if (!mld_enable_dnode
) {
380 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
, NULL
);
381 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
383 if (!yang_dnode_get_bool(mld_enable_dnode
, ".")) {
384 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
,
386 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
388 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
392 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
393 FRR_PIM_AF_XPATH_VAL
);
396 int pim_process_ip_pim_drprio_cmd(struct vty
*vty
, const char *drpriority_str
)
398 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_MODIFY
,
401 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
402 FRR_PIM_AF_XPATH_VAL
);
405 int pim_process_no_ip_pim_drprio_cmd(struct vty
*vty
)
407 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_DESTROY
, NULL
);
409 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
410 FRR_PIM_AF_XPATH_VAL
);
413 int pim_process_ip_pim_hello_cmd(struct vty
*vty
, const char *hello_str
,
414 const char *hold_str
)
416 const struct lyd_node
*mld_enable_dnode
;
418 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
419 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
420 FRR_PIM_AF_XPATH_VAL
);
422 if (!mld_enable_dnode
) {
423 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
426 if (!yang_dnode_get_bool(mld_enable_dnode
, "."))
427 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
431 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_MODIFY
, hello_str
);
434 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_MODIFY
,
437 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
438 FRR_PIM_AF_XPATH_VAL
);
441 int pim_process_no_ip_pim_hello_cmd(struct vty
*vty
)
443 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_DESTROY
, NULL
);
444 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_DESTROY
, NULL
);
446 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
447 FRR_PIM_AF_XPATH_VAL
);
450 int pim_process_ip_pim_activeactive_cmd(struct vty
*vty
, const char *no
)
453 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
456 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
459 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
463 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
464 FRR_PIM_AF_XPATH_VAL
);
467 int pim_process_ip_pim_boundary_oil_cmd(struct vty
*vty
, const char *oil
)
469 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_MODIFY
,
472 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
473 FRR_PIM_AF_XPATH_VAL
);
476 int pim_process_no_ip_pim_boundary_oil_cmd(struct vty
*vty
)
478 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_DESTROY
,
481 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
482 FRR_PIM_AF_XPATH_VAL
);
485 int pim_process_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
486 const char *group_str
, const char *source_str
)
488 nb_cli_enqueue_change(vty
, "./oif", NB_OP_MODIFY
, interface
);
491 char buf
[SRCDEST2STR_BUFFER
];
493 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
494 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
495 FRR_PIM_AF_XPATH_VAL
, buf
,
499 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
500 FRR_PIM_AF_XPATH_VAL
, source_str
,
504 int pim_process_no_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
505 const char *group_str
, const char *source_str
)
507 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
510 char buf
[SRCDEST2STR_BUFFER
];
512 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
513 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
514 FRR_PIM_AF_XPATH_VAL
, buf
,
518 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
519 FRR_PIM_AF_XPATH_VAL
, source_str
,
523 int pim_process_rp_cmd(struct vty
*vty
, const char *rp_str
,
524 const char *group_str
)
527 char rp_group_xpath
[XPATH_MAXLEN
];
532 result
= str2prefix(group_str
, &group
);
536 prefix_copy(&temp
, &group
);
538 if (!prefix_same(&group
, &temp
)) {
539 vty_out(vty
, "%% Inconsistent address and mask: %s\n",
541 return CMD_WARNING_CONFIG_FAILED
;
546 vty_out(vty
, "%% Bad group address specified: %s\n", group_str
);
547 return CMD_WARNING_CONFIG_FAILED
;
550 result
= inet_pton(PIM_AF
, rp_str
, &rp_addr
);
552 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
553 return CMD_WARNING_CONFIG_FAILED
;
556 if (pim_addr_is_any(rp_addr
) || pim_addr_is_multicast(rp_addr
)) {
557 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
558 return CMD_WARNING_CONFIG_FAILED
;
562 if (IN6_IS_ADDR_LINKLOCAL(&rp_addr
)) {
563 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
564 return CMD_WARNING_CONFIG_FAILED
;
568 vrfname
= pim_cli_get_vrf_name(vty
);
570 return CMD_WARNING_CONFIG_FAILED
;
572 snprintf(rp_group_xpath
, sizeof(rp_group_xpath
),
573 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
574 FRR_PIM_AF_XPATH_VAL
, rp_str
);
575 strlcat(rp_group_xpath
, "/group-list", sizeof(rp_group_xpath
));
577 nb_cli_enqueue_change(vty
, rp_group_xpath
, NB_OP_CREATE
, group_str
);
579 return nb_cli_apply_changes(vty
, NULL
);
582 int pim_process_no_rp_cmd(struct vty
*vty
, const char *rp_str
,
583 const char *group_str
)
585 char group_list_xpath
[XPATH_MAXLEN
];
586 char group_xpath
[XPATH_MAXLEN
];
587 char rp_xpath
[XPATH_MAXLEN
];
590 const struct lyd_node
*group_dnode
;
592 vrfname
= pim_cli_get_vrf_name(vty
);
594 return CMD_WARNING_CONFIG_FAILED
;
596 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
597 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
599 printed
= snprintf(group_list_xpath
, sizeof(group_list_xpath
),
600 "%s/group-list", rp_xpath
);
602 if (printed
>= (int)(sizeof(group_list_xpath
))) {
603 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
605 return CMD_WARNING_CONFIG_FAILED
;
608 printed
= snprintf(group_xpath
, sizeof(group_xpath
), "%s[.='%s']",
609 group_list_xpath
, group_str
);
611 if (printed
>= (int)(sizeof(group_xpath
))) {
612 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
614 return CMD_WARNING_CONFIG_FAILED
;
617 group_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, group_xpath
);
619 vty_out(vty
, "%% Unable to find specified RP\n");
623 if (yang_is_last_list_dnode(group_dnode
))
624 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
626 nb_cli_enqueue_change(vty
, group_list_xpath
, NB_OP_DESTROY
,
629 return nb_cli_apply_changes(vty
, NULL
);
632 int pim_process_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
633 const char *prefix_list
)
636 char rp_plist_xpath
[XPATH_MAXLEN
];
638 vrfname
= pim_cli_get_vrf_name(vty
);
640 return CMD_WARNING_CONFIG_FAILED
;
642 snprintf(rp_plist_xpath
, sizeof(rp_plist_xpath
),
643 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
644 FRR_PIM_AF_XPATH_VAL
, rp_str
);
645 strlcat(rp_plist_xpath
, "/prefix-list", sizeof(rp_plist_xpath
));
647 nb_cli_enqueue_change(vty
, rp_plist_xpath
, NB_OP_MODIFY
, prefix_list
);
649 return nb_cli_apply_changes(vty
, NULL
);
652 int pim_process_no_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
653 const char *prefix_list
)
655 char rp_xpath
[XPATH_MAXLEN
];
656 char plist_xpath
[XPATH_MAXLEN
];
658 const struct lyd_node
*plist_dnode
;
661 vrfname
= pim_cli_get_vrf_name(vty
);
663 return CMD_WARNING_CONFIG_FAILED
;
665 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
666 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
668 snprintf(plist_xpath
, sizeof(plist_xpath
), FRR_PIM_STATIC_RP_XPATH
,
669 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
670 strlcat(plist_xpath
, "/prefix-list", sizeof(plist_xpath
));
672 plist_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, plist_xpath
);
674 vty_out(vty
, "%% Unable to find specified RP\n");
678 plist
= yang_dnode_get_string(plist_dnode
, "%s", plist_xpath
);
679 if (strcmp(prefix_list
, plist
)) {
680 vty_out(vty
, "%% Unable to find specified RP\n");
684 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
686 return nb_cli_apply_changes(vty
, NULL
);
689 bool pim_sgaddr_match(pim_sgaddr item
, pim_sgaddr match
)
691 return (pim_addr_is_any(match
.grp
) ||
692 !pim_addr_cmp(match
.grp
, item
.grp
)) &&
693 (pim_addr_is_any(match
.src
) ||
694 !pim_addr_cmp(match
.src
, item
.src
));
697 void json_object_pim_ifp_add(struct json_object
*json
, struct interface
*ifp
)
699 struct pim_interface
*pim_ifp
;
702 json_object_string_add(json
, "name", ifp
->name
);
703 json_object_string_add(json
, "state", if_is_up(ifp
) ? "up" : "down");
704 json_object_string_addf(json
, "address", "%pPA",
705 &pim_ifp
->primary_address
);
706 json_object_int_add(json
, "index", ifp
->ifindex
);
708 if (if_is_multicast(ifp
))
709 json_object_boolean_true_add(json
, "flagMulticast");
711 if (if_is_broadcast(ifp
))
712 json_object_boolean_true_add(json
, "flagBroadcast");
714 if (ifp
->flags
& IFF_ALLMULTI
)
715 json_object_boolean_true_add(json
, "flagAllMulticast");
717 if (ifp
->flags
& IFF_PROMISC
)
718 json_object_boolean_true_add(json
, "flagPromiscuous");
720 if (PIM_IF_IS_DELETED(ifp
))
721 json_object_boolean_true_add(json
, "flagDeleted");
723 if (pim_if_lan_delay_enabled(ifp
))
724 json_object_boolean_true_add(json
, "lanDelayEnabled");
727 void pim_print_ifp_flags(struct vty
*vty
, struct interface
*ifp
)
729 vty_out(vty
, "Flags\n");
730 vty_out(vty
, "-----\n");
731 vty_out(vty
, "All Multicast : %s\n",
732 (ifp
->flags
& IFF_ALLMULTI
) ? "yes" : "no");
733 vty_out(vty
, "Broadcast : %s\n",
734 if_is_broadcast(ifp
) ? "yes" : "no");
735 vty_out(vty
, "Deleted : %s\n",
736 PIM_IF_IS_DELETED(ifp
) ? "yes" : "no");
737 vty_out(vty
, "Interface Index : %d\n", ifp
->ifindex
);
738 vty_out(vty
, "Multicast : %s\n",
739 if_is_multicast(ifp
) ? "yes" : "no");
740 vty_out(vty
, "Promiscuous : %s\n",
741 (ifp
->flags
& IFF_PROMISC
) ? "yes" : "no");
746 void json_object_pim_upstream_add(json_object
*json
, struct pim_upstream
*up
)
748 json_object_boolean_add(
749 json
, "drJoinDesired",
750 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED
));
751 json_object_boolean_add(
752 json
, "drJoinDesiredUpdated",
753 CHECK_FLAG(up
->flags
,
754 PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED
));
755 json_object_boolean_add(
756 json
, "firstHopRouter",
757 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FHR
));
758 json_object_boolean_add(
760 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
));
761 json_object_boolean_add(
763 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_PIM
));
764 json_object_boolean_add(
765 json
, "sourceStream",
766 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM
));
767 /* XXX: need to print ths flag in the plain text display as well */
768 json_object_boolean_add(
770 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP
));
771 json_object_boolean_add(
772 json
, "sendSGRptPrune",
773 CHECK_FLAG(up
->flags
,
774 PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE
));
775 json_object_boolean_add(
776 json
, "lastHopRouter",
777 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_LHR
));
778 json_object_boolean_add(
779 json
, "disableKATExpiry",
780 CHECK_FLAG(up
->flags
,
781 PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY
));
782 json_object_boolean_add(
783 json
, "staticIncomingInterface",
784 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF
));
785 json_object_boolean_add(
786 json
, "allowIncomingInterfaceinOil",
787 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL
));
788 json_object_boolean_add(
789 json
, "noPimRegistrationData",
790 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA
));
791 json_object_boolean_add(
792 json
, "forcePimRegistration",
793 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG
));
794 json_object_boolean_add(
795 json
, "sourceVxlanOrigination",
796 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG
));
797 json_object_boolean_add(
798 json
, "sourceVxlanTermination",
799 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM
));
800 json_object_boolean_add(
802 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN
));
803 json_object_boolean_add(
804 json
, "mlagNonDesignatedForwarder",
805 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF
));
809 pim_upstream_state2brief_str(enum pim_upstream_state join_state
,
810 char *state_str
, size_t state_str_len
)
812 switch (join_state
) {
813 case PIM_UPSTREAM_NOTJOINED
:
814 strlcpy(state_str
, "NotJ", state_str_len
);
816 case PIM_UPSTREAM_JOINED
:
817 strlcpy(state_str
, "J", state_str_len
);
820 strlcpy(state_str
, "Unk", state_str_len
);
825 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state
,
827 size_t state_str_len
)
831 strlcpy(state_str
, "RegNI", state_str_len
);
834 strlcpy(state_str
, "RegJ", state_str_len
);
836 case PIM_REG_JOIN_PENDING
:
838 strlcpy(state_str
, "RegP", state_str_len
);
844 void pim_show_rpf_refresh_stats(struct vty
*vty
, struct pim_instance
*pim
,
845 time_t now
, json_object
*json
)
847 char refresh_uptime
[10];
849 pim_time_uptime_begin(refresh_uptime
, sizeof(refresh_uptime
), now
,
850 pim
->rpf_cache_refresh_last
);
853 json_object_int_add(json
, "rpfCacheRefreshDelayMsecs",
854 router
->rpf_cache_refresh_delay_msec
);
856 json
, "rpfCacheRefreshTimer",
857 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
));
858 json_object_int_add(json
, "rpfCacheRefreshRequests",
859 pim
->rpf_cache_refresh_requests
);
860 json_object_int_add(json
, "rpfCacheRefreshEvents",
861 pim
->rpf_cache_refresh_events
);
862 json_object_string_add(json
, "rpfCacheRefreshLast",
864 json_object_int_add(json
, "nexthopLookups",
865 pim
->nexthop_lookups
);
866 json_object_int_add(json
, "nexthopLookupsAvoided",
867 pim
->nexthop_lookups_avoided
);
870 "RPF Cache Refresh Delay: %ld msecs\n"
871 "RPF Cache Refresh Timer: %ld msecs\n"
872 "RPF Cache Refresh Requests: %lld\n"
873 "RPF Cache Refresh Events: %lld\n"
874 "RPF Cache Refresh Last: %s\n"
875 "Nexthop Lookups: %lld\n"
876 "Nexthop Lookups Avoided: %lld\n",
877 router
->rpf_cache_refresh_delay_msec
,
878 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
),
879 (long long)pim
->rpf_cache_refresh_requests
,
880 (long long)pim
->rpf_cache_refresh_events
,
881 refresh_uptime
, (long long)pim
->nexthop_lookups
,
882 (long long)pim
->nexthop_lookups_avoided
);
886 void pim_show_rpf(struct pim_instance
*pim
, struct vty
*vty
, json_object
*json
)
888 struct pim_upstream
*up
;
889 time_t now
= pim_time_monotonic_sec();
890 struct ttable
*tt
= NULL
;
892 json_object
*json_group
= NULL
;
893 json_object
*json_row
= NULL
;
895 pim_show_rpf_refresh_stats(vty
, pim
, now
, json
);
901 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
904 "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
905 tt
->style
.cell
.rpad
= 2;
906 tt
->style
.corner
= '+';
910 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
911 const char *rpf_ifname
;
912 struct pim_rpf
*rpf
= &up
->rpf
;
915 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
920 char grp_str
[PIM_ADDRSTRLEN
];
921 char src_str
[PIM_ADDRSTRLEN
];
923 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
925 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
928 json_object_object_get_ex(json
, grp_str
, &json_group
);
931 json_group
= json_object_new_object();
932 json_object_object_add(json
, grp_str
,
936 json_row
= json_object_new_object();
937 json_object_string_add(json_row
, "source", src_str
);
938 json_object_string_add(json_row
, "group", grp_str
);
939 json_object_string_add(json_row
, "rpfInterface",
941 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
943 json_object_string_addf(
944 json_row
, "ribNexthop", "%pPAs",
945 &rpf
->source_nexthop
.mrib_nexthop_addr
);
947 json_row
, "routeMetric",
948 rpf
->source_nexthop
.mrib_route_metric
);
950 json_row
, "routePreference",
951 rpf
->source_nexthop
.mrib_metric_preference
);
952 json_object_object_add(json_group
, src_str
, json_row
);
956 tt
, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
957 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
959 &rpf
->source_nexthop
.mrib_nexthop_addr
,
960 rpf
->source_nexthop
.mrib_route_metric
,
961 rpf
->source_nexthop
.mrib_metric_preference
);
964 /* Dump the generated table. */
966 table
= ttable_dump(tt
, "\n");
967 vty_out(vty
, "%s\n", table
);
968 XFREE(MTYPE_TMP
, table
);
973 void pim_show_neighbors_secondary(struct pim_instance
*pim
, struct vty
*vty
)
975 struct interface
*ifp
;
976 struct ttable
*tt
= NULL
;
980 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
981 ttable_add_row(tt
, "Interface|Address|Neighbor|Secondary");
982 tt
->style
.cell
.rpad
= 2;
983 tt
->style
.corner
= '+';
986 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
987 struct pim_interface
*pim_ifp
;
989 struct listnode
*neighnode
;
990 struct pim_neighbor
*neigh
;
997 if (pim_ifp
->pim_sock_fd
< 0)
1000 ifaddr
= pim_ifp
->primary_address
;
1002 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1004 struct listnode
*prefix_node
;
1007 if (!neigh
->prefix_list
)
1010 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
,
1012 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pFX",
1014 &neigh
->source_addr
, p
);
1017 /* Dump the generated table. */
1018 table
= ttable_dump(tt
, "\n");
1019 vty_out(vty
, "%s\n", table
);
1020 XFREE(MTYPE_TMP
, table
);
1024 void pim_show_state(struct pim_instance
*pim
, struct vty
*vty
,
1025 const char *src_or_group
, const char *group
,
1028 struct channel_oil
*c_oil
;
1030 struct ttable
*tt
= NULL
;
1034 json_object
*json_group
= NULL
;
1035 json_object
*json_ifp_in
= NULL
;
1036 json_object
*json_ifp_out
= NULL
;
1037 json_object
*json_source
= NULL
;
1041 now
= pim_time_monotonic_sec();
1045 "Codes: J -> Pim Join, I -> " GM
" Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
1048 "Active Source Group RPT IIF OIL\n");
1050 /* Prepare table. */
1051 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1052 ttable_add_row(tt
, "Active|Source|Group|RPT|IIF|OIL");
1053 tt
->style
.cell
.rpad
= 2;
1054 tt
->style
.corner
= '+';
1059 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
1060 char src_str
[PIM_ADDRSTRLEN
];
1061 char grp_str
[PIM_ADDRSTRLEN
];
1062 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
1063 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
1065 struct interface
*ifp_in
;
1071 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil
->up
->flags
)) ||
1072 pim_addr_is_any(*oil_origin(c_oil
)))
1077 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1078 oil_mcastgrp(c_oil
));
1079 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1081 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
1084 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
1086 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
1089 if (strcmp(src_or_group
, src_str
) &&
1090 strcmp(src_or_group
, grp_str
))
1093 if (group
&& strcmp(group
, grp_str
))
1099 /* Find the group, create it if it doesn't exist */
1100 json_object_object_get_ex(json
, grp_str
, &json_group
);
1103 json_group
= json_object_new_object();
1104 json_object_object_add(json
, grp_str
,
1108 /* Find the source nested under the group, create it if
1111 json_object_object_get_ex(json_group
, src_str
,
1115 json_source
= json_object_new_object();
1116 json_object_object_add(json_group
, src_str
,
1120 /* Find the inbound interface nested under the source,
1121 * create it if it doesn't exist
1123 json_object_object_get_ex(json_source
, in_ifname
,
1127 json_ifp_in
= json_object_new_object();
1128 json_object_object_add(json_source
, in_ifname
,
1130 json_object_int_add(json_source
, "installed",
1132 json_object_boolean_add(json_source
, "isRpt",
1134 json_object_int_add(json_source
, "refCount",
1135 c_oil
->oil_ref_count
);
1136 json_object_int_add(json_source
, "oilListSize",
1138 json_object_int_add(
1139 json_source
, "oilRescan",
1140 c_oil
->oil_inherited_rescan
);
1141 json_object_int_add(json_source
, "lastUsed",
1142 c_oil
->cc
.lastused
);
1143 json_object_int_add(json_source
, "packetCount",
1145 json_object_int_add(json_source
, "byteCount",
1147 json_object_int_add(json_source
,
1149 c_oil
->cc
.wrong_if
);
1154 vty_out(vty
, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1155 c_oil
->installed
, oil_origin(c_oil
),
1156 oil_mcastgrp(c_oil
), isRpt
? "y" : "n",
1160 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
1162 struct interface
*ifp_out
;
1163 char oif_uptime
[10];
1166 ttl
= oil_if_has(c_oil
, oif_vif_index
);
1170 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
1172 oif_uptime
, sizeof(oif_uptime
),
1173 now
- c_oil
->oif_creation
[oif_vif_index
]);
1176 strlcpy(out_ifname
, ifp_out
->name
,
1177 sizeof(out_ifname
));
1179 strlcpy(out_ifname
, "<oif?>",
1180 sizeof(out_ifname
));
1183 json_ifp_out
= json_object_new_object();
1184 json_object_string_add(json_ifp_out
, "source",
1186 json_object_string_add(json_ifp_out
, "group",
1188 json_object_string_add(json_ifp_out
,
1191 json_object_string_add(json_ifp_out
,
1192 "outboundInterface",
1194 json_object_int_add(json_ifp_out
, "installed",
1197 json_object_object_add(json_ifp_in
, out_ifname
,
1201 snprintf(flag
, sizeof(flag
), "(%c%c%c%c%c)",
1202 (c_oil
->oif_flags
[oif_vif_index
] &
1203 PIM_OIF_FLAG_PROTO_GM
)
1206 (c_oil
->oif_flags
[oif_vif_index
] &
1207 PIM_OIF_FLAG_PROTO_PIM
)
1210 (c_oil
->oif_flags
[oif_vif_index
] &
1211 PIM_OIF_FLAG_PROTO_VXLAN
)
1214 (c_oil
->oif_flags
[oif_vif_index
] &
1215 PIM_OIF_FLAG_PROTO_STAR
)
1218 (c_oil
->oif_flags
[oif_vif_index
] &
1226 vty_out(vty
, "%s%s", out_ifname
, flag
);
1229 tt
, "%d|%pPAs|%pPAs|%s|%s|%s%s",
1232 oil_mcastgrp(c_oil
),
1233 isRpt
? "y" : "n", in_ifname
,
1238 vty_out(vty
, ", %s%s", out_ifname
,
1242 "%c|%c|%c|%c|%c|%s%s",
1243 ' ', ' ', ' ', ' ', ' ',
1255 /* Dump the generated table. */
1260 table
= ttable_dump(tt
, "\n");
1261 vty_out(vty
, "%s\n", table
);
1262 XFREE(MTYPE_TMP
, table
);
1268 /* pim statistics - just adding only bsm related now.
1269 * We can continue to add all pim related stats here.
1271 void pim_show_statistics(struct pim_instance
*pim
, struct vty
*vty
,
1272 const char *ifname
, bool uj
)
1274 json_object
*json
= NULL
;
1275 struct interface
*ifp
;
1278 json
= json_object_new_object();
1279 json_object_int_add(json
, "bsmRx", pim
->bsm_rcvd
);
1280 json_object_int_add(json
, "bsmTx", pim
->bsm_sent
);
1281 json_object_int_add(json
, "bsmDropped", pim
->bsm_dropped
);
1283 vty_out(vty
, "BSM Statistics :\n");
1284 vty_out(vty
, "----------------\n");
1285 vty_out(vty
, "Number of Received BSMs : %" PRIu64
"\n",
1287 vty_out(vty
, "Number of Forwared BSMs : %" PRIu64
"\n",
1289 vty_out(vty
, "Number of Dropped BSMs : %" PRIu64
"\n",
1295 /* scan interfaces */
1296 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1297 struct pim_interface
*pim_ifp
= ifp
->info
;
1299 if (ifname
&& strcmp(ifname
, ifp
->name
))
1306 vty_out(vty
, "Interface : %s\n", ifp
->name
);
1307 vty_out(vty
, "-------------------\n");
1309 "Number of BSMs dropped due to config miss : %u\n",
1310 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1311 vty_out(vty
, "Number of unicast BSMs dropped : %u\n",
1312 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1314 "Number of BSMs dropped due to invalid scope zone : %u\n",
1315 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1318 json_object
*json_row
= NULL
;
1320 json_row
= json_object_new_object();
1322 json_object_string_add(json_row
, "If Name", ifp
->name
);
1323 json_object_int_add(json_row
, "bsmDroppedConfig",
1324 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1325 json_object_int_add(
1326 json_row
, "bsmDroppedUnicast",
1327 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1328 json_object_int_add(json_row
,
1329 "bsmDroppedInvalidScopeZone",
1330 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1331 json_object_object_add(json
, ifp
->name
, json_row
);
1337 vty_json(vty
, json
);
1340 void pim_show_upstream(struct pim_instance
*pim
, struct vty
*vty
,
1341 pim_sgaddr
*sg
, json_object
*json
)
1343 struct pim_upstream
*up
;
1344 struct ttable
*tt
= NULL
;
1347 json_object
*json_group
= NULL
;
1348 json_object
*json_row
= NULL
;
1350 now
= pim_time_monotonic_sec();
1353 /* Prepare table. */
1354 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1357 "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
1358 tt
->style
.cell
.rpad
= 2;
1359 tt
->style
.corner
= '+';
1363 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1365 char join_timer
[10];
1368 char msdp_reg_timer
[10];
1369 char state_str
[PIM_REG_STATE_STR_LEN
];
1371 if (!pim_sgaddr_match(up
->sg
, *sg
))
1374 pim_time_uptime(uptime
, sizeof(uptime
),
1375 now
- up
->state_transition
);
1376 pim_time_timer_to_hhmmss(join_timer
, sizeof(join_timer
),
1380 * If the upstream is not dummy and it has a J/P timer for the
1381 * neighbor display that
1383 if (!up
->t_join_timer
&& up
->rpf
.source_nexthop
.interface
) {
1384 struct pim_neighbor
*nbr
;
1386 nbr
= pim_neighbor_find(
1387 up
->rpf
.source_nexthop
.interface
,
1390 pim_time_timer_to_hhmmss(join_timer
,
1395 pim_time_timer_to_hhmmss(rs_timer
, sizeof(rs_timer
),
1397 pim_time_timer_to_hhmmss(ka_timer
, sizeof(ka_timer
),
1399 pim_time_timer_to_hhmmss(msdp_reg_timer
, sizeof(msdp_reg_timer
),
1400 up
->t_msdp_reg_timer
);
1402 pim_upstream_state2brief_str(up
->join_state
, state_str
,
1404 if (up
->reg_state
!= PIM_REG_NOINFO
) {
1405 char tmp_str
[PIM_REG_STATE_STR_LEN
];
1406 char tmp
[sizeof(state_str
) + 1];
1408 snprintf(tmp
, sizeof(tmp
), ",%s",
1409 pim_reg_state2brief_str(up
->reg_state
, tmp_str
,
1411 strlcat(state_str
, tmp
, sizeof(state_str
));
1415 char grp_str
[PIM_ADDRSTRLEN
];
1416 char src_str
[PIM_ADDRSTRLEN
];
1418 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1420 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1423 json_object_object_get_ex(json
, grp_str
, &json_group
);
1426 json_group
= json_object_new_object();
1427 json_object_object_add(json
, grp_str
,
1431 json_row
= json_object_new_object();
1432 json_object_pim_upstream_add(json_row
, up
);
1433 json_object_string_add(
1434 json_row
, "inboundInterface",
1435 up
->rpf
.source_nexthop
.interface
1436 ? up
->rpf
.source_nexthop
.interface
->name
1440 * The RPF address we use is slightly different
1441 * based upon what we are looking up.
1442 * If we have a S, list that unless
1443 * we are the FHR, else we just put
1444 * the RP as the rpfAddress
1446 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
||
1447 pim_addr_is_any(up
->sg
.src
)) {
1448 struct pim_rpf
*rpg
;
1450 rpg
= RP(pim
, up
->sg
.grp
);
1451 json_object_string_addf(json_row
, "rpfAddress",
1452 "%pPA", &rpg
->rpf_addr
);
1454 json_object_string_add(json_row
, "rpfAddress",
1458 json_object_string_add(json_row
, "source", src_str
);
1459 json_object_string_add(json_row
, "group", grp_str
);
1460 json_object_string_add(json_row
, "state", state_str
);
1461 json_object_string_add(
1462 json_row
, "joinState",
1463 pim_upstream_state2str(up
->join_state
));
1464 json_object_string_add(
1465 json_row
, "regState",
1466 pim_reg_state2str(up
->reg_state
, state_str
,
1467 sizeof(state_str
)));
1468 json_object_string_add(json_row
, "upTime", uptime
);
1469 json_object_string_add(json_row
, "joinTimer",
1471 json_object_string_add(json_row
, "resetTimer",
1473 json_object_string_add(json_row
, "keepaliveTimer",
1475 json_object_string_add(json_row
, "msdpRegTimer",
1477 json_object_int_add(json_row
, "refCount",
1479 json_object_int_add(json_row
, "sptBit", up
->sptbit
);
1480 json_object_object_add(json_group
, src_str
, json_row
);
1483 "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
1484 up
->rpf
.source_nexthop
.interface
1485 ? up
->rpf
.source_nexthop
.interface
->name
1487 &up
->sg
.src
, &up
->sg
.grp
, state_str
, uptime
,
1488 join_timer
, rs_timer
, ka_timer
, up
->ref_count
);
1491 /* Dump the generated table. */
1493 table
= ttable_dump(tt
, "\n");
1494 vty_out(vty
, "%s\n", table
);
1495 XFREE(MTYPE_TMP
, table
);
1500 static void pim_show_join_desired_helper(struct pim_instance
*pim
,
1502 struct pim_upstream
*up
,
1503 json_object
*json
, bool uj
,
1506 json_object
*json_group
= NULL
;
1507 json_object
*json_row
= NULL
;
1510 char grp_str
[PIM_ADDRSTRLEN
];
1511 char src_str
[PIM_ADDRSTRLEN
];
1513 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
1514 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &up
->sg
.src
);
1516 json_object_object_get_ex(json
, grp_str
, &json_group
);
1519 json_group
= json_object_new_object();
1520 json_object_object_add(json
, grp_str
, json_group
);
1523 json_row
= json_object_new_object();
1524 json_object_pim_upstream_add(json_row
, up
);
1525 json_object_string_add(json_row
, "source", src_str
);
1526 json_object_string_add(json_row
, "group", grp_str
);
1528 if (pim_upstream_evaluate_join_desired(pim
, up
))
1529 json_object_boolean_true_add(json_row
,
1530 "evaluateJoinDesired");
1532 json_object_object_add(json_group
, src_str
, json_row
);
1535 ttable_add_row(tt
, "%pPAs|%pPAs|%s", &up
->sg
.src
, &up
->sg
.grp
,
1536 pim_upstream_evaluate_join_desired(pim
, up
)
1542 void pim_show_join_desired(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1544 struct pim_upstream
*up
;
1545 struct ttable
*tt
= NULL
;
1548 json_object
*json
= NULL
;
1551 json
= json_object_new_object();
1553 /* Prepare table. */
1554 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1555 ttable_add_row(tt
, "Source|Group|EvalJD");
1556 tt
->style
.cell
.rpad
= 2;
1557 tt
->style
.corner
= '+';
1561 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1562 /* scan all interfaces */
1563 pim_show_join_desired_helper(pim
, vty
, up
, json
, uj
, tt
);
1567 vty_json(vty
, json
);
1569 /* Dump the generated table. */
1570 table
= ttable_dump(tt
, "\n");
1571 vty_out(vty
, "%s\n", table
);
1572 XFREE(MTYPE_TMP
, table
);
1577 void pim_show_upstream_rpf(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1579 struct pim_upstream
*up
;
1580 struct ttable
*tt
= NULL
;
1582 json_object
*json
= NULL
;
1583 json_object
*json_group
= NULL
;
1584 json_object
*json_row
= NULL
;
1587 json
= json_object_new_object();
1589 /* Prepare table. */
1590 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1592 "Source|Group|RpfIface|RibNextHop|RpfAddress");
1593 tt
->style
.cell
.rpad
= 2;
1594 tt
->style
.corner
= '+';
1598 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1599 struct pim_rpf
*rpf
;
1600 const char *rpf_ifname
;
1605 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
1610 char grp_str
[PIM_ADDRSTRLEN
];
1611 char src_str
[PIM_ADDRSTRLEN
];
1613 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1615 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1617 json_object_object_get_ex(json
, grp_str
, &json_group
);
1620 json_group
= json_object_new_object();
1621 json_object_object_add(json
, grp_str
,
1625 json_row
= json_object_new_object();
1626 json_object_pim_upstream_add(json_row
, up
);
1627 json_object_string_add(json_row
, "source", src_str
);
1628 json_object_string_add(json_row
, "group", grp_str
);
1629 json_object_string_add(json_row
, "rpfInterface",
1631 json_object_string_addf(
1632 json_row
, "ribNexthop", "%pPAs",
1633 &rpf
->source_nexthop
.mrib_nexthop_addr
);
1634 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
1636 json_object_object_add(json_group
, src_str
, json_row
);
1638 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%pPA|%pPA",
1639 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
1640 &rpf
->source_nexthop
.mrib_nexthop_addr
,
1646 vty_json(vty
, json
);
1648 /* Dump the generated table. */
1649 table
= ttable_dump(tt
, "\n");
1650 vty_out(vty
, "%s\n", table
);
1651 XFREE(MTYPE_TMP
, table
);
1656 static void pim_show_join_helper(struct pim_interface
*pim_ifp
,
1657 struct pim_ifchannel
*ch
, json_object
*json
,
1658 time_t now
, struct ttable
*tt
)
1660 json_object
*json_iface
= NULL
;
1661 json_object
*json_row
= NULL
;
1662 json_object
*json_grp
= NULL
;
1668 ifaddr
= pim_ifp
->primary_address
;
1670 pim_time_uptime_begin(uptime
, sizeof(uptime
), now
, ch
->ifjoin_creation
);
1671 pim_time_timer_to_mmss(expire
, sizeof(expire
),
1672 ch
->t_ifjoin_expiry_timer
);
1673 pim_time_timer_to_mmss(prune
, sizeof(prune
),
1674 ch
->t_ifjoin_prune_pending_timer
);
1677 char ch_grp_str
[PIM_ADDRSTRLEN
];
1679 json_object_object_get_ex(json
, ch
->interface
->name
,
1683 json_iface
= json_object_new_object();
1684 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1685 json_object_object_add(json
, ch
->interface
->name
,
1689 json_row
= json_object_new_object();
1690 json_object_string_addf(json_row
, "source", "%pPAs",
1692 json_object_string_addf(json_row
, "group", "%pPAs",
1694 json_object_string_add(json_row
, "upTime", uptime
);
1695 json_object_string_add(json_row
, "expire", expire
);
1696 json_object_string_add(json_row
, "prune", prune
);
1697 json_object_string_add(
1698 json_row
, "channelJoinName",
1699 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
));
1700 if (PIM_IF_FLAG_TEST_S_G_RPT(ch
->flags
))
1701 json_object_int_add(json_row
, "sgRpt", 1);
1702 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch
->flags
))
1703 json_object_int_add(json_row
, "protocolPim", 1);
1704 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch
->flags
))
1705 json_object_int_add(json_row
, "protocolIgmp", 1);
1706 snprintfrr(ch_grp_str
, sizeof(ch_grp_str
), "%pPAs",
1708 json_object_object_get_ex(json_iface
, ch_grp_str
, &json_grp
);
1710 json_grp
= json_object_new_object();
1711 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1713 json_object_object_addf(json_iface
, json_grp
, "%pPAs",
1716 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1720 tt
, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
1721 ch
->interface
->name
, &ifaddr
, &ch
->sg
.src
, &ch
->sg
.grp
,
1722 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
),
1723 uptime
, expire
, prune
);
1727 int pim_show_join_cmd_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
1728 pim_addr g
, const char *json
)
1732 struct pim_instance
*pim
;
1733 json_object
*json_parent
= NULL
;
1735 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1738 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1744 vty_out(vty
, "%% Unable to find pim instance\n");
1748 if (!pim_addr_is_any(s_or_g
)) {
1749 if (!pim_addr_is_any(g
)) {
1757 json_parent
= json_object_new_object();
1759 pim_show_join(pim
, vty
, &sg
, json_parent
);
1762 vty_json(vty
, json_parent
);
1767 int pim_show_join_vrf_all_cmd_helper(struct vty
*vty
, const char *json
)
1769 pim_sgaddr sg
= {0};
1770 struct vrf
*vrf_struct
;
1771 json_object
*json_parent
= NULL
;
1772 json_object
*json_vrf
= NULL
;
1775 json_parent
= json_object_new_object();
1777 RB_FOREACH (vrf_struct
, vrf_name_head
, &vrfs_by_name
) {
1779 vty_out(vty
, "VRF: %s\n", vrf_struct
->name
);
1781 json_vrf
= json_object_new_object();
1782 pim_show_join(vrf_struct
->info
, vty
, &sg
, json_vrf
);
1785 json_object_object_add(json_parent
, vrf_struct
->name
,
1789 vty_json(vty
, json_parent
);
1794 void pim_show_join(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
1797 struct pim_interface
*pim_ifp
;
1798 struct pim_ifchannel
*ch
;
1799 struct interface
*ifp
;
1801 struct ttable
*tt
= NULL
;
1804 now
= pim_time_monotonic_sec();
1807 /* Prepare table. */
1808 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1811 "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
1812 tt
->style
.cell
.rpad
= 2;
1813 tt
->style
.corner
= '+';
1817 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1818 pim_ifp
= ifp
->info
;
1822 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1823 if (!pim_sgaddr_match(ch
->sg
, *sg
))
1826 pim_show_join_helper(pim_ifp
, ch
, json
, now
, tt
);
1827 } /* scan interface channels */
1829 /* Dump the generated table. */
1831 table
= ttable_dump(tt
, "\n");
1832 vty_out(vty
, "%s\n", table
);
1833 XFREE(MTYPE_TMP
, table
);
1838 static void pim_show_jp_agg_helper(struct interface
*ifp
,
1839 struct pim_neighbor
*neigh
,
1840 struct pim_upstream
*up
, int is_join
,
1843 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pPAs|%s", ifp
->name
,
1844 &neigh
->source_addr
, &up
->sg
.src
, &up
->sg
.grp
,
1845 is_join
? "J" : "P");
1848 int pim_show_jp_agg_list_cmd_helper(const char *vrf
, struct vty
*vty
)
1851 struct pim_instance
*pim
;
1853 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1856 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1862 vty_out(vty
, "%% Unable to find pim instance\n");
1866 pim_show_jp_agg_list(pim
, vty
);
1871 void pim_show_jp_agg_list(struct pim_instance
*pim
, struct vty
*vty
)
1873 struct interface
*ifp
;
1874 struct pim_interface
*pim_ifp
;
1875 struct listnode
*n_node
;
1876 struct pim_neighbor
*neigh
;
1877 struct listnode
*jag_node
;
1878 struct pim_jp_agg_group
*jag
;
1879 struct listnode
*js_node
;
1880 struct pim_jp_sources
*js
;
1884 /* Prepare table. */
1885 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1886 ttable_add_row(tt
, "Interface|RPF Nbr|Source|Group|State");
1887 tt
->style
.cell
.rpad
= 2;
1888 tt
->style
.corner
= '+';
1891 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1892 pim_ifp
= ifp
->info
;
1896 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, n_node
,
1898 for (ALL_LIST_ELEMENTS_RO(neigh
->upstream_jp_agg
,
1900 for (ALL_LIST_ELEMENTS_RO(jag
->sources
, js_node
,
1902 pim_show_jp_agg_helper(ifp
, neigh
,
1910 /* Dump the generated table. */
1911 table
= ttable_dump(tt
, "\n");
1912 vty_out(vty
, "%s\n", table
);
1913 XFREE(MTYPE_TMP
, table
);
1917 int pim_show_membership_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
1921 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1926 pim_show_membership(v
->info
, vty
, uj
);
1931 static void pim_show_membership_helper(struct vty
*vty
,
1932 struct pim_interface
*pim_ifp
,
1933 struct pim_ifchannel
*ch
,
1934 struct json_object
*json
)
1936 json_object
*json_iface
= NULL
;
1937 json_object
*json_row
= NULL
;
1939 json_object_object_get_ex(json
, ch
->interface
->name
, &json_iface
);
1941 json_iface
= json_object_new_object();
1942 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1943 json_object_object_add(json
, ch
->interface
->name
, json_iface
);
1946 json_row
= json_object_new_object();
1947 json_object_string_addf(json_row
, "source", "%pPAs", &ch
->sg
.src
);
1948 json_object_string_addf(json_row
, "group", "%pPAs", &ch
->sg
.grp
);
1949 json_object_string_add(json_row
, "localMembership",
1950 ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
1953 json_object_object_addf(json_iface
, json_row
, "%pPAs", &ch
->sg
.grp
);
1956 void pim_show_membership(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1958 struct pim_interface
*pim_ifp
;
1959 struct pim_ifchannel
*ch
;
1960 struct interface
*ifp
;
1961 enum json_type type
;
1962 json_object
*json
= NULL
;
1963 json_object
*json_tmp
= NULL
;
1964 struct ttable
*tt
= NULL
;
1967 json
= json_object_new_object();
1969 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1970 pim_ifp
= ifp
->info
;
1974 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1975 pim_show_membership_helper(vty
, pim_ifp
, ch
, json
);
1976 } /* scan interface channels */
1980 vty_json(vty
, json
);
1982 /* Prepare table. */
1983 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1984 ttable_add_row(tt
, "Interface|Address|Source|Group|Membership");
1985 tt
->style
.cell
.rpad
= 2;
1986 tt
->style
.corner
= '+';
1990 * Example of the json data we are traversing
1996 * "address":"10.1.20.1",
1998 * "flagMulticast":true,
1999 * "flagBroadcast":true,
2000 * "lanDelayEnabled":true,
2003 * "group":"226.10.10.10",
2004 * "localMembership":"INCLUDE"
2010 /* foreach interface */
2011 json_object_object_foreach(json
, key
, val
)
2014 /* Find all of the keys where the val is an object. In
2016 * above the only one is 226.10.10.10
2018 json_object_object_foreach(val
, if_field_key
,
2021 type
= json_object_get_type(if_field_val
);
2023 if (type
== json_type_object
) {
2024 const char *address
, *source
,
2027 json_object_object_get_ex(
2028 val
, "address", &json_tmp
);
2029 address
= json_object_get_string(
2032 json_object_object_get_ex(if_field_val
,
2035 source
= json_object_get_string(
2038 json_object_object_get_ex(
2039 if_field_val
, "localMembership",
2042 json_object_get_string(
2045 ttable_add_row(tt
, "%s|%s|%s|%s|%s",
2046 key
, address
, source
,
2052 json_object_free(json
);
2053 /* Dump the generated table. */
2054 table
= ttable_dump(tt
, "\n");
2055 vty_out(vty
, "%s\n", table
);
2056 XFREE(MTYPE_TMP
, table
);
2061 static void pim_show_channel_helper(struct pim_instance
*pim
,
2062 struct pim_interface
*pim_ifp
,
2063 struct pim_ifchannel
*ch
, json_object
*json
,
2064 bool uj
, struct ttable
*tt
)
2066 struct pim_upstream
*up
= ch
->upstream
;
2067 json_object
*json_group
= NULL
;
2068 json_object
*json_row
= NULL
;
2071 char grp_str
[PIM_ADDRSTRLEN
];
2073 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
2074 json_object_object_get_ex(json
, grp_str
, &json_group
);
2077 json_group
= json_object_new_object();
2078 json_object_object_add(json
, grp_str
, json_group
);
2081 json_row
= json_object_new_object();
2082 json_object_pim_upstream_add(json_row
, up
);
2083 json_object_string_add(json_row
, "interface",
2084 ch
->interface
->name
);
2085 json_object_string_addf(json_row
, "source", "%pPAs",
2087 json_object_string_addf(json_row
, "group", "%pPAs",
2090 if (pim_macro_ch_lost_assert(ch
))
2091 json_object_boolean_true_add(json_row
, "lostAssert");
2093 if (pim_macro_chisin_joins(ch
))
2094 json_object_boolean_true_add(json_row
, "joins");
2096 if (pim_macro_chisin_pim_include(ch
))
2097 json_object_boolean_true_add(json_row
, "pimInclude");
2099 if (pim_upstream_evaluate_join_desired(pim
, up
))
2100 json_object_boolean_true_add(json_row
,
2101 "evaluateJoinDesired");
2103 json_object_object_addf(json_group
, json_row
, "%pPAs",
2107 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
2108 ch
->interface
->name
, &up
->sg
.src
, &up
->sg
.grp
,
2109 pim_macro_ch_lost_assert(ch
) ? "yes" : "no",
2110 pim_macro_chisin_joins(ch
) ? "yes" : "no",
2111 pim_macro_chisin_pim_include(ch
) ? "yes" : "no",
2112 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up
->flags
)
2115 pim_upstream_evaluate_join_desired(pim
, up
)
2121 void pim_show_channel(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2123 struct pim_interface
*pim_ifp
;
2124 struct pim_ifchannel
*ch
;
2125 struct interface
*ifp
;
2126 struct ttable
*tt
= NULL
;
2127 json_object
*json
= NULL
;
2131 json
= json_object_new_object();
2133 /* Prepare table. */
2134 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2137 "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
2138 tt
->style
.cell
.rpad
= 2;
2139 tt
->style
.corner
= '+';
2143 /* scan per-interface (S,G) state */
2144 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2145 pim_ifp
= ifp
->info
;
2149 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
2150 /* scan all interfaces */
2151 pim_show_channel_helper(pim
, pim_ifp
, ch
, json
, uj
, tt
);
2156 vty_json(vty
, json
);
2158 /* Dump the generated table. */
2159 table
= ttable_dump(tt
, "\n");
2160 vty_out(vty
, "%s\n", table
);
2161 XFREE(MTYPE_TMP
, table
);
2166 int pim_show_channel_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2170 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2175 pim_show_channel(v
->info
, vty
, uj
);
2180 int pim_show_interface_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
,
2181 bool mlag
, const char *interface
)
2184 json_object
*json_parent
= NULL
;
2186 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2192 json_parent
= json_object_new_object();
2195 pim_show_interfaces_single(v
->info
, vty
, interface
, mlag
,
2198 pim_show_interfaces(v
->info
, vty
, mlag
, json_parent
);
2201 vty_json(vty
, json_parent
);
2206 int pim_show_interface_vrf_all_cmd_helper(struct vty
*vty
, bool uj
, bool mlag
,
2207 const char *interface
)
2210 json_object
*json_parent
= NULL
;
2211 json_object
*json_vrf
= NULL
;
2214 json_parent
= json_object_new_object();
2216 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
2218 vty_out(vty
, "VRF: %s\n", v
->name
);
2220 json_vrf
= json_object_new_object();
2223 pim_show_interfaces_single(v
->info
, vty
, interface
,
2226 pim_show_interfaces(v
->info
, vty
, mlag
, json_vrf
);
2229 json_object_object_add(json_parent
, v
->name
, json_vrf
);
2232 vty_json(vty
, json_parent
);
2237 void pim_show_interfaces(struct pim_instance
*pim
, struct vty
*vty
, bool mlag
,
2240 struct interface
*ifp
;
2241 struct pim_interface
*pim_ifp
;
2242 struct pim_upstream
*up
;
2245 int pim_ifchannels
= 0;
2247 struct ttable
*tt
= NULL
;
2249 json_object
*json_row
= NULL
;
2250 json_object
*json_tmp
;
2254 json
= json_object_new_object();
2257 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2258 pim_ifp
= ifp
->info
;
2263 if (mlag
== true && pim_ifp
->activeactive
== false)
2266 pim_nbrs
= pim_ifp
->pim_neighbor_list
->count
;
2267 pim_ifchannels
= pim_if_ifchannel_count(pim_ifp
);
2270 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
)
2271 if (ifp
== up
->rpf
.source_nexthop
.interface
)
2272 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
)
2275 json_row
= json_object_new_object();
2276 json_object_pim_ifp_add(json_row
, ifp
);
2277 json_object_int_add(json_row
, "pimNeighbors", pim_nbrs
);
2278 json_object_int_add(json_row
, "pimIfChannels", pim_ifchannels
);
2279 json_object_int_add(json_row
, "firstHopRouterCount", fhr
);
2280 json_object_string_addf(json_row
, "pimDesignatedRouter",
2281 "%pPAs", &pim_ifp
->pim_dr_addr
);
2283 if (!pim_addr_cmp(pim_ifp
->pim_dr_addr
,
2284 pim_ifp
->primary_address
))
2285 json_object_boolean_true_add(
2286 json_row
, "pimDesignatedRouterLocal");
2288 json_object_object_add(json
, ifp
->name
, json_row
);
2293 /* Prepare table. */
2294 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2297 "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
2298 tt
->style
.cell
.rpad
= 2;
2299 tt
->style
.corner
= '+';
2302 json_object_object_foreach(json
, key
, val
)
2304 const char *state
, *address
, *pimdr
;
2305 int neighbors
, firsthpr
, pimifchnl
;
2307 json_object_object_get_ex(val
, "state", &json_tmp
);
2308 state
= json_object_get_string(json_tmp
);
2310 json_object_object_get_ex(val
, "address", &json_tmp
);
2311 address
= json_object_get_string(json_tmp
);
2313 json_object_object_get_ex(val
, "pimNeighbors",
2315 neighbors
= json_object_get_int(json_tmp
);
2317 if (json_object_object_get_ex(
2318 val
, "pimDesignatedRouterLocal",
2322 json_object_object_get_ex(
2323 val
, "pimDesignatedRouter", &json_tmp
);
2324 pimdr
= json_object_get_string(json_tmp
);
2327 json_object_object_get_ex(val
, "firstHopRouter",
2329 firsthpr
= json_object_get_int(json_tmp
);
2331 json_object_object_get_ex(val
, "pimIfChannels",
2333 pimifchnl
= json_object_get_int(json_tmp
);
2335 ttable_add_row(tt
, "%s|%s|%s|%d|%s|%d|%d", key
, state
,
2336 address
, neighbors
, pimdr
, firsthpr
,
2339 json_object_free(json
);
2341 /* Dump the generated table. */
2342 table
= ttable_dump(tt
, "\n");
2343 vty_out(vty
, "%s\n", table
);
2344 XFREE(MTYPE_TMP
, table
);
2350 void pim_show_interfaces_single(struct pim_instance
*pim
, struct vty
*vty
,
2351 const char *ifname
, bool mlag
,
2355 struct interface
*ifp
;
2356 struct listnode
*neighnode
;
2357 struct pim_interface
*pim_ifp
;
2358 struct pim_neighbor
*neigh
;
2359 struct pim_upstream
*up
;
2361 char dr_str
[PIM_ADDRSTRLEN
];
2364 char grp_str
[PIM_ADDRSTRLEN
];
2365 char hello_period
[10];
2366 char hello_timer
[10];
2367 char neigh_src_str
[PIM_ADDRSTRLEN
];
2368 char src_str
[PIM_ADDRSTRLEN
];
2369 char stat_uptime
[10];
2371 int found_ifname
= 0;
2373 json_object
*json_row
= NULL
;
2374 json_object
*json_pim_neighbor
= NULL
;
2375 json_object
*json_pim_neighbors
= NULL
;
2376 json_object
*json_group
= NULL
;
2377 json_object
*json_group_source
= NULL
;
2378 json_object
*json_fhr_sources
= NULL
;
2379 struct pim_secondary_addr
*sec_addr
;
2380 struct listnode
*sec_node
;
2382 now
= pim_time_monotonic_sec();
2384 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2385 pim_ifp
= ifp
->info
;
2390 if (mlag
== true && pim_ifp
->activeactive
== false)
2393 if (strcmp(ifname
, "detail") && strcmp(ifname
, ifp
->name
))
2397 ifaddr
= pim_ifp
->primary_address
;
2398 snprintfrr(dr_str
, sizeof(dr_str
), "%pPAs",
2399 &pim_ifp
->pim_dr_addr
);
2400 pim_time_uptime_begin(dr_uptime
, sizeof(dr_uptime
), now
,
2401 pim_ifp
->pim_dr_election_last
);
2402 pim_time_timer_to_hhmmss(hello_timer
, sizeof(hello_timer
),
2403 pim_ifp
->t_pim_hello_timer
);
2404 pim_time_mmss(hello_period
, sizeof(hello_period
),
2405 pim_ifp
->pim_hello_period
);
2406 pim_time_uptime(stat_uptime
, sizeof(stat_uptime
),
2407 now
- pim_ifp
->pim_ifstat_start
);
2410 json_row
= json_object_new_object();
2411 json_object_pim_ifp_add(json_row
, ifp
);
2413 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2414 json_object_string_addf(
2415 json_row
, "useSource", "%pPAs",
2416 &pim_ifp
->update_source
);
2418 if (pim_ifp
->sec_addr_list
) {
2419 json_object
*sec_list
= NULL
;
2421 sec_list
= json_object_new_array();
2422 for (ALL_LIST_ELEMENTS_RO(
2423 pim_ifp
->sec_addr_list
, sec_node
,
2425 json_object_array_add(
2427 json_object_new_stringf(
2431 json_object_object_add(json_row
,
2432 "secondaryAddressList",
2436 if (pim_ifp
->pim_passive_enable
)
2437 json_object_boolean_true_add(json_row
,
2441 if (pim_ifp
->pim_neighbor_list
->count
) {
2442 json_pim_neighbors
= json_object_new_object();
2444 for (ALL_LIST_ELEMENTS_RO(
2445 pim_ifp
->pim_neighbor_list
,
2446 neighnode
, neigh
)) {
2448 json_object_new_object();
2449 snprintfrr(neigh_src_str
,
2450 sizeof(neigh_src_str
),
2452 &neigh
->source_addr
);
2453 pim_time_uptime(uptime
, sizeof(uptime
),
2454 now
- neigh
->creation
);
2455 pim_time_timer_to_hhmmss(
2456 expire
, sizeof(expire
),
2457 neigh
->t_expire_timer
);
2459 json_object_string_add(
2460 json_pim_neighbor
, "address",
2462 json_object_string_add(
2463 json_pim_neighbor
, "upTime",
2465 json_object_string_add(
2466 json_pim_neighbor
, "holdtime",
2469 json_object_object_add(
2475 json_object_object_add(json_row
, "neighbors",
2476 json_pim_neighbors
);
2479 json_object_string_add(json_row
, "drAddress", dr_str
);
2480 json_object_int_add(json_row
, "drPriority",
2481 pim_ifp
->pim_dr_priority
);
2482 json_object_string_add(json_row
, "drUptime", dr_uptime
);
2483 json_object_int_add(json_row
, "drElections",
2484 pim_ifp
->pim_dr_election_count
);
2485 json_object_int_add(json_row
, "drChanges",
2486 pim_ifp
->pim_dr_election_changes
);
2489 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2490 if (ifp
!= up
->rpf
.source_nexthop
.interface
)
2493 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2496 if (!json_fhr_sources
)
2498 json_object_new_object();
2500 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
2502 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
2504 pim_time_uptime(uptime
, sizeof(uptime
),
2505 now
- up
->state_transition
);
2508 * Does this group live in json_fhr_sources?
2511 json_object_object_get_ex(json_fhr_sources
,
2512 grp_str
, &json_group
);
2515 json_group
= json_object_new_object();
2516 json_object_object_add(json_fhr_sources
,
2521 json_group_source
= json_object_new_object();
2522 json_object_string_add(json_group_source
,
2524 json_object_string_add(json_group_source
,
2526 json_object_string_add(json_group_source
,
2528 json_object_object_add(json_group
, src_str
,
2532 if (json_fhr_sources
) {
2533 json_object_object_add(json_row
,
2538 json_object_int_add(json_row
, "helloPeriod",
2539 pim_ifp
->pim_hello_period
);
2540 json_object_int_add(json_row
, "holdTime",
2541 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2542 json_object_string_add(json_row
, "helloTimer",
2544 json_object_string_add(json_row
, "helloStatStart",
2546 json_object_int_add(json_row
, "helloReceived",
2547 pim_ifp
->pim_ifstat_hello_recv
);
2548 json_object_int_add(json_row
, "helloReceivedFailed",
2549 pim_ifp
->pim_ifstat_hello_recvfail
);
2550 json_object_int_add(json_row
, "helloSend",
2551 pim_ifp
->pim_ifstat_hello_sent
);
2552 json_object_int_add(json_row
, "hellosendFailed",
2553 pim_ifp
->pim_ifstat_hello_sendfail
);
2554 json_object_int_add(json_row
, "helloGenerationId",
2555 pim_ifp
->pim_generation_id
);
2557 json_object_int_add(
2558 json_row
, "effectivePropagationDelay",
2559 pim_if_effective_propagation_delay_msec(ifp
));
2560 json_object_int_add(
2561 json_row
, "effectiveOverrideInterval",
2562 pim_if_effective_override_interval_msec(ifp
));
2563 json_object_int_add(
2564 json_row
, "joinPruneOverrideInterval",
2565 pim_if_jp_override_interval_msec(ifp
));
2567 json_object_int_add(
2568 json_row
, "propagationDelay",
2569 pim_ifp
->pim_propagation_delay_msec
);
2570 json_object_int_add(
2571 json_row
, "propagationDelayHighest",
2572 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2573 json_object_int_add(
2574 json_row
, "overrideInterval",
2575 pim_ifp
->pim_override_interval_msec
);
2576 json_object_int_add(
2577 json_row
, "overrideIntervalHighest",
2578 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2579 if (pim_ifp
->bsm_enable
)
2580 json_object_boolean_true_add(json_row
,
2582 if (pim_ifp
->ucast_bsm_accept
)
2583 json_object_boolean_true_add(json_row
,
2585 json_object_object_add(json
, ifp
->name
, json_row
);
2588 vty_out(vty
, "Interface : %s\n", ifp
->name
);
2589 vty_out(vty
, "State : %s\n",
2590 if_is_up(ifp
) ? "up" : "down");
2591 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2592 vty_out(vty
, "Use Source : %pPAs\n",
2593 &pim_ifp
->update_source
);
2595 if (pim_ifp
->sec_addr_list
) {
2596 vty_out(vty
, "Address : %pPAs (primary)\n",
2598 for (ALL_LIST_ELEMENTS_RO(
2599 pim_ifp
->sec_addr_list
, sec_node
,
2601 vty_out(vty
, " %pFX\n",
2604 vty_out(vty
, "Address : %pPAs\n", &ifaddr
);
2607 if (pim_ifp
->pim_passive_enable
)
2608 vty_out(vty
, "Passive : %s\n",
2609 (pim_ifp
->pim_passive_enable
) ? "yes"
2617 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
2618 neighnode
, neigh
)) {
2621 vty_out(vty
, "PIM Neighbors\n");
2622 vty_out(vty
, "-------------\n");
2626 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
2627 "%pPAs", &neigh
->source_addr
);
2628 pim_time_uptime(uptime
, sizeof(uptime
),
2629 now
- neigh
->creation
);
2630 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
2631 neigh
->t_expire_timer
);
2633 "%-15s : up for %s, holdtime expires in %s\n",
2634 neigh_src_str
, uptime
, expire
);
2637 if (!print_header
) {
2642 vty_out(vty
, "Designated Router\n");
2643 vty_out(vty
, "-----------------\n");
2644 vty_out(vty
, "Address : %s\n", dr_str
);
2645 vty_out(vty
, "Priority : %u(%d)\n",
2646 pim_ifp
->pim_dr_priority
,
2647 pim_ifp
->pim_dr_num_nondrpri_neighbors
);
2648 vty_out(vty
, "Uptime : %s\n", dr_uptime
);
2649 vty_out(vty
, "Elections : %d\n",
2650 pim_ifp
->pim_dr_election_count
);
2651 vty_out(vty
, "Changes : %d\n",
2652 pim_ifp
->pim_dr_election_changes
);
2658 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2659 if (!up
->rpf
.source_nexthop
.interface
)
2662 if (strcmp(ifp
->name
,
2663 up
->rpf
.source_nexthop
2664 .interface
->name
) != 0)
2667 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2672 "FHR - First Hop Router\n");
2674 "----------------------\n");
2678 pim_time_uptime(uptime
, sizeof(uptime
),
2679 now
- up
->state_transition
);
2681 "%pPAs : %pPAs is a source, uptime is %s\n",
2682 &up
->sg
.grp
, &up
->sg
.src
, uptime
);
2685 if (!print_header
) {
2690 vty_out(vty
, "Hellos\n");
2691 vty_out(vty
, "------\n");
2692 vty_out(vty
, "Period : %d\n",
2693 pim_ifp
->pim_hello_period
);
2694 vty_out(vty
, "HoldTime : %d\n",
2695 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2696 vty_out(vty
, "Timer : %s\n", hello_timer
);
2697 vty_out(vty
, "StatStart : %s\n", stat_uptime
);
2698 vty_out(vty
, "Receive : %d\n",
2699 pim_ifp
->pim_ifstat_hello_recv
);
2700 vty_out(vty
, "Receive Failed : %d\n",
2701 pim_ifp
->pim_ifstat_hello_recvfail
);
2702 vty_out(vty
, "Send : %d\n",
2703 pim_ifp
->pim_ifstat_hello_sent
);
2704 vty_out(vty
, "Send Failed : %d\n",
2705 pim_ifp
->pim_ifstat_hello_sendfail
);
2706 vty_out(vty
, "Generation ID : %08x\n",
2707 pim_ifp
->pim_generation_id
);
2711 pim_print_ifp_flags(vty
, ifp
);
2713 vty_out(vty
, "Join Prune Interval\n");
2714 vty_out(vty
, "-------------------\n");
2715 vty_out(vty
, "LAN Delay : %s\n",
2716 pim_if_lan_delay_enabled(ifp
) ? "yes" : "no");
2717 vty_out(vty
, "Effective Propagation Delay : %d msec\n",
2718 pim_if_effective_propagation_delay_msec(ifp
));
2719 vty_out(vty
, "Effective Override Interval : %d msec\n",
2720 pim_if_effective_override_interval_msec(ifp
));
2721 vty_out(vty
, "Join Prune Override Interval : %d msec\n",
2722 pim_if_jp_override_interval_msec(ifp
));
2726 vty_out(vty
, "LAN Prune Delay\n");
2727 vty_out(vty
, "---------------\n");
2728 vty_out(vty
, "Propagation Delay : %d msec\n",
2729 pim_ifp
->pim_propagation_delay_msec
);
2730 vty_out(vty
, "Propagation Delay (Highest) : %d msec\n",
2731 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2732 vty_out(vty
, "Override Interval : %d msec\n",
2733 pim_ifp
->pim_override_interval_msec
);
2734 vty_out(vty
, "Override Interval (Highest) : %d msec\n",
2735 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2739 vty_out(vty
, "BSM Status\n");
2740 vty_out(vty
, "----------\n");
2741 vty_out(vty
, "Bsm Enabled : %s\n",
2742 pim_ifp
->bsm_enable
? "yes" : "no");
2743 vty_out(vty
, "Unicast Bsm Enabled : %s\n",
2744 pim_ifp
->ucast_bsm_accept
? "yes" : "no");
2751 vty_out(vty
, "%% No such interface\n");
2754 void ip_pim_ssm_show_group_range(struct pim_instance
*pim
, struct vty
*vty
,
2757 struct pim_ssm
*ssm
= pim
->ssm_info
;
2758 const char *range_str
=
2759 ssm
->plist_name
? ssm
->plist_name
: PIM_SSM_STANDARD_RANGE
;
2764 json
= json_object_new_object();
2765 json_object_string_add(json
, "ssmGroups", range_str
);
2766 vty_json(vty
, json
);
2768 vty_out(vty
, "SSM group range : %s\n", range_str
);
2771 struct vty_pnc_cache_walk_data
{
2773 struct pim_instance
*pim
;
2776 struct json_pnc_cache_walk_data
{
2777 json_object
*json_obj
;
2778 struct pim_instance
*pim
;
2781 static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket
*bucket
, void *arg
)
2783 struct pim_nexthop_cache
*pnc
= bucket
->data
;
2784 struct vty_pnc_cache_walk_data
*cwd
= arg
;
2785 struct vty
*vty
= cwd
->vty
;
2786 struct pim_instance
*pim
= cwd
->pim
;
2787 struct nexthop
*nh_node
= NULL
;
2788 ifindex_t first_ifindex
;
2789 struct interface
*ifp
= NULL
;
2790 struct ttable
*tt
= NULL
;
2793 /* Prepare table. */
2794 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2795 ttable_add_row(tt
, "Address|Interface|Nexthop");
2796 tt
->style
.cell
.rpad
= 2;
2797 tt
->style
.corner
= '+';
2800 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2801 first_ifindex
= nh_node
->ifindex
;
2803 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2806 ttable_add_row(tt
, "%pPA|%s|%pI4", &pnc
->rpf
.rpf_addr
,
2807 ifp
? ifp
->name
: "NULL", &nh_node
->gate
.ipv4
);
2809 ttable_add_row(tt
, "%pPA|%s|%pI6", &pnc
->rpf
.rpf_addr
,
2810 ifp
? ifp
->name
: "NULL", &nh_node
->gate
.ipv6
);
2813 /* Dump the generated table. */
2814 table
= ttable_dump(tt
, "\n");
2815 vty_out(vty
, "%s\n", table
);
2816 XFREE(MTYPE_TMP
, table
);
2822 static int pim_print_json_pnc_cache_walkcb(struct hash_bucket
*backet
,
2825 struct pim_nexthop_cache
*pnc
= backet
->data
;
2826 struct json_pnc_cache_walk_data
*cwd
= arg
;
2827 struct pim_instance
*pim
= cwd
->pim
;
2828 struct nexthop
*nh_node
= NULL
;
2829 ifindex_t first_ifindex
;
2830 struct interface
*ifp
= NULL
;
2831 char addr_str
[PIM_ADDRSTRLEN
];
2832 json_object
*json_row
= NULL
;
2833 json_object
*json_ifp
= NULL
;
2834 json_object
*json_arr
= NULL
;
2836 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2837 first_ifindex
= nh_node
->ifindex
;
2838 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2839 snprintfrr(addr_str
, sizeof(addr_str
), "%pPA",
2840 &pnc
->rpf
.rpf_addr
);
2841 json_object_object_get_ex(cwd
->json_obj
, addr_str
, &json_row
);
2843 json_row
= json_object_new_object();
2844 json_object_string_addf(json_row
, "address", "%pPA",
2845 &pnc
->rpf
.rpf_addr
);
2846 json_object_object_addf(cwd
->json_obj
, json_row
, "%pPA",
2847 &pnc
->rpf
.rpf_addr
);
2848 json_arr
= json_object_new_array();
2849 json_object_object_add(json_row
, "nexthops", json_arr
);
2851 json_ifp
= json_object_new_object();
2852 json_object_string_add(json_ifp
, "interface",
2853 ifp
? ifp
->name
: "NULL");
2855 json_object_string_addf(json_ifp
, "nexthop", "%pI4",
2856 &nh_node
->gate
.ipv4
);
2858 json_object_string_addf(json_ifp
, "nexthop", "%pI6",
2859 &nh_node
->gate
.ipv6
);
2861 json_object_array_add(json_arr
, json_ifp
);
2866 int pim_show_nexthop_lookup_cmd_helper(const char *vrf
, struct vty
*vty
,
2867 pim_addr source
, pim_addr group
)
2870 pim_addr vif_source
;
2872 struct pim_nexthop nexthop
;
2874 char grp_str
[PREFIX_STRLEN
];
2876 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2882 if (pim_is_group_224_4(source
)) {
2884 "Invalid argument. Expected Valid Source Address.\n");
2888 if (!pim_is_group_224_4(group
)) {
2890 "Invalid argument. Expected Valid Multicast Group Address.\n");
2895 if (!pim_rp_set_upstream_addr(v
->info
, &vif_source
, source
, group
))
2898 pim_addr_to_prefix(&grp
, group
);
2899 memset(&nexthop
, 0, sizeof(nexthop
));
2902 pim_ecmp_nexthop_lookup(v
->info
, &nexthop
, vif_source
, &grp
, 0);
2906 "Nexthop Lookup failed, no usable routes returned.\n");
2910 pim_addr_dump("<grp?>", &grp
, grp_str
, sizeof(grp_str
));
2912 vty_out(vty
, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str
,
2913 &nexthop
.mrib_nexthop_addr
, nexthop
.interface
->name
);
2918 int pim_show_nexthop_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2922 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2927 pim_show_nexthop(v
->info
, vty
, uj
);
2932 void pim_show_nexthop(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2934 struct vty_pnc_cache_walk_data cwd
;
2935 struct json_pnc_cache_walk_data jcwd
;
2942 jcwd
.json_obj
= json_object_new_object();
2944 vty_out(vty
, "Number of registered addresses: %lu\n",
2945 pim
->rpf_hash
->count
);
2949 hash_walk(pim
->rpf_hash
, pim_print_json_pnc_cache_walkcb
,
2951 vty_json(vty
, jcwd
.json_obj
);
2953 hash_walk(pim
->rpf_hash
, pim_print_vty_pnc_cache_walkcb
, &cwd
);
2956 int pim_show_neighbors_cmd_helper(const char *vrf
, struct vty
*vty
,
2957 const char *json
, const char *interface
)
2960 json_object
*json_parent
= NULL
;
2962 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2968 json_parent
= json_object_new_object();
2971 pim_show_neighbors_single(v
->info
, vty
, interface
, json_parent
);
2973 pim_show_neighbors(v
->info
, vty
, json_parent
);
2976 vty_json(vty
, json_parent
);
2981 int pim_show_neighbors_vrf_all_cmd_helper(struct vty
*vty
, const char *json
,
2982 const char *interface
)
2985 json_object
*json_parent
= NULL
;
2986 json_object
*json_vrf
= NULL
;
2989 json_parent
= json_object_new_object();
2990 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
2992 vty_out(vty
, "VRF: %s\n", v
->name
);
2994 json_vrf
= json_object_new_object();
2997 pim_show_neighbors_single(v
->info
, vty
, interface
,
3000 pim_show_neighbors(v
->info
, vty
, json_vrf
);
3003 json_object_object_add(json_parent
, v
->name
, json_vrf
);
3006 vty_json(vty
, json_parent
);
3011 void pim_show_neighbors_single(struct pim_instance
*pim
, struct vty
*vty
,
3012 const char *neighbor
, json_object
*json
)
3014 struct listnode
*neighnode
;
3015 struct interface
*ifp
;
3016 struct pim_interface
*pim_ifp
;
3017 struct pim_neighbor
*neigh
;
3019 int found_neighbor
= 0;
3020 int option_address_list
;
3021 int option_dr_priority
;
3022 int option_generation_id
;
3023 int option_holdtime
;
3024 int option_lan_prune_delay
;
3028 char neigh_src_str
[PIM_ADDRSTRLEN
];
3030 json_object
*json_ifp
= NULL
;
3031 json_object
*json_row
= NULL
;
3033 now
= pim_time_monotonic_sec();
3035 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3036 pim_ifp
= ifp
->info
;
3041 if (pim_ifp
->pim_sock_fd
< 0)
3044 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3046 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3047 "%pPAs", &neigh
->source_addr
);
3050 * The user can specify either the interface name or the
3052 * If this pim_ifp matches neither then skip.
3054 if (strcmp(neighbor
, "detail") &&
3055 strcmp(neighbor
, ifp
->name
) &&
3056 strcmp(neighbor
, neigh_src_str
))
3060 pim_time_uptime(uptime
, sizeof(uptime
),
3061 now
- neigh
->creation
);
3062 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3063 neigh
->t_expire_timer
);
3065 option_address_list
= 0;
3066 option_dr_priority
= 0;
3067 option_generation_id
= 0;
3068 option_holdtime
= 0;
3069 option_lan_prune_delay
= 0;
3072 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3073 PIM_OPTION_MASK_ADDRESS_LIST
))
3074 option_address_list
= 1;
3076 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3077 PIM_OPTION_MASK_DR_PRIORITY
))
3078 option_dr_priority
= 1;
3080 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3081 PIM_OPTION_MASK_GENERATION_ID
))
3082 option_generation_id
= 1;
3084 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3085 PIM_OPTION_MASK_HOLDTIME
))
3086 option_holdtime
= 1;
3088 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3089 PIM_OPTION_MASK_LAN_PRUNE_DELAY
))
3090 option_lan_prune_delay
= 1;
3092 if (PIM_OPTION_IS_SET(
3093 neigh
->hello_options
,
3094 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION
))
3099 /* Does this ifp live in json? If not create it
3101 json_object_object_get_ex(json
, ifp
->name
,
3105 json_ifp
= json_object_new_object();
3106 json_object_pim_ifp_add(json_ifp
, ifp
);
3107 json_object_object_add(json
, ifp
->name
,
3111 json_row
= json_object_new_object();
3112 json_object_string_add(json_row
, "interface",
3114 json_object_string_add(json_row
, "address",
3116 json_object_string_add(json_row
, "upTime",
3118 json_object_string_add(json_row
, "holdtime",
3120 json_object_int_add(json_row
, "drPriority",
3121 neigh
->dr_priority
);
3122 json_object_int_add(json_row
, "generationId",
3123 neigh
->generation_id
);
3125 if (option_address_list
)
3126 json_object_boolean_true_add(
3128 "helloOptionAddressList");
3130 if (option_dr_priority
)
3131 json_object_boolean_true_add(
3133 "helloOptionDrPriority");
3135 if (option_generation_id
)
3136 json_object_boolean_true_add(
3138 "helloOptionGenerationId");
3140 if (option_holdtime
)
3141 json_object_boolean_true_add(
3143 "helloOptionHoldtime");
3145 if (option_lan_prune_delay
)
3146 json_object_boolean_true_add(
3148 "helloOptionLanPruneDelay");
3151 json_object_boolean_true_add(
3152 json_row
, "helloOptionTBit");
3154 json_object_object_add(json_ifp
, neigh_src_str
,
3158 vty_out(vty
, "Interface : %s\n", ifp
->name
);
3159 vty_out(vty
, "Neighbor : %s\n", neigh_src_str
);
3167 " DR Priority : %d\n",
3168 neigh
->dr_priority
);
3170 " Generation ID : %08x\n",
3171 neigh
->generation_id
);
3173 " Override Interval (msec) : %d\n",
3174 neigh
->override_interval_msec
);
3176 " Propagation Delay (msec) : %d\n",
3177 neigh
->propagation_delay_msec
);
3179 " Hello Option - Address List : %s\n",
3180 option_address_list
? "yes" : "no");
3182 " Hello Option - DR Priority : %s\n",
3183 option_dr_priority
? "yes" : "no");
3185 " Hello Option - Generation ID : %s\n",
3186 option_generation_id
? "yes" : "no");
3188 " Hello Option - Holdtime : %s\n",
3189 option_holdtime
? "yes" : "no");
3191 " Hello Option - LAN Prune Delay : %s\n",
3192 option_lan_prune_delay
? "yes" : "no");
3194 " Hello Option - T-bit : %s\n",
3195 option_t_bit
? "yes" : "no");
3196 bfd_sess_show(vty
, json_ifp
,
3197 neigh
->bfd_session
);
3203 if (!found_neighbor
)
3204 vty_out(vty
, "%% No such interface or neighbor\n");
3207 void pim_show_neighbors(struct pim_instance
*pim
, struct vty
*vty
,
3210 struct listnode
*neighnode
;
3211 struct interface
*ifp
;
3212 struct pim_interface
*pim_ifp
;
3213 struct pim_neighbor
*neigh
;
3214 struct ttable
*tt
= NULL
;
3219 char neigh_src_str
[PIM_ADDRSTRLEN
];
3220 json_object
*json_ifp_rows
= NULL
;
3221 json_object
*json_row
= NULL
;
3223 now
= pim_time_monotonic_sec();
3226 /* Prepare table. */
3227 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3228 ttable_add_row(tt
, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
3229 tt
->style
.cell
.rpad
= 2;
3230 tt
->style
.corner
= '+';
3234 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3235 pim_ifp
= ifp
->info
;
3240 if (pim_ifp
->pim_sock_fd
< 0)
3244 json_ifp_rows
= json_object_new_object();
3246 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3248 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3249 "%pPAs", &neigh
->source_addr
);
3250 pim_time_uptime(uptime
, sizeof(uptime
),
3251 now
- neigh
->creation
);
3252 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3253 neigh
->t_expire_timer
);
3256 json_row
= json_object_new_object();
3257 json_object_string_add(json_row
, "interface",
3259 json_object_string_add(json_row
, "neighbor",
3261 json_object_string_add(json_row
, "upTime",
3263 json_object_string_add(json_row
, "holdTime",
3265 json_object_int_add(json_row
, "holdTimeMax",
3267 json_object_int_add(json_row
, "drPriority",
3268 neigh
->dr_priority
);
3269 json_object_object_add(json_ifp_rows
,
3270 neigh_src_str
, json_row
);
3273 ttable_add_row(tt
, "%s|%pPAs|%s|%s|%d",
3274 ifp
->name
, &neigh
->source_addr
,
3276 neigh
->dr_priority
);
3281 json_object_object_add(json
, ifp
->name
, json_ifp_rows
);
3282 json_ifp_rows
= NULL
;
3285 /* Dump the generated table. */
3287 table
= ttable_dump(tt
, "\n");
3288 vty_out(vty
, "%s\n", table
);
3289 XFREE(MTYPE_TMP
, table
);
3294 int gm_process_query_max_response_time_cmd(struct vty
*vty
,
3295 const char *qmrt_str
)
3297 const struct lyd_node
*pim_enable_dnode
;
3299 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3300 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3301 FRR_PIM_AF_XPATH_VAL
);
3303 if (!pim_enable_dnode
) {
3304 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3306 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3307 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3311 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_MODIFY
,
3313 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3314 FRR_PIM_AF_XPATH_VAL
);
3317 int gm_process_no_query_max_response_time_cmd(struct vty
*vty
)
3319 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_DESTROY
,
3321 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3322 FRR_PIM_AF_XPATH_VAL
);
3325 int gm_process_last_member_query_count_cmd(struct vty
*vty
,
3326 const char *lmqc_str
)
3328 const struct lyd_node
*pim_enable_dnode
;
3330 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3331 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3332 FRR_PIM_AF_XPATH_VAL
);
3333 if (!pim_enable_dnode
) {
3334 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3336 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3337 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3341 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_MODIFY
,
3343 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3344 FRR_PIM_AF_XPATH_VAL
);
3347 int gm_process_no_last_member_query_count_cmd(struct vty
*vty
)
3349 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_DESTROY
,
3351 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3352 FRR_PIM_AF_XPATH_VAL
);
3355 int gm_process_last_member_query_interval_cmd(struct vty
*vty
,
3356 const char *lmqi_str
)
3358 const struct lyd_node
*pim_enable_dnode
;
3360 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3361 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3362 FRR_PIM_AF_XPATH_VAL
);
3363 if (!pim_enable_dnode
) {
3364 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3366 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3367 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3371 nb_cli_enqueue_change(vty
, "./last-member-query-interval", NB_OP_MODIFY
,
3373 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3374 FRR_PIM_AF_XPATH_VAL
);
3377 int gm_process_no_last_member_query_interval_cmd(struct vty
*vty
)
3379 nb_cli_enqueue_change(vty
, "./last-member-query-interval",
3380 NB_OP_DESTROY
, NULL
);
3381 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3382 FRR_PIM_AF_XPATH_VAL
);
3385 int pim_process_ssmpingd_cmd(struct vty
*vty
, enum nb_operation operation
,
3386 const char *src_str
)
3388 const char *vrfname
;
3389 char ssmpingd_ip_xpath
[XPATH_MAXLEN
];
3391 vrfname
= pim_cli_get_vrf_name(vty
);
3392 if (vrfname
== NULL
)
3393 return CMD_WARNING_CONFIG_FAILED
;
3395 snprintf(ssmpingd_ip_xpath
, sizeof(ssmpingd_ip_xpath
),
3396 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
3397 FRR_PIM_AF_XPATH_VAL
);
3398 strlcat(ssmpingd_ip_xpath
, "/ssm-pingd-source-ip",
3399 sizeof(ssmpingd_ip_xpath
));
3401 nb_cli_enqueue_change(vty
, ssmpingd_ip_xpath
, operation
, src_str
);
3403 return nb_cli_apply_changes(vty
, NULL
);
3406 int pim_process_bsm_cmd(struct vty
*vty
)
3408 const struct lyd_node
*gm_enable_dnode
;
3410 gm_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3411 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
3412 FRR_PIM_AF_XPATH_VAL
);
3413 if (!gm_enable_dnode
)
3414 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3417 if (!yang_dnode_get_bool(gm_enable_dnode
, "."))
3418 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3422 nb_cli_enqueue_change(vty
, "./bsm", NB_OP_MODIFY
, "true");
3424 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3425 FRR_PIM_AF_XPATH_VAL
);
3428 int pim_process_no_bsm_cmd(struct vty
*vty
)
3430 nb_cli_enqueue_change(vty
, "./bsm", NB_OP_MODIFY
, "false");
3432 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3433 FRR_PIM_AF_XPATH_VAL
);
3436 int pim_process_unicast_bsm_cmd(struct vty
*vty
)
3438 const struct lyd_node
*gm_enable_dnode
;
3440 gm_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3441 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
3442 FRR_PIM_AF_XPATH_VAL
);
3443 if (!gm_enable_dnode
)
3444 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3447 if (!yang_dnode_get_bool(gm_enable_dnode
, "."))
3448 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3452 nb_cli_enqueue_change(vty
, "./unicast-bsm", NB_OP_MODIFY
, "true");
3454 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3455 FRR_PIM_AF_XPATH_VAL
);
3458 int pim_process_no_unicast_bsm_cmd(struct vty
*vty
)
3460 nb_cli_enqueue_change(vty
, "./unicast-bsm", NB_OP_MODIFY
, "false");
3462 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3463 FRR_PIM_AF_XPATH_VAL
);
3466 static void show_scan_oil_stats(struct pim_instance
*pim
, struct vty
*vty
,
3469 char uptime_scan_oil
[10];
3470 char uptime_mroute_add
[10];
3471 char uptime_mroute_del
[10];
3473 pim_time_uptime_begin(uptime_scan_oil
, sizeof(uptime_scan_oil
), now
,
3474 pim
->scan_oil_last
);
3475 pim_time_uptime_begin(uptime_mroute_add
, sizeof(uptime_mroute_add
), now
,
3476 pim
->mroute_add_last
);
3477 pim_time_uptime_begin(uptime_mroute_del
, sizeof(uptime_mroute_del
), now
,
3478 pim
->mroute_del_last
);
3481 "Scan OIL - Last: %s Events: %lld\n"
3482 "MFC Add - Last: %s Events: %lld\n"
3483 "MFC Del - Last: %s Events: %lld\n",
3484 uptime_scan_oil
, (long long)pim
->scan_oil_events
,
3485 uptime_mroute_add
, (long long)pim
->mroute_add_events
,
3486 uptime_mroute_del
, (long long)pim
->mroute_del_events
);
3489 void show_multicast_interfaces(struct pim_instance
*pim
, struct vty
*vty
,
3492 struct interface
*ifp
;
3493 struct ttable
*tt
= NULL
;
3495 json_object
*json_row
= NULL
;
3500 /* Prepare table. */
3501 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3504 "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
3505 tt
->style
.cell
.rpad
= 2;
3506 tt
->style
.corner
= '+';
3510 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3511 struct pim_interface
*pim_ifp
;
3513 struct sioc_vif_req vreq
;
3515 struct sioc_mif_req6 vreq
;
3518 pim_ifp
= ifp
->info
;
3523 memset(&vreq
, 0, sizeof(vreq
));
3525 vreq
.vifi
= pim_ifp
->mroute_vif_index
;
3526 if (ioctl(pim
->mroute_socket
, SIOCGETVIFCNT
, &vreq
)) {
3528 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3529 (unsigned long)SIOCGETVIFCNT
, ifp
->name
,
3530 pim_ifp
->mroute_vif_index
, errno
,
3531 safe_strerror(errno
));
3534 vreq
.mifi
= pim_ifp
->mroute_vif_index
;
3535 if (ioctl(pim
->mroute_socket
, SIOCGETMIFCNT_IN6
, &vreq
)) {
3537 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3538 (unsigned long)SIOCGETMIFCNT_IN6
, ifp
->name
,
3539 pim_ifp
->mroute_vif_index
, errno
,
3540 safe_strerror(errno
));
3545 json_row
= json_object_new_object();
3546 json_object_string_add(json_row
, "name", ifp
->name
);
3547 json_object_string_add(json_row
, "state",
3548 if_is_up(ifp
) ? "up" : "down");
3549 json_object_string_addf(json_row
, "address", "%pPA",
3550 &pim_ifp
->primary_address
);
3551 json_object_int_add(json_row
, "ifIndex", ifp
->ifindex
);
3552 json_object_int_add(json_row
, "vif",
3553 pim_ifp
->mroute_vif_index
);
3554 json_object_int_add(json_row
, "pktsIn",
3555 (unsigned long)vreq
.icount
);
3556 json_object_int_add(json_row
, "pktsOut",
3557 (unsigned long)vreq
.ocount
);
3558 json_object_int_add(json_row
, "bytesIn",
3559 (unsigned long)vreq
.ibytes
);
3560 json_object_int_add(json_row
, "bytesOut",
3561 (unsigned long)vreq
.obytes
);
3562 json_object_object_add(json
, ifp
->name
, json_row
);
3564 ttable_add_row(tt
, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
3565 ifp
->name
, &pim_ifp
->primary_address
,
3566 ifp
->ifindex
, pim_ifp
->mroute_vif_index
,
3567 (unsigned long)vreq
.icount
,
3568 (unsigned long)vreq
.ocount
,
3569 (unsigned long)vreq
.ibytes
,
3570 (unsigned long)vreq
.obytes
);
3573 /* Dump the generated table. */
3575 table
= ttable_dump(tt
, "\n");
3576 vty_out(vty
, "%s\n", table
);
3577 XFREE(MTYPE_TMP
, table
);
3582 void pim_cmd_show_ip_multicast_helper(struct pim_instance
*pim
, struct vty
*vty
)
3584 struct vrf
*vrf
= pim
->vrf
;
3585 time_t now
= pim_time_monotonic_sec();
3591 vty_out(vty
, "Router MLAG Role: %s\n",
3592 mlag_role2str(router
->mlag_role
, mlag_role
, sizeof(mlag_role
)));
3593 vty_out(vty
, "Mroute socket descriptor:");
3595 vty_out(vty
, " %d(%s)\n", pim
->mroute_socket
, vrf
->name
);
3596 vty_out(vty
, "PIM Register socket descriptor:");
3597 vty_out(vty
, " %d(%s)\n", pim
->reg_sock
, vrf
->name
);
3599 pim_time_uptime(uptime
, sizeof(uptime
),
3600 now
- pim
->mroute_socket_creation
);
3601 vty_out(vty
, "Mroute socket uptime: %s\n", uptime
);
3605 pim_zebra_zclient_update(vty
);
3606 pim_zlookup_show_ip_multicast(vty
);
3609 vty_out(vty
, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS
);
3612 vty_out(vty
, "Upstream Join Timer: %d secs\n", router
->t_periodic
);
3613 vty_out(vty
, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME
);
3614 vty_out(vty
, "PIM ECMP: %s\n", pim
->ecmp_enable
? "Enable" : "Disable");
3615 vty_out(vty
, "PIM ECMP Rebalance: %s\n",
3616 pim
->ecmp_rebalance_enable
? "Enable" : "Disable");
3620 pim_show_rpf_refresh_stats(vty
, pim
, now
, NULL
);
3624 show_scan_oil_stats(pim
, vty
, now
);
3626 show_multicast_interfaces(pim
, vty
, NULL
);
3629 void show_mroute(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
3630 bool fill
, json_object
*json
)
3632 struct listnode
*node
;
3633 struct channel_oil
*c_oil
;
3634 struct static_route
*s_route
;
3635 struct ttable
*tt
= NULL
;
3638 json_object
*json_group
= NULL
;
3639 json_object
*json_source
= NULL
;
3640 json_object
*json_oil
= NULL
;
3641 json_object
*json_ifp_out
= NULL
;
3644 char grp_str
[PIM_ADDRSTRLEN
];
3645 char src_str
[PIM_ADDRSTRLEN
];
3646 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
3647 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
3649 struct interface
*ifp_in
;
3651 char state_str
[PIM_REG_STATE_STR_LEN
];
3652 char mroute_uptime
[10];
3655 vty_out(vty
, "IP Multicast Routing Table\n");
3656 vty_out(vty
, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3658 " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3660 /* Prepare table. */
3661 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3663 tt
, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
3664 tt
->style
.cell
.rpad
= 2;
3665 tt
->style
.corner
= '+';
3669 now
= pim_time_monotonic_sec();
3671 /* print list of PIM and IGMP routes */
3672 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
3675 if (!c_oil
->installed
)
3678 if (!pim_addr_is_any(sg
->grp
) &&
3679 pim_addr_cmp(sg
->grp
, *oil_mcastgrp(c_oil
)))
3681 if (!pim_addr_is_any(sg
->src
) &&
3682 pim_addr_cmp(sg
->src
, *oil_origin(c_oil
)))
3685 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
3686 oil_mcastgrp(c_oil
));
3687 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
3690 strlcpy(state_str
, "S", sizeof(state_str
));
3691 /* When a non DR receives a igmp join, it creates a (*,G)
3692 * channel_oil without any upstream creation
3695 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil
->up
->flags
))
3696 strlcat(state_str
, "C", sizeof(state_str
));
3697 if (pim_upstream_is_sg_rpt(c_oil
->up
))
3698 strlcat(state_str
, "R", sizeof(state_str
));
3699 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil
->up
->flags
))
3700 strlcat(state_str
, "F", sizeof(state_str
));
3701 if (c_oil
->up
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
3702 strlcat(state_str
, "T", sizeof(state_str
));
3704 if (pim_channel_oil_empty(c_oil
))
3705 strlcat(state_str
, "P", sizeof(state_str
));
3707 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
3710 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3712 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3715 pim_time_uptime(mroute_uptime
, sizeof(mroute_uptime
),
3716 now
- c_oil
->mroute_creation
);
3720 /* Find the group, create it if it doesn't exist */
3721 json_object_object_get_ex(json
, grp_str
, &json_group
);
3724 json_group
= json_object_new_object();
3725 json_object_object_add(json
, grp_str
,
3729 /* Find the source nested under the group, create it if
3732 json_object_object_get_ex(json_group
, src_str
,
3736 json_source
= json_object_new_object();
3737 json_object_object_add(json_group
, src_str
,
3741 /* Find the inbound interface nested under the source,
3742 * create it if it doesn't exist
3744 json_object_string_add(json_source
, "source", src_str
);
3745 json_object_string_add(json_source
, "group", grp_str
);
3746 json_object_int_add(json_source
, "installed",
3748 json_object_int_add(json_source
, "refCount",
3749 c_oil
->oil_ref_count
);
3750 json_object_int_add(json_source
, "oilSize",
3752 json_object_int_add(json_source
, "oilInheritedRescan",
3753 c_oil
->oil_inherited_rescan
);
3754 json_object_string_add(json_source
, "iif", in_ifname
);
3755 json_object_string_add(json_source
, "upTime",
3760 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3762 struct interface
*ifp_out
;
3765 ttl
= oil_if_has(c_oil
, oif_vif_index
);
3769 /* do not display muted OIFs */
3770 if (c_oil
->oif_flags
[oif_vif_index
] & PIM_OIF_FLAG_MUTE
)
3773 if (*oil_parent(c_oil
) == oif_vif_index
&&
3774 !pim_mroute_allow_iif_in_oil(c_oil
, oif_vif_index
))
3777 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3781 strlcpy(out_ifname
, ifp_out
->name
,
3782 sizeof(out_ifname
));
3784 strlcpy(out_ifname
, "<oif?>",
3785 sizeof(out_ifname
));
3788 json_ifp_out
= json_object_new_object();
3789 json_object_string_add(json_ifp_out
, "source",
3791 json_object_string_add(json_ifp_out
, "group",
3794 if (c_oil
->oif_flags
[oif_vif_index
] &
3795 PIM_OIF_FLAG_PROTO_PIM
)
3796 json_object_boolean_true_add(
3797 json_ifp_out
, "protocolPim");
3799 if (c_oil
->oif_flags
[oif_vif_index
] &
3800 PIM_OIF_FLAG_PROTO_GM
)
3802 json_object_boolean_true_add(
3803 json_ifp_out
, "protocolIgmp");
3805 json_object_boolean_true_add(
3806 json_ifp_out
, "protocolMld");
3809 if (c_oil
->oif_flags
[oif_vif_index
] &
3810 PIM_OIF_FLAG_PROTO_VXLAN
)
3811 json_object_boolean_true_add(
3812 json_ifp_out
, "protocolVxlan");
3814 if (c_oil
->oif_flags
[oif_vif_index
] &
3815 PIM_OIF_FLAG_PROTO_STAR
)
3816 json_object_boolean_true_add(
3818 "protocolInherited");
3820 json_object_string_add(json_ifp_out
,
3823 json_object_int_add(json_ifp_out
, "iVifI",
3824 *oil_parent(c_oil
));
3825 json_object_string_add(json_ifp_out
,
3826 "outboundInterface",
3828 json_object_int_add(json_ifp_out
, "oVifI",
3830 json_object_int_add(json_ifp_out
, "ttl", ttl
);
3831 json_object_string_add(json_ifp_out
, "upTime",
3833 json_object_string_add(json_source
, "flags",
3836 json_oil
= json_object_new_object();
3837 json_object_object_add(json_source
,
3840 json_object_object_add(json_oil
, out_ifname
,
3844 if (c_oil
->oif_flags
[oif_vif_index
] &
3845 PIM_OIF_FLAG_PROTO_PIM
) {
3846 strlcpy(proto
, "PIM", sizeof(proto
));
3849 if (c_oil
->oif_flags
[oif_vif_index
] &
3850 PIM_OIF_FLAG_PROTO_GM
) {
3852 strlcpy(proto
, "IGMP", sizeof(proto
));
3854 strlcpy(proto
, "MLD", sizeof(proto
));
3858 if (c_oil
->oif_flags
[oif_vif_index
] &
3859 PIM_OIF_FLAG_PROTO_VXLAN
) {
3860 strlcpy(proto
, "VxLAN", sizeof(proto
));
3863 if (c_oil
->oif_flags
[oif_vif_index
] &
3864 PIM_OIF_FLAG_PROTO_STAR
) {
3865 strlcpy(proto
, "STAR", sizeof(proto
));
3868 ttable_add_row(tt
, "%s|%s|%s|%s|%s|%s|%d|%s",
3869 src_str
, grp_str
, state_str
,
3870 proto
, in_ifname
, out_ifname
,
3871 ttl
, mroute_uptime
);
3876 in_ifname
[0] = '\0';
3877 state_str
[0] = '\0';
3878 mroute_uptime
[0] = '\0';
3884 if (!json
&& !found_oif
) {
3885 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3886 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
3887 state_str
, "none", in_ifname
, "none", 0,
3892 /* Print list of static routes */
3893 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
3896 if (!s_route
->c_oil
.installed
)
3899 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &s_route
->group
);
3900 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &s_route
->source
);
3901 ifp_in
= pim_if_find_by_vif_index(pim
, s_route
->iif
);
3905 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3907 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3911 /* Find the group, create it if it doesn't exist */
3912 json_object_object_get_ex(json
, grp_str
, &json_group
);
3915 json_group
= json_object_new_object();
3916 json_object_object_add(json
, grp_str
,
3920 /* Find the source nested under the group, create it if
3923 json_object_object_get_ex(json_group
, src_str
,
3927 json_source
= json_object_new_object();
3928 json_object_object_add(json_group
, src_str
,
3932 json_object_string_add(json_source
, "iif", in_ifname
);
3935 strlcpy(proto
, "STATIC", sizeof(proto
));
3938 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3940 struct interface
*ifp_out
;
3941 char oif_uptime
[10];
3944 ttl
= s_route
->oif_ttls
[oif_vif_index
];
3948 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3950 oif_uptime
, sizeof(oif_uptime
),
3951 now
- s_route
->c_oil
3952 .oif_creation
[oif_vif_index
]);
3956 strlcpy(out_ifname
, ifp_out
->name
,
3957 sizeof(out_ifname
));
3959 strlcpy(out_ifname
, "<oif?>",
3960 sizeof(out_ifname
));
3963 json_ifp_out
= json_object_new_object();
3964 json_object_string_add(json_ifp_out
, "source",
3966 json_object_string_add(json_ifp_out
, "group",
3968 json_object_boolean_true_add(json_ifp_out
,
3970 json_object_string_add(json_ifp_out
,
3973 json_object_int_add(
3974 json_ifp_out
, "iVifI",
3975 *oil_parent(&s_route
->c_oil
));
3976 json_object_string_add(json_ifp_out
,
3977 "outboundInterface",
3979 json_object_int_add(json_ifp_out
, "oVifI",
3981 json_object_int_add(json_ifp_out
, "ttl", ttl
);
3982 json_object_string_add(json_ifp_out
, "upTime",
3985 json_oil
= json_object_new_object();
3986 json_object_object_add(json_source
,
3989 json_object_object_add(json_oil
, out_ifname
,
3993 tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3994 &s_route
->source
, &s_route
->group
, "-",
3995 proto
, in_ifname
, out_ifname
, ttl
,
3997 if (first
&& !fill
) {
4000 in_ifname
[0] = '\0';
4006 if (!json
&& !found_oif
) {
4007 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4008 &s_route
->source
, &s_route
->group
, "-",
4009 proto
, in_ifname
, "none", 0, "--:--:--");
4012 /* Dump the generated table. */
4014 table
= ttable_dump(tt
, "\n");
4015 vty_out(vty
, "%s\n", table
);
4016 XFREE(MTYPE_TMP
, table
);
4021 static void show_mroute_count_per_channel_oil(struct channel_oil
*c_oil
,
4025 json_object
*json_group
= NULL
;
4026 json_object
*json_source
= NULL
;
4028 if (!c_oil
->installed
)
4031 pim_mroute_update_counters(c_oil
);
4034 char group_str
[PIM_ADDRSTRLEN
];
4035 char source_str
[PIM_ADDRSTRLEN
];
4037 snprintfrr(group_str
, sizeof(group_str
), "%pPAs",
4038 oil_mcastgrp(c_oil
));
4039 snprintfrr(source_str
, sizeof(source_str
), "%pPAs",
4042 json_object_object_get_ex(json
, group_str
, &json_group
);
4045 json_group
= json_object_new_object();
4046 json_object_object_add(json
, group_str
, json_group
);
4049 json_source
= json_object_new_object();
4050 json_object_object_add(json_group
, source_str
, json_source
);
4051 json_object_int_add(json_source
, "lastUsed",
4052 c_oil
->cc
.lastused
/ 100);
4053 json_object_int_add(json_source
, "packets", c_oil
->cc
.pktcnt
);
4054 json_object_int_add(json_source
, "bytes", c_oil
->cc
.bytecnt
);
4055 json_object_int_add(json_source
, "wrongIf", c_oil
->cc
.wrong_if
);
4058 ttable_add_row(tt
, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
4059 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
4060 c_oil
->cc
.lastused
/ 100,
4061 c_oil
->cc
.pktcnt
- c_oil
->cc
.origpktcnt
,
4062 c_oil
->cc
.bytecnt
- c_oil
->cc
.origbytecnt
,
4063 c_oil
->cc
.wrong_if
- c_oil
->cc
.origwrong_if
);
4067 void show_mroute_count(struct pim_instance
*pim
, struct vty
*vty
,
4070 struct listnode
*node
;
4071 struct channel_oil
*c_oil
;
4072 struct static_route
*sr
;
4073 struct ttable
*tt
= NULL
;
4079 /* Prepare table. */
4080 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4082 "Source|Group|LastUsed|Packets|Bytes|WrongIf");
4083 tt
->style
.cell
.rpad
= 2;
4084 tt
->style
.corner
= '+';
4088 /* Print PIM and IGMP route counts */
4089 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
4090 show_mroute_count_per_channel_oil(c_oil
, json
, tt
);
4092 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
))
4093 show_mroute_count_per_channel_oil(&sr
->c_oil
, json
, tt
);
4095 /* Dump the generated table. */
4097 table
= ttable_dump(tt
, "\n");
4098 vty_out(vty
, "%s\n", table
);
4099 XFREE(MTYPE_TMP
, table
);
4104 void show_mroute_summary(struct pim_instance
*pim
, struct vty
*vty
,
4107 struct listnode
*node
;
4108 struct channel_oil
*c_oil
;
4109 struct static_route
*s_route
;
4110 uint32_t starg_sw_mroute_cnt
= 0;
4111 uint32_t sg_sw_mroute_cnt
= 0;
4112 uint32_t starg_hw_mroute_cnt
= 0;
4113 uint32_t sg_hw_mroute_cnt
= 0;
4114 json_object
*json_starg
= NULL
;
4115 json_object
*json_sg
= NULL
;
4118 vty_out(vty
, "Mroute Type Installed/Total\n");
4120 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4121 if (!c_oil
->installed
) {
4122 if (pim_addr_is_any(*oil_origin(c_oil
)))
4123 starg_sw_mroute_cnt
++;
4127 if (pim_addr_is_any(*oil_origin(c_oil
)))
4128 starg_hw_mroute_cnt
++;
4134 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
4135 if (!s_route
->c_oil
.installed
) {
4136 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4137 starg_sw_mroute_cnt
++;
4141 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4142 starg_hw_mroute_cnt
++;
4149 vty_out(vty
, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt
,
4150 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4151 vty_out(vty
, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt
,
4152 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4153 vty_out(vty
, "------\n");
4154 vty_out(vty
, "%-20s %u/%u\n", "Total",
4155 (starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
),
4156 (starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4157 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
));
4159 /* (*,G) route details */
4160 json_starg
= json_object_new_object();
4161 json_object_object_add(json
, "wildcardGroup", json_starg
);
4163 json_object_int_add(json_starg
, "installed",
4164 starg_hw_mroute_cnt
);
4165 json_object_int_add(json_starg
, "total",
4166 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4168 /* (S, G) route details */
4169 json_sg
= json_object_new_object();
4170 json_object_object_add(json
, "sourceGroup", json_sg
);
4172 json_object_int_add(json_sg
, "installed", sg_hw_mroute_cnt
);
4173 json_object_int_add(json_sg
, "total",
4174 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4176 json_object_int_add(json
, "totalNumOfInstalledMroutes",
4177 starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
);
4178 json_object_int_add(json
, "totalNumOfMroutes",
4179 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4185 int clear_ip_mroute_count_command(struct vty
*vty
, const char *name
)
4187 struct listnode
*node
;
4188 struct channel_oil
*c_oil
;
4189 struct static_route
*sr
;
4190 struct vrf
*v
= pim_cmd_lookup(vty
, name
);
4191 struct pim_instance
*pim
;
4197 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4198 if (!c_oil
->installed
)
4201 pim_mroute_update_counters(c_oil
);
4202 c_oil
->cc
.origpktcnt
= c_oil
->cc
.pktcnt
;
4203 c_oil
->cc
.origbytecnt
= c_oil
->cc
.bytecnt
;
4204 c_oil
->cc
.origwrong_if
= c_oil
->cc
.wrong_if
;
4207 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
)) {
4208 if (!sr
->c_oil
.installed
)
4211 pim_mroute_update_counters(&sr
->c_oil
);
4213 sr
->c_oil
.cc
.origpktcnt
= sr
->c_oil
.cc
.pktcnt
;
4214 sr
->c_oil
.cc
.origbytecnt
= sr
->c_oil
.cc
.bytecnt
;
4215 sr
->c_oil
.cc
.origwrong_if
= sr
->c_oil
.cc
.wrong_if
;
4220 struct vrf
*pim_cmd_lookup(struct vty
*vty
, const char *name
)
4225 vrf
= vrf_lookup_by_name(name
);
4227 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
4230 vty_out(vty
, "Specified VRF: %s does not exist\n", name
);
4235 void clear_mroute(struct pim_instance
*pim
)
4237 struct pim_upstream
*up
;
4238 struct interface
*ifp
;
4240 /* scan interfaces */
4241 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4242 struct pim_interface
*pim_ifp
= ifp
->info
;
4243 struct pim_ifchannel
*ch
;
4248 /* deleting all ifchannels */
4249 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
4250 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
4252 pim_ifchannel_delete(ch
);
4256 /* clean up all igmp groups */
4257 struct gm_group
*grp
;
4259 if (pim_ifp
->gm_group_list
) {
4260 while (pim_ifp
->gm_group_list
->count
) {
4261 grp
= listnode_head(pim_ifp
->gm_group_list
);
4262 igmp_group_delete(grp
);
4266 struct gm_if
*gm_ifp
;
4268 gm_ifp
= pim_ifp
->mld
;
4270 gm_group_delete(gm_ifp
);
4274 /* clean up all upstreams*/
4275 while ((up
= rb_pim_upstream_first(&pim
->upstream_head
)))
4276 pim_upstream_del(pim
, up
, __func__
);
4279 void clear_pim_statistics(struct pim_instance
*pim
)
4281 struct interface
*ifp
;
4285 pim
->bsm_dropped
= 0;
4287 /* scan interfaces */
4288 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4289 struct pim_interface
*pim_ifp
= ifp
->info
;
4294 pim_ifp
->pim_ifstat_bsm_cfg_miss
= 0;
4295 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
= 0;
4296 pim_ifp
->pim_ifstat_bsm_invalid_sz
= 0;
4300 int clear_pim_interface_traffic(const char *vrf
, struct vty
*vty
)
4302 struct interface
*ifp
= NULL
;
4303 struct pim_interface
*pim_ifp
= NULL
;
4305 struct vrf
*v
= pim_cmd_lookup(vty
, vrf
);
4310 FOR_ALL_INTERFACES (v
, ifp
) {
4311 pim_ifp
= ifp
->info
;
4316 pim_ifp
->pim_ifstat_hello_recv
= 0;
4317 pim_ifp
->pim_ifstat_hello_sent
= 0;
4318 pim_ifp
->pim_ifstat_join_recv
= 0;
4319 pim_ifp
->pim_ifstat_join_send
= 0;
4320 pim_ifp
->pim_ifstat_prune_recv
= 0;
4321 pim_ifp
->pim_ifstat_prune_send
= 0;
4322 pim_ifp
->pim_ifstat_reg_recv
= 0;
4323 pim_ifp
->pim_ifstat_reg_send
= 0;
4324 pim_ifp
->pim_ifstat_reg_stop_recv
= 0;
4325 pim_ifp
->pim_ifstat_reg_stop_send
= 0;
4326 pim_ifp
->pim_ifstat_assert_recv
= 0;
4327 pim_ifp
->pim_ifstat_assert_send
= 0;
4328 pim_ifp
->pim_ifstat_bsm_rx
= 0;
4329 pim_ifp
->pim_ifstat_bsm_tx
= 0;
4331 pim_ifp
->igmp_ifstat_joins_sent
= 0;
4332 pim_ifp
->igmp_ifstat_joins_failed
= 0;
4333 pim_ifp
->igmp_peak_group_count
= 0;
4340 int pim_debug_pim_cmd(void)
4342 PIM_DO_DEBUG_PIM_EVENTS
;
4343 PIM_DO_DEBUG_PIM_PACKETS
;
4344 PIM_DO_DEBUG_PIM_TRACE
;
4345 PIM_DO_DEBUG_MSDP_EVENTS
;
4346 PIM_DO_DEBUG_MSDP_PACKETS
;
4352 int pim_no_debug_pim_cmd(void)
4354 PIM_DONT_DEBUG_PIM_EVENTS
;
4355 PIM_DONT_DEBUG_PIM_PACKETS
;
4356 PIM_DONT_DEBUG_PIM_TRACE
;
4357 PIM_DONT_DEBUG_MSDP_EVENTS
;
4358 PIM_DONT_DEBUG_MSDP_PACKETS
;
4360 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND
;
4361 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV
;
4363 PIM_DONT_DEBUG_VXLAN
;
4367 int pim_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4368 const char *registers
, struct vty
*vty
)
4371 PIM_DO_DEBUG_PIM_HELLO
;
4372 vty_out(vty
, "PIM Hello debugging is on\n");
4374 PIM_DO_DEBUG_PIM_J_P
;
4375 vty_out(vty
, "PIM Join/Prune debugging is on\n");
4376 } else if (registers
) {
4377 PIM_DO_DEBUG_PIM_REG
;
4378 vty_out(vty
, "PIM Register debugging is on\n");
4380 PIM_DO_DEBUG_PIM_PACKETS
;
4381 vty_out(vty
, "PIM Packet debugging is on\n");
4386 int pim_no_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4387 const char *registers
, struct vty
*vty
)
4390 PIM_DONT_DEBUG_PIM_HELLO
;
4391 vty_out(vty
, "PIM Hello debugging is off\n");
4393 PIM_DONT_DEBUG_PIM_J_P
;
4394 vty_out(vty
, "PIM Join/Prune debugging is off\n");
4395 } else if (registers
) {
4396 PIM_DONT_DEBUG_PIM_REG
;
4397 vty_out(vty
, "PIM Register debugging is off\n");
4399 PIM_DONT_DEBUG_PIM_PACKETS
;
4400 vty_out(vty
, "PIM Packet debugging is off\n");
4406 int pim_show_rpf_helper(const char *vrf
, struct vty
*vty
, bool json
)
4408 struct pim_instance
*pim
;
4410 json_object
*json_parent
= NULL
;
4412 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4420 vty_out(vty
, "%% Unable to find pim instance\n");
4425 json_parent
= json_object_new_object();
4427 pim_show_rpf(pim
, vty
, json_parent
);
4430 vty_json(vty
, json_parent
);
4435 int pim_show_rpf_vrf_all_helper(struct vty
*vty
, bool json
)
4438 json_object
*json_parent
= NULL
;
4439 json_object
*json_vrf
= NULL
;
4442 json_parent
= json_object_new_object();
4444 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4446 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4448 json_vrf
= json_object_new_object();
4449 pim_show_rpf(vrf
->info
, vty
, json_vrf
);
4451 json_object_object_add(json_parent
, vrf
->name
,
4455 vty_json(vty
, json_parent
);
4460 int pim_show_rp_helper(const char *vrf
, struct vty
*vty
, const char *group_str
,
4461 const struct prefix
*group
, bool json
)
4463 struct pim_instance
*pim
;
4465 json_object
*json_parent
= NULL
;
4466 struct prefix
*range
= NULL
;
4468 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4476 vty_out(vty
, "%% Unable to find pim instance\n");
4481 range
= prefix_new();
4482 prefix_copy(range
, group
);
4487 json_parent
= json_object_new_object();
4489 pim_rp_show_information(pim
, range
, vty
, json_parent
);
4492 vty_json(vty
, json_parent
);
4494 prefix_free(&range
);
4499 int pim_show_rp_vrf_all_helper(struct vty
*vty
, const char *group_str
,
4500 const struct prefix
*group
, bool json
)
4503 json_object
*json_parent
= NULL
;
4504 json_object
*json_vrf
= NULL
;
4505 struct prefix
*range
= NULL
;
4508 range
= prefix_new();
4509 prefix_copy(range
, group
);
4514 json_parent
= json_object_new_object();
4516 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4518 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4520 json_vrf
= json_object_new_object();
4521 pim_rp_show_information(vrf
->info
, range
, vty
, json_vrf
);
4523 json_object_object_add(json_parent
, vrf
->name
,
4527 vty_json(vty
, json_parent
);
4529 prefix_free(&range
);
4534 int pim_show_secondary_helper(const char *vrf
, struct vty
*vty
)
4536 struct pim_instance
*pim
;
4539 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4547 vty_out(vty
, "%% Unable to find pim instance\n");
4551 pim_show_neighbors_secondary(pim
, vty
);
4556 int pim_show_statistics_helper(const char *vrf
, struct vty
*vty
,
4557 const char *word
, bool uj
)
4559 struct pim_instance
*pim
;
4562 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4570 vty_out(vty
, "%% Unable to find pim instance\n");
4575 pim_show_statistics(pim
, vty
, word
, uj
);
4577 pim_show_statistics(pim
, vty
, NULL
, uj
);
4582 int pim_show_upstream_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4583 pim_addr g
, bool json
)
4585 pim_sgaddr sg
= {0};
4587 struct pim_instance
*pim
;
4588 json_object
*json_parent
= NULL
;
4590 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4593 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
4599 vty_out(vty
, "%% Unable to find pim instance\n");
4604 json_parent
= json_object_new_object();
4606 if (!pim_addr_is_any(s_or_g
)) {
4607 if (!pim_addr_is_any(g
)) {
4614 pim_show_upstream(pim
, vty
, &sg
, json_parent
);
4617 vty_json(vty
, json_parent
);
4622 int pim_show_upstream_vrf_all_helper(struct vty
*vty
, bool json
)
4624 pim_sgaddr sg
= {0};
4626 json_object
*json_parent
= NULL
;
4627 json_object
*json_vrf
= NULL
;
4630 json_parent
= json_object_new_object();
4632 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4634 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4636 json_vrf
= json_object_new_object();
4637 pim_show_upstream(vrf
->info
, vty
, &sg
, json_vrf
);
4639 json_object_object_add(json_parent
, vrf
->name
,
4644 vty_json(vty
, json_parent
);
4649 int pim_show_upstream_join_desired_helper(const char *vrf
, struct vty
*vty
,
4652 struct pim_instance
*pim
;
4655 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4663 vty_out(vty
, "%% Unable to find pim instance\n");
4667 pim_show_join_desired(pim
, vty
, uj
);
4672 int pim_show_upstream_rpf_helper(const char *vrf
, struct vty
*vty
, bool uj
)
4674 struct pim_instance
*pim
;
4677 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4685 vty_out(vty
, "%% Unable to find pim instance\n");
4689 pim_show_upstream_rpf(pim
, vty
, uj
);
4694 int pim_show_state_helper(const char *vrf
, struct vty
*vty
,
4695 const char *s_or_g_str
, const char *g_str
, bool json
)
4697 struct pim_instance
*pim
;
4699 json_object
*json_parent
= NULL
;
4701 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4709 vty_out(vty
, "%% Unable to find pim instance\n");
4714 json_parent
= json_object_new_object();
4716 pim_show_state(pim
, vty
, s_or_g_str
, g_str
, json_parent
);
4719 vty_json(vty
, json_parent
);
4724 int pim_show_state_vrf_all_helper(struct vty
*vty
, const char *s_or_g_str
,
4725 const char *g_str
, bool json
)
4728 json_object
*json_parent
= NULL
;
4729 json_object
*json_vrf
= NULL
;
4732 json_parent
= json_object_new_object();
4734 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4736 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4738 json_vrf
= json_object_new_object();
4739 pim_show_state(vrf
->info
, vty
, s_or_g_str
, g_str
, json_vrf
);
4741 json_object_object_add(json_parent
, vrf
->name
,
4745 vty_json(vty
, json_parent
);
4750 int pim_show_multicast_helper(const char *vrf
, struct vty
*vty
)
4753 struct pim_instance
*pim
;
4755 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4763 vty_out(vty
, "%% Unable to find pim instance\n");
4767 pim_cmd_show_ip_multicast_helper(pim
, vty
);
4772 int pim_show_multicast_vrf_all_helper(struct vty
*vty
)
4776 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4777 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4778 pim_cmd_show_ip_multicast_helper(vrf
->info
, vty
);
4784 int pim_show_multicast_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4786 struct pim_instance
*pim
;
4788 json_object
*json_parent
= NULL
;
4790 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4798 vty_out(vty
, "%% Unable to find pim instance\n");
4803 json_parent
= json_object_new_object();
4805 show_multicast_interfaces(pim
, vty
, json_parent
);
4808 vty_json(vty
, json_parent
);
4813 int pim_show_multicast_count_vrf_all_helper(struct vty
*vty
, bool json
)
4816 json_object
*json_parent
= NULL
;
4817 json_object
*json_vrf
= NULL
;
4820 json_parent
= json_object_new_object();
4822 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4824 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4826 json_vrf
= json_object_new_object();
4828 show_multicast_interfaces(vrf
->info
, vty
, json_vrf
);
4830 json_object_object_add(json_parent
, vrf
->name
,
4834 vty_json(vty
, json_parent
);
4839 int pim_show_mroute_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4840 pim_addr g
, bool fill
, bool json
)
4842 pim_sgaddr sg
= {0};
4843 struct pim_instance
*pim
;
4845 json_object
*json_parent
= NULL
;
4847 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4855 vty_out(vty
, "%% Unable to find pim instance\n");
4860 json_parent
= json_object_new_object();
4862 if (!pim_addr_is_any(s_or_g
)) {
4863 if (!pim_addr_is_any(g
)) {
4870 show_mroute(pim
, vty
, &sg
, fill
, json_parent
);
4873 vty_json(vty
, json_parent
);
4878 int pim_show_mroute_vrf_all_helper(struct vty
*vty
, bool fill
, bool json
)
4880 pim_sgaddr sg
= {0};
4882 json_object
*json_parent
= NULL
;
4883 json_object
*json_vrf
= NULL
;
4886 json_parent
= json_object_new_object();
4888 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4890 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4892 json_vrf
= json_object_new_object();
4893 show_mroute(vrf
->info
, vty
, &sg
, fill
, json_vrf
);
4895 json_object_object_add(json_parent
, vrf
->name
,
4899 vty_json(vty
, json_parent
);
4904 int pim_show_mroute_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4906 struct pim_instance
*pim
;
4908 json_object
*json_parent
= NULL
;
4910 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4918 vty_out(vty
, "%% Unable to find pim instance\n");
4923 json_parent
= json_object_new_object();
4925 show_mroute_count(pim
, vty
, json_parent
);
4928 vty_json(vty
, json_parent
);
4933 int pim_show_mroute_count_vrf_all_helper(struct vty
*vty
, bool json
)
4936 json_object
*json_parent
= NULL
;
4937 json_object
*json_vrf
= NULL
;
4940 json_parent
= json_object_new_object();
4942 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4944 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4946 json_vrf
= json_object_new_object();
4948 show_mroute_count(vrf
->info
, vty
, json_vrf
);
4951 json_object_object_add(json_parent
, vrf
->name
,
4955 vty_json(vty
, json_parent
);
4960 int pim_show_mroute_summary_helper(const char *vrf
, struct vty
*vty
, bool json
)
4962 struct pim_instance
*pim
;
4964 json_object
*json_parent
= NULL
;
4966 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4974 vty_out(vty
, "%% Unable to find pim instance\n");
4979 json_parent
= json_object_new_object();
4981 show_mroute_summary(pim
, vty
, json_parent
);
4984 vty_json(vty
, json_parent
);
4989 int pim_show_mroute_summary_vrf_all_helper(struct vty
*vty
, bool json
)
4992 json_object
*json_parent
= NULL
;
4993 json_object
*json_vrf
= NULL
;
4996 json_parent
= json_object_new_object();
4998 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
5000 vty_out(vty
, "VRF: %s\n", vrf
->name
);
5002 json_vrf
= json_object_new_object();
5004 show_mroute_summary(vrf
->info
, vty
, json_vrf
);
5007 json_object_object_add(json_parent
, vrf
->name
,
5012 vty_json(vty
, json_parent
);
5017 void pim_show_interface_traffic(struct pim_instance
*pim
, struct vty
*vty
,
5020 struct interface
*ifp
= NULL
;
5021 struct pim_interface
*pim_ifp
= NULL
;
5022 json_object
*json
= NULL
;
5023 json_object
*json_row
= NULL
;
5026 json
= json_object_new_object();
5029 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5030 "Interface", " HELLO", " JOIN",
5031 " PRUNE", " REGISTER", "REGISTER-STOP",
5033 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5034 " Rx/Tx", " Rx/Tx", " Rx/Tx",
5035 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
5037 "---------------------------------------------------------------------------------------------------------------\n");
5040 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5041 pim_ifp
= ifp
->info
;
5047 json_row
= json_object_new_object();
5048 json_object_pim_ifp_add(json_row
, ifp
);
5049 json_object_int_add(json_row
, "helloRx",
5050 pim_ifp
->pim_ifstat_hello_recv
);
5051 json_object_int_add(json_row
, "helloTx",
5052 pim_ifp
->pim_ifstat_hello_sent
);
5053 json_object_int_add(json_row
, "joinRx",
5054 pim_ifp
->pim_ifstat_join_recv
);
5055 json_object_int_add(json_row
, "joinTx",
5056 pim_ifp
->pim_ifstat_join_send
);
5057 json_object_int_add(json_row
, "pruneRx",
5058 pim_ifp
->pim_ifstat_prune_recv
);
5059 json_object_int_add(json_row
, "pruneTx",
5060 pim_ifp
->pim_ifstat_prune_send
);
5061 json_object_int_add(json_row
, "registerRx",
5062 pim_ifp
->pim_ifstat_reg_recv
);
5063 json_object_int_add(json_row
, "registerTx",
5064 pim_ifp
->pim_ifstat_reg_send
);
5065 json_object_int_add(json_row
, "registerStopRx",
5066 pim_ifp
->pim_ifstat_reg_stop_recv
);
5067 json_object_int_add(json_row
, "registerStopTx",
5068 pim_ifp
->pim_ifstat_reg_stop_send
);
5069 json_object_int_add(json_row
, "assertRx",
5070 pim_ifp
->pim_ifstat_assert_recv
);
5071 json_object_int_add(json_row
, "assertTx",
5072 pim_ifp
->pim_ifstat_assert_send
);
5073 json_object_int_add(json_row
, "bsmRx",
5074 pim_ifp
->pim_ifstat_bsm_rx
);
5075 json_object_int_add(json_row
, "bsmTx",
5076 pim_ifp
->pim_ifstat_bsm_tx
);
5077 json_object_object_add(json
, ifp
->name
, json_row
);
5080 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5082 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5083 pim_ifp
->pim_ifstat_hello_sent
,
5084 pim_ifp
->pim_ifstat_join_recv
,
5085 pim_ifp
->pim_ifstat_join_send
,
5086 pim_ifp
->pim_ifstat_prune_recv
,
5087 pim_ifp
->pim_ifstat_prune_send
,
5088 pim_ifp
->pim_ifstat_reg_recv
,
5089 pim_ifp
->pim_ifstat_reg_send
,
5090 pim_ifp
->pim_ifstat_reg_stop_recv
,
5091 pim_ifp
->pim_ifstat_reg_stop_send
,
5092 pim_ifp
->pim_ifstat_assert_recv
,
5093 pim_ifp
->pim_ifstat_assert_send
,
5094 pim_ifp
->pim_ifstat_bsm_rx
,
5095 pim_ifp
->pim_ifstat_bsm_tx
);
5099 vty_json(vty
, json
);
5102 void pim_show_interface_traffic_single(struct pim_instance
*pim
,
5103 struct vty
*vty
, const char *ifname
,
5106 struct interface
*ifp
= NULL
;
5107 struct pim_interface
*pim_ifp
= NULL
;
5108 json_object
*json
= NULL
;
5109 json_object
*json_row
= NULL
;
5110 uint8_t found_ifname
= 0;
5113 json
= json_object_new_object();
5116 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5117 "Interface", " HELLO", " JOIN", " PRUNE",
5118 " REGISTER", " REGISTER-STOP", " ASSERT",
5120 vty_out(vty
, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5121 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
5122 " Rx/Tx", " Rx/Tx", " Rx/Tx");
5124 "-------------------------------------------------------------------------------------------------------------------------------\n");
5127 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5128 if (strcmp(ifname
, ifp
->name
))
5131 pim_ifp
= ifp
->info
;
5138 json_row
= json_object_new_object();
5139 json_object_pim_ifp_add(json_row
, ifp
);
5140 json_object_int_add(json_row
, "helloRx",
5141 pim_ifp
->pim_ifstat_hello_recv
);
5142 json_object_int_add(json_row
, "helloTx",
5143 pim_ifp
->pim_ifstat_hello_sent
);
5144 json_object_int_add(json_row
, "joinRx",
5145 pim_ifp
->pim_ifstat_join_recv
);
5146 json_object_int_add(json_row
, "joinTx",
5147 pim_ifp
->pim_ifstat_join_send
);
5148 json_object_int_add(json_row
, "pruneRx",
5149 pim_ifp
->pim_ifstat_prune_recv
);
5150 json_object_int_add(json_row
, "pruneTx",
5151 pim_ifp
->pim_ifstat_prune_send
);
5152 json_object_int_add(json_row
, "registerRx",
5153 pim_ifp
->pim_ifstat_reg_recv
);
5154 json_object_int_add(json_row
, "registerTx",
5155 pim_ifp
->pim_ifstat_reg_send
);
5156 json_object_int_add(json_row
, "registerStopRx",
5157 pim_ifp
->pim_ifstat_reg_stop_recv
);
5158 json_object_int_add(json_row
, "registerStopTx",
5159 pim_ifp
->pim_ifstat_reg_stop_send
);
5160 json_object_int_add(json_row
, "assertRx",
5161 pim_ifp
->pim_ifstat_assert_recv
);
5162 json_object_int_add(json_row
, "assertTx",
5163 pim_ifp
->pim_ifstat_assert_send
);
5164 json_object_int_add(json_row
, "bsmRx",
5165 pim_ifp
->pim_ifstat_bsm_rx
);
5166 json_object_int_add(json_row
, "bsmTx",
5167 pim_ifp
->pim_ifstat_bsm_tx
);
5169 json_object_object_add(json
, ifp
->name
, json_row
);
5172 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5174 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5175 pim_ifp
->pim_ifstat_hello_sent
,
5176 pim_ifp
->pim_ifstat_join_recv
,
5177 pim_ifp
->pim_ifstat_join_send
,
5178 pim_ifp
->pim_ifstat_prune_recv
,
5179 pim_ifp
->pim_ifstat_prune_send
,
5180 pim_ifp
->pim_ifstat_reg_recv
,
5181 pim_ifp
->pim_ifstat_reg_send
,
5182 pim_ifp
->pim_ifstat_reg_stop_recv
,
5183 pim_ifp
->pim_ifstat_reg_stop_send
,
5184 pim_ifp
->pim_ifstat_assert_recv
,
5185 pim_ifp
->pim_ifstat_assert_send
,
5186 pim_ifp
->pim_ifstat_bsm_rx
,
5187 pim_ifp
->pim_ifstat_bsm_tx
);
5191 vty_json(vty
, json
);
5192 else if (!found_ifname
)
5193 vty_out(vty
, "%% No such interface\n");
5196 int pim_show_interface_traffic_helper(const char *vrf
, const char *if_name
,
5197 struct vty
*vty
, bool uj
)
5199 struct pim_instance
*pim
;
5202 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5210 vty_out(vty
, "%% Unable to find pim instance\n");
5215 pim_show_interface_traffic_single(v
->info
, vty
, if_name
, uj
);
5217 pim_show_interface_traffic(v
->info
, vty
, uj
);
5222 void clear_pim_interfaces(struct pim_instance
*pim
)
5224 struct interface
*ifp
;
5226 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5228 pim_neighbor_delete_all(ifp
, "interface cleared");
5232 void pim_show_bsr(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
5235 char last_bsm_seen
[10];
5238 json_object
*json
= NULL
;
5240 if (pim_addr_is_any(pim
->global_scope
.current_bsr
)) {
5241 pim_time_uptime(uptime
, sizeof(uptime
),
5242 pim
->global_scope
.current_bsr_first_ts
);
5243 pim_time_uptime(last_bsm_seen
, sizeof(last_bsm_seen
),
5244 pim
->global_scope
.current_bsr_last_ts
);
5248 now
= pim_time_monotonic_sec();
5249 pim_time_uptime(uptime
, sizeof(uptime
),
5250 (now
- pim
->global_scope
.current_bsr_first_ts
));
5251 pim_time_uptime(last_bsm_seen
, sizeof(last_bsm_seen
),
5252 now
- pim
->global_scope
.current_bsr_last_ts
);
5255 switch (pim
->global_scope
.state
) {
5257 strlcpy(bsr_state
, "NO_INFO", sizeof(bsr_state
));
5260 strlcpy(bsr_state
, "ACCEPT_ANY", sizeof(bsr_state
));
5262 case ACCEPT_PREFERRED
:
5263 strlcpy(bsr_state
, "ACCEPT_PREFERRED", sizeof(bsr_state
));
5266 strlcpy(bsr_state
, "", sizeof(bsr_state
));
5271 json
= json_object_new_object();
5272 json_object_string_addf(json
, "bsr", "%pPA",
5273 &pim
->global_scope
.current_bsr
);
5274 json_object_int_add(json
, "priority",
5275 pim
->global_scope
.current_bsr_prio
);
5276 json_object_int_add(json
, "fragmentTag",
5277 pim
->global_scope
.bsm_frag_tag
);
5278 json_object_string_add(json
, "state", bsr_state
);
5279 json_object_string_add(json
, "upTime", uptime
);
5280 json_object_string_add(json
, "lastBsmSeen", last_bsm_seen
);
5284 vty_out(vty
, "PIMv2 Bootstrap information\n");
5285 vty_out(vty
, "Current preferred BSR address: %pPA\n",
5286 &pim
->global_scope
.current_bsr
);
5288 "Priority Fragment-Tag State UpTime\n");
5289 vty_out(vty
, " %-12d %-12d %-13s %7s\n",
5290 pim
->global_scope
.current_bsr_prio
,
5291 pim
->global_scope
.bsm_frag_tag
, bsr_state
, uptime
);
5292 vty_out(vty
, "Last BSM seen: %s\n", last_bsm_seen
);
5296 vty_json(vty
, json
);
5299 int pim_show_bsr_helper(const char *vrf
, struct vty
*vty
, bool uj
)
5301 struct pim_instance
*pim
;
5304 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5309 pim
= pim_get_pim_instance(v
->vrf_id
);
5312 vty_out(vty
, "%% Unable to find pim instance\n");
5316 pim_show_bsr(v
->info
, vty
, uj
);
5321 /*Display the group-rp mappings */
5322 static void pim_show_group_rp_mappings_info(struct pim_instance
*pim
,
5323 struct vty
*vty
, bool uj
)
5325 struct bsgrp_node
*bsgrp
;
5326 struct bsm_rpinfo
*bsm_rp
;
5327 struct route_node
*rn
;
5328 json_object
*json
= NULL
;
5329 json_object
*json_group
= NULL
;
5330 json_object
*json_row
= NULL
;
5331 struct ttable
*tt
= NULL
;
5334 json
= json_object_new_object();
5335 json_object_string_addf(json
, "BSR Address", "%pPA",
5336 &pim
->global_scope
.current_bsr
);
5338 vty_out(vty
, "BSR Address %pPA\n",
5339 &pim
->global_scope
.current_bsr
);
5341 for (rn
= route_top(pim
->global_scope
.bsrp_table
); rn
;
5342 rn
= route_next(rn
)) {
5343 bsgrp
= (struct bsgrp_node
*)rn
->info
;
5348 char grp_str
[PREFIX_STRLEN
];
5350 prefix2str(&bsgrp
->group
, grp_str
, sizeof(grp_str
));
5353 json_object_object_get_ex(json
, grp_str
, &json_group
);
5355 json_group
= json_object_new_object();
5356 json_object_object_add(json
, grp_str
,
5360 vty_out(vty
, "Group Address %pFX\n", &bsgrp
->group
);
5361 vty_out(vty
, "--------------------------\n");
5362 /* Prepare table. */
5363 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
5364 ttable_add_row(tt
, "Rp Address|priority|Holdtime|Hash");
5365 tt
->style
.cell
.rpad
= 2;
5366 tt
->style
.corner
= '+';
5369 ttable_add_row(tt
, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ',
5373 frr_each (bsm_rpinfos
, bsgrp
->bsrp_list
, bsm_rp
) {
5375 json_row
= json_object_new_object();
5376 json_object_string_addf(json_row
, "Rp Address",
5378 &bsm_rp
->rp_address
);
5379 json_object_int_add(json_row
, "Rp HoldTime",
5380 bsm_rp
->rp_holdtime
);
5381 json_object_int_add(json_row
, "Rp Priority",
5383 json_object_int_add(json_row
, "Hash Val",
5385 json_object_object_addf(json_group
, json_row
,
5387 &bsm_rp
->rp_address
);
5391 tt
, "%pPA|%u|%u|%u",
5392 &bsm_rp
->rp_address
, bsm_rp
->rp_prio
,
5393 bsm_rp
->rp_holdtime
, bsm_rp
->hash
);
5396 /* Dump the generated table. */
5400 table
= ttable_dump(tt
, "\n");
5401 vty_out(vty
, "%s\n", table
);
5402 XFREE(MTYPE_TMP
, table
);
5406 if (!bsm_rpinfos_count(bsgrp
->bsrp_list
) && !uj
)
5407 vty_out(vty
, "Active List is empty.\n");
5410 json_object_int_add(json_group
, "Pending RP count",
5411 bsgrp
->pend_rp_cnt
);
5413 vty_out(vty
, "(PENDING)\n");
5414 vty_out(vty
, "Pending RP count :%d\n",
5415 bsgrp
->pend_rp_cnt
);
5416 if (bsgrp
->pend_rp_cnt
) {
5417 /* Prepare table. */
5418 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
5421 "Rp Address|priority|Holdtime|Hash");
5422 tt
->style
.cell
.rpad
= 2;
5423 tt
->style
.corner
= '+';
5428 frr_each (bsm_rpinfos
, bsgrp
->partial_bsrp_list
, bsm_rp
) {
5430 json_row
= json_object_new_object();
5431 json_object_string_addf(json_row
, "Rp Address",
5433 &bsm_rp
->rp_address
);
5434 json_object_int_add(json_row
, "Rp HoldTime",
5435 bsm_rp
->rp_holdtime
);
5436 json_object_int_add(json_row
, "Rp Priority",
5438 json_object_int_add(json_row
, "Hash Val",
5440 json_object_object_addf(json_group
, json_row
,
5442 &bsm_rp
->rp_address
);
5445 tt
, "%pPA|%u|%u|%u",
5446 &bsm_rp
->rp_address
, bsm_rp
->rp_prio
,
5447 bsm_rp
->rp_holdtime
, bsm_rp
->hash
);
5450 /* Dump the generated table. */
5454 table
= ttable_dump(tt
, "\n");
5455 vty_out(vty
, "%s\n", table
);
5456 XFREE(MTYPE_TMP
, table
);
5459 if (!bsm_rpinfos_count(bsgrp
->partial_bsrp_list
) && !uj
)
5460 vty_out(vty
, "Partial List is empty\n");
5467 vty_json(vty
, json
);
5470 int pim_show_group_rp_mappings_info_helper(const char *vrf
, struct vty
*vty
,
5473 struct pim_instance
*pim
;
5476 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5484 vty_out(vty
, "%% Unable to find pim instance\n");
5488 pim_show_group_rp_mappings_info(v
->info
, vty
, uj
);
5493 /* Display the bsm database details */
5494 static void pim_show_bsm_db(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
5498 struct bsm_frag
*bsfrag
;
5499 json_object
*json
= NULL
;
5500 json_object
*json_group
= NULL
;
5501 json_object
*json_row
= NULL
;
5503 count
= bsm_frags_count(pim
->global_scope
.bsm_frags
);
5506 json
= json_object_new_object();
5507 json_object_int_add(json
, "Number of the fragments", count
);
5509 vty_out(vty
, "Scope Zone: Global\n");
5510 vty_out(vty
, "Number of the fragments: %d\n", count
);
5514 frr_each (bsm_frags
, pim
->global_scope
.bsm_frags
, bsfrag
) {
5515 char grp_str
[PREFIX_STRLEN
];
5516 struct bsmmsg_grpinfo
*group
;
5517 struct bsmmsg_rpinfo
*bsm_rpinfo
;
5519 struct bsm_hdr
*hdr
;
5521 uint32_t offset
= 0;
5524 uint32_t frag_rp_cnt
= 0;
5529 /* skip pim header */
5530 buf
+= PIM_MSG_HEADER_LEN
;
5531 len
-= PIM_MSG_HEADER_LEN
;
5533 hdr
= (struct bsm_hdr
*)buf
;
5534 /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
5535 memcpy(&bsr_addr
, &hdr
->bsr_addr
.addr
, sizeof(bsr_addr
));
5537 /* BSM starts with bsr header */
5538 buf
+= sizeof(struct bsm_hdr
);
5539 len
-= sizeof(struct bsm_hdr
);
5542 json_object_string_addf(json
, "BSR address", "%pPA",
5544 json_object_int_add(json
, "BSR priority",
5546 json_object_int_add(json
, "Hashmask Length",
5548 json_object_int_add(json
, "Fragment Tag",
5549 ntohs(hdr
->frag_tag
));
5551 vty_out(vty
, "BSM Fragment : %d\n", fragment
);
5552 vty_out(vty
, "------------------\n");
5553 vty_out(vty
, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
5554 "BSR-Priority", "Hashmask-len", "Fragment-Tag");
5555 vty_out(vty
, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr
,
5556 hdr
->bsr_prio
, hdr
->hm_len
,
5557 ntohs(hdr
->frag_tag
));
5562 while (offset
< len
) {
5563 group
= (struct bsmmsg_grpinfo
*)buf
;
5565 if (group
->group
.family
== PIM_MSG_ADDRESS_FAMILY_IPV4
)
5566 grp
.family
= AF_INET
;
5567 else if (group
->group
.family
==
5568 PIM_MSG_ADDRESS_FAMILY_IPV6
)
5569 grp
.family
= AF_INET6
;
5571 grp
.prefixlen
= group
->group
.mask
;
5573 grp
.u
.prefix4
= group
->group
.addr
;
5575 grp
.u
.prefix6
= group
->group
.addr
;
5578 prefix2str(&grp
, grp_str
, sizeof(grp_str
));
5580 buf
+= sizeof(struct bsmmsg_grpinfo
);
5581 offset
+= sizeof(struct bsmmsg_grpinfo
);
5584 json_object_object_get_ex(json
, grp_str
,
5587 json_group
= json_object_new_object();
5588 json_object_int_add(json_group
,
5591 json_object_int_add(
5592 json_group
, "Fragment Rp count",
5593 group
->frag_rp_count
);
5594 json_object_object_add(json
, grp_str
,
5598 vty_out(vty
, "Group : %s\n", grp_str
);
5599 vty_out(vty
, "-------------------\n");
5600 vty_out(vty
, "Rp Count:%d\n", group
->rp_count
);
5601 vty_out(vty
, "Fragment Rp Count : %d\n",
5602 group
->frag_rp_count
);
5605 frag_rp_cnt
= group
->frag_rp_count
;
5612 "RpAddress HoldTime Priority\n");
5614 while (frag_rp_cnt
--) {
5617 bsm_rpinfo
= (struct bsmmsg_rpinfo
*)buf
;
5618 /* unaligned, again */
5619 memcpy(&rp_addr
, &bsm_rpinfo
->rpaddr
.addr
,
5622 buf
+= sizeof(struct bsmmsg_rpinfo
);
5623 offset
+= sizeof(struct bsmmsg_rpinfo
);
5626 json_row
= json_object_new_object();
5627 json_object_string_addf(
5628 json_row
, "Rp Address", "%pPA",
5630 json_object_int_add(
5631 json_row
, "Rp HoldTime",
5632 ntohs(bsm_rpinfo
->rp_holdtime
));
5633 json_object_int_add(json_row
,
5635 bsm_rpinfo
->rp_pri
);
5636 json_object_object_addf(
5637 json_group
, json_row
, "%pPA",
5640 vty_out(vty
, "%-15pPA %-12d %d\n",
5642 ntohs(bsm_rpinfo
->rp_holdtime
),
5643 bsm_rpinfo
->rp_pri
);
5653 vty_json(vty
, json
);
5656 int pim_show_bsm_db_helper(const char *vrf
, struct vty
*vty
, bool uj
)
5658 struct pim_instance
*pim
;
5661 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5669 vty_out(vty
, "%% Unable to find pim instance\n");
5673 pim_show_bsm_db(v
->info
, vty
, uj
);