3 * Copyright (C) 2022 Vmware, Inc.
4 * Mobashshera Rasool <mrasool@vmware.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "lib/srcdest_table.h"
34 #include "lib/linklist.h"
35 #include "termtable.h"
38 #include "pim_instance.h"
40 #include "lib/northbound_cli.h"
41 #include "pim_errors.h"
43 #include "pim_mroute.h"
46 #include "pim_cmd_common.h"
48 #include "pim_zebra.h"
49 #include "pim_zlookup.h"
50 #include "pim_iface.h"
51 #include "pim_macro.h"
52 #include "pim_neighbor.h"
56 #include "pim_static.h"
58 #include "pim_static.h"
63 * Get current node VRF name.
66 * In case of failure it will print error message to user.
68 * \returns name or NULL if failed to get VRF.
70 const char *pim_cli_get_vrf_name(struct vty
*vty
)
72 const struct lyd_node
*vrf_node
;
74 /* Not inside any VRF context. */
75 if (vty
->xpath_index
== 0)
76 return VRF_DEFAULT_NAME
;
78 vrf_node
= yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
79 if (vrf_node
== NULL
) {
80 vty_out(vty
, "%% Failed to get vrf dnode in configuration\n");
84 return yang_dnode_get_string(vrf_node
, "./name");
87 int pim_process_join_prune_cmd(struct vty
*vty
, const char *jpi_str
)
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_MODIFY
, jpi_str
);
97 return nb_cli_apply_changes(vty
, NULL
);
100 int pim_process_no_join_prune_cmd(struct vty
*vty
)
102 char xpath
[XPATH_MAXLEN
];
104 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
105 FRR_PIM_AF_XPATH_VAL
);
106 strlcat(xpath
, "/join-prune-interval", sizeof(xpath
));
108 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
110 return nb_cli_apply_changes(vty
, NULL
);
113 int pim_process_spt_switchover_infinity_cmd(struct vty
*vty
)
116 char spt_plist_xpath
[XPATH_MAXLEN
];
117 char spt_action_xpath
[XPATH_MAXLEN
];
119 vrfname
= pim_cli_get_vrf_name(vty
);
121 return CMD_WARNING_CONFIG_FAILED
;
123 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
124 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
125 FRR_PIM_AF_XPATH_VAL
);
126 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
127 sizeof(spt_plist_xpath
));
129 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
130 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
131 FRR_PIM_AF_XPATH_VAL
);
132 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
133 sizeof(spt_action_xpath
));
135 if (yang_dnode_exists(vty
->candidate_config
->dnode
, spt_plist_xpath
))
136 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
,
138 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
141 return nb_cli_apply_changes(vty
, NULL
);
144 int pim_process_spt_switchover_prefixlist_cmd(struct vty
*vty
,
148 char spt_plist_xpath
[XPATH_MAXLEN
];
149 char spt_action_xpath
[XPATH_MAXLEN
];
151 vrfname
= pim_cli_get_vrf_name(vty
);
153 return CMD_WARNING_CONFIG_FAILED
;
155 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
156 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
157 FRR_PIM_AF_XPATH_VAL
);
158 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
159 sizeof(spt_plist_xpath
));
161 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
162 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
163 FRR_PIM_AF_XPATH_VAL
);
164 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
165 sizeof(spt_action_xpath
));
167 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
169 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_MODIFY
,
172 return nb_cli_apply_changes(vty
, NULL
);
175 int pim_process_no_spt_switchover_cmd(struct vty
*vty
)
178 char spt_plist_xpath
[XPATH_MAXLEN
];
179 char spt_action_xpath
[XPATH_MAXLEN
];
181 vrfname
= pim_cli_get_vrf_name(vty
);
183 return CMD_WARNING_CONFIG_FAILED
;
185 snprintf(spt_plist_xpath
, sizeof(spt_plist_xpath
),
186 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
187 FRR_PIM_AF_XPATH_VAL
);
188 strlcat(spt_plist_xpath
, "/spt-switchover/spt-infinity-prefix-list",
189 sizeof(spt_plist_xpath
));
191 snprintf(spt_action_xpath
, sizeof(spt_action_xpath
),
192 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
193 FRR_PIM_AF_XPATH_VAL
);
194 strlcat(spt_action_xpath
, "/spt-switchover/spt-action",
195 sizeof(spt_action_xpath
));
197 nb_cli_enqueue_change(vty
, spt_plist_xpath
, NB_OP_DESTROY
, NULL
);
198 nb_cli_enqueue_change(vty
, spt_action_xpath
, NB_OP_MODIFY
,
199 "PIM_SPT_IMMEDIATE");
201 return nb_cli_apply_changes(vty
, NULL
);
204 int pim_process_pim_packet_cmd(struct vty
*vty
, const char *packet
)
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_MODIFY
, packet
);
214 return nb_cli_apply_changes(vty
, NULL
);
217 int pim_process_no_pim_packet_cmd(struct vty
*vty
)
219 char xpath
[XPATH_MAXLEN
];
221 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
222 FRR_PIM_AF_XPATH_VAL
);
223 strlcat(xpath
, "/packets", sizeof(xpath
));
225 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
227 return nb_cli_apply_changes(vty
, NULL
);
230 int pim_process_keepalivetimer_cmd(struct vty
*vty
, const char *kat
)
233 char ka_timer_xpath
[XPATH_MAXLEN
];
235 vrfname
= pim_cli_get_vrf_name(vty
);
237 return CMD_WARNING_CONFIG_FAILED
;
239 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
240 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
241 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
243 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_MODIFY
,
246 return nb_cli_apply_changes(vty
, NULL
);
249 int pim_process_no_keepalivetimer_cmd(struct vty
*vty
)
252 char ka_timer_xpath
[XPATH_MAXLEN
];
254 vrfname
= pim_cli_get_vrf_name(vty
);
256 return CMD_WARNING_CONFIG_FAILED
;
258 snprintf(ka_timer_xpath
, sizeof(ka_timer_xpath
), FRR_PIM_VRF_XPATH
,
259 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
);
260 strlcat(ka_timer_xpath
, "/keep-alive-timer", sizeof(ka_timer_xpath
));
262 nb_cli_enqueue_change(vty
, ka_timer_xpath
, NB_OP_DESTROY
, NULL
);
264 return nb_cli_apply_changes(vty
, NULL
);
267 int pim_process_rp_kat_cmd(struct vty
*vty
, const char *rpkat
)
270 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
272 vrfname
= pim_cli_get_vrf_name(vty
);
274 return CMD_WARNING_CONFIG_FAILED
;
276 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
277 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
278 FRR_PIM_AF_XPATH_VAL
);
279 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
280 sizeof(rp_ka_timer_xpath
));
282 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
285 return nb_cli_apply_changes(vty
, NULL
);
288 int pim_process_no_rp_kat_cmd(struct vty
*vty
)
292 char rp_ka_timer_xpath
[XPATH_MAXLEN
];
294 char rs_timer_xpath
[XPATH_MAXLEN
];
296 snprintf(rs_timer_xpath
, sizeof(rs_timer_xpath
),
297 FRR_PIM_ROUTER_XPATH
, FRR_PIM_AF_XPATH_VAL
);
298 strlcat(rs_timer_xpath
, "/register-suppress-time",
299 sizeof(rs_timer_xpath
));
302 v
= yang_dnode_get_uint16(vty
->candidate_config
->dnode
,
304 v
= 3 * v
+ PIM_REGISTER_PROBE_TIME_DEFAULT
;
307 snprintf(rp_ka_timer
, sizeof(rp_ka_timer
), "%u", v
);
309 vrfname
= pim_cli_get_vrf_name(vty
);
311 return CMD_WARNING_CONFIG_FAILED
;
313 snprintf(rp_ka_timer_xpath
, sizeof(rp_ka_timer_xpath
),
314 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
315 FRR_PIM_AF_XPATH_VAL
);
316 strlcat(rp_ka_timer_xpath
, "/rp-keep-alive-timer",
317 sizeof(rp_ka_timer_xpath
));
319 nb_cli_enqueue_change(vty
, rp_ka_timer_xpath
, NB_OP_MODIFY
,
322 return nb_cli_apply_changes(vty
, NULL
);
325 int pim_process_register_suppress_cmd(struct vty
*vty
, const char *rst
)
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_MODIFY
, rst
);
335 return nb_cli_apply_changes(vty
, NULL
);
338 int pim_process_no_register_suppress_cmd(struct vty
*vty
)
340 char xpath
[XPATH_MAXLEN
];
342 snprintf(xpath
, sizeof(xpath
), FRR_PIM_ROUTER_XPATH
,
343 FRR_PIM_AF_XPATH_VAL
);
344 strlcat(xpath
, "/register-suppress-time", sizeof(xpath
));
346 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
348 return nb_cli_apply_changes(vty
, NULL
);
351 int pim_process_ip_pim_cmd(struct vty
*vty
)
353 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
, "true");
355 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
356 FRR_PIM_AF_XPATH_VAL
);
359 int pim_process_ip_pim_passive_cmd(struct vty
*vty
, bool enable
)
362 nb_cli_enqueue_change(vty
, "./pim-passive-enable", NB_OP_MODIFY
,
365 nb_cli_enqueue_change(vty
, "./pim-passive-enable", NB_OP_MODIFY
,
368 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
369 FRR_PIM_AF_XPATH_VAL
);
372 int pim_process_no_ip_pim_cmd(struct vty
*vty
)
374 const struct lyd_node
*mld_enable_dnode
;
375 char mld_if_xpath
[XPATH_MAXLEN
];
378 snprintf(mld_if_xpath
, sizeof(mld_if_xpath
),
379 "%s/frr-gmp:gmp/address-family[address-family='%s']",
380 VTY_CURR_XPATH
, FRR_PIM_AF_XPATH_VAL
);
382 if (printed
>= (int)(sizeof(mld_if_xpath
))) {
383 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
385 return CMD_WARNING_CONFIG_FAILED
;
388 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
389 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
390 FRR_PIM_AF_XPATH_VAL
);
392 if (!mld_enable_dnode
) {
393 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
, NULL
);
394 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
396 if (!yang_dnode_get_bool(mld_enable_dnode
, ".")) {
397 nb_cli_enqueue_change(vty
, mld_if_xpath
, NB_OP_DESTROY
,
399 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
401 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
405 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
406 FRR_PIM_AF_XPATH_VAL
);
409 int pim_process_ip_pim_drprio_cmd(struct vty
*vty
, const char *drpriority_str
)
411 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_MODIFY
,
414 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
415 FRR_PIM_AF_XPATH_VAL
);
418 int pim_process_no_ip_pim_drprio_cmd(struct vty
*vty
)
420 nb_cli_enqueue_change(vty
, "./dr-priority", NB_OP_DESTROY
, NULL
);
422 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
423 FRR_PIM_AF_XPATH_VAL
);
426 int pim_process_ip_pim_hello_cmd(struct vty
*vty
, const char *hello_str
,
427 const char *hold_str
)
429 const struct lyd_node
*mld_enable_dnode
;
431 mld_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
432 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
433 FRR_PIM_AF_XPATH_VAL
);
435 if (!mld_enable_dnode
) {
436 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
439 if (!yang_dnode_get_bool(mld_enable_dnode
, "."))
440 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
444 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_MODIFY
, hello_str
);
447 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_MODIFY
,
450 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
451 FRR_PIM_AF_XPATH_VAL
);
454 int pim_process_no_ip_pim_hello_cmd(struct vty
*vty
)
456 nb_cli_enqueue_change(vty
, "./hello-interval", NB_OP_DESTROY
, NULL
);
457 nb_cli_enqueue_change(vty
, "./hello-holdtime", NB_OP_DESTROY
, NULL
);
459 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
460 FRR_PIM_AF_XPATH_VAL
);
463 int pim_process_ip_pim_activeactive_cmd(struct vty
*vty
, const char *no
)
466 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
469 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
472 nb_cli_enqueue_change(vty
, "./active-active", NB_OP_MODIFY
,
476 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
477 FRR_PIM_AF_XPATH_VAL
);
480 int pim_process_ip_pim_boundary_oil_cmd(struct vty
*vty
, const char *oil
)
482 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_MODIFY
,
485 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
486 FRR_PIM_AF_XPATH_VAL
);
489 int pim_process_no_ip_pim_boundary_oil_cmd(struct vty
*vty
)
491 nb_cli_enqueue_change(vty
, "./multicast-boundary-oil", NB_OP_DESTROY
,
494 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
495 FRR_PIM_AF_XPATH_VAL
);
498 int pim_process_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
499 const char *group_str
, const char *source_str
)
501 nb_cli_enqueue_change(vty
, "./oif", NB_OP_MODIFY
, interface
);
504 char buf
[SRCDEST2STR_BUFFER
];
506 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
507 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
508 FRR_PIM_AF_XPATH_VAL
, buf
,
512 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
513 FRR_PIM_AF_XPATH_VAL
, source_str
,
517 int pim_process_no_ip_mroute_cmd(struct vty
*vty
, const char *interface
,
518 const char *group_str
, const char *source_str
)
520 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
523 char buf
[SRCDEST2STR_BUFFER
];
525 inet_ntop(AF_INET6
, &in6addr_any
, buf
, sizeof(buf
));
526 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
527 FRR_PIM_AF_XPATH_VAL
, buf
,
531 return nb_cli_apply_changes(vty
, FRR_PIM_MROUTE_XPATH
,
532 FRR_PIM_AF_XPATH_VAL
, source_str
,
536 int pim_process_rp_cmd(struct vty
*vty
, const char *rp_str
,
537 const char *group_str
)
540 char rp_group_xpath
[XPATH_MAXLEN
];
545 result
= str2prefix(group_str
, &group
);
549 prefix_copy(&temp
, &group
);
551 if (!prefix_same(&group
, &temp
)) {
552 vty_out(vty
, "%% Inconsistent address and mask: %s\n",
554 return CMD_WARNING_CONFIG_FAILED
;
559 vty_out(vty
, "%% Bad group address specified: %s\n", group_str
);
560 return CMD_WARNING_CONFIG_FAILED
;
563 result
= inet_pton(PIM_AF
, rp_str
, &rp_addr
);
565 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
566 return CMD_WARNING_CONFIG_FAILED
;
569 if (pim_addr_is_any(rp_addr
) || pim_addr_is_multicast(rp_addr
)) {
570 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
571 return CMD_WARNING_CONFIG_FAILED
;
575 if (IN6_IS_ADDR_LINKLOCAL(&rp_addr
)) {
576 vty_out(vty
, "%% Bad RP address specified: %s\n", rp_str
);
577 return CMD_WARNING_CONFIG_FAILED
;
581 vrfname
= pim_cli_get_vrf_name(vty
);
583 return CMD_WARNING_CONFIG_FAILED
;
585 snprintf(rp_group_xpath
, sizeof(rp_group_xpath
),
586 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
587 FRR_PIM_AF_XPATH_VAL
, rp_str
);
588 strlcat(rp_group_xpath
, "/group-list", sizeof(rp_group_xpath
));
590 nb_cli_enqueue_change(vty
, rp_group_xpath
, NB_OP_CREATE
, group_str
);
592 return nb_cli_apply_changes(vty
, NULL
);
595 int pim_process_no_rp_cmd(struct vty
*vty
, const char *rp_str
,
596 const char *group_str
)
598 char group_list_xpath
[XPATH_MAXLEN
];
599 char group_xpath
[XPATH_MAXLEN
];
600 char rp_xpath
[XPATH_MAXLEN
];
603 const struct lyd_node
*group_dnode
;
605 vrfname
= pim_cli_get_vrf_name(vty
);
607 return CMD_WARNING_CONFIG_FAILED
;
609 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
610 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
612 printed
= snprintf(group_list_xpath
, sizeof(group_list_xpath
),
613 "%s/group-list", rp_xpath
);
615 if (printed
>= (int)(sizeof(group_list_xpath
))) {
616 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
618 return CMD_WARNING_CONFIG_FAILED
;
621 printed
= snprintf(group_xpath
, sizeof(group_xpath
), "%s[.='%s']",
622 group_list_xpath
, group_str
);
624 if (printed
>= (int)(sizeof(group_xpath
))) {
625 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
627 return CMD_WARNING_CONFIG_FAILED
;
630 group_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, group_xpath
);
632 vty_out(vty
, "%% Unable to find specified RP\n");
636 if (yang_is_last_list_dnode(group_dnode
))
637 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
639 nb_cli_enqueue_change(vty
, group_list_xpath
, NB_OP_DESTROY
,
642 return nb_cli_apply_changes(vty
, NULL
);
645 int pim_process_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
646 const char *prefix_list
)
649 char rp_plist_xpath
[XPATH_MAXLEN
];
651 vrfname
= pim_cli_get_vrf_name(vty
);
653 return CMD_WARNING_CONFIG_FAILED
;
655 snprintf(rp_plist_xpath
, sizeof(rp_plist_xpath
),
656 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
657 FRR_PIM_AF_XPATH_VAL
, rp_str
);
658 strlcat(rp_plist_xpath
, "/prefix-list", sizeof(rp_plist_xpath
));
660 nb_cli_enqueue_change(vty
, rp_plist_xpath
, NB_OP_MODIFY
, prefix_list
);
662 return nb_cli_apply_changes(vty
, NULL
);
665 int pim_process_no_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
666 const char *prefix_list
)
668 char rp_xpath
[XPATH_MAXLEN
];
669 char plist_xpath
[XPATH_MAXLEN
];
671 const struct lyd_node
*plist_dnode
;
674 vrfname
= pim_cli_get_vrf_name(vty
);
676 return CMD_WARNING_CONFIG_FAILED
;
678 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
679 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
681 snprintf(plist_xpath
, sizeof(plist_xpath
), FRR_PIM_STATIC_RP_XPATH
,
682 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
683 strlcat(plist_xpath
, "/prefix-list", sizeof(plist_xpath
));
685 plist_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, plist_xpath
);
687 vty_out(vty
, "%% Unable to find specified RP\n");
691 plist
= yang_dnode_get_string(plist_dnode
, plist_xpath
);
692 if (strcmp(prefix_list
, plist
)) {
693 vty_out(vty
, "%% Unable to find specified RP\n");
697 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
699 return nb_cli_apply_changes(vty
, NULL
);
702 bool pim_sgaddr_match(pim_sgaddr item
, pim_sgaddr match
)
704 return (pim_addr_is_any(match
.grp
) ||
705 !pim_addr_cmp(match
.grp
, item
.grp
)) &&
706 (pim_addr_is_any(match
.src
) ||
707 !pim_addr_cmp(match
.src
, item
.src
));
710 void json_object_pim_ifp_add(struct json_object
*json
, struct interface
*ifp
)
712 struct pim_interface
*pim_ifp
;
715 json_object_string_add(json
, "name", ifp
->name
);
716 json_object_string_add(json
, "state", if_is_up(ifp
) ? "up" : "down");
717 json_object_string_addf(json
, "address", "%pPA",
718 &pim_ifp
->primary_address
);
719 json_object_int_add(json
, "index", ifp
->ifindex
);
721 if (if_is_multicast(ifp
))
722 json_object_boolean_true_add(json
, "flagMulticast");
724 if (if_is_broadcast(ifp
))
725 json_object_boolean_true_add(json
, "flagBroadcast");
727 if (ifp
->flags
& IFF_ALLMULTI
)
728 json_object_boolean_true_add(json
, "flagAllMulticast");
730 if (ifp
->flags
& IFF_PROMISC
)
731 json_object_boolean_true_add(json
, "flagPromiscuous");
733 if (PIM_IF_IS_DELETED(ifp
))
734 json_object_boolean_true_add(json
, "flagDeleted");
736 if (pim_if_lan_delay_enabled(ifp
))
737 json_object_boolean_true_add(json
, "lanDelayEnabled");
740 void pim_print_ifp_flags(struct vty
*vty
, struct interface
*ifp
)
742 vty_out(vty
, "Flags\n");
743 vty_out(vty
, "-----\n");
744 vty_out(vty
, "All Multicast : %s\n",
745 (ifp
->flags
& IFF_ALLMULTI
) ? "yes" : "no");
746 vty_out(vty
, "Broadcast : %s\n",
747 if_is_broadcast(ifp
) ? "yes" : "no");
748 vty_out(vty
, "Deleted : %s\n",
749 PIM_IF_IS_DELETED(ifp
) ? "yes" : "no");
750 vty_out(vty
, "Interface Index : %d\n", ifp
->ifindex
);
751 vty_out(vty
, "Multicast : %s\n",
752 if_is_multicast(ifp
) ? "yes" : "no");
753 vty_out(vty
, "Promiscuous : %s\n",
754 (ifp
->flags
& IFF_PROMISC
) ? "yes" : "no");
759 void json_object_pim_upstream_add(json_object
*json
, struct pim_upstream
*up
)
761 json_object_boolean_add(
762 json
, "drJoinDesired",
763 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED
));
764 json_object_boolean_add(
765 json
, "drJoinDesiredUpdated",
766 CHECK_FLAG(up
->flags
,
767 PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED
));
768 json_object_boolean_add(
769 json
, "firstHopRouter",
770 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FHR
));
771 json_object_boolean_add(
773 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
));
774 json_object_boolean_add(
776 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_PIM
));
777 json_object_boolean_add(
778 json
, "sourceStream",
779 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM
));
780 /* XXX: need to print ths flag in the plain text display as well */
781 json_object_boolean_add(
783 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP
));
784 json_object_boolean_add(
785 json
, "sendSGRptPrune",
786 CHECK_FLAG(up
->flags
,
787 PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE
));
788 json_object_boolean_add(
789 json
, "lastHopRouter",
790 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_LHR
));
791 json_object_boolean_add(
792 json
, "disableKATExpiry",
793 CHECK_FLAG(up
->flags
,
794 PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY
));
795 json_object_boolean_add(
796 json
, "staticIncomingInterface",
797 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF
));
798 json_object_boolean_add(
799 json
, "allowIncomingInterfaceinOil",
800 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL
));
801 json_object_boolean_add(
802 json
, "noPimRegistrationData",
803 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA
));
804 json_object_boolean_add(
805 json
, "forcePimRegistration",
806 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG
));
807 json_object_boolean_add(
808 json
, "sourceVxlanOrigination",
809 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG
));
810 json_object_boolean_add(
811 json
, "sourceVxlanTermination",
812 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM
));
813 json_object_boolean_add(
815 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN
));
816 json_object_boolean_add(
817 json
, "mlagNonDesignatedForwarder",
818 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF
));
822 pim_upstream_state2brief_str(enum pim_upstream_state join_state
,
823 char *state_str
, size_t state_str_len
)
825 switch (join_state
) {
826 case PIM_UPSTREAM_NOTJOINED
:
827 strlcpy(state_str
, "NotJ", state_str_len
);
829 case PIM_UPSTREAM_JOINED
:
830 strlcpy(state_str
, "J", state_str_len
);
833 strlcpy(state_str
, "Unk", state_str_len
);
838 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state
,
840 size_t state_str_len
)
844 strlcpy(state_str
, "RegNI", state_str_len
);
847 strlcpy(state_str
, "RegJ", state_str_len
);
849 case PIM_REG_JOIN_PENDING
:
851 strlcpy(state_str
, "RegP", state_str_len
);
857 void pim_show_rpf_refresh_stats(struct vty
*vty
, struct pim_instance
*pim
,
858 time_t now
, json_object
*json
)
860 char refresh_uptime
[10];
862 pim_time_uptime_begin(refresh_uptime
, sizeof(refresh_uptime
), now
,
863 pim
->rpf_cache_refresh_last
);
866 json_object_int_add(json
, "rpfCacheRefreshDelayMsecs",
867 router
->rpf_cache_refresh_delay_msec
);
869 json
, "rpfCacheRefreshTimer",
870 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
));
871 json_object_int_add(json
, "rpfCacheRefreshRequests",
872 pim
->rpf_cache_refresh_requests
);
873 json_object_int_add(json
, "rpfCacheRefreshEvents",
874 pim
->rpf_cache_refresh_events
);
875 json_object_string_add(json
, "rpfCacheRefreshLast",
877 json_object_int_add(json
, "nexthopLookups",
878 pim
->nexthop_lookups
);
879 json_object_int_add(json
, "nexthopLookupsAvoided",
880 pim
->nexthop_lookups_avoided
);
883 "RPF Cache Refresh Delay: %ld msecs\n"
884 "RPF Cache Refresh Timer: %ld msecs\n"
885 "RPF Cache Refresh Requests: %lld\n"
886 "RPF Cache Refresh Events: %lld\n"
887 "RPF Cache Refresh Last: %s\n"
888 "Nexthop Lookups: %lld\n"
889 "Nexthop Lookups Avoided: %lld\n",
890 router
->rpf_cache_refresh_delay_msec
,
891 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
),
892 (long long)pim
->rpf_cache_refresh_requests
,
893 (long long)pim
->rpf_cache_refresh_events
,
894 refresh_uptime
, (long long)pim
->nexthop_lookups
,
895 (long long)pim
->nexthop_lookups_avoided
);
899 void pim_show_rpf(struct pim_instance
*pim
, struct vty
*vty
, json_object
*json
)
901 struct pim_upstream
*up
;
902 time_t now
= pim_time_monotonic_sec();
903 struct ttable
*tt
= NULL
;
905 json_object
*json_group
= NULL
;
906 json_object
*json_row
= NULL
;
908 pim_show_rpf_refresh_stats(vty
, pim
, now
, json
);
914 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
917 "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
918 tt
->style
.cell
.rpad
= 2;
919 tt
->style
.corner
= '+';
923 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
924 const char *rpf_ifname
;
925 struct pim_rpf
*rpf
= &up
->rpf
;
928 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
933 char grp_str
[PIM_ADDRSTRLEN
];
934 char src_str
[PIM_ADDRSTRLEN
];
936 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
938 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
941 json_object_object_get_ex(json
, grp_str
, &json_group
);
944 json_group
= json_object_new_object();
945 json_object_object_add(json
, grp_str
,
949 json_row
= json_object_new_object();
950 json_object_string_add(json_row
, "source", src_str
);
951 json_object_string_add(json_row
, "group", grp_str
);
952 json_object_string_add(json_row
, "rpfInterface",
954 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
956 json_object_string_addf(
957 json_row
, "ribNexthop", "%pPAs",
958 &rpf
->source_nexthop
.mrib_nexthop_addr
);
960 json_row
, "routeMetric",
961 rpf
->source_nexthop
.mrib_route_metric
);
963 json_row
, "routePreference",
964 rpf
->source_nexthop
.mrib_metric_preference
);
965 json_object_object_add(json_group
, src_str
, json_row
);
969 tt
, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
970 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
972 &rpf
->source_nexthop
.mrib_nexthop_addr
,
973 rpf
->source_nexthop
.mrib_route_metric
,
974 rpf
->source_nexthop
.mrib_metric_preference
);
977 /* Dump the generated table. */
979 table
= ttable_dump(tt
, "\n");
980 vty_out(vty
, "%s\n", table
);
981 XFREE(MTYPE_TMP
, table
);
986 void pim_show_neighbors_secondary(struct pim_instance
*pim
, struct vty
*vty
)
988 struct interface
*ifp
;
989 struct ttable
*tt
= NULL
;
993 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
994 ttable_add_row(tt
, "Interface|Address|Neighbor|Secondary");
995 tt
->style
.cell
.rpad
= 2;
996 tt
->style
.corner
= '+';
999 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1000 struct pim_interface
*pim_ifp
;
1002 struct listnode
*neighnode
;
1003 struct pim_neighbor
*neigh
;
1005 pim_ifp
= ifp
->info
;
1010 if (pim_ifp
->pim_sock_fd
< 0)
1013 ifaddr
= pim_ifp
->primary_address
;
1015 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1017 struct listnode
*prefix_node
;
1020 if (!neigh
->prefix_list
)
1023 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
,
1025 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pFX",
1027 &neigh
->source_addr
, p
);
1030 /* Dump the generated table. */
1031 table
= ttable_dump(tt
, "\n");
1032 vty_out(vty
, "%s\n", table
);
1033 XFREE(MTYPE_TMP
, table
);
1037 void pim_show_state(struct pim_instance
*pim
, struct vty
*vty
,
1038 const char *src_or_group
, const char *group
,
1041 struct channel_oil
*c_oil
;
1043 struct ttable
*tt
= NULL
;
1047 json_object
*json_group
= NULL
;
1048 json_object
*json_ifp_in
= NULL
;
1049 json_object
*json_ifp_out
= NULL
;
1050 json_object
*json_source
= NULL
;
1054 now
= pim_time_monotonic_sec();
1058 "Codes: J -> Pim Join, I -> " GM
" Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
1061 "Active Source Group RPT IIF OIL\n");
1063 /* Prepare table. */
1064 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1065 ttable_add_row(tt
, "Active|Source|Group|RPT|IIF|OIL");
1066 tt
->style
.cell
.rpad
= 2;
1067 tt
->style
.corner
= '+';
1072 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
1073 char src_str
[PIM_ADDRSTRLEN
];
1074 char grp_str
[PIM_ADDRSTRLEN
];
1075 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
1076 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
1078 struct interface
*ifp_in
;
1084 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil
->up
->flags
)) ||
1085 pim_addr_is_any(*oil_origin(c_oil
)))
1090 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1091 oil_mcastgrp(c_oil
));
1092 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1094 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
1097 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
1099 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
1102 if (strcmp(src_or_group
, src_str
) &&
1103 strcmp(src_or_group
, grp_str
))
1106 if (group
&& strcmp(group
, grp_str
))
1112 /* Find the group, create it if it doesn't exist */
1113 json_object_object_get_ex(json
, grp_str
, &json_group
);
1116 json_group
= json_object_new_object();
1117 json_object_object_add(json
, grp_str
,
1121 /* Find the source nested under the group, create it if
1124 json_object_object_get_ex(json_group
, src_str
,
1128 json_source
= json_object_new_object();
1129 json_object_object_add(json_group
, src_str
,
1133 /* Find the inbound interface nested under the source,
1134 * create it if it doesn't exist
1136 json_object_object_get_ex(json_source
, in_ifname
,
1140 json_ifp_in
= json_object_new_object();
1141 json_object_object_add(json_source
, in_ifname
,
1143 json_object_int_add(json_source
, "Installed",
1145 json_object_int_add(json_source
, "installed",
1147 json_object_boolean_add(json_source
, "isRpt",
1149 json_object_int_add(json_source
, "RefCount",
1150 c_oil
->oil_ref_count
);
1151 json_object_int_add(json_source
, "refCount",
1152 c_oil
->oil_ref_count
);
1153 json_object_int_add(json_source
, "OilListSize",
1155 json_object_int_add(json_source
, "oilListSize",
1157 json_object_int_add(
1158 json_source
, "OilRescan",
1159 c_oil
->oil_inherited_rescan
);
1160 json_object_int_add(
1161 json_source
, "oilRescan",
1162 c_oil
->oil_inherited_rescan
);
1163 json_object_int_add(json_source
, "LastUsed",
1164 c_oil
->cc
.lastused
);
1165 json_object_int_add(json_source
, "lastUsed",
1166 c_oil
->cc
.lastused
);
1167 json_object_int_add(json_source
, "PacketCount",
1169 json_object_int_add(json_source
, "packetCount",
1171 json_object_int_add(json_source
, "ByteCount",
1173 json_object_int_add(json_source
, "byteCount",
1175 json_object_int_add(json_source
,
1177 c_oil
->cc
.wrong_if
);
1178 json_object_int_add(json_source
,
1180 c_oil
->cc
.wrong_if
);
1185 vty_out(vty
, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1186 c_oil
->installed
, oil_origin(c_oil
),
1187 oil_mcastgrp(c_oil
), isRpt
? "y" : "n",
1191 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
1193 struct interface
*ifp_out
;
1194 char oif_uptime
[10];
1197 ttl
= oil_if_has(c_oil
, oif_vif_index
);
1201 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
1203 oif_uptime
, sizeof(oif_uptime
),
1204 now
- c_oil
->oif_creation
[oif_vif_index
]);
1207 strlcpy(out_ifname
, ifp_out
->name
,
1208 sizeof(out_ifname
));
1210 strlcpy(out_ifname
, "<oif?>",
1211 sizeof(out_ifname
));
1214 json_ifp_out
= json_object_new_object();
1215 json_object_string_add(json_ifp_out
, "source",
1217 json_object_string_add(json_ifp_out
, "group",
1219 json_object_string_add(json_ifp_out
,
1222 json_object_string_add(json_ifp_out
,
1223 "outboundInterface",
1225 json_object_int_add(json_ifp_out
, "installed",
1228 json_object_object_add(json_ifp_in
, out_ifname
,
1232 snprintf(flag
, sizeof(flag
), "(%c%c%c%c%c)",
1233 (c_oil
->oif_flags
[oif_vif_index
] &
1234 PIM_OIF_FLAG_PROTO_GM
)
1237 (c_oil
->oif_flags
[oif_vif_index
] &
1238 PIM_OIF_FLAG_PROTO_PIM
)
1241 (c_oil
->oif_flags
[oif_vif_index
] &
1242 PIM_OIF_FLAG_PROTO_VXLAN
)
1245 (c_oil
->oif_flags
[oif_vif_index
] &
1246 PIM_OIF_FLAG_PROTO_STAR
)
1249 (c_oil
->oif_flags
[oif_vif_index
] &
1257 vty_out(vty
, "%s%s", out_ifname
, flag
);
1260 tt
, "%d|%pPAs|%pPAs|%s|%s|%s%s",
1263 oil_mcastgrp(c_oil
),
1264 isRpt
? "y" : "n", in_ifname
,
1269 vty_out(vty
, ", %s%s", out_ifname
,
1273 "%c|%c|%c|%c|%c|%s%s",
1274 ' ', ' ', ' ', ' ', ' ',
1286 /* Dump the generated table. */
1291 table
= ttable_dump(tt
, "\n");
1292 vty_out(vty
, "%s\n", table
);
1293 XFREE(MTYPE_TMP
, table
);
1299 /* pim statistics - just adding only bsm related now.
1300 * We can continue to add all pim related stats here.
1302 void pim_show_statistics(struct pim_instance
*pim
, struct vty
*vty
,
1303 const char *ifname
, bool uj
)
1305 json_object
*json
= NULL
;
1306 struct interface
*ifp
;
1309 json
= json_object_new_object();
1310 json_object_int_add(json
, "bsmRx", pim
->bsm_rcvd
);
1311 json_object_int_add(json
, "bsmTx", pim
->bsm_sent
);
1312 json_object_int_add(json
, "bsmDropped", pim
->bsm_dropped
);
1314 vty_out(vty
, "BSM Statistics :\n");
1315 vty_out(vty
, "----------------\n");
1316 vty_out(vty
, "Number of Received BSMs : %" PRIu64
"\n",
1318 vty_out(vty
, "Number of Forwared BSMs : %" PRIu64
"\n",
1320 vty_out(vty
, "Number of Dropped BSMs : %" PRIu64
"\n",
1326 /* scan interfaces */
1327 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1328 struct pim_interface
*pim_ifp
= ifp
->info
;
1330 if (ifname
&& strcmp(ifname
, ifp
->name
))
1337 vty_out(vty
, "Interface : %s\n", ifp
->name
);
1338 vty_out(vty
, "-------------------\n");
1340 "Number of BSMs dropped due to config miss : %u\n",
1341 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1342 vty_out(vty
, "Number of unicast BSMs dropped : %u\n",
1343 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1345 "Number of BSMs dropped due to invalid scope zone : %u\n",
1346 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1349 json_object
*json_row
= NULL
;
1351 json_row
= json_object_new_object();
1353 json_object_string_add(json_row
, "If Name", ifp
->name
);
1354 json_object_int_add(json_row
, "bsmDroppedConfig",
1355 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1356 json_object_int_add(
1357 json_row
, "bsmDroppedUnicast",
1358 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1359 json_object_int_add(json_row
,
1360 "bsmDroppedInvalidScopeZone",
1361 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1362 json_object_object_add(json
, ifp
->name
, json_row
);
1368 vty_json(vty
, json
);
1371 void pim_show_upstream(struct pim_instance
*pim
, struct vty
*vty
,
1372 pim_sgaddr
*sg
, json_object
*json
)
1374 struct pim_upstream
*up
;
1375 struct ttable
*tt
= NULL
;
1378 json_object
*json_group
= NULL
;
1379 json_object
*json_row
= NULL
;
1381 now
= pim_time_monotonic_sec();
1384 /* Prepare table. */
1385 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1388 "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
1389 tt
->style
.cell
.rpad
= 2;
1390 tt
->style
.corner
= '+';
1394 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1396 char join_timer
[10];
1399 char msdp_reg_timer
[10];
1400 char state_str
[PIM_REG_STATE_STR_LEN
];
1402 if (!pim_sgaddr_match(up
->sg
, *sg
))
1405 pim_time_uptime(uptime
, sizeof(uptime
),
1406 now
- up
->state_transition
);
1407 pim_time_timer_to_hhmmss(join_timer
, sizeof(join_timer
),
1411 * If the upstream is not dummy and it has a J/P timer for the
1412 * neighbor display that
1414 if (!up
->t_join_timer
&& up
->rpf
.source_nexthop
.interface
) {
1415 struct pim_neighbor
*nbr
;
1417 nbr
= pim_neighbor_find(
1418 up
->rpf
.source_nexthop
.interface
,
1421 pim_time_timer_to_hhmmss(join_timer
,
1426 pim_time_timer_to_hhmmss(rs_timer
, sizeof(rs_timer
),
1428 pim_time_timer_to_hhmmss(ka_timer
, sizeof(ka_timer
),
1430 pim_time_timer_to_hhmmss(msdp_reg_timer
, sizeof(msdp_reg_timer
),
1431 up
->t_msdp_reg_timer
);
1433 pim_upstream_state2brief_str(up
->join_state
, state_str
,
1435 if (up
->reg_state
!= PIM_REG_NOINFO
) {
1436 char tmp_str
[PIM_REG_STATE_STR_LEN
];
1437 char tmp
[sizeof(state_str
) + 1];
1439 snprintf(tmp
, sizeof(tmp
), ",%s",
1440 pim_reg_state2brief_str(up
->reg_state
, tmp_str
,
1442 strlcat(state_str
, tmp
, sizeof(state_str
));
1446 char grp_str
[PIM_ADDRSTRLEN
];
1447 char src_str
[PIM_ADDRSTRLEN
];
1449 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1451 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1454 json_object_object_get_ex(json
, grp_str
, &json_group
);
1457 json_group
= json_object_new_object();
1458 json_object_object_add(json
, grp_str
,
1462 json_row
= json_object_new_object();
1463 json_object_pim_upstream_add(json_row
, up
);
1464 json_object_string_add(
1465 json_row
, "inboundInterface",
1466 up
->rpf
.source_nexthop
.interface
1467 ? up
->rpf
.source_nexthop
.interface
->name
1471 * The RPF address we use is slightly different
1472 * based upon what we are looking up.
1473 * If we have a S, list that unless
1474 * we are the FHR, else we just put
1475 * the RP as the rpfAddress
1477 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
||
1478 pim_addr_is_any(up
->sg
.src
)) {
1479 struct pim_rpf
*rpg
;
1481 rpg
= RP(pim
, up
->sg
.grp
);
1482 json_object_string_addf(json_row
, "rpfAddress",
1483 "%pPA", &rpg
->rpf_addr
);
1485 json_object_string_add(json_row
, "rpfAddress",
1489 json_object_string_add(json_row
, "source", src_str
);
1490 json_object_string_add(json_row
, "group", grp_str
);
1491 json_object_string_add(json_row
, "state", state_str
);
1492 json_object_string_add(
1493 json_row
, "joinState",
1494 pim_upstream_state2str(up
->join_state
));
1495 json_object_string_add(
1496 json_row
, "regState",
1497 pim_reg_state2str(up
->reg_state
, state_str
,
1498 sizeof(state_str
)));
1499 json_object_string_add(json_row
, "upTime", uptime
);
1500 json_object_string_add(json_row
, "joinTimer",
1502 json_object_string_add(json_row
, "resetTimer",
1504 json_object_string_add(json_row
, "keepaliveTimer",
1506 json_object_string_add(json_row
, "msdpRegTimer",
1508 json_object_int_add(json_row
, "refCount",
1510 json_object_int_add(json_row
, "sptBit", up
->sptbit
);
1511 json_object_object_add(json_group
, src_str
, json_row
);
1514 "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
1515 up
->rpf
.source_nexthop
.interface
1516 ? up
->rpf
.source_nexthop
.interface
->name
1518 &up
->sg
.src
, &up
->sg
.grp
, state_str
, uptime
,
1519 join_timer
, rs_timer
, ka_timer
, up
->ref_count
);
1522 /* Dump the generated table. */
1524 table
= ttable_dump(tt
, "\n");
1525 vty_out(vty
, "%s\n", table
);
1526 XFREE(MTYPE_TMP
, table
);
1531 static void pim_show_join_desired_helper(struct pim_instance
*pim
,
1533 struct pim_upstream
*up
,
1534 json_object
*json
, bool uj
,
1537 json_object
*json_group
= NULL
;
1538 json_object
*json_row
= NULL
;
1541 char grp_str
[PIM_ADDRSTRLEN
];
1542 char src_str
[PIM_ADDRSTRLEN
];
1544 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
1545 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &up
->sg
.src
);
1547 json_object_object_get_ex(json
, grp_str
, &json_group
);
1550 json_group
= json_object_new_object();
1551 json_object_object_add(json
, grp_str
, json_group
);
1554 json_row
= json_object_new_object();
1555 json_object_pim_upstream_add(json_row
, up
);
1556 json_object_string_add(json_row
, "source", src_str
);
1557 json_object_string_add(json_row
, "group", grp_str
);
1559 if (pim_upstream_evaluate_join_desired(pim
, up
))
1560 json_object_boolean_true_add(json_row
,
1561 "evaluateJoinDesired");
1563 json_object_object_add(json_group
, src_str
, json_row
);
1566 ttable_add_row(tt
, "%pPAs|%pPAs|%s", &up
->sg
.src
, &up
->sg
.grp
,
1567 pim_upstream_evaluate_join_desired(pim
, up
)
1573 void pim_show_join_desired(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1575 struct pim_upstream
*up
;
1576 struct ttable
*tt
= NULL
;
1579 json_object
*json
= NULL
;
1582 json
= json_object_new_object();
1584 /* Prepare table. */
1585 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1586 ttable_add_row(tt
, "Source|Group|EvalJD");
1587 tt
->style
.cell
.rpad
= 2;
1588 tt
->style
.corner
= '+';
1592 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1593 /* scan all interfaces */
1594 pim_show_join_desired_helper(pim
, vty
, up
, json
, uj
, tt
);
1598 vty_json(vty
, json
);
1600 /* Dump the generated table. */
1601 table
= ttable_dump(tt
, "\n");
1602 vty_out(vty
, "%s\n", table
);
1603 XFREE(MTYPE_TMP
, table
);
1608 void pim_show_upstream_rpf(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1610 struct pim_upstream
*up
;
1611 struct ttable
*tt
= NULL
;
1613 json_object
*json
= NULL
;
1614 json_object
*json_group
= NULL
;
1615 json_object
*json_row
= NULL
;
1618 json
= json_object_new_object();
1620 /* Prepare table. */
1621 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1623 "Source|Group|RpfIface|RibNextHop|RpfAddress");
1624 tt
->style
.cell
.rpad
= 2;
1625 tt
->style
.corner
= '+';
1629 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1630 struct pim_rpf
*rpf
;
1631 const char *rpf_ifname
;
1636 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
1641 char grp_str
[PIM_ADDRSTRLEN
];
1642 char src_str
[PIM_ADDRSTRLEN
];
1644 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1646 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1648 json_object_object_get_ex(json
, grp_str
, &json_group
);
1651 json_group
= json_object_new_object();
1652 json_object_object_add(json
, grp_str
,
1656 json_row
= json_object_new_object();
1657 json_object_pim_upstream_add(json_row
, up
);
1658 json_object_string_add(json_row
, "source", src_str
);
1659 json_object_string_add(json_row
, "group", grp_str
);
1660 json_object_string_add(json_row
, "rpfInterface",
1662 json_object_string_addf(
1663 json_row
, "ribNexthop", "%pPAs",
1664 &rpf
->source_nexthop
.mrib_nexthop_addr
);
1665 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
1667 json_object_object_add(json_group
, src_str
, json_row
);
1669 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%pPA|%pPA",
1670 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
1671 &rpf
->source_nexthop
.mrib_nexthop_addr
,
1677 vty_json(vty
, json
);
1679 /* Dump the generated table. */
1680 table
= ttable_dump(tt
, "\n");
1681 vty_out(vty
, "%s\n", table
);
1682 XFREE(MTYPE_TMP
, table
);
1687 static void pim_show_join_helper(struct pim_interface
*pim_ifp
,
1688 struct pim_ifchannel
*ch
, json_object
*json
,
1689 time_t now
, struct ttable
*tt
)
1691 json_object
*json_iface
= NULL
;
1692 json_object
*json_row
= NULL
;
1693 json_object
*json_grp
= NULL
;
1699 ifaddr
= pim_ifp
->primary_address
;
1701 pim_time_uptime_begin(uptime
, sizeof(uptime
), now
, ch
->ifjoin_creation
);
1702 pim_time_timer_to_mmss(expire
, sizeof(expire
),
1703 ch
->t_ifjoin_expiry_timer
);
1704 pim_time_timer_to_mmss(prune
, sizeof(prune
),
1705 ch
->t_ifjoin_prune_pending_timer
);
1708 char ch_grp_str
[PIM_ADDRSTRLEN
];
1710 json_object_object_get_ex(json
, ch
->interface
->name
,
1714 json_iface
= json_object_new_object();
1715 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1716 json_object_object_add(json
, ch
->interface
->name
,
1720 json_row
= json_object_new_object();
1721 json_object_string_addf(json_row
, "source", "%pPAs",
1723 json_object_string_addf(json_row
, "group", "%pPAs",
1725 json_object_string_add(json_row
, "upTime", uptime
);
1726 json_object_string_add(json_row
, "expire", expire
);
1727 json_object_string_add(json_row
, "prune", prune
);
1728 json_object_string_add(
1729 json_row
, "channelJoinName",
1730 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
));
1731 if (PIM_IF_FLAG_TEST_S_G_RPT(ch
->flags
)) {
1732 #if CONFDATE > 20230131
1734 "Remove JSON object commands with keys starting with capital")
1736 json_object_int_add(json_row
, "SGRpt", 1);
1737 json_object_int_add(json_row
, "sgRpt", 1);
1739 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch
->flags
))
1740 json_object_int_add(json_row
, "protocolPim", 1);
1741 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch
->flags
))
1742 json_object_int_add(json_row
, "protocolIgmp", 1);
1743 snprintfrr(ch_grp_str
, sizeof(ch_grp_str
), "%pPAs",
1745 json_object_object_get_ex(json_iface
, ch_grp_str
, &json_grp
);
1747 json_grp
= json_object_new_object();
1748 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1750 json_object_object_addf(json_iface
, json_grp
, "%pPAs",
1753 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1757 tt
, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
1758 ch
->interface
->name
, &ifaddr
, &ch
->sg
.src
, &ch
->sg
.grp
,
1759 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
),
1760 uptime
, expire
, prune
);
1764 int pim_show_join_cmd_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
1765 pim_addr g
, const char *json
)
1769 struct pim_instance
*pim
;
1770 json_object
*json_parent
= NULL
;
1772 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1775 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1781 vty_out(vty
, "%% Unable to find pim instance\n");
1785 if (!pim_addr_is_any(s_or_g
)) {
1786 if (!pim_addr_is_any(g
)) {
1794 json_parent
= json_object_new_object();
1796 pim_show_join(pim
, vty
, &sg
, json_parent
);
1799 vty_json(vty
, json_parent
);
1804 int pim_show_join_vrf_all_cmd_helper(struct vty
*vty
, const char *json
)
1806 pim_sgaddr sg
= {0};
1807 struct vrf
*vrf_struct
;
1808 json_object
*json_parent
= NULL
;
1809 json_object
*json_vrf
= NULL
;
1812 json_parent
= json_object_new_object();
1814 RB_FOREACH (vrf_struct
, vrf_name_head
, &vrfs_by_name
) {
1816 vty_out(vty
, "VRF: %s\n", vrf_struct
->name
);
1818 json_vrf
= json_object_new_object();
1819 pim_show_join(vrf_struct
->info
, vty
, &sg
, json_vrf
);
1822 json_object_object_add(json_parent
, vrf_struct
->name
,
1826 vty_json(vty
, json_parent
);
1831 void pim_show_join(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
1834 struct pim_interface
*pim_ifp
;
1835 struct pim_ifchannel
*ch
;
1836 struct interface
*ifp
;
1838 struct ttable
*tt
= NULL
;
1841 now
= pim_time_monotonic_sec();
1844 /* Prepare table. */
1845 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1848 "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
1849 tt
->style
.cell
.rpad
= 2;
1850 tt
->style
.corner
= '+';
1854 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1855 pim_ifp
= ifp
->info
;
1859 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1860 if (!pim_sgaddr_match(ch
->sg
, *sg
))
1863 pim_show_join_helper(pim_ifp
, ch
, json
, now
, tt
);
1864 } /* scan interface channels */
1866 /* Dump the generated table. */
1868 table
= ttable_dump(tt
, "\n");
1869 vty_out(vty
, "%s\n", table
);
1870 XFREE(MTYPE_TMP
, table
);
1875 static void pim_show_jp_agg_helper(struct interface
*ifp
,
1876 struct pim_neighbor
*neigh
,
1877 struct pim_upstream
*up
, int is_join
,
1880 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pPAs|%s", ifp
->name
,
1881 &neigh
->source_addr
, &up
->sg
.src
, &up
->sg
.grp
,
1882 is_join
? "J" : "P");
1885 int pim_show_jp_agg_list_cmd_helper(const char *vrf
, struct vty
*vty
)
1888 struct pim_instance
*pim
;
1890 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1893 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1899 vty_out(vty
, "%% Unable to find pim instance\n");
1903 pim_show_jp_agg_list(pim
, vty
);
1908 void pim_show_jp_agg_list(struct pim_instance
*pim
, struct vty
*vty
)
1910 struct interface
*ifp
;
1911 struct pim_interface
*pim_ifp
;
1912 struct listnode
*n_node
;
1913 struct pim_neighbor
*neigh
;
1914 struct listnode
*jag_node
;
1915 struct pim_jp_agg_group
*jag
;
1916 struct listnode
*js_node
;
1917 struct pim_jp_sources
*js
;
1921 /* Prepare table. */
1922 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1923 ttable_add_row(tt
, "Interface|RPF Nbr|Source|Group|State");
1924 tt
->style
.cell
.rpad
= 2;
1925 tt
->style
.corner
= '+';
1928 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1929 pim_ifp
= ifp
->info
;
1933 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, n_node
,
1935 for (ALL_LIST_ELEMENTS_RO(neigh
->upstream_jp_agg
,
1937 for (ALL_LIST_ELEMENTS_RO(jag
->sources
, js_node
,
1939 pim_show_jp_agg_helper(ifp
, neigh
,
1947 /* Dump the generated table. */
1948 table
= ttable_dump(tt
, "\n");
1949 vty_out(vty
, "%s\n", table
);
1950 XFREE(MTYPE_TMP
, table
);
1954 int pim_show_membership_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
1958 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1963 pim_show_membership(v
->info
, vty
, uj
);
1968 static void pim_show_membership_helper(struct vty
*vty
,
1969 struct pim_interface
*pim_ifp
,
1970 struct pim_ifchannel
*ch
,
1971 struct json_object
*json
)
1973 json_object
*json_iface
= NULL
;
1974 json_object
*json_row
= NULL
;
1976 json_object_object_get_ex(json
, ch
->interface
->name
, &json_iface
);
1978 json_iface
= json_object_new_object();
1979 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1980 json_object_object_add(json
, ch
->interface
->name
, json_iface
);
1983 json_row
= json_object_new_object();
1984 json_object_string_addf(json_row
, "source", "%pPAs", &ch
->sg
.src
);
1985 json_object_string_addf(json_row
, "group", "%pPAs", &ch
->sg
.grp
);
1986 json_object_string_add(json_row
, "localMembership",
1987 ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
1990 json_object_object_addf(json_iface
, json_row
, "%pPAs", &ch
->sg
.grp
);
1993 void pim_show_membership(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1995 struct pim_interface
*pim_ifp
;
1996 struct pim_ifchannel
*ch
;
1997 struct interface
*ifp
;
1998 enum json_type type
;
1999 json_object
*json
= NULL
;
2000 json_object
*json_tmp
= NULL
;
2001 struct ttable
*tt
= NULL
;
2004 json
= json_object_new_object();
2006 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2007 pim_ifp
= ifp
->info
;
2011 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
2012 pim_show_membership_helper(vty
, pim_ifp
, ch
, json
);
2013 } /* scan interface channels */
2017 vty_json(vty
, json
);
2019 /* Prepare table. */
2020 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2021 ttable_add_row(tt
, "Interface|Address|Source|Group|Membership");
2022 tt
->style
.cell
.rpad
= 2;
2023 tt
->style
.corner
= '+';
2027 * Example of the json data we are traversing
2033 * "address":"10.1.20.1",
2035 * "flagMulticast":true,
2036 * "flagBroadcast":true,
2037 * "lanDelayEnabled":true,
2040 * "group":"226.10.10.10",
2041 * "localMembership":"INCLUDE"
2047 /* foreach interface */
2048 json_object_object_foreach(json
, key
, val
)
2051 /* Find all of the keys where the val is an object. In
2053 * above the only one is 226.10.10.10
2055 json_object_object_foreach(val
, if_field_key
,
2058 type
= json_object_get_type(if_field_val
);
2060 if (type
== json_type_object
) {
2061 const char *address
, *source
,
2064 json_object_object_get_ex(
2065 val
, "address", &json_tmp
);
2066 address
= json_object_get_string(
2069 json_object_object_get_ex(if_field_val
,
2072 source
= json_object_get_string(
2075 json_object_object_get_ex(
2076 if_field_val
, "localMembership",
2079 json_object_get_string(
2082 ttable_add_row(tt
, "%s|%s|%s|%s|%s",
2083 key
, address
, source
,
2089 json_object_free(json
);
2090 /* Dump the generated table. */
2091 table
= ttable_dump(tt
, "\n");
2092 vty_out(vty
, "%s\n", table
);
2093 XFREE(MTYPE_TMP
, table
);
2098 static void pim_show_channel_helper(struct pim_instance
*pim
,
2099 struct pim_interface
*pim_ifp
,
2100 struct pim_ifchannel
*ch
, json_object
*json
,
2101 bool uj
, struct ttable
*tt
)
2103 struct pim_upstream
*up
= ch
->upstream
;
2104 json_object
*json_group
= NULL
;
2105 json_object
*json_row
= NULL
;
2108 char grp_str
[PIM_ADDRSTRLEN
];
2110 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
2111 json_object_object_get_ex(json
, grp_str
, &json_group
);
2114 json_group
= json_object_new_object();
2115 json_object_object_add(json
, grp_str
, json_group
);
2118 json_row
= json_object_new_object();
2119 json_object_pim_upstream_add(json_row
, up
);
2120 json_object_string_add(json_row
, "interface",
2121 ch
->interface
->name
);
2122 json_object_string_addf(json_row
, "source", "%pPAs",
2124 json_object_string_addf(json_row
, "group", "%pPAs",
2127 if (pim_macro_ch_lost_assert(ch
))
2128 json_object_boolean_true_add(json_row
, "lostAssert");
2130 if (pim_macro_chisin_joins(ch
))
2131 json_object_boolean_true_add(json_row
, "joins");
2133 if (pim_macro_chisin_pim_include(ch
))
2134 json_object_boolean_true_add(json_row
, "pimInclude");
2136 if (pim_upstream_evaluate_join_desired(pim
, up
))
2137 json_object_boolean_true_add(json_row
,
2138 "evaluateJoinDesired");
2140 json_object_object_addf(json_group
, json_row
, "%pPAs",
2144 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
2145 ch
->interface
->name
, &up
->sg
.src
, &up
->sg
.grp
,
2146 pim_macro_ch_lost_assert(ch
) ? "yes" : "no",
2147 pim_macro_chisin_joins(ch
) ? "yes" : "no",
2148 pim_macro_chisin_pim_include(ch
) ? "yes" : "no",
2149 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up
->flags
)
2152 pim_upstream_evaluate_join_desired(pim
, up
)
2158 void pim_show_channel(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2160 struct pim_interface
*pim_ifp
;
2161 struct pim_ifchannel
*ch
;
2162 struct interface
*ifp
;
2163 struct ttable
*tt
= NULL
;
2164 json_object
*json
= NULL
;
2168 json
= json_object_new_object();
2170 /* Prepare table. */
2171 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2174 "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
2175 tt
->style
.cell
.rpad
= 2;
2176 tt
->style
.corner
= '+';
2180 /* scan per-interface (S,G) state */
2181 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2182 pim_ifp
= ifp
->info
;
2186 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
2187 /* scan all interfaces */
2188 pim_show_channel_helper(pim
, pim_ifp
, ch
, json
, uj
, tt
);
2193 vty_json(vty
, json
);
2195 /* Dump the generated table. */
2196 table
= ttable_dump(tt
, "\n");
2197 vty_out(vty
, "%s\n", table
);
2198 XFREE(MTYPE_TMP
, table
);
2203 int pim_show_channel_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2207 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2212 pim_show_channel(v
->info
, vty
, uj
);
2217 int pim_show_interface_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
,
2218 bool mlag
, const char *interface
)
2221 json_object
*json_parent
= NULL
;
2223 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2229 json_parent
= json_object_new_object();
2232 pim_show_interfaces_single(v
->info
, vty
, interface
, mlag
,
2235 pim_show_interfaces(v
->info
, vty
, mlag
, json_parent
);
2238 vty_json(vty
, json_parent
);
2243 int pim_show_interface_vrf_all_cmd_helper(struct vty
*vty
, bool uj
, bool mlag
,
2244 const char *interface
)
2247 json_object
*json_parent
= NULL
;
2248 json_object
*json_vrf
= NULL
;
2251 json_parent
= json_object_new_object();
2253 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
2255 vty_out(vty
, "VRF: %s\n", v
->name
);
2257 json_vrf
= json_object_new_object();
2260 pim_show_interfaces_single(v
->info
, vty
, interface
,
2263 pim_show_interfaces(v
->info
, vty
, mlag
, json_vrf
);
2266 json_object_object_add(json_parent
, v
->name
, json_vrf
);
2269 vty_json(vty
, json_parent
);
2274 void pim_show_interfaces(struct pim_instance
*pim
, struct vty
*vty
, bool mlag
,
2277 struct interface
*ifp
;
2278 struct pim_interface
*pim_ifp
;
2279 struct pim_upstream
*up
;
2282 int pim_ifchannels
= 0;
2284 struct ttable
*tt
= NULL
;
2286 json_object
*json_row
= NULL
;
2287 json_object
*json_tmp
;
2291 json
= json_object_new_object();
2294 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2295 pim_ifp
= ifp
->info
;
2300 if (mlag
== true && pim_ifp
->activeactive
== false)
2303 pim_nbrs
= pim_ifp
->pim_neighbor_list
->count
;
2304 pim_ifchannels
= pim_if_ifchannel_count(pim_ifp
);
2307 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
)
2308 if (ifp
== up
->rpf
.source_nexthop
.interface
)
2309 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
)
2312 json_row
= json_object_new_object();
2313 json_object_pim_ifp_add(json_row
, ifp
);
2314 json_object_int_add(json_row
, "pimNeighbors", pim_nbrs
);
2315 json_object_int_add(json_row
, "pimIfChannels", pim_ifchannels
);
2316 json_object_int_add(json_row
, "firstHopRouterCount", fhr
);
2317 json_object_string_addf(json_row
, "pimDesignatedRouter",
2318 "%pPAs", &pim_ifp
->pim_dr_addr
);
2320 if (!pim_addr_cmp(pim_ifp
->pim_dr_addr
,
2321 pim_ifp
->primary_address
))
2322 json_object_boolean_true_add(
2323 json_row
, "pimDesignatedRouterLocal");
2325 json_object_object_add(json
, ifp
->name
, json_row
);
2330 /* Prepare table. */
2331 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2334 "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
2335 tt
->style
.cell
.rpad
= 2;
2336 tt
->style
.corner
= '+';
2339 json_object_object_foreach(json
, key
, val
)
2341 const char *state
, *address
, *pimdr
;
2342 int neighbors
, firsthpr
, pimifchnl
;
2344 json_object_object_get_ex(val
, "state", &json_tmp
);
2345 state
= json_object_get_string(json_tmp
);
2347 json_object_object_get_ex(val
, "address", &json_tmp
);
2348 address
= json_object_get_string(json_tmp
);
2350 json_object_object_get_ex(val
, "pimNeighbors",
2352 neighbors
= json_object_get_int(json_tmp
);
2354 if (json_object_object_get_ex(
2355 val
, "pimDesignatedRouterLocal",
2359 json_object_object_get_ex(
2360 val
, "pimDesignatedRouter", &json_tmp
);
2361 pimdr
= json_object_get_string(json_tmp
);
2364 json_object_object_get_ex(val
, "firstHopRouter",
2366 firsthpr
= json_object_get_int(json_tmp
);
2368 json_object_object_get_ex(val
, "pimIfChannels",
2370 pimifchnl
= json_object_get_int(json_tmp
);
2372 ttable_add_row(tt
, "%s|%s|%s|%d|%s|%d|%d", key
, state
,
2373 address
, neighbors
, pimdr
, firsthpr
,
2376 json_object_free(json
);
2378 /* Dump the generated table. */
2379 table
= ttable_dump(tt
, "\n");
2380 vty_out(vty
, "%s\n", table
);
2381 XFREE(MTYPE_TMP
, table
);
2387 void pim_show_interfaces_single(struct pim_instance
*pim
, struct vty
*vty
,
2388 const char *ifname
, bool mlag
,
2392 struct interface
*ifp
;
2393 struct listnode
*neighnode
;
2394 struct pim_interface
*pim_ifp
;
2395 struct pim_neighbor
*neigh
;
2396 struct pim_upstream
*up
;
2398 char dr_str
[PIM_ADDRSTRLEN
];
2401 char grp_str
[PIM_ADDRSTRLEN
];
2402 char hello_period
[10];
2403 char hello_timer
[10];
2404 char neigh_src_str
[PIM_ADDRSTRLEN
];
2405 char src_str
[PIM_ADDRSTRLEN
];
2406 char stat_uptime
[10];
2408 int found_ifname
= 0;
2410 json_object
*json_row
= NULL
;
2411 json_object
*json_pim_neighbor
= NULL
;
2412 json_object
*json_pim_neighbors
= NULL
;
2413 json_object
*json_group
= NULL
;
2414 json_object
*json_group_source
= NULL
;
2415 json_object
*json_fhr_sources
= NULL
;
2416 struct pim_secondary_addr
*sec_addr
;
2417 struct listnode
*sec_node
;
2419 now
= pim_time_monotonic_sec();
2421 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2422 pim_ifp
= ifp
->info
;
2427 if (mlag
== true && pim_ifp
->activeactive
== false)
2430 if (strcmp(ifname
, "detail") && strcmp(ifname
, ifp
->name
))
2434 ifaddr
= pim_ifp
->primary_address
;
2435 snprintfrr(dr_str
, sizeof(dr_str
), "%pPAs",
2436 &pim_ifp
->pim_dr_addr
);
2437 pim_time_uptime_begin(dr_uptime
, sizeof(dr_uptime
), now
,
2438 pim_ifp
->pim_dr_election_last
);
2439 pim_time_timer_to_hhmmss(hello_timer
, sizeof(hello_timer
),
2440 pim_ifp
->t_pim_hello_timer
);
2441 pim_time_mmss(hello_period
, sizeof(hello_period
),
2442 pim_ifp
->pim_hello_period
);
2443 pim_time_uptime(stat_uptime
, sizeof(stat_uptime
),
2444 now
- pim_ifp
->pim_ifstat_start
);
2447 json_row
= json_object_new_object();
2448 json_object_pim_ifp_add(json_row
, ifp
);
2450 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2451 json_object_string_addf(
2452 json_row
, "useSource", "%pPAs",
2453 &pim_ifp
->update_source
);
2455 if (pim_ifp
->sec_addr_list
) {
2456 json_object
*sec_list
= NULL
;
2458 sec_list
= json_object_new_array();
2459 for (ALL_LIST_ELEMENTS_RO(
2460 pim_ifp
->sec_addr_list
, sec_node
,
2462 json_object_array_add(
2464 json_object_new_stringf(
2468 json_object_object_add(json_row
,
2469 "secondaryAddressList",
2473 if (pim_ifp
->pim_passive_enable
)
2474 json_object_boolean_true_add(json_row
,
2478 if (pim_ifp
->pim_neighbor_list
->count
) {
2479 json_pim_neighbors
= json_object_new_object();
2481 for (ALL_LIST_ELEMENTS_RO(
2482 pim_ifp
->pim_neighbor_list
,
2483 neighnode
, neigh
)) {
2485 json_object_new_object();
2486 snprintfrr(neigh_src_str
,
2487 sizeof(neigh_src_str
),
2489 &neigh
->source_addr
);
2490 pim_time_uptime(uptime
, sizeof(uptime
),
2491 now
- neigh
->creation
);
2492 pim_time_timer_to_hhmmss(
2493 expire
, sizeof(expire
),
2494 neigh
->t_expire_timer
);
2496 json_object_string_add(
2497 json_pim_neighbor
, "address",
2499 json_object_string_add(
2500 json_pim_neighbor
, "upTime",
2502 json_object_string_add(
2503 json_pim_neighbor
, "holdtime",
2506 json_object_object_add(
2512 json_object_object_add(json_row
, "neighbors",
2513 json_pim_neighbors
);
2516 json_object_string_add(json_row
, "drAddress", dr_str
);
2517 json_object_int_add(json_row
, "drPriority",
2518 pim_ifp
->pim_dr_priority
);
2519 json_object_string_add(json_row
, "drUptime", dr_uptime
);
2520 json_object_int_add(json_row
, "drElections",
2521 pim_ifp
->pim_dr_election_count
);
2522 json_object_int_add(json_row
, "drChanges",
2523 pim_ifp
->pim_dr_election_changes
);
2526 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2527 if (ifp
!= up
->rpf
.source_nexthop
.interface
)
2530 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2533 if (!json_fhr_sources
)
2535 json_object_new_object();
2537 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
2539 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
2541 pim_time_uptime(uptime
, sizeof(uptime
),
2542 now
- up
->state_transition
);
2545 * Does this group live in json_fhr_sources?
2548 json_object_object_get_ex(json_fhr_sources
,
2549 grp_str
, &json_group
);
2552 json_group
= json_object_new_object();
2553 json_object_object_add(json_fhr_sources
,
2558 json_group_source
= json_object_new_object();
2559 json_object_string_add(json_group_source
,
2561 json_object_string_add(json_group_source
,
2563 json_object_string_add(json_group_source
,
2565 json_object_object_add(json_group
, src_str
,
2569 if (json_fhr_sources
) {
2570 json_object_object_add(json_row
,
2575 json_object_int_add(json_row
, "helloPeriod",
2576 pim_ifp
->pim_hello_period
);
2577 json_object_int_add(json_row
, "holdTime",
2578 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2579 json_object_string_add(json_row
, "helloTimer",
2581 json_object_string_add(json_row
, "helloStatStart",
2583 json_object_int_add(json_row
, "helloReceived",
2584 pim_ifp
->pim_ifstat_hello_recv
);
2585 json_object_int_add(json_row
, "helloReceivedFailed",
2586 pim_ifp
->pim_ifstat_hello_recvfail
);
2587 json_object_int_add(json_row
, "helloSend",
2588 pim_ifp
->pim_ifstat_hello_sent
);
2589 json_object_int_add(json_row
, "hellosendFailed",
2590 pim_ifp
->pim_ifstat_hello_sendfail
);
2591 json_object_int_add(json_row
, "helloGenerationId",
2592 pim_ifp
->pim_generation_id
);
2594 json_object_int_add(
2595 json_row
, "effectivePropagationDelay",
2596 pim_if_effective_propagation_delay_msec(ifp
));
2597 json_object_int_add(
2598 json_row
, "effectiveOverrideInterval",
2599 pim_if_effective_override_interval_msec(ifp
));
2600 json_object_int_add(
2601 json_row
, "joinPruneOverrideInterval",
2602 pim_if_jp_override_interval_msec(ifp
));
2604 json_object_int_add(
2605 json_row
, "propagationDelay",
2606 pim_ifp
->pim_propagation_delay_msec
);
2607 json_object_int_add(
2608 json_row
, "propagationDelayHighest",
2609 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2610 json_object_int_add(
2611 json_row
, "overrideInterval",
2612 pim_ifp
->pim_override_interval_msec
);
2613 json_object_int_add(
2614 json_row
, "overrideIntervalHighest",
2615 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2616 if (pim_ifp
->bsm_enable
)
2617 json_object_boolean_true_add(json_row
,
2619 if (pim_ifp
->ucast_bsm_accept
)
2620 json_object_boolean_true_add(json_row
,
2622 json_object_object_add(json
, ifp
->name
, json_row
);
2625 vty_out(vty
, "Interface : %s\n", ifp
->name
);
2626 vty_out(vty
, "State : %s\n",
2627 if_is_up(ifp
) ? "up" : "down");
2628 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2629 vty_out(vty
, "Use Source : %pPAs\n",
2630 &pim_ifp
->update_source
);
2632 if (pim_ifp
->sec_addr_list
) {
2633 vty_out(vty
, "Address : %pPAs (primary)\n",
2635 for (ALL_LIST_ELEMENTS_RO(
2636 pim_ifp
->sec_addr_list
, sec_node
,
2638 vty_out(vty
, " %pFX\n",
2641 vty_out(vty
, "Address : %pPAs\n", &ifaddr
);
2644 if (pim_ifp
->pim_passive_enable
)
2645 vty_out(vty
, "Passive : %s\n",
2646 (pim_ifp
->pim_passive_enable
) ? "yes"
2654 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
2655 neighnode
, neigh
)) {
2658 vty_out(vty
, "PIM Neighbors\n");
2659 vty_out(vty
, "-------------\n");
2663 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
2664 "%pPAs", &neigh
->source_addr
);
2665 pim_time_uptime(uptime
, sizeof(uptime
),
2666 now
- neigh
->creation
);
2667 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
2668 neigh
->t_expire_timer
);
2670 "%-15s : up for %s, holdtime expires in %s\n",
2671 neigh_src_str
, uptime
, expire
);
2674 if (!print_header
) {
2679 vty_out(vty
, "Designated Router\n");
2680 vty_out(vty
, "-----------------\n");
2681 vty_out(vty
, "Address : %s\n", dr_str
);
2682 vty_out(vty
, "Priority : %u(%d)\n",
2683 pim_ifp
->pim_dr_priority
,
2684 pim_ifp
->pim_dr_num_nondrpri_neighbors
);
2685 vty_out(vty
, "Uptime : %s\n", dr_uptime
);
2686 vty_out(vty
, "Elections : %d\n",
2687 pim_ifp
->pim_dr_election_count
);
2688 vty_out(vty
, "Changes : %d\n",
2689 pim_ifp
->pim_dr_election_changes
);
2695 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2696 if (!up
->rpf
.source_nexthop
.interface
)
2699 if (strcmp(ifp
->name
,
2700 up
->rpf
.source_nexthop
2701 .interface
->name
) != 0)
2704 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2709 "FHR - First Hop Router\n");
2711 "----------------------\n");
2715 pim_time_uptime(uptime
, sizeof(uptime
),
2716 now
- up
->state_transition
);
2718 "%pPAs : %pPAs is a source, uptime is %s\n",
2719 &up
->sg
.grp
, &up
->sg
.src
, uptime
);
2722 if (!print_header
) {
2727 vty_out(vty
, "Hellos\n");
2728 vty_out(vty
, "------\n");
2729 vty_out(vty
, "Period : %d\n",
2730 pim_ifp
->pim_hello_period
);
2731 vty_out(vty
, "HoldTime : %d\n",
2732 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2733 vty_out(vty
, "Timer : %s\n", hello_timer
);
2734 vty_out(vty
, "StatStart : %s\n", stat_uptime
);
2735 vty_out(vty
, "Receive : %d\n",
2736 pim_ifp
->pim_ifstat_hello_recv
);
2737 vty_out(vty
, "Receive Failed : %d\n",
2738 pim_ifp
->pim_ifstat_hello_recvfail
);
2739 vty_out(vty
, "Send : %d\n",
2740 pim_ifp
->pim_ifstat_hello_sent
);
2741 vty_out(vty
, "Send Failed : %d\n",
2742 pim_ifp
->pim_ifstat_hello_sendfail
);
2743 vty_out(vty
, "Generation ID : %08x\n",
2744 pim_ifp
->pim_generation_id
);
2748 pim_print_ifp_flags(vty
, ifp
);
2750 vty_out(vty
, "Join Prune Interval\n");
2751 vty_out(vty
, "-------------------\n");
2752 vty_out(vty
, "LAN Delay : %s\n",
2753 pim_if_lan_delay_enabled(ifp
) ? "yes" : "no");
2754 vty_out(vty
, "Effective Propagation Delay : %d msec\n",
2755 pim_if_effective_propagation_delay_msec(ifp
));
2756 vty_out(vty
, "Effective Override Interval : %d msec\n",
2757 pim_if_effective_override_interval_msec(ifp
));
2758 vty_out(vty
, "Join Prune Override Interval : %d msec\n",
2759 pim_if_jp_override_interval_msec(ifp
));
2763 vty_out(vty
, "LAN Prune Delay\n");
2764 vty_out(vty
, "---------------\n");
2765 vty_out(vty
, "Propagation Delay : %d msec\n",
2766 pim_ifp
->pim_propagation_delay_msec
);
2767 vty_out(vty
, "Propagation Delay (Highest) : %d msec\n",
2768 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2769 vty_out(vty
, "Override Interval : %d msec\n",
2770 pim_ifp
->pim_override_interval_msec
);
2771 vty_out(vty
, "Override Interval (Highest) : %d msec\n",
2772 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2776 vty_out(vty
, "BSM Status\n");
2777 vty_out(vty
, "----------\n");
2778 vty_out(vty
, "Bsm Enabled : %s\n",
2779 pim_ifp
->bsm_enable
? "yes" : "no");
2780 vty_out(vty
, "Unicast Bsm Enabled : %s\n",
2781 pim_ifp
->ucast_bsm_accept
? "yes" : "no");
2788 vty_out(vty
, "%% No such interface\n");
2791 void ip_pim_ssm_show_group_range(struct pim_instance
*pim
, struct vty
*vty
,
2794 struct pim_ssm
*ssm
= pim
->ssm_info
;
2795 const char *range_str
=
2796 ssm
->plist_name
? ssm
->plist_name
: PIM_SSM_STANDARD_RANGE
;
2801 json
= json_object_new_object();
2802 json_object_string_add(json
, "ssmGroups", range_str
);
2803 vty_json(vty
, json
);
2805 vty_out(vty
, "SSM group range : %s\n", range_str
);
2808 struct vty_pnc_cache_walk_data
{
2810 struct pim_instance
*pim
;
2813 struct json_pnc_cache_walk_data
{
2814 json_object
*json_obj
;
2815 struct pim_instance
*pim
;
2818 static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket
*bucket
, void *arg
)
2820 struct pim_nexthop_cache
*pnc
= bucket
->data
;
2821 struct vty_pnc_cache_walk_data
*cwd
= arg
;
2822 struct vty
*vty
= cwd
->vty
;
2823 struct pim_instance
*pim
= cwd
->pim
;
2824 struct nexthop
*nh_node
= NULL
;
2825 ifindex_t first_ifindex
;
2826 struct interface
*ifp
= NULL
;
2827 struct ttable
*tt
= NULL
;
2830 /* Prepare table. */
2831 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2832 ttable_add_row(tt
, "Address|Interface|Nexthop");
2833 tt
->style
.cell
.rpad
= 2;
2834 tt
->style
.corner
= '+';
2837 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2838 first_ifindex
= nh_node
->ifindex
;
2840 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2843 ttable_add_row(tt
, "%pPA|%s|%pI4", &pnc
->rpf
.rpf_addr
,
2844 ifp
? ifp
->name
: "NULL", &nh_node
->gate
.ipv4
);
2846 ttable_add_row(tt
, "%pPA|%s|%pI6", &pnc
->rpf
.rpf_addr
,
2847 ifp
? ifp
->name
: "NULL", &nh_node
->gate
.ipv6
);
2850 /* Dump the generated table. */
2851 table
= ttable_dump(tt
, "\n");
2852 vty_out(vty
, "%s\n", table
);
2853 XFREE(MTYPE_TMP
, table
);
2859 static int pim_print_json_pnc_cache_walkcb(struct hash_bucket
*backet
,
2862 struct pim_nexthop_cache
*pnc
= backet
->data
;
2863 struct json_pnc_cache_walk_data
*cwd
= arg
;
2864 struct pim_instance
*pim
= cwd
->pim
;
2865 struct nexthop
*nh_node
= NULL
;
2866 ifindex_t first_ifindex
;
2867 struct interface
*ifp
= NULL
;
2868 char addr_str
[PIM_ADDRSTRLEN
];
2869 json_object
*json_row
= NULL
;
2870 json_object
*json_ifp
= NULL
;
2871 json_object
*json_arr
= NULL
;
2873 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2874 first_ifindex
= nh_node
->ifindex
;
2875 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2876 snprintfrr(addr_str
, sizeof(addr_str
), "%pPA",
2877 &pnc
->rpf
.rpf_addr
);
2878 json_object_object_get_ex(cwd
->json_obj
, addr_str
, &json_row
);
2880 json_row
= json_object_new_object();
2881 json_object_string_addf(json_row
, "address", "%pPA",
2882 &pnc
->rpf
.rpf_addr
);
2883 json_object_object_addf(cwd
->json_obj
, json_row
, "%pPA",
2884 &pnc
->rpf
.rpf_addr
);
2885 json_arr
= json_object_new_array();
2886 json_object_object_add(json_row
, "nexthops", json_arr
);
2888 json_ifp
= json_object_new_object();
2889 json_object_string_add(json_ifp
, "interface",
2890 ifp
? ifp
->name
: "NULL");
2892 json_object_string_addf(json_ifp
, "nexthop", "%pI4",
2893 &nh_node
->gate
.ipv4
);
2895 json_object_string_addf(json_ifp
, "nexthop", "%pI6",
2896 &nh_node
->gate
.ipv6
);
2898 json_object_array_add(json_arr
, json_ifp
);
2903 int pim_show_nexthop_lookup_cmd_helper(const char *vrf
, struct vty
*vty
,
2904 pim_addr source
, pim_addr group
)
2907 pim_addr vif_source
;
2909 struct pim_nexthop nexthop
;
2911 char grp_str
[PREFIX_STRLEN
];
2913 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2919 if (pim_is_group_224_4(source
)) {
2921 "Invalid argument. Expected Valid Source Address.\n");
2925 if (!pim_is_group_224_4(group
)) {
2927 "Invalid argument. Expected Valid Multicast Group Address.\n");
2932 if (!pim_rp_set_upstream_addr(v
->info
, &vif_source
, source
, group
))
2935 pim_addr_to_prefix(&grp
, group
);
2936 memset(&nexthop
, 0, sizeof(nexthop
));
2939 pim_ecmp_nexthop_lookup(v
->info
, &nexthop
, vif_source
, &grp
, 0);
2943 "Nexthop Lookup failed, no usable routes returned.\n");
2947 pim_addr_dump("<grp?>", &grp
, grp_str
, sizeof(grp_str
));
2949 vty_out(vty
, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str
,
2950 &nexthop
.mrib_nexthop_addr
, nexthop
.interface
->name
);
2955 int pim_show_nexthop_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2959 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2964 pim_show_nexthop(v
->info
, vty
, uj
);
2969 void pim_show_nexthop(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2971 struct vty_pnc_cache_walk_data cwd
;
2972 struct json_pnc_cache_walk_data jcwd
;
2979 jcwd
.json_obj
= json_object_new_object();
2981 vty_out(vty
, "Number of registered addresses: %lu\n",
2982 pim
->rpf_hash
->count
);
2986 hash_walk(pim
->rpf_hash
, pim_print_json_pnc_cache_walkcb
,
2988 vty_json(vty
, jcwd
.json_obj
);
2990 hash_walk(pim
->rpf_hash
, pim_print_vty_pnc_cache_walkcb
, &cwd
);
2993 int pim_show_neighbors_cmd_helper(const char *vrf
, struct vty
*vty
,
2994 const char *json
, const char *interface
)
2997 json_object
*json_parent
= NULL
;
2999 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
3005 json_parent
= json_object_new_object();
3008 pim_show_neighbors_single(v
->info
, vty
, interface
, json_parent
);
3010 pim_show_neighbors(v
->info
, vty
, json_parent
);
3013 vty_json(vty
, json_parent
);
3018 int pim_show_neighbors_vrf_all_cmd_helper(struct vty
*vty
, const char *json
,
3019 const char *interface
)
3022 json_object
*json_parent
= NULL
;
3023 json_object
*json_vrf
= NULL
;
3026 json_parent
= json_object_new_object();
3027 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
3029 vty_out(vty
, "VRF: %s\n", v
->name
);
3031 json_vrf
= json_object_new_object();
3034 pim_show_neighbors_single(v
->info
, vty
, interface
,
3037 pim_show_neighbors(v
->info
, vty
, json_vrf
);
3040 json_object_object_add(json_parent
, v
->name
, json_vrf
);
3043 vty_json(vty
, json_parent
);
3048 void pim_show_neighbors_single(struct pim_instance
*pim
, struct vty
*vty
,
3049 const char *neighbor
, json_object
*json
)
3051 struct listnode
*neighnode
;
3052 struct interface
*ifp
;
3053 struct pim_interface
*pim_ifp
;
3054 struct pim_neighbor
*neigh
;
3056 int found_neighbor
= 0;
3057 int option_address_list
;
3058 int option_dr_priority
;
3059 int option_generation_id
;
3060 int option_holdtime
;
3061 int option_lan_prune_delay
;
3065 char neigh_src_str
[PIM_ADDRSTRLEN
];
3067 json_object
*json_ifp
= NULL
;
3068 json_object
*json_row
= NULL
;
3070 now
= pim_time_monotonic_sec();
3072 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3073 pim_ifp
= ifp
->info
;
3078 if (pim_ifp
->pim_sock_fd
< 0)
3081 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3083 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3084 "%pPAs", &neigh
->source_addr
);
3087 * The user can specify either the interface name or the
3089 * If this pim_ifp matches neither then skip.
3091 if (strcmp(neighbor
, "detail") &&
3092 strcmp(neighbor
, ifp
->name
) &&
3093 strcmp(neighbor
, neigh_src_str
))
3097 pim_time_uptime(uptime
, sizeof(uptime
),
3098 now
- neigh
->creation
);
3099 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3100 neigh
->t_expire_timer
);
3102 option_address_list
= 0;
3103 option_dr_priority
= 0;
3104 option_generation_id
= 0;
3105 option_holdtime
= 0;
3106 option_lan_prune_delay
= 0;
3109 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3110 PIM_OPTION_MASK_ADDRESS_LIST
))
3111 option_address_list
= 1;
3113 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3114 PIM_OPTION_MASK_DR_PRIORITY
))
3115 option_dr_priority
= 1;
3117 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3118 PIM_OPTION_MASK_GENERATION_ID
))
3119 option_generation_id
= 1;
3121 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3122 PIM_OPTION_MASK_HOLDTIME
))
3123 option_holdtime
= 1;
3125 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3126 PIM_OPTION_MASK_LAN_PRUNE_DELAY
))
3127 option_lan_prune_delay
= 1;
3129 if (PIM_OPTION_IS_SET(
3130 neigh
->hello_options
,
3131 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION
))
3136 /* Does this ifp live in json? If not create it
3138 json_object_object_get_ex(json
, ifp
->name
,
3142 json_ifp
= json_object_new_object();
3143 json_object_pim_ifp_add(json_ifp
, ifp
);
3144 json_object_object_add(json
, ifp
->name
,
3148 json_row
= json_object_new_object();
3149 json_object_string_add(json_row
, "interface",
3151 json_object_string_add(json_row
, "address",
3153 json_object_string_add(json_row
, "upTime",
3155 json_object_string_add(json_row
, "holdtime",
3157 json_object_int_add(json_row
, "drPriority",
3158 neigh
->dr_priority
);
3159 json_object_int_add(json_row
, "generationId",
3160 neigh
->generation_id
);
3162 if (option_address_list
)
3163 json_object_boolean_true_add(
3165 "helloOptionAddressList");
3167 if (option_dr_priority
)
3168 json_object_boolean_true_add(
3170 "helloOptionDrPriority");
3172 if (option_generation_id
)
3173 json_object_boolean_true_add(
3175 "helloOptionGenerationId");
3177 if (option_holdtime
)
3178 json_object_boolean_true_add(
3180 "helloOptionHoldtime");
3182 if (option_lan_prune_delay
)
3183 json_object_boolean_true_add(
3185 "helloOptionLanPruneDelay");
3188 json_object_boolean_true_add(
3189 json_row
, "helloOptionTBit");
3191 json_object_object_add(json_ifp
, neigh_src_str
,
3195 vty_out(vty
, "Interface : %s\n", ifp
->name
);
3196 vty_out(vty
, "Neighbor : %s\n", neigh_src_str
);
3204 " DR Priority : %d\n",
3205 neigh
->dr_priority
);
3207 " Generation ID : %08x\n",
3208 neigh
->generation_id
);
3210 " Override Interval (msec) : %d\n",
3211 neigh
->override_interval_msec
);
3213 " Propagation Delay (msec) : %d\n",
3214 neigh
->propagation_delay_msec
);
3216 " Hello Option - Address List : %s\n",
3217 option_address_list
? "yes" : "no");
3219 " Hello Option - DR Priority : %s\n",
3220 option_dr_priority
? "yes" : "no");
3222 " Hello Option - Generation ID : %s\n",
3223 option_generation_id
? "yes" : "no");
3225 " Hello Option - Holdtime : %s\n",
3226 option_holdtime
? "yes" : "no");
3228 " Hello Option - LAN Prune Delay : %s\n",
3229 option_lan_prune_delay
? "yes" : "no");
3231 " Hello Option - T-bit : %s\n",
3232 option_t_bit
? "yes" : "no");
3233 bfd_sess_show(vty
, json_ifp
,
3234 neigh
->bfd_session
);
3240 if (!found_neighbor
)
3241 vty_out(vty
, "%% No such interface or neighbor\n");
3244 void pim_show_neighbors(struct pim_instance
*pim
, struct vty
*vty
,
3247 struct listnode
*neighnode
;
3248 struct interface
*ifp
;
3249 struct pim_interface
*pim_ifp
;
3250 struct pim_neighbor
*neigh
;
3251 struct ttable
*tt
= NULL
;
3256 char neigh_src_str
[PIM_ADDRSTRLEN
];
3257 json_object
*json_ifp_rows
= NULL
;
3258 json_object
*json_row
= NULL
;
3260 now
= pim_time_monotonic_sec();
3263 /* Prepare table. */
3264 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3265 ttable_add_row(tt
, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
3266 tt
->style
.cell
.rpad
= 2;
3267 tt
->style
.corner
= '+';
3271 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3272 pim_ifp
= ifp
->info
;
3277 if (pim_ifp
->pim_sock_fd
< 0)
3281 json_ifp_rows
= json_object_new_object();
3283 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3285 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3286 "%pPAs", &neigh
->source_addr
);
3287 pim_time_uptime(uptime
, sizeof(uptime
),
3288 now
- neigh
->creation
);
3289 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3290 neigh
->t_expire_timer
);
3293 json_row
= json_object_new_object();
3294 json_object_string_add(json_row
, "interface",
3296 json_object_string_add(json_row
, "neighbor",
3298 json_object_string_add(json_row
, "upTime",
3300 json_object_string_add(json_row
, "holdTime",
3302 json_object_int_add(json_row
, "holdTimeMax",
3304 json_object_int_add(json_row
, "drPriority",
3305 neigh
->dr_priority
);
3306 json_object_object_add(json_ifp_rows
,
3307 neigh_src_str
, json_row
);
3310 ttable_add_row(tt
, "%s|%pPAs|%s|%s|%d",
3311 ifp
->name
, &neigh
->source_addr
,
3313 neigh
->dr_priority
);
3318 json_object_object_add(json
, ifp
->name
, json_ifp_rows
);
3319 json_ifp_rows
= NULL
;
3322 /* Dump the generated table. */
3324 table
= ttable_dump(tt
, "\n");
3325 vty_out(vty
, "%s\n", table
);
3326 XFREE(MTYPE_TMP
, table
);
3331 int gm_process_query_max_response_time_cmd(struct vty
*vty
,
3332 const char *qmrt_str
)
3334 const struct lyd_node
*pim_enable_dnode
;
3336 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3337 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3338 FRR_PIM_AF_XPATH_VAL
);
3340 if (!pim_enable_dnode
) {
3341 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3343 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3344 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3348 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_MODIFY
,
3350 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3351 FRR_PIM_AF_XPATH_VAL
);
3354 int gm_process_no_query_max_response_time_cmd(struct vty
*vty
)
3356 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_DESTROY
,
3358 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3359 FRR_PIM_AF_XPATH_VAL
);
3362 int gm_process_last_member_query_count_cmd(struct vty
*vty
,
3363 const char *lmqc_str
)
3365 const struct lyd_node
*pim_enable_dnode
;
3367 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3368 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3369 FRR_PIM_AF_XPATH_VAL
);
3370 if (!pim_enable_dnode
) {
3371 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3373 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3374 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3378 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_MODIFY
,
3380 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3381 FRR_PIM_AF_XPATH_VAL
);
3384 int gm_process_no_last_member_query_count_cmd(struct vty
*vty
)
3386 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_DESTROY
,
3388 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3389 FRR_PIM_AF_XPATH_VAL
);
3392 int gm_process_last_member_query_interval_cmd(struct vty
*vty
,
3393 const char *lmqi_str
)
3395 const struct lyd_node
*pim_enable_dnode
;
3397 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3398 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3399 FRR_PIM_AF_XPATH_VAL
);
3400 if (!pim_enable_dnode
) {
3401 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3403 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3404 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3408 nb_cli_enqueue_change(vty
, "./last-member-query-interval", NB_OP_MODIFY
,
3410 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3411 FRR_PIM_AF_XPATH_VAL
);
3414 int gm_process_no_last_member_query_interval_cmd(struct vty
*vty
)
3416 nb_cli_enqueue_change(vty
, "./last-member-query-interval",
3417 NB_OP_DESTROY
, NULL
);
3418 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3419 FRR_PIM_AF_XPATH_VAL
);
3422 int pim_process_ssmpingd_cmd(struct vty
*vty
, enum nb_operation operation
,
3423 const char *src_str
)
3425 const char *vrfname
;
3426 char ssmpingd_ip_xpath
[XPATH_MAXLEN
];
3428 vrfname
= pim_cli_get_vrf_name(vty
);
3429 if (vrfname
== NULL
)
3430 return CMD_WARNING_CONFIG_FAILED
;
3432 snprintf(ssmpingd_ip_xpath
, sizeof(ssmpingd_ip_xpath
),
3433 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
3434 FRR_PIM_AF_XPATH_VAL
);
3435 strlcat(ssmpingd_ip_xpath
, "/ssm-pingd-source-ip",
3436 sizeof(ssmpingd_ip_xpath
));
3438 nb_cli_enqueue_change(vty
, ssmpingd_ip_xpath
, operation
, src_str
);
3440 return nb_cli_apply_changes(vty
, NULL
);
3443 int pim_process_bsm_cmd(struct vty
*vty
)
3445 const struct lyd_node
*gm_enable_dnode
;
3447 gm_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3448 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
3449 FRR_PIM_AF_XPATH_VAL
);
3450 if (!gm_enable_dnode
)
3451 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3454 if (!yang_dnode_get_bool(gm_enable_dnode
, "."))
3455 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3459 nb_cli_enqueue_change(vty
, "./bsm", NB_OP_MODIFY
, "true");
3461 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3462 FRR_PIM_AF_XPATH_VAL
);
3465 int pim_process_no_bsm_cmd(struct vty
*vty
)
3467 nb_cli_enqueue_change(vty
, "./bsm", NB_OP_MODIFY
, "false");
3469 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3470 FRR_PIM_AF_XPATH_VAL
);
3473 int pim_process_unicast_bsm_cmd(struct vty
*vty
)
3475 const struct lyd_node
*gm_enable_dnode
;
3477 gm_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3478 FRR_GMP_ENABLE_XPATH
, VTY_CURR_XPATH
,
3479 FRR_PIM_AF_XPATH_VAL
);
3480 if (!gm_enable_dnode
)
3481 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3484 if (!yang_dnode_get_bool(gm_enable_dnode
, "."))
3485 nb_cli_enqueue_change(vty
, "./pim-enable", NB_OP_MODIFY
,
3489 nb_cli_enqueue_change(vty
, "./unicast-bsm", NB_OP_MODIFY
, "true");
3491 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3492 FRR_PIM_AF_XPATH_VAL
);
3495 int pim_process_no_unicast_bsm_cmd(struct vty
*vty
)
3497 nb_cli_enqueue_change(vty
, "./unicast-bsm", NB_OP_MODIFY
, "false");
3499 return nb_cli_apply_changes(vty
, FRR_PIM_INTERFACE_XPATH
,
3500 FRR_PIM_AF_XPATH_VAL
);
3503 static void show_scan_oil_stats(struct pim_instance
*pim
, struct vty
*vty
,
3506 char uptime_scan_oil
[10];
3507 char uptime_mroute_add
[10];
3508 char uptime_mroute_del
[10];
3510 pim_time_uptime_begin(uptime_scan_oil
, sizeof(uptime_scan_oil
), now
,
3511 pim
->scan_oil_last
);
3512 pim_time_uptime_begin(uptime_mroute_add
, sizeof(uptime_mroute_add
), now
,
3513 pim
->mroute_add_last
);
3514 pim_time_uptime_begin(uptime_mroute_del
, sizeof(uptime_mroute_del
), now
,
3515 pim
->mroute_del_last
);
3518 "Scan OIL - Last: %s Events: %lld\n"
3519 "MFC Add - Last: %s Events: %lld\n"
3520 "MFC Del - Last: %s Events: %lld\n",
3521 uptime_scan_oil
, (long long)pim
->scan_oil_events
,
3522 uptime_mroute_add
, (long long)pim
->mroute_add_events
,
3523 uptime_mroute_del
, (long long)pim
->mroute_del_events
);
3526 void show_multicast_interfaces(struct pim_instance
*pim
, struct vty
*vty
,
3529 struct interface
*ifp
;
3530 struct ttable
*tt
= NULL
;
3532 json_object
*json_row
= NULL
;
3537 /* Prepare table. */
3538 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3541 "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
3542 tt
->style
.cell
.rpad
= 2;
3543 tt
->style
.corner
= '+';
3547 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3548 struct pim_interface
*pim_ifp
;
3550 struct sioc_vif_req vreq
;
3552 struct sioc_mif_req6 vreq
;
3555 pim_ifp
= ifp
->info
;
3560 memset(&vreq
, 0, sizeof(vreq
));
3562 vreq
.vifi
= pim_ifp
->mroute_vif_index
;
3563 if (ioctl(pim
->mroute_socket
, SIOCGETVIFCNT
, &vreq
)) {
3565 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3566 (unsigned long)SIOCGETVIFCNT
, ifp
->name
,
3567 pim_ifp
->mroute_vif_index
, errno
,
3568 safe_strerror(errno
));
3571 vreq
.mifi
= pim_ifp
->mroute_vif_index
;
3572 if (ioctl(pim
->mroute_socket
, SIOCGETMIFCNT_IN6
, &vreq
)) {
3574 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3575 (unsigned long)SIOCGETMIFCNT_IN6
, ifp
->name
,
3576 pim_ifp
->mroute_vif_index
, errno
,
3577 safe_strerror(errno
));
3582 json_row
= json_object_new_object();
3583 json_object_string_add(json_row
, "name", ifp
->name
);
3584 json_object_string_add(json_row
, "state",
3585 if_is_up(ifp
) ? "up" : "down");
3586 json_object_string_addf(json_row
, "address", "%pPA",
3587 &pim_ifp
->primary_address
);
3588 json_object_int_add(json_row
, "ifIndex", ifp
->ifindex
);
3589 json_object_int_add(json_row
, "vif",
3590 pim_ifp
->mroute_vif_index
);
3591 json_object_int_add(json_row
, "pktsIn",
3592 (unsigned long)vreq
.icount
);
3593 json_object_int_add(json_row
, "pktsOut",
3594 (unsigned long)vreq
.ocount
);
3595 json_object_int_add(json_row
, "bytesIn",
3596 (unsigned long)vreq
.ibytes
);
3597 json_object_int_add(json_row
, "bytesOut",
3598 (unsigned long)vreq
.obytes
);
3599 json_object_object_add(json
, ifp
->name
, json_row
);
3601 ttable_add_row(tt
, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
3602 ifp
->name
, &pim_ifp
->primary_address
,
3603 ifp
->ifindex
, pim_ifp
->mroute_vif_index
,
3604 (unsigned long)vreq
.icount
,
3605 (unsigned long)vreq
.ocount
,
3606 (unsigned long)vreq
.ibytes
,
3607 (unsigned long)vreq
.obytes
);
3610 /* Dump the generated table. */
3612 table
= ttable_dump(tt
, "\n");
3613 vty_out(vty
, "%s\n", table
);
3614 XFREE(MTYPE_TMP
, table
);
3619 void pim_cmd_show_ip_multicast_helper(struct pim_instance
*pim
, struct vty
*vty
)
3621 struct vrf
*vrf
= pim
->vrf
;
3622 time_t now
= pim_time_monotonic_sec();
3628 vty_out(vty
, "Router MLAG Role: %s\n",
3629 mlag_role2str(router
->mlag_role
, mlag_role
, sizeof(mlag_role
)));
3630 vty_out(vty
, "Mroute socket descriptor:");
3632 vty_out(vty
, " %d(%s)\n", pim
->mroute_socket
, vrf
->name
);
3633 vty_out(vty
, "PIM Register socket descriptor:");
3634 vty_out(vty
, " %d(%s)\n", pim
->reg_sock
, vrf
->name
);
3636 pim_time_uptime(uptime
, sizeof(uptime
),
3637 now
- pim
->mroute_socket_creation
);
3638 vty_out(vty
, "Mroute socket uptime: %s\n", uptime
);
3642 pim_zebra_zclient_update(vty
);
3643 pim_zlookup_show_ip_multicast(vty
);
3646 vty_out(vty
, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS
);
3649 vty_out(vty
, "Upstream Join Timer: %d secs\n", router
->t_periodic
);
3650 vty_out(vty
, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME
);
3651 vty_out(vty
, "PIM ECMP: %s\n", pim
->ecmp_enable
? "Enable" : "Disable");
3652 vty_out(vty
, "PIM ECMP Rebalance: %s\n",
3653 pim
->ecmp_rebalance_enable
? "Enable" : "Disable");
3657 pim_show_rpf_refresh_stats(vty
, pim
, now
, NULL
);
3661 show_scan_oil_stats(pim
, vty
, now
);
3663 show_multicast_interfaces(pim
, vty
, NULL
);
3666 void show_mroute(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
3667 bool fill
, json_object
*json
)
3669 struct listnode
*node
;
3670 struct channel_oil
*c_oil
;
3671 struct static_route
*s_route
;
3672 struct ttable
*tt
= NULL
;
3675 json_object
*json_group
= NULL
;
3676 json_object
*json_source
= NULL
;
3677 json_object
*json_oil
= NULL
;
3678 json_object
*json_ifp_out
= NULL
;
3681 char grp_str
[PIM_ADDRSTRLEN
];
3682 char src_str
[PIM_ADDRSTRLEN
];
3683 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
3684 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
3686 struct interface
*ifp_in
;
3688 char state_str
[PIM_REG_STATE_STR_LEN
];
3689 char mroute_uptime
[10];
3692 vty_out(vty
, "IP Multicast Routing Table\n");
3693 vty_out(vty
, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3695 " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3697 /* Prepare table. */
3698 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3700 tt
, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
3701 tt
->style
.cell
.rpad
= 2;
3702 tt
->style
.corner
= '+';
3706 now
= pim_time_monotonic_sec();
3708 /* print list of PIM and IGMP routes */
3709 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
3712 if (!c_oil
->installed
)
3715 if (!pim_addr_is_any(sg
->grp
) &&
3716 pim_addr_cmp(sg
->grp
, *oil_mcastgrp(c_oil
)))
3718 if (!pim_addr_is_any(sg
->src
) &&
3719 pim_addr_cmp(sg
->src
, *oil_origin(c_oil
)))
3722 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
3723 oil_mcastgrp(c_oil
));
3724 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
3727 strlcpy(state_str
, "S", sizeof(state_str
));
3728 /* When a non DR receives a igmp join, it creates a (*,G)
3729 * channel_oil without any upstream creation
3732 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil
->up
->flags
))
3733 strlcat(state_str
, "C", sizeof(state_str
));
3734 if (pim_upstream_is_sg_rpt(c_oil
->up
))
3735 strlcat(state_str
, "R", sizeof(state_str
));
3736 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil
->up
->flags
))
3737 strlcat(state_str
, "F", sizeof(state_str
));
3738 if (c_oil
->up
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
3739 strlcat(state_str
, "T", sizeof(state_str
));
3741 if (pim_channel_oil_empty(c_oil
))
3742 strlcat(state_str
, "P", sizeof(state_str
));
3744 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
3747 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3749 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3752 pim_time_uptime(mroute_uptime
, sizeof(mroute_uptime
),
3753 now
- c_oil
->mroute_creation
);
3757 /* Find the group, create it if it doesn't exist */
3758 json_object_object_get_ex(json
, grp_str
, &json_group
);
3761 json_group
= json_object_new_object();
3762 json_object_object_add(json
, grp_str
,
3766 /* Find the source nested under the group, create it if
3769 json_object_object_get_ex(json_group
, src_str
,
3773 json_source
= json_object_new_object();
3774 json_object_object_add(json_group
, src_str
,
3778 /* Find the inbound interface nested under the source,
3779 * create it if it doesn't exist
3781 json_object_string_add(json_source
, "source", src_str
);
3782 json_object_string_add(json_source
, "group", grp_str
);
3783 json_object_int_add(json_source
, "installed",
3785 json_object_int_add(json_source
, "refCount",
3786 c_oil
->oil_ref_count
);
3787 json_object_int_add(json_source
, "oilSize",
3789 json_object_int_add(json_source
, "OilInheritedRescan",
3790 c_oil
->oil_inherited_rescan
);
3791 json_object_int_add(json_source
, "oilInheritedRescan",
3792 c_oil
->oil_inherited_rescan
);
3793 json_object_string_add(json_source
, "iif", in_ifname
);
3794 json_object_string_add(json_source
, "upTime",
3799 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3801 struct interface
*ifp_out
;
3804 ttl
= oil_if_has(c_oil
, oif_vif_index
);
3808 /* do not display muted OIFs */
3809 if (c_oil
->oif_flags
[oif_vif_index
] & PIM_OIF_FLAG_MUTE
)
3812 if (*oil_parent(c_oil
) == oif_vif_index
&&
3813 !pim_mroute_allow_iif_in_oil(c_oil
, oif_vif_index
))
3816 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3820 strlcpy(out_ifname
, ifp_out
->name
,
3821 sizeof(out_ifname
));
3823 strlcpy(out_ifname
, "<oif?>",
3824 sizeof(out_ifname
));
3827 json_ifp_out
= json_object_new_object();
3828 json_object_string_add(json_ifp_out
, "source",
3830 json_object_string_add(json_ifp_out
, "group",
3833 if (c_oil
->oif_flags
[oif_vif_index
] &
3834 PIM_OIF_FLAG_PROTO_PIM
)
3835 json_object_boolean_true_add(
3836 json_ifp_out
, "protocolPim");
3838 if (c_oil
->oif_flags
[oif_vif_index
] &
3839 PIM_OIF_FLAG_PROTO_GM
)
3841 json_object_boolean_true_add(
3842 json_ifp_out
, "protocolIgmp");
3844 json_object_boolean_true_add(
3845 json_ifp_out
, "protocolMld");
3848 if (c_oil
->oif_flags
[oif_vif_index
] &
3849 PIM_OIF_FLAG_PROTO_VXLAN
)
3850 json_object_boolean_true_add(
3851 json_ifp_out
, "protocolVxlan");
3853 if (c_oil
->oif_flags
[oif_vif_index
] &
3854 PIM_OIF_FLAG_PROTO_STAR
)
3855 json_object_boolean_true_add(
3857 "protocolInherited");
3859 json_object_string_add(json_ifp_out
,
3862 json_object_int_add(json_ifp_out
, "iVifI",
3863 *oil_parent(c_oil
));
3864 json_object_string_add(json_ifp_out
,
3865 "outboundInterface",
3867 json_object_int_add(json_ifp_out
, "oVifI",
3869 json_object_int_add(json_ifp_out
, "ttl", ttl
);
3870 json_object_string_add(json_ifp_out
, "upTime",
3872 json_object_string_add(json_source
, "flags",
3875 json_oil
= json_object_new_object();
3876 json_object_object_add(json_source
,
3879 json_object_object_add(json_oil
, out_ifname
,
3883 if (c_oil
->oif_flags
[oif_vif_index
] &
3884 PIM_OIF_FLAG_PROTO_PIM
) {
3885 strlcpy(proto
, "PIM", sizeof(proto
));
3888 if (c_oil
->oif_flags
[oif_vif_index
] &
3889 PIM_OIF_FLAG_PROTO_GM
) {
3891 strlcpy(proto
, "IGMP", sizeof(proto
));
3893 strlcpy(proto
, "MLD", sizeof(proto
));
3897 if (c_oil
->oif_flags
[oif_vif_index
] &
3898 PIM_OIF_FLAG_PROTO_VXLAN
) {
3899 strlcpy(proto
, "VxLAN", sizeof(proto
));
3902 if (c_oil
->oif_flags
[oif_vif_index
] &
3903 PIM_OIF_FLAG_PROTO_STAR
) {
3904 strlcpy(proto
, "STAR", sizeof(proto
));
3907 ttable_add_row(tt
, "%s|%s|%s|%s|%s|%s|%d|%s",
3908 src_str
, grp_str
, state_str
,
3909 proto
, in_ifname
, out_ifname
,
3910 ttl
, mroute_uptime
);
3915 in_ifname
[0] = '\0';
3916 state_str
[0] = '\0';
3917 mroute_uptime
[0] = '\0';
3923 if (!json
&& !found_oif
) {
3924 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3925 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
3926 state_str
, "none", in_ifname
, "none", 0,
3931 /* Print list of static routes */
3932 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
3935 if (!s_route
->c_oil
.installed
)
3938 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &s_route
->group
);
3939 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &s_route
->source
);
3940 ifp_in
= pim_if_find_by_vif_index(pim
, s_route
->iif
);
3944 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3946 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3950 /* Find the group, create it if it doesn't exist */
3951 json_object_object_get_ex(json
, grp_str
, &json_group
);
3954 json_group
= json_object_new_object();
3955 json_object_object_add(json
, grp_str
,
3959 /* Find the source nested under the group, create it if
3962 json_object_object_get_ex(json_group
, src_str
,
3966 json_source
= json_object_new_object();
3967 json_object_object_add(json_group
, src_str
,
3971 json_object_string_add(json_source
, "iif", in_ifname
);
3974 strlcpy(proto
, "STATIC", sizeof(proto
));
3977 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3979 struct interface
*ifp_out
;
3980 char oif_uptime
[10];
3983 ttl
= s_route
->oif_ttls
[oif_vif_index
];
3987 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3989 oif_uptime
, sizeof(oif_uptime
),
3990 now
- s_route
->c_oil
3991 .oif_creation
[oif_vif_index
]);
3995 strlcpy(out_ifname
, ifp_out
->name
,
3996 sizeof(out_ifname
));
3998 strlcpy(out_ifname
, "<oif?>",
3999 sizeof(out_ifname
));
4002 json_ifp_out
= json_object_new_object();
4003 json_object_string_add(json_ifp_out
, "source",
4005 json_object_string_add(json_ifp_out
, "group",
4007 json_object_boolean_true_add(json_ifp_out
,
4009 json_object_string_add(json_ifp_out
,
4012 json_object_int_add(
4013 json_ifp_out
, "iVifI",
4014 *oil_parent(&s_route
->c_oil
));
4015 json_object_string_add(json_ifp_out
,
4016 "outboundInterface",
4018 json_object_int_add(json_ifp_out
, "oVifI",
4020 json_object_int_add(json_ifp_out
, "ttl", ttl
);
4021 json_object_string_add(json_ifp_out
, "upTime",
4024 json_oil
= json_object_new_object();
4025 json_object_object_add(json_source
,
4028 json_object_object_add(json_oil
, out_ifname
,
4032 tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4033 &s_route
->source
, &s_route
->group
, "-",
4034 proto
, in_ifname
, out_ifname
, ttl
,
4036 if (first
&& !fill
) {
4039 in_ifname
[0] = '\0';
4045 if (!json
&& !found_oif
) {
4046 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4047 &s_route
->source
, &s_route
->group
, "-",
4048 proto
, in_ifname
, "none", 0, "--:--:--");
4051 /* Dump the generated table. */
4053 table
= ttable_dump(tt
, "\n");
4054 vty_out(vty
, "%s\n", table
);
4055 XFREE(MTYPE_TMP
, table
);
4060 static void show_mroute_count_per_channel_oil(struct channel_oil
*c_oil
,
4064 json_object
*json_group
= NULL
;
4065 json_object
*json_source
= NULL
;
4067 if (!c_oil
->installed
)
4070 pim_mroute_update_counters(c_oil
);
4073 char group_str
[PIM_ADDRSTRLEN
];
4074 char source_str
[PIM_ADDRSTRLEN
];
4076 snprintfrr(group_str
, sizeof(group_str
), "%pPAs",
4077 oil_mcastgrp(c_oil
));
4078 snprintfrr(source_str
, sizeof(source_str
), "%pPAs",
4081 json_object_object_get_ex(json
, group_str
, &json_group
);
4084 json_group
= json_object_new_object();
4085 json_object_object_add(json
, group_str
, json_group
);
4088 json_source
= json_object_new_object();
4089 json_object_object_add(json_group
, source_str
, json_source
);
4090 json_object_int_add(json_source
, "lastUsed",
4091 c_oil
->cc
.lastused
/ 100);
4092 json_object_int_add(json_source
, "packets", c_oil
->cc
.pktcnt
);
4093 json_object_int_add(json_source
, "bytes", c_oil
->cc
.bytecnt
);
4094 json_object_int_add(json_source
, "wrongIf", c_oil
->cc
.wrong_if
);
4097 ttable_add_row(tt
, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
4098 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
4099 c_oil
->cc
.lastused
/ 100,
4100 c_oil
->cc
.pktcnt
- c_oil
->cc
.origpktcnt
,
4101 c_oil
->cc
.bytecnt
- c_oil
->cc
.origbytecnt
,
4102 c_oil
->cc
.wrong_if
- c_oil
->cc
.origwrong_if
);
4106 void show_mroute_count(struct pim_instance
*pim
, struct vty
*vty
,
4109 struct listnode
*node
;
4110 struct channel_oil
*c_oil
;
4111 struct static_route
*sr
;
4112 struct ttable
*tt
= NULL
;
4118 /* Prepare table. */
4119 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4121 "Source|Group|LastUsed|Packets|Bytes|WrongIf");
4122 tt
->style
.cell
.rpad
= 2;
4123 tt
->style
.corner
= '+';
4127 /* Print PIM and IGMP route counts */
4128 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
4129 show_mroute_count_per_channel_oil(c_oil
, json
, tt
);
4131 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
))
4132 show_mroute_count_per_channel_oil(&sr
->c_oil
, json
, tt
);
4134 /* Dump the generated table. */
4136 table
= ttable_dump(tt
, "\n");
4137 vty_out(vty
, "%s\n", table
);
4138 XFREE(MTYPE_TMP
, table
);
4143 void show_mroute_summary(struct pim_instance
*pim
, struct vty
*vty
,
4146 struct listnode
*node
;
4147 struct channel_oil
*c_oil
;
4148 struct static_route
*s_route
;
4149 uint32_t starg_sw_mroute_cnt
= 0;
4150 uint32_t sg_sw_mroute_cnt
= 0;
4151 uint32_t starg_hw_mroute_cnt
= 0;
4152 uint32_t sg_hw_mroute_cnt
= 0;
4153 json_object
*json_starg
= NULL
;
4154 json_object
*json_sg
= NULL
;
4157 vty_out(vty
, "Mroute Type Installed/Total\n");
4159 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4160 if (!c_oil
->installed
) {
4161 if (pim_addr_is_any(*oil_origin(c_oil
)))
4162 starg_sw_mroute_cnt
++;
4166 if (pim_addr_is_any(*oil_origin(c_oil
)))
4167 starg_hw_mroute_cnt
++;
4173 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
4174 if (!s_route
->c_oil
.installed
) {
4175 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4176 starg_sw_mroute_cnt
++;
4180 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4181 starg_hw_mroute_cnt
++;
4188 vty_out(vty
, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt
,
4189 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4190 vty_out(vty
, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt
,
4191 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4192 vty_out(vty
, "------\n");
4193 vty_out(vty
, "%-20s %u/%u\n", "Total",
4194 (starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
),
4195 (starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4196 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
));
4198 /* (*,G) route details */
4199 json_starg
= json_object_new_object();
4200 json_object_object_add(json
, "wildcardGroup", json_starg
);
4202 json_object_int_add(json_starg
, "installed",
4203 starg_hw_mroute_cnt
);
4204 json_object_int_add(json_starg
, "total",
4205 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4207 /* (S, G) route details */
4208 json_sg
= json_object_new_object();
4209 json_object_object_add(json
, "sourceGroup", json_sg
);
4211 json_object_int_add(json_sg
, "installed", sg_hw_mroute_cnt
);
4212 json_object_int_add(json_sg
, "total",
4213 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4215 json_object_int_add(json
, "totalNumOfInstalledMroutes",
4216 starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
);
4217 json_object_int_add(json
, "totalNumOfMroutes",
4218 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4224 int clear_ip_mroute_count_command(struct vty
*vty
, const char *name
)
4226 struct listnode
*node
;
4227 struct channel_oil
*c_oil
;
4228 struct static_route
*sr
;
4229 struct vrf
*v
= pim_cmd_lookup(vty
, name
);
4230 struct pim_instance
*pim
;
4236 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4237 if (!c_oil
->installed
)
4240 pim_mroute_update_counters(c_oil
);
4241 c_oil
->cc
.origpktcnt
= c_oil
->cc
.pktcnt
;
4242 c_oil
->cc
.origbytecnt
= c_oil
->cc
.bytecnt
;
4243 c_oil
->cc
.origwrong_if
= c_oil
->cc
.wrong_if
;
4246 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
)) {
4247 if (!sr
->c_oil
.installed
)
4250 pim_mroute_update_counters(&sr
->c_oil
);
4252 sr
->c_oil
.cc
.origpktcnt
= sr
->c_oil
.cc
.pktcnt
;
4253 sr
->c_oil
.cc
.origbytecnt
= sr
->c_oil
.cc
.bytecnt
;
4254 sr
->c_oil
.cc
.origwrong_if
= sr
->c_oil
.cc
.wrong_if
;
4259 struct vrf
*pim_cmd_lookup(struct vty
*vty
, const char *name
)
4264 vrf
= vrf_lookup_by_name(name
);
4266 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
4269 vty_out(vty
, "Specified VRF: %s does not exist\n", name
);
4274 void clear_mroute(struct pim_instance
*pim
)
4276 struct pim_upstream
*up
;
4277 struct interface
*ifp
;
4279 /* scan interfaces */
4280 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4281 struct pim_interface
*pim_ifp
= ifp
->info
;
4282 struct pim_ifchannel
*ch
;
4287 /* deleting all ifchannels */
4288 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
4289 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
4291 pim_ifchannel_delete(ch
);
4295 /* clean up all igmp groups */
4296 struct gm_group
*grp
;
4298 if (pim_ifp
->gm_group_list
) {
4299 while (pim_ifp
->gm_group_list
->count
) {
4300 grp
= listnode_head(pim_ifp
->gm_group_list
);
4301 igmp_group_delete(grp
);
4305 struct gm_if
*gm_ifp
;
4307 gm_ifp
= pim_ifp
->mld
;
4309 gm_group_delete(gm_ifp
);
4313 /* clean up all upstreams*/
4314 while ((up
= rb_pim_upstream_first(&pim
->upstream_head
)))
4315 pim_upstream_del(pim
, up
, __func__
);
4318 void clear_pim_statistics(struct pim_instance
*pim
)
4320 struct interface
*ifp
;
4324 pim
->bsm_dropped
= 0;
4326 /* scan interfaces */
4327 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4328 struct pim_interface
*pim_ifp
= ifp
->info
;
4333 pim_ifp
->pim_ifstat_bsm_cfg_miss
= 0;
4334 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
= 0;
4335 pim_ifp
->pim_ifstat_bsm_invalid_sz
= 0;
4339 int clear_pim_interface_traffic(const char *vrf
, struct vty
*vty
)
4341 struct interface
*ifp
= NULL
;
4342 struct pim_interface
*pim_ifp
= NULL
;
4344 struct vrf
*v
= pim_cmd_lookup(vty
, vrf
);
4349 FOR_ALL_INTERFACES (v
, ifp
) {
4350 pim_ifp
= ifp
->info
;
4355 pim_ifp
->pim_ifstat_hello_recv
= 0;
4356 pim_ifp
->pim_ifstat_hello_sent
= 0;
4357 pim_ifp
->pim_ifstat_join_recv
= 0;
4358 pim_ifp
->pim_ifstat_join_send
= 0;
4359 pim_ifp
->pim_ifstat_prune_recv
= 0;
4360 pim_ifp
->pim_ifstat_prune_send
= 0;
4361 pim_ifp
->pim_ifstat_reg_recv
= 0;
4362 pim_ifp
->pim_ifstat_reg_send
= 0;
4363 pim_ifp
->pim_ifstat_reg_stop_recv
= 0;
4364 pim_ifp
->pim_ifstat_reg_stop_send
= 0;
4365 pim_ifp
->pim_ifstat_assert_recv
= 0;
4366 pim_ifp
->pim_ifstat_assert_send
= 0;
4367 pim_ifp
->pim_ifstat_bsm_rx
= 0;
4368 pim_ifp
->pim_ifstat_bsm_tx
= 0;
4370 pim_ifp
->igmp_ifstat_joins_sent
= 0;
4371 pim_ifp
->igmp_ifstat_joins_failed
= 0;
4372 pim_ifp
->igmp_peak_group_count
= 0;
4379 int pim_debug_pim_cmd(void)
4381 PIM_DO_DEBUG_PIM_EVENTS
;
4382 PIM_DO_DEBUG_PIM_PACKETS
;
4383 PIM_DO_DEBUG_PIM_TRACE
;
4384 PIM_DO_DEBUG_MSDP_EVENTS
;
4385 PIM_DO_DEBUG_MSDP_PACKETS
;
4391 int pim_no_debug_pim_cmd(void)
4393 PIM_DONT_DEBUG_PIM_EVENTS
;
4394 PIM_DONT_DEBUG_PIM_PACKETS
;
4395 PIM_DONT_DEBUG_PIM_TRACE
;
4396 PIM_DONT_DEBUG_MSDP_EVENTS
;
4397 PIM_DONT_DEBUG_MSDP_PACKETS
;
4399 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND
;
4400 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV
;
4402 PIM_DONT_DEBUG_VXLAN
;
4406 int pim_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4407 const char *registers
, struct vty
*vty
)
4410 PIM_DO_DEBUG_PIM_HELLO
;
4411 vty_out(vty
, "PIM Hello debugging is on\n");
4413 PIM_DO_DEBUG_PIM_J_P
;
4414 vty_out(vty
, "PIM Join/Prune debugging is on\n");
4415 } else if (registers
) {
4416 PIM_DO_DEBUG_PIM_REG
;
4417 vty_out(vty
, "PIM Register debugging is on\n");
4419 PIM_DO_DEBUG_PIM_PACKETS
;
4420 vty_out(vty
, "PIM Packet debugging is on\n");
4425 int pim_no_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4426 const char *registers
, struct vty
*vty
)
4429 PIM_DONT_DEBUG_PIM_HELLO
;
4430 vty_out(vty
, "PIM Hello debugging is off\n");
4432 PIM_DONT_DEBUG_PIM_J_P
;
4433 vty_out(vty
, "PIM Join/Prune debugging is off\n");
4434 } else if (registers
) {
4435 PIM_DONT_DEBUG_PIM_REG
;
4436 vty_out(vty
, "PIM Register debugging is off\n");
4438 PIM_DONT_DEBUG_PIM_PACKETS
;
4439 vty_out(vty
, "PIM Packet debugging is off\n");
4445 int pim_show_rpf_helper(const char *vrf
, struct vty
*vty
, bool json
)
4447 struct pim_instance
*pim
;
4449 json_object
*json_parent
= NULL
;
4451 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4459 vty_out(vty
, "%% Unable to find pim instance\n");
4464 json_parent
= json_object_new_object();
4466 pim_show_rpf(pim
, vty
, json_parent
);
4469 vty_json(vty
, json_parent
);
4474 int pim_show_rpf_vrf_all_helper(struct vty
*vty
, bool json
)
4477 json_object
*json_parent
= NULL
;
4478 json_object
*json_vrf
= NULL
;
4481 json_parent
= json_object_new_object();
4483 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4485 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4487 json_vrf
= json_object_new_object();
4488 pim_show_rpf(vrf
->info
, vty
, json_vrf
);
4490 json_object_object_add(json_parent
, vrf
->name
,
4494 vty_json(vty
, json_parent
);
4499 int pim_show_rp_helper(const char *vrf
, struct vty
*vty
, const char *group_str
,
4500 const struct prefix
*group
, bool json
)
4502 struct pim_instance
*pim
;
4504 json_object
*json_parent
= NULL
;
4505 struct prefix
*range
= NULL
;
4507 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4515 vty_out(vty
, "%% Unable to find pim instance\n");
4520 range
= prefix_new();
4521 prefix_copy(range
, group
);
4526 json_parent
= json_object_new_object();
4528 pim_rp_show_information(pim
, range
, vty
, json_parent
);
4531 vty_json(vty
, json_parent
);
4533 prefix_free(&range
);
4538 int pim_show_rp_vrf_all_helper(struct vty
*vty
, const char *group_str
,
4539 const struct prefix
*group
, bool json
)
4542 json_object
*json_parent
= NULL
;
4543 json_object
*json_vrf
= NULL
;
4544 struct prefix
*range
= NULL
;
4547 range
= prefix_new();
4548 prefix_copy(range
, group
);
4553 json_parent
= json_object_new_object();
4555 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4557 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4559 json_vrf
= json_object_new_object();
4560 pim_rp_show_information(vrf
->info
, range
, vty
, json_vrf
);
4562 json_object_object_add(json_parent
, vrf
->name
,
4566 vty_json(vty
, json_parent
);
4568 prefix_free(&range
);
4573 int pim_show_secondary_helper(const char *vrf
, struct vty
*vty
)
4575 struct pim_instance
*pim
;
4578 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4586 vty_out(vty
, "%% Unable to find pim instance\n");
4590 pim_show_neighbors_secondary(pim
, vty
);
4595 int pim_show_statistics_helper(const char *vrf
, struct vty
*vty
,
4596 const char *word
, bool uj
)
4598 struct pim_instance
*pim
;
4601 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4609 vty_out(vty
, "%% Unable to find pim instance\n");
4614 pim_show_statistics(pim
, vty
, word
, uj
);
4616 pim_show_statistics(pim
, vty
, NULL
, uj
);
4621 int pim_show_upstream_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4622 pim_addr g
, bool json
)
4624 pim_sgaddr sg
= {0};
4626 struct pim_instance
*pim
;
4627 json_object
*json_parent
= NULL
;
4629 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4632 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
4638 vty_out(vty
, "%% Unable to find pim instance\n");
4643 json_parent
= json_object_new_object();
4645 if (!pim_addr_is_any(s_or_g
)) {
4646 if (!pim_addr_is_any(g
)) {
4653 pim_show_upstream(pim
, vty
, &sg
, json_parent
);
4656 vty_json(vty
, json_parent
);
4661 int pim_show_upstream_vrf_all_helper(struct vty
*vty
, bool json
)
4663 pim_sgaddr sg
= {0};
4665 json_object
*json_parent
= NULL
;
4666 json_object
*json_vrf
= NULL
;
4669 json_parent
= json_object_new_object();
4671 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4673 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4675 json_vrf
= json_object_new_object();
4676 pim_show_upstream(vrf
->info
, vty
, &sg
, json_vrf
);
4678 json_object_object_add(json_parent
, vrf
->name
,
4683 vty_json(vty
, json_parent
);
4688 int pim_show_upstream_join_desired_helper(const char *vrf
, struct vty
*vty
,
4691 struct pim_instance
*pim
;
4694 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4702 vty_out(vty
, "%% Unable to find pim instance\n");
4706 pim_show_join_desired(pim
, vty
, uj
);
4711 int pim_show_upstream_rpf_helper(const char *vrf
, struct vty
*vty
, bool uj
)
4713 struct pim_instance
*pim
;
4716 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4724 vty_out(vty
, "%% Unable to find pim instance\n");
4728 pim_show_upstream_rpf(pim
, vty
, uj
);
4733 int pim_show_state_helper(const char *vrf
, struct vty
*vty
,
4734 const char *s_or_g_str
, const char *g_str
, bool json
)
4736 struct pim_instance
*pim
;
4738 json_object
*json_parent
= NULL
;
4740 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4748 vty_out(vty
, "%% Unable to find pim instance\n");
4753 json_parent
= json_object_new_object();
4755 pim_show_state(pim
, vty
, s_or_g_str
, g_str
, json_parent
);
4758 vty_json(vty
, json_parent
);
4763 int pim_show_state_vrf_all_helper(struct vty
*vty
, const char *s_or_g_str
,
4764 const char *g_str
, bool json
)
4767 json_object
*json_parent
= NULL
;
4768 json_object
*json_vrf
= NULL
;
4771 json_parent
= json_object_new_object();
4773 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4775 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4777 json_vrf
= json_object_new_object();
4778 pim_show_state(vrf
->info
, vty
, s_or_g_str
, g_str
, json_vrf
);
4780 json_object_object_add(json_parent
, vrf
->name
,
4784 vty_json(vty
, json_parent
);
4789 int pim_show_multicast_helper(const char *vrf
, struct vty
*vty
)
4792 struct pim_instance
*pim
;
4794 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4802 vty_out(vty
, "%% Unable to find pim instance\n");
4806 pim_cmd_show_ip_multicast_helper(pim
, vty
);
4811 int pim_show_multicast_vrf_all_helper(struct vty
*vty
)
4815 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4816 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4817 pim_cmd_show_ip_multicast_helper(vrf
->info
, vty
);
4823 int pim_show_multicast_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4825 struct pim_instance
*pim
;
4827 json_object
*json_parent
= NULL
;
4829 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4837 vty_out(vty
, "%% Unable to find pim instance\n");
4842 json_parent
= json_object_new_object();
4844 show_multicast_interfaces(pim
, vty
, json_parent
);
4847 vty_json(vty
, json_parent
);
4852 int pim_show_multicast_count_vrf_all_helper(struct vty
*vty
, bool json
)
4855 json_object
*json_parent
= NULL
;
4856 json_object
*json_vrf
= NULL
;
4859 json_parent
= json_object_new_object();
4861 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4863 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4865 json_vrf
= json_object_new_object();
4867 show_multicast_interfaces(vrf
->info
, vty
, json_vrf
);
4869 json_object_object_add(json_parent
, vrf
->name
,
4873 vty_json(vty
, json_parent
);
4878 int pim_show_mroute_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4879 pim_addr g
, bool fill
, bool json
)
4881 pim_sgaddr sg
= {0};
4882 struct pim_instance
*pim
;
4884 json_object
*json_parent
= NULL
;
4886 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4894 vty_out(vty
, "%% Unable to find pim instance\n");
4899 json_parent
= json_object_new_object();
4901 if (!pim_addr_is_any(s_or_g
)) {
4902 if (!pim_addr_is_any(g
)) {
4909 show_mroute(pim
, vty
, &sg
, fill
, json_parent
);
4912 vty_json(vty
, json_parent
);
4917 int pim_show_mroute_vrf_all_helper(struct vty
*vty
, bool fill
, bool json
)
4919 pim_sgaddr sg
= {0};
4921 json_object
*json_parent
= NULL
;
4922 json_object
*json_vrf
= NULL
;
4925 json_parent
= json_object_new_object();
4927 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4929 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4931 json_vrf
= json_object_new_object();
4932 show_mroute(vrf
->info
, vty
, &sg
, fill
, json_vrf
);
4934 json_object_object_add(json_parent
, vrf
->name
,
4938 vty_json(vty
, json_parent
);
4943 int pim_show_mroute_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4945 struct pim_instance
*pim
;
4947 json_object
*json_parent
= NULL
;
4949 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4957 vty_out(vty
, "%% Unable to find pim instance\n");
4962 json_parent
= json_object_new_object();
4964 show_mroute_count(pim
, vty
, json_parent
);
4967 vty_json(vty
, json_parent
);
4972 int pim_show_mroute_count_vrf_all_helper(struct vty
*vty
, bool json
)
4975 json_object
*json_parent
= NULL
;
4976 json_object
*json_vrf
= NULL
;
4979 json_parent
= json_object_new_object();
4981 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4983 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4985 json_vrf
= json_object_new_object();
4987 show_mroute_count(vrf
->info
, vty
, json_vrf
);
4990 json_object_object_add(json_parent
, vrf
->name
,
4994 vty_json(vty
, json_parent
);
4999 int pim_show_mroute_summary_helper(const char *vrf
, struct vty
*vty
, bool json
)
5001 struct pim_instance
*pim
;
5003 json_object
*json_parent
= NULL
;
5005 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5013 vty_out(vty
, "%% Unable to find pim instance\n");
5018 json_parent
= json_object_new_object();
5020 show_mroute_summary(pim
, vty
, json_parent
);
5023 vty_json(vty
, json_parent
);
5028 int pim_show_mroute_summary_vrf_all_helper(struct vty
*vty
, bool json
)
5031 json_object
*json_parent
= NULL
;
5032 json_object
*json_vrf
= NULL
;
5035 json_parent
= json_object_new_object();
5037 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
5039 vty_out(vty
, "VRF: %s\n", vrf
->name
);
5041 json_vrf
= json_object_new_object();
5043 show_mroute_summary(vrf
->info
, vty
, json_vrf
);
5046 json_object_object_add(json_parent
, vrf
->name
,
5051 vty_json(vty
, json_parent
);
5056 void pim_show_interface_traffic(struct pim_instance
*pim
, struct vty
*vty
,
5059 struct interface
*ifp
= NULL
;
5060 struct pim_interface
*pim_ifp
= NULL
;
5061 json_object
*json
= NULL
;
5062 json_object
*json_row
= NULL
;
5065 json
= json_object_new_object();
5068 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5069 "Interface", " HELLO", " JOIN",
5070 " PRUNE", " REGISTER", "REGISTER-STOP",
5072 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5073 " Rx/Tx", " Rx/Tx", " Rx/Tx",
5074 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
5076 "---------------------------------------------------------------------------------------------------------------\n");
5079 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5080 pim_ifp
= ifp
->info
;
5086 json_row
= json_object_new_object();
5087 json_object_pim_ifp_add(json_row
, ifp
);
5088 json_object_int_add(json_row
, "helloRx",
5089 pim_ifp
->pim_ifstat_hello_recv
);
5090 json_object_int_add(json_row
, "helloTx",
5091 pim_ifp
->pim_ifstat_hello_sent
);
5092 json_object_int_add(json_row
, "joinRx",
5093 pim_ifp
->pim_ifstat_join_recv
);
5094 json_object_int_add(json_row
, "joinTx",
5095 pim_ifp
->pim_ifstat_join_send
);
5096 json_object_int_add(json_row
, "pruneRx",
5097 pim_ifp
->pim_ifstat_prune_recv
);
5098 json_object_int_add(json_row
, "pruneTx",
5099 pim_ifp
->pim_ifstat_prune_send
);
5100 json_object_int_add(json_row
, "registerRx",
5101 pim_ifp
->pim_ifstat_reg_recv
);
5102 json_object_int_add(json_row
, "registerTx",
5103 pim_ifp
->pim_ifstat_reg_send
);
5104 json_object_int_add(json_row
, "registerStopRx",
5105 pim_ifp
->pim_ifstat_reg_stop_recv
);
5106 json_object_int_add(json_row
, "registerStopTx",
5107 pim_ifp
->pim_ifstat_reg_stop_send
);
5108 json_object_int_add(json_row
, "assertRx",
5109 pim_ifp
->pim_ifstat_assert_recv
);
5110 json_object_int_add(json_row
, "assertTx",
5111 pim_ifp
->pim_ifstat_assert_send
);
5112 json_object_int_add(json_row
, "bsmRx",
5113 pim_ifp
->pim_ifstat_bsm_rx
);
5114 json_object_int_add(json_row
, "bsmTx",
5115 pim_ifp
->pim_ifstat_bsm_tx
);
5116 json_object_object_add(json
, ifp
->name
, json_row
);
5119 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5121 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5122 pim_ifp
->pim_ifstat_hello_sent
,
5123 pim_ifp
->pim_ifstat_join_recv
,
5124 pim_ifp
->pim_ifstat_join_send
,
5125 pim_ifp
->pim_ifstat_prune_recv
,
5126 pim_ifp
->pim_ifstat_prune_send
,
5127 pim_ifp
->pim_ifstat_reg_recv
,
5128 pim_ifp
->pim_ifstat_reg_send
,
5129 pim_ifp
->pim_ifstat_reg_stop_recv
,
5130 pim_ifp
->pim_ifstat_reg_stop_send
,
5131 pim_ifp
->pim_ifstat_assert_recv
,
5132 pim_ifp
->pim_ifstat_assert_send
,
5133 pim_ifp
->pim_ifstat_bsm_rx
,
5134 pim_ifp
->pim_ifstat_bsm_tx
);
5138 vty_json(vty
, json
);
5141 void pim_show_interface_traffic_single(struct pim_instance
*pim
,
5142 struct vty
*vty
, const char *ifname
,
5145 struct interface
*ifp
= NULL
;
5146 struct pim_interface
*pim_ifp
= NULL
;
5147 json_object
*json
= NULL
;
5148 json_object
*json_row
= NULL
;
5149 uint8_t found_ifname
= 0;
5152 json
= json_object_new_object();
5155 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5156 "Interface", " HELLO", " JOIN", " PRUNE",
5157 " REGISTER", " REGISTER-STOP", " ASSERT",
5159 vty_out(vty
, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5160 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
5161 " Rx/Tx", " Rx/Tx", " Rx/Tx");
5163 "-------------------------------------------------------------------------------------------------------------------------------\n");
5166 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5167 if (strcmp(ifname
, ifp
->name
))
5170 pim_ifp
= ifp
->info
;
5177 json_row
= json_object_new_object();
5178 json_object_pim_ifp_add(json_row
, ifp
);
5179 json_object_int_add(json_row
, "helloRx",
5180 pim_ifp
->pim_ifstat_hello_recv
);
5181 json_object_int_add(json_row
, "helloTx",
5182 pim_ifp
->pim_ifstat_hello_sent
);
5183 json_object_int_add(json_row
, "joinRx",
5184 pim_ifp
->pim_ifstat_join_recv
);
5185 json_object_int_add(json_row
, "joinTx",
5186 pim_ifp
->pim_ifstat_join_send
);
5187 json_object_int_add(json_row
, "pruneRx",
5188 pim_ifp
->pim_ifstat_prune_recv
);
5189 json_object_int_add(json_row
, "pruneTx",
5190 pim_ifp
->pim_ifstat_prune_send
);
5191 json_object_int_add(json_row
, "registerRx",
5192 pim_ifp
->pim_ifstat_reg_recv
);
5193 json_object_int_add(json_row
, "registerTx",
5194 pim_ifp
->pim_ifstat_reg_send
);
5195 json_object_int_add(json_row
, "registerStopRx",
5196 pim_ifp
->pim_ifstat_reg_stop_recv
);
5197 json_object_int_add(json_row
, "registerStopTx",
5198 pim_ifp
->pim_ifstat_reg_stop_send
);
5199 json_object_int_add(json_row
, "assertRx",
5200 pim_ifp
->pim_ifstat_assert_recv
);
5201 json_object_int_add(json_row
, "assertTx",
5202 pim_ifp
->pim_ifstat_assert_send
);
5203 json_object_int_add(json_row
, "bsmRx",
5204 pim_ifp
->pim_ifstat_bsm_rx
);
5205 json_object_int_add(json_row
, "bsmTx",
5206 pim_ifp
->pim_ifstat_bsm_tx
);
5208 json_object_object_add(json
, ifp
->name
, json_row
);
5211 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5213 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5214 pim_ifp
->pim_ifstat_hello_sent
,
5215 pim_ifp
->pim_ifstat_join_recv
,
5216 pim_ifp
->pim_ifstat_join_send
,
5217 pim_ifp
->pim_ifstat_prune_recv
,
5218 pim_ifp
->pim_ifstat_prune_send
,
5219 pim_ifp
->pim_ifstat_reg_recv
,
5220 pim_ifp
->pim_ifstat_reg_send
,
5221 pim_ifp
->pim_ifstat_reg_stop_recv
,
5222 pim_ifp
->pim_ifstat_reg_stop_send
,
5223 pim_ifp
->pim_ifstat_assert_recv
,
5224 pim_ifp
->pim_ifstat_assert_send
,
5225 pim_ifp
->pim_ifstat_bsm_rx
,
5226 pim_ifp
->pim_ifstat_bsm_tx
);
5230 vty_json(vty
, json
);
5231 else if (!found_ifname
)
5232 vty_out(vty
, "%% No such interface\n");
5235 int pim_show_interface_traffic_helper(const char *vrf
, const char *if_name
,
5236 struct vty
*vty
, bool uj
)
5238 struct pim_instance
*pim
;
5241 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5249 vty_out(vty
, "%% Unable to find pim instance\n");
5254 pim_show_interface_traffic_single(v
->info
, vty
, if_name
, uj
);
5256 pim_show_interface_traffic(v
->info
, vty
, uj
);
5261 void clear_pim_interfaces(struct pim_instance
*pim
)
5263 struct interface
*ifp
;
5265 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5267 pim_neighbor_delete_all(ifp
, "interface cleared");
5271 void pim_show_bsr(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
5274 char last_bsm_seen
[10];
5277 json_object
*json
= NULL
;
5279 if (pim_addr_is_any(pim
->global_scope
.current_bsr
)) {
5280 pim_time_uptime(uptime
, sizeof(uptime
),
5281 pim
->global_scope
.current_bsr_first_ts
);
5282 pim_time_uptime(last_bsm_seen
, sizeof(last_bsm_seen
),
5283 pim
->global_scope
.current_bsr_last_ts
);
5287 now
= pim_time_monotonic_sec();
5288 pim_time_uptime(uptime
, sizeof(uptime
),
5289 (now
- pim
->global_scope
.current_bsr_first_ts
));
5290 pim_time_uptime(last_bsm_seen
, sizeof(last_bsm_seen
),
5291 now
- pim
->global_scope
.current_bsr_last_ts
);
5294 switch (pim
->global_scope
.state
) {
5296 strlcpy(bsr_state
, "NO_INFO", sizeof(bsr_state
));
5299 strlcpy(bsr_state
, "ACCEPT_ANY", sizeof(bsr_state
));
5301 case ACCEPT_PREFERRED
:
5302 strlcpy(bsr_state
, "ACCEPT_PREFERRED", sizeof(bsr_state
));
5305 strlcpy(bsr_state
, "", sizeof(bsr_state
));
5310 json
= json_object_new_object();
5311 json_object_string_addf(json
, "bsr", "%pPA",
5312 &pim
->global_scope
.current_bsr
);
5313 json_object_int_add(json
, "priority",
5314 pim
->global_scope
.current_bsr_prio
);
5315 json_object_int_add(json
, "fragmentTag",
5316 pim
->global_scope
.bsm_frag_tag
);
5317 json_object_string_add(json
, "state", bsr_state
);
5318 json_object_string_add(json
, "upTime", uptime
);
5319 json_object_string_add(json
, "lastBsmSeen", last_bsm_seen
);
5323 vty_out(vty
, "PIMv2 Bootstrap information\n");
5324 vty_out(vty
, "Current preferred BSR address: %pPA\n",
5325 &pim
->global_scope
.current_bsr
);
5327 "Priority Fragment-Tag State UpTime\n");
5328 vty_out(vty
, " %-12d %-12d %-13s %7s\n",
5329 pim
->global_scope
.current_bsr_prio
,
5330 pim
->global_scope
.bsm_frag_tag
, bsr_state
, uptime
);
5331 vty_out(vty
, "Last BSM seen: %s\n", last_bsm_seen
);
5335 vty_json(vty
, json
);
5338 int pim_show_bsr_helper(const char *vrf
, struct vty
*vty
, bool uj
)
5340 struct pim_instance
*pim
;
5343 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5348 pim
= pim_get_pim_instance(v
->vrf_id
);
5351 vty_out(vty
, "%% Unable to find pim instance\n");
5355 pim_show_bsr(v
->info
, vty
, uj
);
5360 /*Display the group-rp mappings */
5361 static void pim_show_group_rp_mappings_info(struct pim_instance
*pim
,
5362 struct vty
*vty
, bool uj
)
5364 struct bsgrp_node
*bsgrp
;
5365 struct bsm_rpinfo
*bsm_rp
;
5366 struct route_node
*rn
;
5367 json_object
*json
= NULL
;
5368 json_object
*json_group
= NULL
;
5369 json_object
*json_row
= NULL
;
5370 struct ttable
*tt
= NULL
;
5373 json
= json_object_new_object();
5374 json_object_string_addf(json
, "BSR Address", "%pPA",
5375 &pim
->global_scope
.current_bsr
);
5377 vty_out(vty
, "BSR Address %pPA\n",
5378 &pim
->global_scope
.current_bsr
);
5380 for (rn
= route_top(pim
->global_scope
.bsrp_table
); rn
;
5381 rn
= route_next(rn
)) {
5382 bsgrp
= (struct bsgrp_node
*)rn
->info
;
5387 char grp_str
[PREFIX_STRLEN
];
5389 prefix2str(&bsgrp
->group
, grp_str
, sizeof(grp_str
));
5392 json_object_object_get_ex(json
, grp_str
, &json_group
);
5394 json_group
= json_object_new_object();
5395 json_object_object_add(json
, grp_str
,
5399 vty_out(vty
, "Group Address %pFX\n", &bsgrp
->group
);
5400 vty_out(vty
, "--------------------------\n");
5401 /* Prepare table. */
5402 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
5403 ttable_add_row(tt
, "Rp Address|priority|Holdtime|Hash");
5404 tt
->style
.cell
.rpad
= 2;
5405 tt
->style
.corner
= '+';
5408 ttable_add_row(tt
, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ',
5412 frr_each (bsm_rpinfos
, bsgrp
->bsrp_list
, bsm_rp
) {
5414 json_row
= json_object_new_object();
5415 json_object_string_addf(json_row
, "Rp Address",
5417 &bsm_rp
->rp_address
);
5418 json_object_int_add(json_row
, "Rp HoldTime",
5419 bsm_rp
->rp_holdtime
);
5420 json_object_int_add(json_row
, "Rp Priority",
5422 json_object_int_add(json_row
, "Hash Val",
5424 json_object_object_addf(json_group
, json_row
,
5426 &bsm_rp
->rp_address
);
5430 tt
, "%pPA|%u|%u|%u",
5431 &bsm_rp
->rp_address
, bsm_rp
->rp_prio
,
5432 bsm_rp
->rp_holdtime
, bsm_rp
->hash
);
5435 /* Dump the generated table. */
5439 table
= ttable_dump(tt
, "\n");
5440 vty_out(vty
, "%s\n", table
);
5441 XFREE(MTYPE_TMP
, table
);
5445 if (!bsm_rpinfos_count(bsgrp
->bsrp_list
) && !uj
)
5446 vty_out(vty
, "Active List is empty.\n");
5449 json_object_int_add(json_group
, "Pending RP count",
5450 bsgrp
->pend_rp_cnt
);
5452 vty_out(vty
, "(PENDING)\n");
5453 vty_out(vty
, "Pending RP count :%d\n",
5454 bsgrp
->pend_rp_cnt
);
5455 if (bsgrp
->pend_rp_cnt
) {
5456 /* Prepare table. */
5457 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
5460 "Rp Address|priority|Holdtime|Hash");
5461 tt
->style
.cell
.rpad
= 2;
5462 tt
->style
.corner
= '+';
5467 frr_each (bsm_rpinfos
, bsgrp
->partial_bsrp_list
, bsm_rp
) {
5469 json_row
= json_object_new_object();
5470 json_object_string_addf(json_row
, "Rp Address",
5472 &bsm_rp
->rp_address
);
5473 json_object_int_add(json_row
, "Rp HoldTime",
5474 bsm_rp
->rp_holdtime
);
5475 json_object_int_add(json_row
, "Rp Priority",
5477 json_object_int_add(json_row
, "Hash Val",
5479 json_object_object_addf(json_group
, json_row
,
5481 &bsm_rp
->rp_address
);
5484 tt
, "%pPA|%u|%u|%u",
5485 &bsm_rp
->rp_address
, bsm_rp
->rp_prio
,
5486 bsm_rp
->rp_holdtime
, bsm_rp
->hash
);
5489 /* Dump the generated table. */
5493 table
= ttable_dump(tt
, "\n");
5494 vty_out(vty
, "%s\n", table
);
5495 XFREE(MTYPE_TMP
, table
);
5498 if (!bsm_rpinfos_count(bsgrp
->partial_bsrp_list
) && !uj
)
5499 vty_out(vty
, "Partial List is empty\n");
5506 vty_json(vty
, json
);
5509 int pim_show_group_rp_mappings_info_helper(const char *vrf
, struct vty
*vty
,
5512 struct pim_instance
*pim
;
5515 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5523 vty_out(vty
, "%% Unable to find pim instance\n");
5527 pim_show_group_rp_mappings_info(v
->info
, vty
, uj
);
5532 /* Display the bsm database details */
5533 static void pim_show_bsm_db(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
5537 struct bsm_frag
*bsfrag
;
5538 json_object
*json
= NULL
;
5539 json_object
*json_group
= NULL
;
5540 json_object
*json_row
= NULL
;
5542 count
= bsm_frags_count(pim
->global_scope
.bsm_frags
);
5545 json
= json_object_new_object();
5546 json_object_int_add(json
, "Number of the fragments", count
);
5548 vty_out(vty
, "Scope Zone: Global\n");
5549 vty_out(vty
, "Number of the fragments: %d\n", count
);
5553 frr_each (bsm_frags
, pim
->global_scope
.bsm_frags
, bsfrag
) {
5554 char grp_str
[PREFIX_STRLEN
];
5555 struct bsmmsg_grpinfo
*group
;
5556 struct bsmmsg_rpinfo
*bsm_rpinfo
;
5558 struct bsm_hdr
*hdr
;
5560 uint32_t offset
= 0;
5563 uint32_t frag_rp_cnt
= 0;
5568 /* skip pim header */
5569 buf
+= PIM_MSG_HEADER_LEN
;
5570 len
-= PIM_MSG_HEADER_LEN
;
5572 hdr
= (struct bsm_hdr
*)buf
;
5573 /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
5574 memcpy(&bsr_addr
, &hdr
->bsr_addr
.addr
, sizeof(bsr_addr
));
5576 /* BSM starts with bsr header */
5577 buf
+= sizeof(struct bsm_hdr
);
5578 len
-= sizeof(struct bsm_hdr
);
5581 json_object_string_addf(json
, "BSR address", "%pPA",
5583 json_object_int_add(json
, "BSR priority",
5585 json_object_int_add(json
, "Hashmask Length",
5587 json_object_int_add(json
, "Fragment Tag",
5588 ntohs(hdr
->frag_tag
));
5590 vty_out(vty
, "BSM Fragment : %d\n", fragment
);
5591 vty_out(vty
, "------------------\n");
5592 vty_out(vty
, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
5593 "BSR-Priority", "Hashmask-len", "Fragment-Tag");
5594 vty_out(vty
, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr
,
5595 hdr
->bsr_prio
, hdr
->hm_len
,
5596 ntohs(hdr
->frag_tag
));
5601 while (offset
< len
) {
5602 group
= (struct bsmmsg_grpinfo
*)buf
;
5604 if (group
->group
.family
== PIM_MSG_ADDRESS_FAMILY_IPV4
)
5605 grp
.family
= AF_INET
;
5606 else if (group
->group
.family
==
5607 PIM_MSG_ADDRESS_FAMILY_IPV6
)
5608 grp
.family
= AF_INET6
;
5610 grp
.prefixlen
= group
->group
.mask
;
5612 grp
.u
.prefix4
= group
->group
.addr
;
5614 grp
.u
.prefix6
= group
->group
.addr
;
5617 prefix2str(&grp
, grp_str
, sizeof(grp_str
));
5619 buf
+= sizeof(struct bsmmsg_grpinfo
);
5620 offset
+= sizeof(struct bsmmsg_grpinfo
);
5623 json_object_object_get_ex(json
, grp_str
,
5626 json_group
= json_object_new_object();
5627 json_object_int_add(json_group
,
5630 json_object_int_add(
5631 json_group
, "Fragment Rp count",
5632 group
->frag_rp_count
);
5633 json_object_object_add(json
, grp_str
,
5637 vty_out(vty
, "Group : %s\n", grp_str
);
5638 vty_out(vty
, "-------------------\n");
5639 vty_out(vty
, "Rp Count:%d\n", group
->rp_count
);
5640 vty_out(vty
, "Fragment Rp Count : %d\n",
5641 group
->frag_rp_count
);
5644 frag_rp_cnt
= group
->frag_rp_count
;
5651 "RpAddress HoldTime Priority\n");
5653 while (frag_rp_cnt
--) {
5656 bsm_rpinfo
= (struct bsmmsg_rpinfo
*)buf
;
5657 /* unaligned, again */
5658 memcpy(&rp_addr
, &bsm_rpinfo
->rpaddr
.addr
,
5661 buf
+= sizeof(struct bsmmsg_rpinfo
);
5662 offset
+= sizeof(struct bsmmsg_rpinfo
);
5665 json_row
= json_object_new_object();
5666 json_object_string_addf(
5667 json_row
, "Rp Address", "%pPA",
5669 json_object_int_add(
5670 json_row
, "Rp HoldTime",
5671 ntohs(bsm_rpinfo
->rp_holdtime
));
5672 json_object_int_add(json_row
,
5674 bsm_rpinfo
->rp_pri
);
5675 json_object_object_addf(
5676 json_group
, json_row
, "%pPA",
5679 vty_out(vty
, "%-15pPA %-12d %d\n",
5681 ntohs(bsm_rpinfo
->rp_holdtime
),
5682 bsm_rpinfo
->rp_pri
);
5692 vty_json(vty
, json
);
5695 int pim_show_bsm_db_helper(const char *vrf
, struct vty
*vty
, bool uj
)
5697 struct pim_instance
*pim
;
5700 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5708 vty_out(vty
, "%% Unable to find pim instance\n");
5712 pim_show_bsm_db(v
->info
, vty
, uj
);