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 vrfname
= pim_cli_get_vrf_name(vty
);
571 return CMD_WARNING_CONFIG_FAILED
;
573 snprintf(rp_group_xpath
, sizeof(rp_group_xpath
),
574 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
575 FRR_PIM_AF_XPATH_VAL
, rp_str
);
576 strlcat(rp_group_xpath
, "/group-list", sizeof(rp_group_xpath
));
578 nb_cli_enqueue_change(vty
, rp_group_xpath
, NB_OP_CREATE
, group_str
);
580 return nb_cli_apply_changes(vty
, NULL
);
583 int pim_process_no_rp_cmd(struct vty
*vty
, const char *rp_str
,
584 const char *group_str
)
586 char group_list_xpath
[XPATH_MAXLEN
];
587 char group_xpath
[XPATH_MAXLEN
];
588 char rp_xpath
[XPATH_MAXLEN
];
591 const struct lyd_node
*group_dnode
;
593 vrfname
= pim_cli_get_vrf_name(vty
);
595 return CMD_WARNING_CONFIG_FAILED
;
597 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
598 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
600 printed
= snprintf(group_list_xpath
, sizeof(group_list_xpath
),
601 "%s/group-list", rp_xpath
);
603 if (printed
>= (int)(sizeof(group_list_xpath
))) {
604 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
606 return CMD_WARNING_CONFIG_FAILED
;
609 printed
= snprintf(group_xpath
, sizeof(group_xpath
), "%s[.='%s']",
610 group_list_xpath
, group_str
);
612 if (printed
>= (int)(sizeof(group_xpath
))) {
613 vty_out(vty
, "Xpath too long (%d > %u)", printed
+ 1,
615 return CMD_WARNING_CONFIG_FAILED
;
618 group_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, group_xpath
);
620 vty_out(vty
, "%% Unable to find specified RP\n");
624 if (yang_is_last_list_dnode(group_dnode
))
625 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
627 nb_cli_enqueue_change(vty
, group_list_xpath
, NB_OP_DESTROY
,
630 return nb_cli_apply_changes(vty
, NULL
);
633 int pim_process_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
634 const char *prefix_list
)
637 char rp_plist_xpath
[XPATH_MAXLEN
];
639 vrfname
= pim_cli_get_vrf_name(vty
);
641 return CMD_WARNING_CONFIG_FAILED
;
643 snprintf(rp_plist_xpath
, sizeof(rp_plist_xpath
),
644 FRR_PIM_STATIC_RP_XPATH
, "frr-pim:pimd", "pim", vrfname
,
645 FRR_PIM_AF_XPATH_VAL
, rp_str
);
646 strlcat(rp_plist_xpath
, "/prefix-list", sizeof(rp_plist_xpath
));
648 nb_cli_enqueue_change(vty
, rp_plist_xpath
, NB_OP_MODIFY
, prefix_list
);
650 return nb_cli_apply_changes(vty
, NULL
);
653 int pim_process_no_rp_plist_cmd(struct vty
*vty
, const char *rp_str
,
654 const char *prefix_list
)
656 char rp_xpath
[XPATH_MAXLEN
];
657 char plist_xpath
[XPATH_MAXLEN
];
659 const struct lyd_node
*plist_dnode
;
662 vrfname
= pim_cli_get_vrf_name(vty
);
664 return CMD_WARNING_CONFIG_FAILED
;
666 snprintf(rp_xpath
, sizeof(rp_xpath
), FRR_PIM_STATIC_RP_XPATH
,
667 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
669 snprintf(plist_xpath
, sizeof(plist_xpath
), FRR_PIM_STATIC_RP_XPATH
,
670 "frr-pim:pimd", "pim", vrfname
, FRR_PIM_AF_XPATH_VAL
, rp_str
);
671 strlcat(plist_xpath
, "/prefix-list", sizeof(plist_xpath
));
673 plist_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, plist_xpath
);
675 vty_out(vty
, "%% Unable to find specified RP\n");
679 plist
= yang_dnode_get_string(plist_dnode
, plist_xpath
);
680 if (strcmp(prefix_list
, plist
)) {
681 vty_out(vty
, "%% Unable to find specified RP\n");
685 nb_cli_enqueue_change(vty
, rp_xpath
, NB_OP_DESTROY
, NULL
);
687 return nb_cli_apply_changes(vty
, NULL
);
690 bool pim_sgaddr_match(pim_sgaddr item
, pim_sgaddr match
)
692 return (pim_addr_is_any(match
.grp
) ||
693 !pim_addr_cmp(match
.grp
, item
.grp
)) &&
694 (pim_addr_is_any(match
.src
) ||
695 !pim_addr_cmp(match
.src
, item
.src
));
698 void json_object_pim_ifp_add(struct json_object
*json
, struct interface
*ifp
)
700 struct pim_interface
*pim_ifp
;
703 json_object_string_add(json
, "name", ifp
->name
);
704 json_object_string_add(json
, "state", if_is_up(ifp
) ? "up" : "down");
705 json_object_string_addf(json
, "address", "%pPA",
706 &pim_ifp
->primary_address
);
707 json_object_int_add(json
, "index", ifp
->ifindex
);
709 if (if_is_multicast(ifp
))
710 json_object_boolean_true_add(json
, "flagMulticast");
712 if (if_is_broadcast(ifp
))
713 json_object_boolean_true_add(json
, "flagBroadcast");
715 if (ifp
->flags
& IFF_ALLMULTI
)
716 json_object_boolean_true_add(json
, "flagAllMulticast");
718 if (ifp
->flags
& IFF_PROMISC
)
719 json_object_boolean_true_add(json
, "flagPromiscuous");
721 if (PIM_IF_IS_DELETED(ifp
))
722 json_object_boolean_true_add(json
, "flagDeleted");
724 if (pim_if_lan_delay_enabled(ifp
))
725 json_object_boolean_true_add(json
, "lanDelayEnabled");
728 void pim_print_ifp_flags(struct vty
*vty
, struct interface
*ifp
)
730 vty_out(vty
, "Flags\n");
731 vty_out(vty
, "-----\n");
732 vty_out(vty
, "All Multicast : %s\n",
733 (ifp
->flags
& IFF_ALLMULTI
) ? "yes" : "no");
734 vty_out(vty
, "Broadcast : %s\n",
735 if_is_broadcast(ifp
) ? "yes" : "no");
736 vty_out(vty
, "Deleted : %s\n",
737 PIM_IF_IS_DELETED(ifp
) ? "yes" : "no");
738 vty_out(vty
, "Interface Index : %d\n", ifp
->ifindex
);
739 vty_out(vty
, "Multicast : %s\n",
740 if_is_multicast(ifp
) ? "yes" : "no");
741 vty_out(vty
, "Promiscuous : %s\n",
742 (ifp
->flags
& IFF_PROMISC
) ? "yes" : "no");
747 void json_object_pim_upstream_add(json_object
*json
, struct pim_upstream
*up
)
749 json_object_boolean_add(
750 json
, "drJoinDesired",
751 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED
));
752 json_object_boolean_add(
753 json
, "drJoinDesiredUpdated",
754 CHECK_FLAG(up
->flags
,
755 PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED
));
756 json_object_boolean_add(
757 json
, "firstHopRouter",
758 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FHR
));
759 json_object_boolean_add(
761 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
));
762 json_object_boolean_add(
764 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_PIM
));
765 json_object_boolean_add(
766 json
, "sourceStream",
767 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM
));
768 /* XXX: need to print ths flag in the plain text display as well */
769 json_object_boolean_add(
771 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP
));
772 json_object_boolean_add(
773 json
, "sendSGRptPrune",
774 CHECK_FLAG(up
->flags
,
775 PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE
));
776 json_object_boolean_add(
777 json
, "lastHopRouter",
778 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_LHR
));
779 json_object_boolean_add(
780 json
, "disableKATExpiry",
781 CHECK_FLAG(up
->flags
,
782 PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY
));
783 json_object_boolean_add(
784 json
, "staticIncomingInterface",
785 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF
));
786 json_object_boolean_add(
787 json
, "allowIncomingInterfaceinOil",
788 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL
));
789 json_object_boolean_add(
790 json
, "noPimRegistrationData",
791 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA
));
792 json_object_boolean_add(
793 json
, "forcePimRegistration",
794 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG
));
795 json_object_boolean_add(
796 json
, "sourceVxlanOrigination",
797 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG
));
798 json_object_boolean_add(
799 json
, "sourceVxlanTermination",
800 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM
));
801 json_object_boolean_add(
803 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN
));
804 json_object_boolean_add(
805 json
, "mlagNonDesignatedForwarder",
806 CHECK_FLAG(up
->flags
, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF
));
810 pim_upstream_state2brief_str(enum pim_upstream_state join_state
,
811 char *state_str
, size_t state_str_len
)
813 switch (join_state
) {
814 case PIM_UPSTREAM_NOTJOINED
:
815 strlcpy(state_str
, "NotJ", state_str_len
);
817 case PIM_UPSTREAM_JOINED
:
818 strlcpy(state_str
, "J", state_str_len
);
821 strlcpy(state_str
, "Unk", state_str_len
);
826 static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state
,
828 size_t state_str_len
)
832 strlcpy(state_str
, "RegNI", state_str_len
);
835 strlcpy(state_str
, "RegJ", state_str_len
);
837 case PIM_REG_JOIN_PENDING
:
839 strlcpy(state_str
, "RegP", state_str_len
);
845 void pim_show_rpf_refresh_stats(struct vty
*vty
, struct pim_instance
*pim
,
846 time_t now
, json_object
*json
)
848 char refresh_uptime
[10];
850 pim_time_uptime_begin(refresh_uptime
, sizeof(refresh_uptime
), now
,
851 pim
->rpf_cache_refresh_last
);
854 json_object_int_add(json
, "rpfCacheRefreshDelayMsecs",
855 router
->rpf_cache_refresh_delay_msec
);
857 json
, "rpfCacheRefreshTimer",
858 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
));
859 json_object_int_add(json
, "rpfCacheRefreshRequests",
860 pim
->rpf_cache_refresh_requests
);
861 json_object_int_add(json
, "rpfCacheRefreshEvents",
862 pim
->rpf_cache_refresh_events
);
863 json_object_string_add(json
, "rpfCacheRefreshLast",
865 json_object_int_add(json
, "nexthopLookups",
866 pim
->nexthop_lookups
);
867 json_object_int_add(json
, "nexthopLookupsAvoided",
868 pim
->nexthop_lookups_avoided
);
871 "RPF Cache Refresh Delay: %ld msecs\n"
872 "RPF Cache Refresh Timer: %ld msecs\n"
873 "RPF Cache Refresh Requests: %lld\n"
874 "RPF Cache Refresh Events: %lld\n"
875 "RPF Cache Refresh Last: %s\n"
876 "Nexthop Lookups: %lld\n"
877 "Nexthop Lookups Avoided: %lld\n",
878 router
->rpf_cache_refresh_delay_msec
,
879 pim_time_timer_remain_msec(pim
->rpf_cache_refresher
),
880 (long long)pim
->rpf_cache_refresh_requests
,
881 (long long)pim
->rpf_cache_refresh_events
,
882 refresh_uptime
, (long long)pim
->nexthop_lookups
,
883 (long long)pim
->nexthop_lookups_avoided
);
887 void pim_show_rpf(struct pim_instance
*pim
, struct vty
*vty
, json_object
*json
)
889 struct pim_upstream
*up
;
890 time_t now
= pim_time_monotonic_sec();
891 struct ttable
*tt
= NULL
;
893 json_object
*json_group
= NULL
;
894 json_object
*json_row
= NULL
;
896 pim_show_rpf_refresh_stats(vty
, pim
, now
, json
);
902 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
905 "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
906 tt
->style
.cell
.rpad
= 2;
907 tt
->style
.corner
= '+';
911 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
912 const char *rpf_ifname
;
913 struct pim_rpf
*rpf
= &up
->rpf
;
916 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
921 char grp_str
[PIM_ADDRSTRLEN
];
922 char src_str
[PIM_ADDRSTRLEN
];
924 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
926 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
929 json_object_object_get_ex(json
, grp_str
, &json_group
);
932 json_group
= json_object_new_object();
933 json_object_object_add(json
, grp_str
,
937 json_row
= json_object_new_object();
938 json_object_string_add(json_row
, "source", src_str
);
939 json_object_string_add(json_row
, "group", grp_str
);
940 json_object_string_add(json_row
, "rpfInterface",
942 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
944 json_object_string_addf(
945 json_row
, "ribNexthop", "%pPAs",
946 &rpf
->source_nexthop
.mrib_nexthop_addr
);
948 json_row
, "routeMetric",
949 rpf
->source_nexthop
.mrib_route_metric
);
951 json_row
, "routePreference",
952 rpf
->source_nexthop
.mrib_metric_preference
);
953 json_object_object_add(json_group
, src_str
, json_row
);
957 tt
, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
958 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
960 &rpf
->source_nexthop
.mrib_nexthop_addr
,
961 rpf
->source_nexthop
.mrib_route_metric
,
962 rpf
->source_nexthop
.mrib_metric_preference
);
965 /* Dump the generated table. */
967 table
= ttable_dump(tt
, "\n");
968 vty_out(vty
, "%s\n", table
);
969 XFREE(MTYPE_TMP
, table
);
974 void pim_show_neighbors_secondary(struct pim_instance
*pim
, struct vty
*vty
)
976 struct interface
*ifp
;
977 struct ttable
*tt
= NULL
;
981 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
982 ttable_add_row(tt
, "Interface|Address|Neighbor|Secondary");
983 tt
->style
.cell
.rpad
= 2;
984 tt
->style
.corner
= '+';
987 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
988 struct pim_interface
*pim_ifp
;
990 struct listnode
*neighnode
;
991 struct pim_neighbor
*neigh
;
998 if (pim_ifp
->pim_sock_fd
< 0)
1001 ifaddr
= pim_ifp
->primary_address
;
1003 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1005 struct listnode
*prefix_node
;
1008 if (!neigh
->prefix_list
)
1011 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
,
1013 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pFX",
1015 &neigh
->source_addr
, p
);
1018 /* Dump the generated table. */
1019 table
= ttable_dump(tt
, "\n");
1020 vty_out(vty
, "%s\n", table
);
1021 XFREE(MTYPE_TMP
, table
);
1025 void pim_show_state(struct pim_instance
*pim
, struct vty
*vty
,
1026 const char *src_or_group
, const char *group
,
1029 struct channel_oil
*c_oil
;
1030 json_object
*json_group
= NULL
;
1031 json_object
*json_ifp_in
= NULL
;
1032 json_object
*json_ifp_out
= NULL
;
1033 json_object
*json_source
= NULL
;
1037 now
= pim_time_monotonic_sec();
1041 "Codes: J -> Pim Join, I -> " GM
" Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
1043 "\nActive Source Group RPT IIF OIL\n");
1046 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
1047 char src_str
[PIM_ADDRSTRLEN
];
1048 char grp_str
[PIM_ADDRSTRLEN
];
1049 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
1050 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
1052 struct interface
*ifp_in
;
1058 PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil
->up
->flags
)) ||
1059 pim_addr_is_any(*oil_origin(c_oil
)))
1064 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1065 oil_mcastgrp(c_oil
));
1066 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1068 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
1071 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
1073 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
1076 if (strcmp(src_or_group
, src_str
) &&
1077 strcmp(src_or_group
, grp_str
))
1080 if (group
&& strcmp(group
, grp_str
))
1086 /* Find the group, create it if it doesn't exist */
1087 json_object_object_get_ex(json
, grp_str
, &json_group
);
1090 json_group
= json_object_new_object();
1091 json_object_object_add(json
, grp_str
,
1095 /* Find the source nested under the group, create it if
1098 json_object_object_get_ex(json_group
, src_str
,
1102 json_source
= json_object_new_object();
1103 json_object_object_add(json_group
, src_str
,
1107 /* Find the inbound interface nested under the source,
1108 * create it if it doesn't exist
1110 json_object_object_get_ex(json_source
, in_ifname
,
1114 json_ifp_in
= json_object_new_object();
1115 json_object_object_add(json_source
, in_ifname
,
1117 json_object_int_add(json_source
, "Installed",
1119 json_object_int_add(json_source
, "installed",
1121 json_object_boolean_add(json_source
, "isRpt",
1123 json_object_int_add(json_source
, "RefCount",
1124 c_oil
->oil_ref_count
);
1125 json_object_int_add(json_source
, "refCount",
1126 c_oil
->oil_ref_count
);
1127 json_object_int_add(json_source
, "OilListSize",
1129 json_object_int_add(json_source
, "oilListSize",
1131 json_object_int_add(
1132 json_source
, "OilRescan",
1133 c_oil
->oil_inherited_rescan
);
1134 json_object_int_add(
1135 json_source
, "oilRescan",
1136 c_oil
->oil_inherited_rescan
);
1137 json_object_int_add(json_source
, "LastUsed",
1138 c_oil
->cc
.lastused
);
1139 json_object_int_add(json_source
, "lastUsed",
1140 c_oil
->cc
.lastused
);
1141 json_object_int_add(json_source
, "PacketCount",
1143 json_object_int_add(json_source
, "packetCount",
1145 json_object_int_add(json_source
, "ByteCount",
1147 json_object_int_add(json_source
, "byteCount",
1149 json_object_int_add(json_source
,
1151 c_oil
->cc
.wrong_if
);
1152 json_object_int_add(json_source
,
1154 c_oil
->cc
.wrong_if
);
1157 vty_out(vty
, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1158 c_oil
->installed
, oil_origin(c_oil
),
1159 oil_mcastgrp(c_oil
), isRpt
? "y" : "n",
1162 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
1164 struct interface
*ifp_out
;
1165 char oif_uptime
[10];
1168 ttl
= oil_if_has(c_oil
, oif_vif_index
);
1172 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
1174 oif_uptime
, sizeof(oif_uptime
),
1175 now
- c_oil
->oif_creation
[oif_vif_index
]);
1178 strlcpy(out_ifname
, ifp_out
->name
,
1179 sizeof(out_ifname
));
1181 strlcpy(out_ifname
, "<oif?>",
1182 sizeof(out_ifname
));
1185 json_ifp_out
= json_object_new_object();
1186 json_object_string_add(json_ifp_out
, "source",
1188 json_object_string_add(json_ifp_out
, "group",
1190 json_object_string_add(json_ifp_out
,
1193 json_object_string_add(json_ifp_out
,
1194 "outboundInterface",
1196 json_object_int_add(json_ifp_out
, "installed",
1199 json_object_object_add(json_ifp_in
, out_ifname
,
1204 vty_out(vty
, "%s(%c%c%c%c%c)",
1208 PIM_OIF_FLAG_PROTO_GM
)
1213 PIM_OIF_FLAG_PROTO_PIM
)
1218 PIM_OIF_FLAG_PROTO_VXLAN
)
1223 PIM_OIF_FLAG_PROTO_STAR
)
1232 vty_out(vty
, ", %s(%c%c%c%c%c)",
1236 PIM_OIF_FLAG_PROTO_GM
)
1241 PIM_OIF_FLAG_PROTO_PIM
)
1246 PIM_OIF_FLAG_PROTO_VXLAN
)
1251 PIM_OIF_FLAG_PROTO_STAR
)
1270 /* pim statistics - just adding only bsm related now.
1271 * We can continue to add all pim related stats here.
1273 void pim_show_statistics(struct pim_instance
*pim
, struct vty
*vty
,
1274 const char *ifname
, bool uj
)
1276 json_object
*json
= NULL
;
1277 struct interface
*ifp
;
1280 json
= json_object_new_object();
1281 json_object_int_add(json
, "bsmRx", pim
->bsm_rcvd
);
1282 json_object_int_add(json
, "bsmTx", pim
->bsm_sent
);
1283 json_object_int_add(json
, "bsmDropped", pim
->bsm_dropped
);
1285 vty_out(vty
, "BSM Statistics :\n");
1286 vty_out(vty
, "----------------\n");
1287 vty_out(vty
, "Number of Received BSMs : %" PRIu64
"\n",
1289 vty_out(vty
, "Number of Forwared BSMs : %" PRIu64
"\n",
1291 vty_out(vty
, "Number of Dropped BSMs : %" PRIu64
"\n",
1297 /* scan interfaces */
1298 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1299 struct pim_interface
*pim_ifp
= ifp
->info
;
1301 if (ifname
&& strcmp(ifname
, ifp
->name
))
1308 vty_out(vty
, "Interface : %s\n", ifp
->name
);
1309 vty_out(vty
, "-------------------\n");
1311 "Number of BSMs dropped due to config miss : %u\n",
1312 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1313 vty_out(vty
, "Number of unicast BSMs dropped : %u\n",
1314 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1316 "Number of BSMs dropped due to invalid scope zone : %u\n",
1317 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1320 json_object
*json_row
= NULL
;
1322 json_row
= json_object_new_object();
1324 json_object_string_add(json_row
, "If Name", ifp
->name
);
1325 json_object_int_add(json_row
, "bsmDroppedConfig",
1326 pim_ifp
->pim_ifstat_bsm_cfg_miss
);
1327 json_object_int_add(
1328 json_row
, "bsmDroppedUnicast",
1329 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
);
1330 json_object_int_add(json_row
,
1331 "bsmDroppedInvalidScopeZone",
1332 pim_ifp
->pim_ifstat_bsm_invalid_sz
);
1333 json_object_object_add(json
, ifp
->name
, json_row
);
1339 vty_json(vty
, json
);
1342 void pim_show_upstream(struct pim_instance
*pim
, struct vty
*vty
,
1343 pim_sgaddr
*sg
, json_object
*json
)
1345 struct pim_upstream
*up
;
1346 struct ttable
*tt
= NULL
;
1349 json_object
*json_group
= NULL
;
1350 json_object
*json_row
= NULL
;
1352 now
= pim_time_monotonic_sec();
1355 /* Prepare table. */
1356 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1359 "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
1360 tt
->style
.cell
.rpad
= 2;
1361 tt
->style
.corner
= '+';
1365 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1367 char join_timer
[10];
1370 char msdp_reg_timer
[10];
1371 char state_str
[PIM_REG_STATE_STR_LEN
];
1373 if (!pim_sgaddr_match(up
->sg
, *sg
))
1376 pim_time_uptime(uptime
, sizeof(uptime
),
1377 now
- up
->state_transition
);
1378 pim_time_timer_to_hhmmss(join_timer
, sizeof(join_timer
),
1382 * If the upstream is not dummy and it has a J/P timer for the
1383 * neighbor display that
1385 if (!up
->t_join_timer
&& up
->rpf
.source_nexthop
.interface
) {
1386 struct pim_neighbor
*nbr
;
1388 nbr
= pim_neighbor_find(
1389 up
->rpf
.source_nexthop
.interface
,
1392 pim_time_timer_to_hhmmss(join_timer
,
1397 pim_time_timer_to_hhmmss(rs_timer
, sizeof(rs_timer
),
1399 pim_time_timer_to_hhmmss(ka_timer
, sizeof(ka_timer
),
1401 pim_time_timer_to_hhmmss(msdp_reg_timer
, sizeof(msdp_reg_timer
),
1402 up
->t_msdp_reg_timer
);
1404 pim_upstream_state2brief_str(up
->join_state
, state_str
,
1406 if (up
->reg_state
!= PIM_REG_NOINFO
) {
1407 char tmp_str
[PIM_REG_STATE_STR_LEN
];
1408 char tmp
[sizeof(state_str
) + 1];
1410 snprintf(tmp
, sizeof(tmp
), ",%s",
1411 pim_reg_state2brief_str(up
->reg_state
, tmp_str
,
1413 strlcat(state_str
, tmp
, sizeof(state_str
));
1417 char grp_str
[PIM_ADDRSTRLEN
];
1418 char src_str
[PIM_ADDRSTRLEN
];
1420 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1422 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1425 json_object_object_get_ex(json
, grp_str
, &json_group
);
1428 json_group
= json_object_new_object();
1429 json_object_object_add(json
, grp_str
,
1433 json_row
= json_object_new_object();
1434 json_object_pim_upstream_add(json_row
, up
);
1435 json_object_string_add(
1436 json_row
, "inboundInterface",
1437 up
->rpf
.source_nexthop
.interface
1438 ? up
->rpf
.source_nexthop
.interface
->name
1442 * The RPF address we use is slightly different
1443 * based upon what we are looking up.
1444 * If we have a S, list that unless
1445 * we are the FHR, else we just put
1446 * the RP as the rpfAddress
1448 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
||
1449 pim_addr_is_any(up
->sg
.src
)) {
1450 struct pim_rpf
*rpg
;
1452 rpg
= RP(pim
, up
->sg
.grp
);
1453 json_object_string_addf(json_row
, "rpfAddress",
1454 "%pPA", &rpg
->rpf_addr
);
1456 json_object_string_add(json_row
, "rpfAddress",
1460 json_object_string_add(json_row
, "source", src_str
);
1461 json_object_string_add(json_row
, "group", grp_str
);
1462 json_object_string_add(json_row
, "state", state_str
);
1463 json_object_string_add(
1464 json_row
, "joinState",
1465 pim_upstream_state2str(up
->join_state
));
1466 json_object_string_add(
1467 json_row
, "regState",
1468 pim_reg_state2str(up
->reg_state
, state_str
,
1469 sizeof(state_str
)));
1470 json_object_string_add(json_row
, "upTime", uptime
);
1471 json_object_string_add(json_row
, "joinTimer",
1473 json_object_string_add(json_row
, "resetTimer",
1475 json_object_string_add(json_row
, "keepaliveTimer",
1477 json_object_string_add(json_row
, "msdpRegTimer",
1479 json_object_int_add(json_row
, "refCount",
1481 json_object_int_add(json_row
, "sptBit", up
->sptbit
);
1482 json_object_object_add(json_group
, src_str
, json_row
);
1485 "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
1486 up
->rpf
.source_nexthop
.interface
1487 ? up
->rpf
.source_nexthop
.interface
->name
1489 &up
->sg
.src
, &up
->sg
.grp
, state_str
, uptime
,
1490 join_timer
, rs_timer
, ka_timer
, up
->ref_count
);
1493 /* Dump the generated table. */
1495 table
= ttable_dump(tt
, "\n");
1496 vty_out(vty
, "%s\n", table
);
1497 XFREE(MTYPE_TMP
, table
);
1502 static void pim_show_join_desired_helper(struct pim_instance
*pim
,
1504 struct pim_upstream
*up
,
1505 json_object
*json
, bool uj
,
1508 json_object
*json_group
= NULL
;
1509 json_object
*json_row
= NULL
;
1512 char grp_str
[PIM_ADDRSTRLEN
];
1513 char src_str
[PIM_ADDRSTRLEN
];
1515 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
1516 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &up
->sg
.src
);
1518 json_object_object_get_ex(json
, grp_str
, &json_group
);
1521 json_group
= json_object_new_object();
1522 json_object_object_add(json
, grp_str
, json_group
);
1525 json_row
= json_object_new_object();
1526 json_object_pim_upstream_add(json_row
, up
);
1527 json_object_string_add(json_row
, "source", src_str
);
1528 json_object_string_add(json_row
, "group", grp_str
);
1530 if (pim_upstream_evaluate_join_desired(pim
, up
))
1531 json_object_boolean_true_add(json_row
,
1532 "evaluateJoinDesired");
1534 json_object_object_add(json_group
, src_str
, json_row
);
1537 ttable_add_row(tt
, "%pPAs|%pPAs|%s", &up
->sg
.src
, &up
->sg
.grp
,
1538 pim_upstream_evaluate_join_desired(pim
, up
)
1544 void pim_show_join_desired(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1546 struct pim_upstream
*up
;
1547 struct ttable
*tt
= NULL
;
1550 json_object
*json
= NULL
;
1553 json
= json_object_new_object();
1555 /* Prepare table. */
1556 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1557 ttable_add_row(tt
, "Source|Group|EvalJD");
1558 tt
->style
.cell
.rpad
= 2;
1559 tt
->style
.corner
= '+';
1563 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1564 /* scan all interfaces */
1565 pim_show_join_desired_helper(pim
, vty
, up
, json
, uj
, tt
);
1569 vty_json(vty
, json
);
1571 /* Dump the generated table. */
1572 table
= ttable_dump(tt
, "\n");
1573 vty_out(vty
, "%s\n", table
);
1574 XFREE(MTYPE_TMP
, table
);
1579 void pim_show_upstream_rpf(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1581 struct pim_upstream
*up
;
1582 struct ttable
*tt
= NULL
;
1584 json_object
*json
= NULL
;
1585 json_object
*json_group
= NULL
;
1586 json_object
*json_row
= NULL
;
1589 json
= json_object_new_object();
1591 /* Prepare table. */
1592 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1594 "Source|Group|RpfIface|RibNextHop|RpfAddress");
1595 tt
->style
.cell
.rpad
= 2;
1596 tt
->style
.corner
= '+';
1600 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
1601 struct pim_rpf
*rpf
;
1602 const char *rpf_ifname
;
1607 rpf
->source_nexthop
.interface
? rpf
->source_nexthop
1612 char grp_str
[PIM_ADDRSTRLEN
];
1613 char src_str
[PIM_ADDRSTRLEN
];
1615 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
1617 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
1619 json_object_object_get_ex(json
, grp_str
, &json_group
);
1622 json_group
= json_object_new_object();
1623 json_object_object_add(json
, grp_str
,
1627 json_row
= json_object_new_object();
1628 json_object_pim_upstream_add(json_row
, up
);
1629 json_object_string_add(json_row
, "source", src_str
);
1630 json_object_string_add(json_row
, "group", grp_str
);
1631 json_object_string_add(json_row
, "rpfInterface",
1633 json_object_string_addf(
1634 json_row
, "ribNexthop", "%pPAs",
1635 &rpf
->source_nexthop
.mrib_nexthop_addr
);
1636 json_object_string_addf(json_row
, "rpfAddress", "%pPA",
1638 json_object_object_add(json_group
, src_str
, json_row
);
1640 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%pPA|%pPA",
1641 &up
->sg
.src
, &up
->sg
.grp
, rpf_ifname
,
1642 &rpf
->source_nexthop
.mrib_nexthop_addr
,
1648 vty_json(vty
, json
);
1650 /* Dump the generated table. */
1651 table
= ttable_dump(tt
, "\n");
1652 vty_out(vty
, "%s\n", table
);
1653 XFREE(MTYPE_TMP
, table
);
1658 static void pim_show_join_helper(struct pim_interface
*pim_ifp
,
1659 struct pim_ifchannel
*ch
, json_object
*json
,
1660 time_t now
, struct ttable
*tt
)
1662 json_object
*json_iface
= NULL
;
1663 json_object
*json_row
= NULL
;
1664 json_object
*json_grp
= NULL
;
1670 ifaddr
= pim_ifp
->primary_address
;
1672 pim_time_uptime_begin(uptime
, sizeof(uptime
), now
, ch
->ifjoin_creation
);
1673 pim_time_timer_to_mmss(expire
, sizeof(expire
),
1674 ch
->t_ifjoin_expiry_timer
);
1675 pim_time_timer_to_mmss(prune
, sizeof(prune
),
1676 ch
->t_ifjoin_prune_pending_timer
);
1679 char ch_grp_str
[PIM_ADDRSTRLEN
];
1681 json_object_object_get_ex(json
, ch
->interface
->name
,
1685 json_iface
= json_object_new_object();
1686 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1687 json_object_object_add(json
, ch
->interface
->name
,
1691 json_row
= json_object_new_object();
1692 json_object_string_addf(json_row
, "source", "%pPAs",
1694 json_object_string_addf(json_row
, "group", "%pPAs",
1696 json_object_string_add(json_row
, "upTime", uptime
);
1697 json_object_string_add(json_row
, "expire", expire
);
1698 json_object_string_add(json_row
, "prune", prune
);
1699 json_object_string_add(
1700 json_row
, "channelJoinName",
1701 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
));
1702 if (PIM_IF_FLAG_TEST_S_G_RPT(ch
->flags
)) {
1703 #if CONFDATE > 20230131
1705 "Remove JSON object commands with keys starting with capital")
1707 json_object_int_add(json_row
, "SGRpt", 1);
1708 json_object_int_add(json_row
, "sgRpt", 1);
1710 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch
->flags
))
1711 json_object_int_add(json_row
, "protocolPim", 1);
1712 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch
->flags
))
1713 json_object_int_add(json_row
, "protocolIgmp", 1);
1714 snprintfrr(ch_grp_str
, sizeof(ch_grp_str
), "%pPAs",
1716 json_object_object_get_ex(json_iface
, ch_grp_str
, &json_grp
);
1718 json_grp
= json_object_new_object();
1719 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1721 json_object_object_addf(json_iface
, json_grp
, "%pPAs",
1724 json_object_object_addf(json_grp
, json_row
, "%pPAs",
1728 tt
, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
1729 ch
->interface
->name
, &ifaddr
, &ch
->sg
.src
, &ch
->sg
.grp
,
1730 pim_ifchannel_ifjoin_name(ch
->ifjoin_state
, ch
->flags
),
1731 uptime
, expire
, prune
);
1735 int pim_show_join_cmd_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
1736 pim_addr g
, const char *json
)
1740 struct pim_instance
*pim
;
1741 json_object
*json_parent
= NULL
;
1743 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1746 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1752 vty_out(vty
, "%% Unable to find pim instance\n");
1756 if (!pim_addr_is_any(s_or_g
)) {
1757 if (!pim_addr_is_any(g
)) {
1765 json_parent
= json_object_new_object();
1767 pim_show_join(pim
, vty
, &sg
, json_parent
);
1770 vty_json(vty
, json_parent
);
1775 int pim_show_join_vrf_all_cmd_helper(struct vty
*vty
, const char *json
)
1777 pim_sgaddr sg
= {0};
1778 struct vrf
*vrf_struct
;
1779 json_object
*json_parent
= NULL
;
1780 json_object
*json_vrf
= NULL
;
1783 json_parent
= json_object_new_object();
1785 RB_FOREACH (vrf_struct
, vrf_name_head
, &vrfs_by_name
) {
1787 vty_out(vty
, "VRF: %s\n", vrf_struct
->name
);
1789 json_vrf
= json_object_new_object();
1790 pim_show_join(vrf_struct
->info
, vty
, &sg
, json_vrf
);
1793 json_object_object_add(json_parent
, vrf_struct
->name
,
1797 vty_json(vty
, json_parent
);
1802 void pim_show_join(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
1805 struct pim_interface
*pim_ifp
;
1806 struct pim_ifchannel
*ch
;
1807 struct interface
*ifp
;
1809 struct ttable
*tt
= NULL
;
1812 now
= pim_time_monotonic_sec();
1815 /* Prepare table. */
1816 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1819 "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
1820 tt
->style
.cell
.rpad
= 2;
1821 tt
->style
.corner
= '+';
1825 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1826 pim_ifp
= ifp
->info
;
1830 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1831 if (!pim_sgaddr_match(ch
->sg
, *sg
))
1834 pim_show_join_helper(pim_ifp
, ch
, json
, now
, tt
);
1835 } /* scan interface channels */
1837 /* Dump the generated table. */
1839 table
= ttable_dump(tt
, "\n");
1840 vty_out(vty
, "%s\n", table
);
1841 XFREE(MTYPE_TMP
, table
);
1846 static void pim_show_jp_agg_helper(struct interface
*ifp
,
1847 struct pim_neighbor
*neigh
,
1848 struct pim_upstream
*up
, int is_join
,
1851 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%pPAs|%s", ifp
->name
,
1852 &neigh
->source_addr
, &up
->sg
.src
, &up
->sg
.grp
,
1853 is_join
? "J" : "P");
1856 int pim_show_jp_agg_list_cmd_helper(const char *vrf
, struct vty
*vty
)
1859 struct pim_instance
*pim
;
1861 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1864 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
1870 vty_out(vty
, "%% Unable to find pim instance\n");
1874 pim_show_jp_agg_list(pim
, vty
);
1879 void pim_show_jp_agg_list(struct pim_instance
*pim
, struct vty
*vty
)
1881 struct interface
*ifp
;
1882 struct pim_interface
*pim_ifp
;
1883 struct listnode
*n_node
;
1884 struct pim_neighbor
*neigh
;
1885 struct listnode
*jag_node
;
1886 struct pim_jp_agg_group
*jag
;
1887 struct listnode
*js_node
;
1888 struct pim_jp_sources
*js
;
1892 /* Prepare table. */
1893 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1894 ttable_add_row(tt
, "Interface|RPF Nbr|Source|Group|State");
1895 tt
->style
.cell
.rpad
= 2;
1896 tt
->style
.corner
= '+';
1899 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1900 pim_ifp
= ifp
->info
;
1904 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, n_node
,
1906 for (ALL_LIST_ELEMENTS_RO(neigh
->upstream_jp_agg
,
1908 for (ALL_LIST_ELEMENTS_RO(jag
->sources
, js_node
,
1910 pim_show_jp_agg_helper(ifp
, neigh
,
1918 /* Dump the generated table. */
1919 table
= ttable_dump(tt
, "\n");
1920 vty_out(vty
, "%s\n", table
);
1921 XFREE(MTYPE_TMP
, table
);
1925 int pim_show_membership_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
1929 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
1934 pim_show_membership(v
->info
, vty
, uj
);
1939 static void pim_show_membership_helper(struct vty
*vty
,
1940 struct pim_interface
*pim_ifp
,
1941 struct pim_ifchannel
*ch
,
1942 struct json_object
*json
)
1944 json_object
*json_iface
= NULL
;
1945 json_object
*json_row
= NULL
;
1947 json_object_object_get_ex(json
, ch
->interface
->name
, &json_iface
);
1949 json_iface
= json_object_new_object();
1950 json_object_pim_ifp_add(json_iface
, ch
->interface
);
1951 json_object_object_add(json
, ch
->interface
->name
, json_iface
);
1954 json_row
= json_object_new_object();
1955 json_object_string_addf(json_row
, "source", "%pPAs", &ch
->sg
.src
);
1956 json_object_string_addf(json_row
, "group", "%pPAs", &ch
->sg
.grp
);
1957 json_object_string_add(json_row
, "localMembership",
1958 ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
1961 json_object_object_addf(json_iface
, json_row
, "%pPAs", &ch
->sg
.grp
);
1964 void pim_show_membership(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
1966 struct pim_interface
*pim_ifp
;
1967 struct pim_ifchannel
*ch
;
1968 struct interface
*ifp
;
1969 enum json_type type
;
1970 json_object
*json
= NULL
;
1971 json_object
*json_tmp
= NULL
;
1972 struct ttable
*tt
= NULL
;
1975 json
= json_object_new_object();
1977 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1978 pim_ifp
= ifp
->info
;
1982 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1983 pim_show_membership_helper(vty
, pim_ifp
, ch
, json
);
1984 } /* scan interface channels */
1988 vty_json(vty
, json
);
1990 /* Prepare table. */
1991 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
1992 ttable_add_row(tt
, "Interface|Address|Source|Group|Membership");
1993 tt
->style
.cell
.rpad
= 2;
1994 tt
->style
.corner
= '+';
1998 * Example of the json data we are traversing
2004 * "address":"10.1.20.1",
2006 * "flagMulticast":true,
2007 * "flagBroadcast":true,
2008 * "lanDelayEnabled":true,
2011 * "group":"226.10.10.10",
2012 * "localMembership":"INCLUDE"
2018 /* foreach interface */
2019 json_object_object_foreach(json
, key
, val
)
2022 /* Find all of the keys where the val is an object. In
2024 * above the only one is 226.10.10.10
2026 json_object_object_foreach(val
, if_field_key
,
2029 type
= json_object_get_type(if_field_val
);
2031 if (type
== json_type_object
) {
2032 const char *address
, *source
,
2035 json_object_object_get_ex(
2036 val
, "address", &json_tmp
);
2037 address
= json_object_get_string(
2040 json_object_object_get_ex(if_field_val
,
2043 source
= json_object_get_string(
2046 json_object_object_get_ex(
2047 if_field_val
, "localMembership",
2050 json_object_get_string(
2053 ttable_add_row(tt
, "%s|%s|%s|%s|%s",
2054 key
, address
, source
,
2060 json_object_free(json
);
2061 /* Dump the generated table. */
2062 table
= ttable_dump(tt
, "\n");
2063 vty_out(vty
, "%s\n", table
);
2064 XFREE(MTYPE_TMP
, table
);
2069 static void pim_show_channel_helper(struct pim_instance
*pim
,
2070 struct pim_interface
*pim_ifp
,
2071 struct pim_ifchannel
*ch
, json_object
*json
,
2072 bool uj
, struct ttable
*tt
)
2074 struct pim_upstream
*up
= ch
->upstream
;
2075 json_object
*json_group
= NULL
;
2076 json_object
*json_row
= NULL
;
2079 char grp_str
[PIM_ADDRSTRLEN
];
2081 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &up
->sg
.grp
);
2082 json_object_object_get_ex(json
, grp_str
, &json_group
);
2085 json_group
= json_object_new_object();
2086 json_object_object_add(json
, grp_str
, json_group
);
2089 json_row
= json_object_new_object();
2090 json_object_pim_upstream_add(json_row
, up
);
2091 json_object_string_add(json_row
, "interface",
2092 ch
->interface
->name
);
2093 json_object_string_addf(json_row
, "source", "%pPAs",
2095 json_object_string_addf(json_row
, "group", "%pPAs",
2098 if (pim_macro_ch_lost_assert(ch
))
2099 json_object_boolean_true_add(json_row
, "lostAssert");
2101 if (pim_macro_chisin_joins(ch
))
2102 json_object_boolean_true_add(json_row
, "joins");
2104 if (pim_macro_chisin_pim_include(ch
))
2105 json_object_boolean_true_add(json_row
, "pimInclude");
2107 if (pim_upstream_evaluate_join_desired(pim
, up
))
2108 json_object_boolean_true_add(json_row
,
2109 "evaluateJoinDesired");
2111 json_object_object_addf(json_group
, json_row
, "%pPAs",
2115 ttable_add_row(tt
, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
2116 ch
->interface
->name
, &up
->sg
.src
, &up
->sg
.grp
,
2117 pim_macro_ch_lost_assert(ch
) ? "yes" : "no",
2118 pim_macro_chisin_joins(ch
) ? "yes" : "no",
2119 pim_macro_chisin_pim_include(ch
) ? "yes" : "no",
2120 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up
->flags
)
2123 pim_upstream_evaluate_join_desired(pim
, up
)
2129 void pim_show_channel(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2131 struct pim_interface
*pim_ifp
;
2132 struct pim_ifchannel
*ch
;
2133 struct interface
*ifp
;
2134 struct ttable
*tt
= NULL
;
2135 json_object
*json
= NULL
;
2139 json
= json_object_new_object();
2141 /* Prepare table. */
2142 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2145 "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
2146 tt
->style
.cell
.rpad
= 2;
2147 tt
->style
.corner
= '+';
2151 /* scan per-interface (S,G) state */
2152 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2153 pim_ifp
= ifp
->info
;
2157 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
2158 /* scan all interfaces */
2159 pim_show_channel_helper(pim
, pim_ifp
, ch
, json
, uj
, tt
);
2164 vty_json(vty
, json
);
2166 /* Dump the generated table. */
2167 table
= ttable_dump(tt
, "\n");
2168 vty_out(vty
, "%s\n", table
);
2169 XFREE(MTYPE_TMP
, table
);
2174 int pim_show_channel_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2178 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2183 pim_show_channel(v
->info
, vty
, uj
);
2188 int pim_show_interface_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
,
2189 bool mlag
, const char *interface
)
2192 json_object
*json_parent
= NULL
;
2194 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2200 json_parent
= json_object_new_object();
2203 pim_show_interfaces_single(v
->info
, vty
, interface
, mlag
,
2206 pim_show_interfaces(v
->info
, vty
, mlag
, json_parent
);
2209 vty_json(vty
, json_parent
);
2214 int pim_show_interface_vrf_all_cmd_helper(struct vty
*vty
, bool uj
, bool mlag
,
2215 const char *interface
)
2218 json_object
*json_parent
= NULL
;
2219 json_object
*json_vrf
= NULL
;
2222 json_parent
= json_object_new_object();
2224 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
2226 vty_out(vty
, "VRF: %s\n", v
->name
);
2228 json_vrf
= json_object_new_object();
2231 pim_show_interfaces_single(v
->info
, vty
, interface
,
2234 pim_show_interfaces(v
->info
, vty
, mlag
, json_vrf
);
2237 json_object_object_add(json_parent
, v
->name
, json_vrf
);
2240 vty_json(vty
, json_parent
);
2245 void pim_show_interfaces(struct pim_instance
*pim
, struct vty
*vty
, bool mlag
,
2248 struct interface
*ifp
;
2249 struct pim_interface
*pim_ifp
;
2250 struct pim_upstream
*up
;
2253 int pim_ifchannels
= 0;
2255 struct ttable
*tt
= NULL
;
2257 json_object
*json_row
= NULL
;
2258 json_object
*json_tmp
;
2262 json
= json_object_new_object();
2265 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2266 pim_ifp
= ifp
->info
;
2271 if (mlag
== true && pim_ifp
->activeactive
== false)
2274 pim_nbrs
= pim_ifp
->pim_neighbor_list
->count
;
2275 pim_ifchannels
= pim_if_ifchannel_count(pim_ifp
);
2278 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
)
2279 if (ifp
== up
->rpf
.source_nexthop
.interface
)
2280 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
)
2283 json_row
= json_object_new_object();
2284 json_object_pim_ifp_add(json_row
, ifp
);
2285 json_object_int_add(json_row
, "pimNeighbors", pim_nbrs
);
2286 json_object_int_add(json_row
, "pimIfChannels", pim_ifchannels
);
2287 json_object_int_add(json_row
, "firstHopRouterCount", fhr
);
2288 json_object_string_addf(json_row
, "pimDesignatedRouter",
2289 "%pPAs", &pim_ifp
->pim_dr_addr
);
2291 if (!pim_addr_cmp(pim_ifp
->pim_dr_addr
,
2292 pim_ifp
->primary_address
))
2293 json_object_boolean_true_add(
2294 json_row
, "pimDesignatedRouterLocal");
2296 json_object_object_add(json
, ifp
->name
, json_row
);
2301 /* Prepare table. */
2302 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
2305 "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
2306 tt
->style
.cell
.rpad
= 2;
2307 tt
->style
.corner
= '+';
2310 json_object_object_foreach(json
, key
, val
)
2312 const char *state
, *address
, *pimdr
;
2313 int neighbors
, firsthpr
, pimifchnl
;
2315 json_object_object_get_ex(val
, "state", &json_tmp
);
2316 state
= json_object_get_string(json_tmp
);
2318 json_object_object_get_ex(val
, "address", &json_tmp
);
2319 address
= json_object_get_string(json_tmp
);
2321 json_object_object_get_ex(val
, "pimNeighbors",
2323 neighbors
= json_object_get_int(json_tmp
);
2325 if (json_object_object_get_ex(
2326 val
, "pimDesignatedRouterLocal",
2330 json_object_object_get_ex(
2331 val
, "pimDesignatedRouter", &json_tmp
);
2332 pimdr
= json_object_get_string(json_tmp
);
2335 json_object_object_get_ex(val
, "firstHopRouter",
2337 firsthpr
= json_object_get_int(json_tmp
);
2339 json_object_object_get_ex(val
, "pimIfChannels",
2341 pimifchnl
= json_object_get_int(json_tmp
);
2343 ttable_add_row(tt
, "%s|%s|%s|%d|%s|%d|%d", key
, state
,
2344 address
, neighbors
, pimdr
, firsthpr
,
2347 json_object_free(json
);
2349 /* Dump the generated table. */
2350 table
= ttable_dump(tt
, "\n");
2351 vty_out(vty
, "%s\n", table
);
2352 XFREE(MTYPE_TMP
, table
);
2358 void pim_show_interfaces_single(struct pim_instance
*pim
, struct vty
*vty
,
2359 const char *ifname
, bool mlag
,
2363 struct interface
*ifp
;
2364 struct listnode
*neighnode
;
2365 struct pim_interface
*pim_ifp
;
2366 struct pim_neighbor
*neigh
;
2367 struct pim_upstream
*up
;
2369 char dr_str
[PIM_ADDRSTRLEN
];
2372 char grp_str
[PIM_ADDRSTRLEN
];
2373 char hello_period
[10];
2374 char hello_timer
[10];
2375 char neigh_src_str
[PIM_ADDRSTRLEN
];
2376 char src_str
[PIM_ADDRSTRLEN
];
2377 char stat_uptime
[10];
2379 int found_ifname
= 0;
2381 json_object
*json_row
= NULL
;
2382 json_object
*json_pim_neighbor
= NULL
;
2383 json_object
*json_pim_neighbors
= NULL
;
2384 json_object
*json_group
= NULL
;
2385 json_object
*json_group_source
= NULL
;
2386 json_object
*json_fhr_sources
= NULL
;
2387 struct pim_secondary_addr
*sec_addr
;
2388 struct listnode
*sec_node
;
2390 now
= pim_time_monotonic_sec();
2392 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
2393 pim_ifp
= ifp
->info
;
2398 if (mlag
== true && pim_ifp
->activeactive
== false)
2401 if (strcmp(ifname
, "detail") && strcmp(ifname
, ifp
->name
))
2405 ifaddr
= pim_ifp
->primary_address
;
2406 snprintfrr(dr_str
, sizeof(dr_str
), "%pPAs",
2407 &pim_ifp
->pim_dr_addr
);
2408 pim_time_uptime_begin(dr_uptime
, sizeof(dr_uptime
), now
,
2409 pim_ifp
->pim_dr_election_last
);
2410 pim_time_timer_to_hhmmss(hello_timer
, sizeof(hello_timer
),
2411 pim_ifp
->t_pim_hello_timer
);
2412 pim_time_mmss(hello_period
, sizeof(hello_period
),
2413 pim_ifp
->pim_hello_period
);
2414 pim_time_uptime(stat_uptime
, sizeof(stat_uptime
),
2415 now
- pim_ifp
->pim_ifstat_start
);
2418 json_row
= json_object_new_object();
2419 json_object_pim_ifp_add(json_row
, ifp
);
2421 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2422 json_object_string_addf(
2423 json_row
, "useSource", "%pPAs",
2424 &pim_ifp
->update_source
);
2426 if (pim_ifp
->sec_addr_list
) {
2427 json_object
*sec_list
= NULL
;
2429 sec_list
= json_object_new_array();
2430 for (ALL_LIST_ELEMENTS_RO(
2431 pim_ifp
->sec_addr_list
, sec_node
,
2433 json_object_array_add(
2435 json_object_new_stringf(
2439 json_object_object_add(json_row
,
2440 "secondaryAddressList",
2444 if (pim_ifp
->pim_passive_enable
)
2445 json_object_boolean_true_add(json_row
,
2449 if (pim_ifp
->pim_neighbor_list
->count
) {
2450 json_pim_neighbors
= json_object_new_object();
2452 for (ALL_LIST_ELEMENTS_RO(
2453 pim_ifp
->pim_neighbor_list
,
2454 neighnode
, neigh
)) {
2456 json_object_new_object();
2457 snprintfrr(neigh_src_str
,
2458 sizeof(neigh_src_str
),
2460 &neigh
->source_addr
);
2461 pim_time_uptime(uptime
, sizeof(uptime
),
2462 now
- neigh
->creation
);
2463 pim_time_timer_to_hhmmss(
2464 expire
, sizeof(expire
),
2465 neigh
->t_expire_timer
);
2467 json_object_string_add(
2468 json_pim_neighbor
, "address",
2470 json_object_string_add(
2471 json_pim_neighbor
, "upTime",
2473 json_object_string_add(
2474 json_pim_neighbor
, "holdtime",
2477 json_object_object_add(
2483 json_object_object_add(json_row
, "neighbors",
2484 json_pim_neighbors
);
2487 json_object_string_add(json_row
, "drAddress", dr_str
);
2488 json_object_int_add(json_row
, "drPriority",
2489 pim_ifp
->pim_dr_priority
);
2490 json_object_string_add(json_row
, "drUptime", dr_uptime
);
2491 json_object_int_add(json_row
, "drElections",
2492 pim_ifp
->pim_dr_election_count
);
2493 json_object_int_add(json_row
, "drChanges",
2494 pim_ifp
->pim_dr_election_changes
);
2497 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2498 if (ifp
!= up
->rpf
.source_nexthop
.interface
)
2501 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2504 if (!json_fhr_sources
)
2506 json_object_new_object();
2508 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
2510 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
2512 pim_time_uptime(uptime
, sizeof(uptime
),
2513 now
- up
->state_transition
);
2516 * Does this group live in json_fhr_sources?
2519 json_object_object_get_ex(json_fhr_sources
,
2520 grp_str
, &json_group
);
2523 json_group
= json_object_new_object();
2524 json_object_object_add(json_fhr_sources
,
2529 json_group_source
= json_object_new_object();
2530 json_object_string_add(json_group_source
,
2532 json_object_string_add(json_group_source
,
2534 json_object_string_add(json_group_source
,
2536 json_object_object_add(json_group
, src_str
,
2540 if (json_fhr_sources
) {
2541 json_object_object_add(json_row
,
2546 json_object_int_add(json_row
, "helloPeriod",
2547 pim_ifp
->pim_hello_period
);
2548 json_object_int_add(json_row
, "holdTime",
2549 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2550 json_object_string_add(json_row
, "helloTimer",
2552 json_object_string_add(json_row
, "helloStatStart",
2554 json_object_int_add(json_row
, "helloReceived",
2555 pim_ifp
->pim_ifstat_hello_recv
);
2556 json_object_int_add(json_row
, "helloReceivedFailed",
2557 pim_ifp
->pim_ifstat_hello_recvfail
);
2558 json_object_int_add(json_row
, "helloSend",
2559 pim_ifp
->pim_ifstat_hello_sent
);
2560 json_object_int_add(json_row
, "hellosendFailed",
2561 pim_ifp
->pim_ifstat_hello_sendfail
);
2562 json_object_int_add(json_row
, "helloGenerationId",
2563 pim_ifp
->pim_generation_id
);
2565 json_object_int_add(
2566 json_row
, "effectivePropagationDelay",
2567 pim_if_effective_propagation_delay_msec(ifp
));
2568 json_object_int_add(
2569 json_row
, "effectiveOverrideInterval",
2570 pim_if_effective_override_interval_msec(ifp
));
2571 json_object_int_add(
2572 json_row
, "joinPruneOverrideInterval",
2573 pim_if_jp_override_interval_msec(ifp
));
2575 json_object_int_add(
2576 json_row
, "propagationDelay",
2577 pim_ifp
->pim_propagation_delay_msec
);
2578 json_object_int_add(
2579 json_row
, "propagationDelayHighest",
2580 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2581 json_object_int_add(
2582 json_row
, "overrideInterval",
2583 pim_ifp
->pim_override_interval_msec
);
2584 json_object_int_add(
2585 json_row
, "overrideIntervalHighest",
2586 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2587 if (pim_ifp
->bsm_enable
)
2588 json_object_boolean_true_add(json_row
,
2590 if (pim_ifp
->ucast_bsm_accept
)
2591 json_object_boolean_true_add(json_row
,
2593 json_object_object_add(json
, ifp
->name
, json_row
);
2596 vty_out(vty
, "Interface : %s\n", ifp
->name
);
2597 vty_out(vty
, "State : %s\n",
2598 if_is_up(ifp
) ? "up" : "down");
2599 if (!pim_addr_is_any(pim_ifp
->update_source
)) {
2600 vty_out(vty
, "Use Source : %pPAs\n",
2601 &pim_ifp
->update_source
);
2603 if (pim_ifp
->sec_addr_list
) {
2604 vty_out(vty
, "Address : %pPAs (primary)\n",
2606 for (ALL_LIST_ELEMENTS_RO(
2607 pim_ifp
->sec_addr_list
, sec_node
,
2609 vty_out(vty
, " %pFX\n",
2612 vty_out(vty
, "Address : %pPAs\n", &ifaddr
);
2615 if (pim_ifp
->pim_passive_enable
)
2616 vty_out(vty
, "Passive : %s\n",
2617 (pim_ifp
->pim_passive_enable
) ? "yes"
2625 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
2626 neighnode
, neigh
)) {
2629 vty_out(vty
, "PIM Neighbors\n");
2630 vty_out(vty
, "-------------\n");
2634 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
2635 "%pPAs", &neigh
->source_addr
);
2636 pim_time_uptime(uptime
, sizeof(uptime
),
2637 now
- neigh
->creation
);
2638 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
2639 neigh
->t_expire_timer
);
2641 "%-15s : up for %s, holdtime expires in %s\n",
2642 neigh_src_str
, uptime
, expire
);
2645 if (!print_header
) {
2650 vty_out(vty
, "Designated Router\n");
2651 vty_out(vty
, "-----------------\n");
2652 vty_out(vty
, "Address : %s\n", dr_str
);
2653 vty_out(vty
, "Priority : %u(%d)\n",
2654 pim_ifp
->pim_dr_priority
,
2655 pim_ifp
->pim_dr_num_nondrpri_neighbors
);
2656 vty_out(vty
, "Uptime : %s\n", dr_uptime
);
2657 vty_out(vty
, "Elections : %d\n",
2658 pim_ifp
->pim_dr_election_count
);
2659 vty_out(vty
, "Changes : %d\n",
2660 pim_ifp
->pim_dr_election_changes
);
2666 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
2667 if (!up
->rpf
.source_nexthop
.interface
)
2670 if (strcmp(ifp
->name
,
2671 up
->rpf
.source_nexthop
2672 .interface
->name
) != 0)
2675 if (!(up
->flags
& PIM_UPSTREAM_FLAG_MASK_FHR
))
2680 "FHR - First Hop Router\n");
2682 "----------------------\n");
2686 pim_time_uptime(uptime
, sizeof(uptime
),
2687 now
- up
->state_transition
);
2689 "%pPAs : %pPAs is a source, uptime is %s\n",
2690 &up
->sg
.grp
, &up
->sg
.src
, uptime
);
2693 if (!print_header
) {
2698 vty_out(vty
, "Hellos\n");
2699 vty_out(vty
, "------\n");
2700 vty_out(vty
, "Period : %d\n",
2701 pim_ifp
->pim_hello_period
);
2702 vty_out(vty
, "HoldTime : %d\n",
2703 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
2704 vty_out(vty
, "Timer : %s\n", hello_timer
);
2705 vty_out(vty
, "StatStart : %s\n", stat_uptime
);
2706 vty_out(vty
, "Receive : %d\n",
2707 pim_ifp
->pim_ifstat_hello_recv
);
2708 vty_out(vty
, "Receive Failed : %d\n",
2709 pim_ifp
->pim_ifstat_hello_recvfail
);
2710 vty_out(vty
, "Send : %d\n",
2711 pim_ifp
->pim_ifstat_hello_sent
);
2712 vty_out(vty
, "Send Failed : %d\n",
2713 pim_ifp
->pim_ifstat_hello_sendfail
);
2714 vty_out(vty
, "Generation ID : %08x\n",
2715 pim_ifp
->pim_generation_id
);
2719 pim_print_ifp_flags(vty
, ifp
);
2721 vty_out(vty
, "Join Prune Interval\n");
2722 vty_out(vty
, "-------------------\n");
2723 vty_out(vty
, "LAN Delay : %s\n",
2724 pim_if_lan_delay_enabled(ifp
) ? "yes" : "no");
2725 vty_out(vty
, "Effective Propagation Delay : %d msec\n",
2726 pim_if_effective_propagation_delay_msec(ifp
));
2727 vty_out(vty
, "Effective Override Interval : %d msec\n",
2728 pim_if_effective_override_interval_msec(ifp
));
2729 vty_out(vty
, "Join Prune Override Interval : %d msec\n",
2730 pim_if_jp_override_interval_msec(ifp
));
2734 vty_out(vty
, "LAN Prune Delay\n");
2735 vty_out(vty
, "---------------\n");
2736 vty_out(vty
, "Propagation Delay : %d msec\n",
2737 pim_ifp
->pim_propagation_delay_msec
);
2738 vty_out(vty
, "Propagation Delay (Highest) : %d msec\n",
2739 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
2740 vty_out(vty
, "Override Interval : %d msec\n",
2741 pim_ifp
->pim_override_interval_msec
);
2742 vty_out(vty
, "Override Interval (Highest) : %d msec\n",
2743 pim_ifp
->pim_neighbors_highest_override_interval_msec
);
2747 vty_out(vty
, "BSM Status\n");
2748 vty_out(vty
, "----------\n");
2749 vty_out(vty
, "Bsm Enabled : %s\n",
2750 pim_ifp
->bsm_enable
? "yes" : "no");
2751 vty_out(vty
, "Unicast Bsm Enabled : %s\n",
2752 pim_ifp
->ucast_bsm_accept
? "yes" : "no");
2759 vty_out(vty
, "%% No such interface\n");
2762 void ip_pim_ssm_show_group_range(struct pim_instance
*pim
, struct vty
*vty
,
2765 struct pim_ssm
*ssm
= pim
->ssm_info
;
2766 const char *range_str
=
2767 ssm
->plist_name
? ssm
->plist_name
: PIM_SSM_STANDARD_RANGE
;
2772 json
= json_object_new_object();
2773 json_object_string_add(json
, "ssmGroups", range_str
);
2774 vty_json(vty
, json
);
2776 vty_out(vty
, "SSM group range : %s\n", range_str
);
2779 struct vty_pnc_cache_walk_data
{
2781 struct pim_instance
*pim
;
2784 struct json_pnc_cache_walk_data
{
2785 json_object
*json_obj
;
2786 struct pim_instance
*pim
;
2789 static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket
*bucket
, void *arg
)
2791 struct pim_nexthop_cache
*pnc
= bucket
->data
;
2792 struct vty_pnc_cache_walk_data
*cwd
= arg
;
2793 struct vty
*vty
= cwd
->vty
;
2794 struct pim_instance
*pim
= cwd
->pim
;
2795 struct nexthop
*nh_node
= NULL
;
2796 ifindex_t first_ifindex
;
2797 struct interface
*ifp
= NULL
;
2799 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2800 first_ifindex
= nh_node
->ifindex
;
2802 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2804 vty_out(vty
, "%-15pPA ", &pnc
->rpf
.rpf_addr
);
2805 vty_out(vty
, "%-16s ", ifp
? ifp
->name
: "NULL");
2807 vty_out(vty
, "%pI4 ", &nh_node
->gate
.ipv4
);
2809 vty_out(vty
, "%pI6 ", &nh_node
->gate
.ipv6
);
2816 static int pim_print_json_pnc_cache_walkcb(struct hash_bucket
*backet
,
2819 struct pim_nexthop_cache
*pnc
= backet
->data
;
2820 struct json_pnc_cache_walk_data
*cwd
= arg
;
2821 struct pim_instance
*pim
= cwd
->pim
;
2822 struct nexthop
*nh_node
= NULL
;
2823 ifindex_t first_ifindex
;
2824 struct interface
*ifp
= NULL
;
2825 char addr_str
[PIM_ADDRSTRLEN
];
2826 json_object
*json_row
= NULL
;
2827 json_object
*json_ifp
= NULL
;
2828 json_object
*json_arr
= NULL
;
2830 for (nh_node
= pnc
->nexthop
; nh_node
; nh_node
= nh_node
->next
) {
2831 first_ifindex
= nh_node
->ifindex
;
2832 ifp
= if_lookup_by_index(first_ifindex
, pim
->vrf
->vrf_id
);
2833 snprintfrr(addr_str
, sizeof(addr_str
), "%pPA",
2834 &pnc
->rpf
.rpf_addr
);
2835 json_object_object_get_ex(cwd
->json_obj
, addr_str
, &json_row
);
2837 json_row
= json_object_new_object();
2838 json_object_string_addf(json_row
, "address", "%pPA",
2839 &pnc
->rpf
.rpf_addr
);
2840 json_object_object_addf(cwd
->json_obj
, json_row
, "%pPA",
2841 &pnc
->rpf
.rpf_addr
);
2842 json_arr
= json_object_new_array();
2843 json_object_object_add(json_row
, "nexthops", json_arr
);
2845 json_ifp
= json_object_new_object();
2846 json_object_string_add(json_ifp
, "interface",
2847 ifp
? ifp
->name
: "NULL");
2849 json_object_string_addf(json_ifp
, "nexthop", "%pI4",
2850 &nh_node
->gate
.ipv4
);
2852 json_object_string_addf(json_ifp
, "nexthop", "%pI6",
2853 &nh_node
->gate
.ipv6
);
2855 json_object_array_add(json_arr
, json_ifp
);
2860 int pim_show_nexthop_lookup_cmd_helper(const char *vrf
, struct vty
*vty
,
2861 pim_addr source
, pim_addr group
)
2864 pim_addr vif_source
;
2866 struct pim_nexthop nexthop
;
2868 char grp_str
[PREFIX_STRLEN
];
2870 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2876 if (pim_is_group_224_4(source
)) {
2878 "Invalid argument. Expected Valid Source Address.\n");
2882 if (!pim_is_group_224_4(group
)) {
2884 "Invalid argument. Expected Valid Multicast Group Address.\n");
2889 if (!pim_rp_set_upstream_addr(v
->info
, &vif_source
, source
, group
))
2892 pim_addr_to_prefix(&grp
, group
);
2893 memset(&nexthop
, 0, sizeof(nexthop
));
2896 pim_ecmp_nexthop_lookup(v
->info
, &nexthop
, vif_source
, &grp
, 0);
2900 "Nexthop Lookup failed, no usable routes returned.\n");
2904 pim_addr_dump("<grp?>", &grp
, grp_str
, sizeof(grp_str
));
2906 vty_out(vty
, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str
,
2907 &nexthop
.mrib_nexthop_addr
, nexthop
.interface
->name
);
2912 int pim_show_nexthop_cmd_helper(const char *vrf
, struct vty
*vty
, bool uj
)
2916 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2921 pim_show_nexthop(v
->info
, vty
, uj
);
2926 void pim_show_nexthop(struct pim_instance
*pim
, struct vty
*vty
, bool uj
)
2928 struct vty_pnc_cache_walk_data cwd
;
2929 struct json_pnc_cache_walk_data jcwd
;
2936 jcwd
.json_obj
= json_object_new_object();
2938 vty_out(vty
, "Number of registered addresses: %lu\n",
2939 pim
->rpf_hash
->count
);
2940 vty_out(vty
, "Address Interface Nexthop\n");
2941 vty_out(vty
, "---------------------------------------------\n");
2945 hash_walk(pim
->rpf_hash
, pim_print_json_pnc_cache_walkcb
,
2947 vty_json(vty
, jcwd
.json_obj
);
2949 hash_walk(pim
->rpf_hash
, pim_print_vty_pnc_cache_walkcb
, &cwd
);
2952 int pim_show_neighbors_cmd_helper(const char *vrf
, struct vty
*vty
,
2953 const char *json
, const char *interface
)
2956 json_object
*json_parent
= NULL
;
2958 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
2964 json_parent
= json_object_new_object();
2967 pim_show_neighbors_single(v
->info
, vty
, interface
, json_parent
);
2969 pim_show_neighbors(v
->info
, vty
, json_parent
);
2972 vty_json(vty
, json_parent
);
2977 int pim_show_neighbors_vrf_all_cmd_helper(struct vty
*vty
, const char *json
,
2978 const char *interface
)
2981 json_object
*json_parent
= NULL
;
2982 json_object
*json_vrf
= NULL
;
2985 json_parent
= json_object_new_object();
2986 RB_FOREACH (v
, vrf_name_head
, &vrfs_by_name
) {
2988 vty_out(vty
, "VRF: %s\n", v
->name
);
2990 json_vrf
= json_object_new_object();
2993 pim_show_neighbors_single(v
->info
, vty
, interface
,
2996 pim_show_neighbors(v
->info
, vty
, json_vrf
);
2999 json_object_object_add(json_parent
, v
->name
, json_vrf
);
3002 vty_json(vty
, json_parent
);
3007 void pim_show_neighbors_single(struct pim_instance
*pim
, struct vty
*vty
,
3008 const char *neighbor
, json_object
*json
)
3010 struct listnode
*neighnode
;
3011 struct interface
*ifp
;
3012 struct pim_interface
*pim_ifp
;
3013 struct pim_neighbor
*neigh
;
3015 int found_neighbor
= 0;
3016 int option_address_list
;
3017 int option_dr_priority
;
3018 int option_generation_id
;
3019 int option_holdtime
;
3020 int option_lan_prune_delay
;
3024 char neigh_src_str
[PIM_ADDRSTRLEN
];
3026 json_object
*json_ifp
= NULL
;
3027 json_object
*json_row
= NULL
;
3029 now
= pim_time_monotonic_sec();
3031 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3032 pim_ifp
= ifp
->info
;
3037 if (pim_ifp
->pim_sock_fd
< 0)
3040 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3042 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3043 "%pPAs", &neigh
->source_addr
);
3046 * The user can specify either the interface name or the
3048 * If this pim_ifp matches neither then skip.
3050 if (strcmp(neighbor
, "detail") &&
3051 strcmp(neighbor
, ifp
->name
) &&
3052 strcmp(neighbor
, neigh_src_str
))
3056 pim_time_uptime(uptime
, sizeof(uptime
),
3057 now
- neigh
->creation
);
3058 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3059 neigh
->t_expire_timer
);
3061 option_address_list
= 0;
3062 option_dr_priority
= 0;
3063 option_generation_id
= 0;
3064 option_holdtime
= 0;
3065 option_lan_prune_delay
= 0;
3068 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3069 PIM_OPTION_MASK_ADDRESS_LIST
))
3070 option_address_list
= 1;
3072 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3073 PIM_OPTION_MASK_DR_PRIORITY
))
3074 option_dr_priority
= 1;
3076 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3077 PIM_OPTION_MASK_GENERATION_ID
))
3078 option_generation_id
= 1;
3080 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3081 PIM_OPTION_MASK_HOLDTIME
))
3082 option_holdtime
= 1;
3084 if (PIM_OPTION_IS_SET(neigh
->hello_options
,
3085 PIM_OPTION_MASK_LAN_PRUNE_DELAY
))
3086 option_lan_prune_delay
= 1;
3088 if (PIM_OPTION_IS_SET(
3089 neigh
->hello_options
,
3090 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION
))
3095 /* Does this ifp live in json? If not create it
3097 json_object_object_get_ex(json
, ifp
->name
,
3101 json_ifp
= json_object_new_object();
3102 json_object_pim_ifp_add(json_ifp
, ifp
);
3103 json_object_object_add(json
, ifp
->name
,
3107 json_row
= json_object_new_object();
3108 json_object_string_add(json_row
, "interface",
3110 json_object_string_add(json_row
, "address",
3112 json_object_string_add(json_row
, "upTime",
3114 json_object_string_add(json_row
, "holdtime",
3116 json_object_int_add(json_row
, "drPriority",
3117 neigh
->dr_priority
);
3118 json_object_int_add(json_row
, "generationId",
3119 neigh
->generation_id
);
3121 if (option_address_list
)
3122 json_object_boolean_true_add(
3124 "helloOptionAddressList");
3126 if (option_dr_priority
)
3127 json_object_boolean_true_add(
3129 "helloOptionDrPriority");
3131 if (option_generation_id
)
3132 json_object_boolean_true_add(
3134 "helloOptionGenerationId");
3136 if (option_holdtime
)
3137 json_object_boolean_true_add(
3139 "helloOptionHoldtime");
3141 if (option_lan_prune_delay
)
3142 json_object_boolean_true_add(
3144 "helloOptionLanPruneDelay");
3147 json_object_boolean_true_add(
3148 json_row
, "helloOptionTBit");
3150 json_object_object_add(json_ifp
, neigh_src_str
,
3154 vty_out(vty
, "Interface : %s\n", ifp
->name
);
3155 vty_out(vty
, "Neighbor : %s\n", neigh_src_str
);
3163 " DR Priority : %d\n",
3164 neigh
->dr_priority
);
3166 " Generation ID : %08x\n",
3167 neigh
->generation_id
);
3169 " Override Interval (msec) : %d\n",
3170 neigh
->override_interval_msec
);
3172 " Propagation Delay (msec) : %d\n",
3173 neigh
->propagation_delay_msec
);
3175 " Hello Option - Address List : %s\n",
3176 option_address_list
? "yes" : "no");
3178 " Hello Option - DR Priority : %s\n",
3179 option_dr_priority
? "yes" : "no");
3181 " Hello Option - Generation ID : %s\n",
3182 option_generation_id
? "yes" : "no");
3184 " Hello Option - Holdtime : %s\n",
3185 option_holdtime
? "yes" : "no");
3187 " Hello Option - LAN Prune Delay : %s\n",
3188 option_lan_prune_delay
? "yes" : "no");
3190 " Hello Option - T-bit : %s\n",
3191 option_t_bit
? "yes" : "no");
3192 bfd_sess_show(vty
, json_ifp
,
3193 neigh
->bfd_session
);
3199 if (!found_neighbor
)
3200 vty_out(vty
, "%% No such interface or neighbor\n");
3203 void pim_show_neighbors(struct pim_instance
*pim
, struct vty
*vty
,
3206 struct listnode
*neighnode
;
3207 struct interface
*ifp
;
3208 struct pim_interface
*pim_ifp
;
3209 struct pim_neighbor
*neigh
;
3210 struct ttable
*tt
= NULL
;
3215 char neigh_src_str
[PIM_ADDRSTRLEN
];
3216 json_object
*json_ifp_rows
= NULL
;
3217 json_object
*json_row
= NULL
;
3219 now
= pim_time_monotonic_sec();
3222 /* Prepare table. */
3223 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3224 ttable_add_row(tt
, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
3225 tt
->style
.cell
.rpad
= 2;
3226 tt
->style
.corner
= '+';
3230 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3231 pim_ifp
= ifp
->info
;
3236 if (pim_ifp
->pim_sock_fd
< 0)
3240 json_ifp_rows
= json_object_new_object();
3242 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
3244 snprintfrr(neigh_src_str
, sizeof(neigh_src_str
),
3245 "%pPAs", &neigh
->source_addr
);
3246 pim_time_uptime(uptime
, sizeof(uptime
),
3247 now
- neigh
->creation
);
3248 pim_time_timer_to_hhmmss(expire
, sizeof(expire
),
3249 neigh
->t_expire_timer
);
3252 json_row
= json_object_new_object();
3253 json_object_string_add(json_row
, "interface",
3255 json_object_string_add(json_row
, "neighbor",
3257 json_object_string_add(json_row
, "upTime",
3259 json_object_string_add(json_row
, "holdTime",
3261 json_object_int_add(json_row
, "holdTimeMax",
3263 json_object_int_add(json_row
, "drPriority",
3264 neigh
->dr_priority
);
3265 json_object_object_add(json_ifp_rows
,
3266 neigh_src_str
, json_row
);
3269 ttable_add_row(tt
, "%s|%pPAs|%s|%s|%d",
3270 ifp
->name
, &neigh
->source_addr
,
3272 neigh
->dr_priority
);
3277 json_object_object_add(json
, ifp
->name
, json_ifp_rows
);
3278 json_ifp_rows
= NULL
;
3281 /* Dump the generated table. */
3283 table
= ttable_dump(tt
, "\n");
3284 vty_out(vty
, "%s\n", table
);
3285 XFREE(MTYPE_TMP
, table
);
3290 int gm_process_query_max_response_time_cmd(struct vty
*vty
,
3291 const char *qmrt_str
)
3293 const struct lyd_node
*pim_enable_dnode
;
3295 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3296 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3297 FRR_PIM_AF_XPATH_VAL
);
3299 if (!pim_enable_dnode
) {
3300 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3302 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3303 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3307 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_MODIFY
,
3309 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3310 FRR_PIM_AF_XPATH_VAL
);
3313 int gm_process_no_query_max_response_time_cmd(struct vty
*vty
)
3315 nb_cli_enqueue_change(vty
, "./query-max-response-time", NB_OP_DESTROY
,
3317 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3318 FRR_PIM_AF_XPATH_VAL
);
3321 int gm_process_last_member_query_count_cmd(struct vty
*vty
,
3322 const char *lmqc_str
)
3324 const struct lyd_node
*pim_enable_dnode
;
3326 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3327 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3328 FRR_PIM_AF_XPATH_VAL
);
3329 if (!pim_enable_dnode
) {
3330 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3332 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3333 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3337 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_MODIFY
,
3339 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3340 FRR_PIM_AF_XPATH_VAL
);
3343 int gm_process_no_last_member_query_count_cmd(struct vty
*vty
)
3345 nb_cli_enqueue_change(vty
, "./robustness-variable", NB_OP_DESTROY
,
3347 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3348 FRR_PIM_AF_XPATH_VAL
);
3351 int gm_process_last_member_query_interval_cmd(struct vty
*vty
,
3352 const char *lmqi_str
)
3354 const struct lyd_node
*pim_enable_dnode
;
3356 pim_enable_dnode
= yang_dnode_getf(vty
->candidate_config
->dnode
,
3357 FRR_PIM_ENABLE_XPATH
, VTY_CURR_XPATH
,
3358 FRR_PIM_AF_XPATH_VAL
);
3359 if (!pim_enable_dnode
) {
3360 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
, "true");
3362 if (!yang_dnode_get_bool(pim_enable_dnode
, "."))
3363 nb_cli_enqueue_change(vty
, "./enable", NB_OP_MODIFY
,
3367 nb_cli_enqueue_change(vty
, "./last-member-query-interval", NB_OP_MODIFY
,
3369 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3370 FRR_PIM_AF_XPATH_VAL
);
3373 int gm_process_no_last_member_query_interval_cmd(struct vty
*vty
)
3375 nb_cli_enqueue_change(vty
, "./last-member-query-interval",
3376 NB_OP_DESTROY
, NULL
);
3377 return nb_cli_apply_changes(vty
, FRR_GMP_INTERFACE_XPATH
,
3378 FRR_PIM_AF_XPATH_VAL
);
3381 int pim_process_ssmpingd_cmd(struct vty
*vty
, enum nb_operation operation
,
3382 const char *src_str
)
3384 const char *vrfname
;
3385 char ssmpingd_ip_xpath
[XPATH_MAXLEN
];
3387 vrfname
= pim_cli_get_vrf_name(vty
);
3388 if (vrfname
== NULL
)
3389 return CMD_WARNING_CONFIG_FAILED
;
3391 snprintf(ssmpingd_ip_xpath
, sizeof(ssmpingd_ip_xpath
),
3392 FRR_PIM_VRF_XPATH
, "frr-pim:pimd", "pim", vrfname
,
3393 FRR_PIM_AF_XPATH_VAL
);
3394 strlcat(ssmpingd_ip_xpath
, "/ssm-pingd-source-ip",
3395 sizeof(ssmpingd_ip_xpath
));
3397 nb_cli_enqueue_change(vty
, ssmpingd_ip_xpath
, operation
, src_str
);
3399 return nb_cli_apply_changes(vty
, NULL
);
3402 static void show_scan_oil_stats(struct pim_instance
*pim
, struct vty
*vty
,
3405 char uptime_scan_oil
[10];
3406 char uptime_mroute_add
[10];
3407 char uptime_mroute_del
[10];
3409 pim_time_uptime_begin(uptime_scan_oil
, sizeof(uptime_scan_oil
), now
,
3410 pim
->scan_oil_last
);
3411 pim_time_uptime_begin(uptime_mroute_add
, sizeof(uptime_mroute_add
), now
,
3412 pim
->mroute_add_last
);
3413 pim_time_uptime_begin(uptime_mroute_del
, sizeof(uptime_mroute_del
), now
,
3414 pim
->mroute_del_last
);
3417 "Scan OIL - Last: %s Events: %lld\n"
3418 "MFC Add - Last: %s Events: %lld\n"
3419 "MFC Del - Last: %s Events: %lld\n",
3420 uptime_scan_oil
, (long long)pim
->scan_oil_events
,
3421 uptime_mroute_add
, (long long)pim
->mroute_add_events
,
3422 uptime_mroute_del
, (long long)pim
->mroute_del_events
);
3425 void show_multicast_interfaces(struct pim_instance
*pim
, struct vty
*vty
,
3428 struct interface
*ifp
;
3429 struct ttable
*tt
= NULL
;
3431 json_object
*json_row
= NULL
;
3436 /* Prepare table. */
3437 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3440 "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
3441 tt
->style
.cell
.rpad
= 2;
3442 tt
->style
.corner
= '+';
3446 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
3447 struct pim_interface
*pim_ifp
;
3449 struct sioc_vif_req vreq
;
3451 struct sioc_mif_req6 vreq
;
3454 pim_ifp
= ifp
->info
;
3459 memset(&vreq
, 0, sizeof(vreq
));
3461 vreq
.vifi
= pim_ifp
->mroute_vif_index
;
3462 if (ioctl(pim
->mroute_socket
, SIOCGETVIFCNT
, &vreq
)) {
3464 "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3465 (unsigned long)SIOCGETVIFCNT
, ifp
->name
,
3466 pim_ifp
->mroute_vif_index
, errno
,
3467 safe_strerror(errno
));
3470 vreq
.mifi
= pim_ifp
->mroute_vif_index
;
3471 if (ioctl(pim
->mroute_socket
, SIOCGETMIFCNT_IN6
, &vreq
)) {
3473 "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3474 (unsigned long)SIOCGETMIFCNT_IN6
, ifp
->name
,
3475 pim_ifp
->mroute_vif_index
, errno
,
3476 safe_strerror(errno
));
3481 json_row
= json_object_new_object();
3482 json_object_string_add(json_row
, "name", ifp
->name
);
3483 json_object_string_add(json_row
, "state",
3484 if_is_up(ifp
) ? "up" : "down");
3485 json_object_string_addf(json_row
, "address", "%pPA",
3486 &pim_ifp
->primary_address
);
3487 json_object_int_add(json_row
, "ifIndex", ifp
->ifindex
);
3488 json_object_int_add(json_row
, "vif",
3489 pim_ifp
->mroute_vif_index
);
3490 json_object_int_add(json_row
, "pktsIn",
3491 (unsigned long)vreq
.icount
);
3492 json_object_int_add(json_row
, "pktsOut",
3493 (unsigned long)vreq
.ocount
);
3494 json_object_int_add(json_row
, "bytesIn",
3495 (unsigned long)vreq
.ibytes
);
3496 json_object_int_add(json_row
, "bytesOut",
3497 (unsigned long)vreq
.obytes
);
3498 json_object_object_add(json
, ifp
->name
, json_row
);
3500 ttable_add_row(tt
, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
3501 ifp
->name
, &pim_ifp
->primary_address
,
3502 ifp
->ifindex
, pim_ifp
->mroute_vif_index
,
3503 (unsigned long)vreq
.icount
,
3504 (unsigned long)vreq
.ocount
,
3505 (unsigned long)vreq
.ibytes
,
3506 (unsigned long)vreq
.obytes
);
3509 /* Dump the generated table. */
3511 table
= ttable_dump(tt
, "\n");
3512 vty_out(vty
, "%s\n", table
);
3513 XFREE(MTYPE_TMP
, table
);
3518 void pim_cmd_show_ip_multicast_helper(struct pim_instance
*pim
, struct vty
*vty
)
3520 struct vrf
*vrf
= pim
->vrf
;
3521 time_t now
= pim_time_monotonic_sec();
3527 vty_out(vty
, "Router MLAG Role: %s\n",
3528 mlag_role2str(router
->mlag_role
, mlag_role
, sizeof(mlag_role
)));
3529 vty_out(vty
, "Mroute socket descriptor:");
3531 vty_out(vty
, " %d(%s)\n", pim
->mroute_socket
, vrf
->name
);
3532 vty_out(vty
, "PIM Register socket descriptor:");
3533 vty_out(vty
, " %d(%s)\n", pim
->reg_sock
, vrf
->name
);
3535 pim_time_uptime(uptime
, sizeof(uptime
),
3536 now
- pim
->mroute_socket_creation
);
3537 vty_out(vty
, "Mroute socket uptime: %s\n", uptime
);
3541 pim_zebra_zclient_update(vty
);
3542 pim_zlookup_show_ip_multicast(vty
);
3545 vty_out(vty
, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS
);
3548 vty_out(vty
, "Upstream Join Timer: %d secs\n", router
->t_periodic
);
3549 vty_out(vty
, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME
);
3550 vty_out(vty
, "PIM ECMP: %s\n", pim
->ecmp_enable
? "Enable" : "Disable");
3551 vty_out(vty
, "PIM ECMP Rebalance: %s\n",
3552 pim
->ecmp_rebalance_enable
? "Enable" : "Disable");
3556 pim_show_rpf_refresh_stats(vty
, pim
, now
, NULL
);
3560 show_scan_oil_stats(pim
, vty
, now
);
3562 show_multicast_interfaces(pim
, vty
, NULL
);
3565 void show_mroute(struct pim_instance
*pim
, struct vty
*vty
, pim_sgaddr
*sg
,
3566 bool fill
, json_object
*json
)
3568 struct listnode
*node
;
3569 struct channel_oil
*c_oil
;
3570 struct static_route
*s_route
;
3571 struct ttable
*tt
= NULL
;
3574 json_object
*json_group
= NULL
;
3575 json_object
*json_source
= NULL
;
3576 json_object
*json_oil
= NULL
;
3577 json_object
*json_ifp_out
= NULL
;
3580 char grp_str
[PIM_ADDRSTRLEN
];
3581 char src_str
[PIM_ADDRSTRLEN
];
3582 char in_ifname
[INTERFACE_NAMSIZ
+ 1];
3583 char out_ifname
[INTERFACE_NAMSIZ
+ 1];
3585 struct interface
*ifp_in
;
3587 char state_str
[PIM_REG_STATE_STR_LEN
];
3588 char mroute_uptime
[10];
3591 vty_out(vty
, "IP Multicast Routing Table\n");
3592 vty_out(vty
, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3594 " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3596 /* Prepare table. */
3597 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3599 tt
, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
3600 tt
->style
.cell
.rpad
= 2;
3601 tt
->style
.corner
= '+';
3605 now
= pim_time_monotonic_sec();
3607 /* print list of PIM and IGMP routes */
3608 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
3611 if (!c_oil
->installed
)
3614 if (!pim_addr_is_any(sg
->grp
) &&
3615 pim_addr_cmp(sg
->grp
, *oil_mcastgrp(c_oil
)))
3617 if (!pim_addr_is_any(sg
->src
) &&
3618 pim_addr_cmp(sg
->src
, *oil_origin(c_oil
)))
3621 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs",
3622 oil_mcastgrp(c_oil
));
3623 snprintfrr(src_str
, sizeof(src_str
), "%pPAs",
3626 strlcpy(state_str
, "S", sizeof(state_str
));
3627 /* When a non DR receives a igmp join, it creates a (*,G)
3628 * channel_oil without any upstream creation
3631 if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil
->up
->flags
))
3632 strlcat(state_str
, "C", sizeof(state_str
));
3633 if (pim_upstream_is_sg_rpt(c_oil
->up
))
3634 strlcat(state_str
, "R", sizeof(state_str
));
3635 if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil
->up
->flags
))
3636 strlcat(state_str
, "F", sizeof(state_str
));
3637 if (c_oil
->up
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
3638 strlcat(state_str
, "T", sizeof(state_str
));
3640 if (pim_channel_oil_empty(c_oil
))
3641 strlcat(state_str
, "P", sizeof(state_str
));
3643 ifp_in
= pim_if_find_by_vif_index(pim
, *oil_parent(c_oil
));
3646 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3648 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3651 pim_time_uptime(mroute_uptime
, sizeof(mroute_uptime
),
3652 now
- c_oil
->mroute_creation
);
3656 /* Find the group, create it if it doesn't exist */
3657 json_object_object_get_ex(json
, grp_str
, &json_group
);
3660 json_group
= json_object_new_object();
3661 json_object_object_add(json
, grp_str
,
3665 /* Find the source nested under the group, create it if
3668 json_object_object_get_ex(json_group
, src_str
,
3672 json_source
= json_object_new_object();
3673 json_object_object_add(json_group
, src_str
,
3677 /* Find the inbound interface nested under the source,
3678 * create it if it doesn't exist
3680 json_object_string_add(json_source
, "source", src_str
);
3681 json_object_string_add(json_source
, "group", grp_str
);
3682 json_object_int_add(json_source
, "installed",
3684 json_object_int_add(json_source
, "refCount",
3685 c_oil
->oil_ref_count
);
3686 json_object_int_add(json_source
, "oilSize",
3688 json_object_int_add(json_source
, "OilInheritedRescan",
3689 c_oil
->oil_inherited_rescan
);
3690 json_object_int_add(json_source
, "oilInheritedRescan",
3691 c_oil
->oil_inherited_rescan
);
3692 json_object_string_add(json_source
, "iif", in_ifname
);
3693 json_object_string_add(json_source
, "upTime",
3698 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3700 struct interface
*ifp_out
;
3703 ttl
= oil_if_has(c_oil
, oif_vif_index
);
3707 /* do not display muted OIFs */
3708 if (c_oil
->oif_flags
[oif_vif_index
] & PIM_OIF_FLAG_MUTE
)
3711 if (*oil_parent(c_oil
) == oif_vif_index
&&
3712 !pim_mroute_allow_iif_in_oil(c_oil
, oif_vif_index
))
3715 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3719 strlcpy(out_ifname
, ifp_out
->name
,
3720 sizeof(out_ifname
));
3722 strlcpy(out_ifname
, "<oif?>",
3723 sizeof(out_ifname
));
3726 json_ifp_out
= json_object_new_object();
3727 json_object_string_add(json_ifp_out
, "source",
3729 json_object_string_add(json_ifp_out
, "group",
3732 if (c_oil
->oif_flags
[oif_vif_index
] &
3733 PIM_OIF_FLAG_PROTO_PIM
)
3734 json_object_boolean_true_add(
3735 json_ifp_out
, "protocolPim");
3737 if (c_oil
->oif_flags
[oif_vif_index
] &
3738 PIM_OIF_FLAG_PROTO_GM
)
3740 json_object_boolean_true_add(
3741 json_ifp_out
, "protocolIgmp");
3743 json_object_boolean_true_add(
3744 json_ifp_out
, "protocolMld");
3747 if (c_oil
->oif_flags
[oif_vif_index
] &
3748 PIM_OIF_FLAG_PROTO_VXLAN
)
3749 json_object_boolean_true_add(
3750 json_ifp_out
, "protocolVxlan");
3752 if (c_oil
->oif_flags
[oif_vif_index
] &
3753 PIM_OIF_FLAG_PROTO_STAR
)
3754 json_object_boolean_true_add(
3756 "protocolInherited");
3758 json_object_string_add(json_ifp_out
,
3761 json_object_int_add(json_ifp_out
, "iVifI",
3762 *oil_parent(c_oil
));
3763 json_object_string_add(json_ifp_out
,
3764 "outboundInterface",
3766 json_object_int_add(json_ifp_out
, "oVifI",
3768 json_object_int_add(json_ifp_out
, "ttl", ttl
);
3769 json_object_string_add(json_ifp_out
, "upTime",
3771 json_object_string_add(json_source
, "flags",
3774 json_oil
= json_object_new_object();
3775 json_object_object_add(json_source
,
3778 json_object_object_add(json_oil
, out_ifname
,
3782 if (c_oil
->oif_flags
[oif_vif_index
] &
3783 PIM_OIF_FLAG_PROTO_PIM
) {
3784 strlcpy(proto
, "PIM", sizeof(proto
));
3787 if (c_oil
->oif_flags
[oif_vif_index
] &
3788 PIM_OIF_FLAG_PROTO_GM
) {
3790 strlcpy(proto
, "IGMP", sizeof(proto
));
3792 strlcpy(proto
, "MLD", sizeof(proto
));
3796 if (c_oil
->oif_flags
[oif_vif_index
] &
3797 PIM_OIF_FLAG_PROTO_VXLAN
) {
3798 strlcpy(proto
, "VxLAN", sizeof(proto
));
3801 if (c_oil
->oif_flags
[oif_vif_index
] &
3802 PIM_OIF_FLAG_PROTO_STAR
) {
3803 strlcpy(proto
, "STAR", sizeof(proto
));
3806 ttable_add_row(tt
, "%s|%s|%s|%s|%s|%s|%d|%s",
3807 src_str
, grp_str
, state_str
,
3808 proto
, in_ifname
, out_ifname
,
3809 ttl
, mroute_uptime
);
3814 in_ifname
[0] = '\0';
3815 state_str
[0] = '\0';
3816 mroute_uptime
[0] = '\0';
3822 if (!json
&& !found_oif
) {
3823 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3824 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
3825 state_str
, "none", in_ifname
, "none", 0,
3830 /* Print list of static routes */
3831 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
3834 if (!s_route
->c_oil
.installed
)
3837 snprintfrr(grp_str
, sizeof(grp_str
), "%pPAs", &s_route
->group
);
3838 snprintfrr(src_str
, sizeof(src_str
), "%pPAs", &s_route
->source
);
3839 ifp_in
= pim_if_find_by_vif_index(pim
, s_route
->iif
);
3843 strlcpy(in_ifname
, ifp_in
->name
, sizeof(in_ifname
));
3845 strlcpy(in_ifname
, "<iif?>", sizeof(in_ifname
));
3849 /* Find the group, create it if it doesn't exist */
3850 json_object_object_get_ex(json
, grp_str
, &json_group
);
3853 json_group
= json_object_new_object();
3854 json_object_object_add(json
, grp_str
,
3858 /* Find the source nested under the group, create it if
3861 json_object_object_get_ex(json_group
, src_str
,
3865 json_source
= json_object_new_object();
3866 json_object_object_add(json_group
, src_str
,
3870 json_object_string_add(json_source
, "iif", in_ifname
);
3873 strlcpy(proto
, "STATIC", sizeof(proto
));
3876 for (oif_vif_index
= 0; oif_vif_index
< MAXVIFS
;
3878 struct interface
*ifp_out
;
3879 char oif_uptime
[10];
3882 ttl
= s_route
->oif_ttls
[oif_vif_index
];
3886 ifp_out
= pim_if_find_by_vif_index(pim
, oif_vif_index
);
3888 oif_uptime
, sizeof(oif_uptime
),
3889 now
- s_route
->c_oil
3890 .oif_creation
[oif_vif_index
]);
3894 strlcpy(out_ifname
, ifp_out
->name
,
3895 sizeof(out_ifname
));
3897 strlcpy(out_ifname
, "<oif?>",
3898 sizeof(out_ifname
));
3901 json_ifp_out
= json_object_new_object();
3902 json_object_string_add(json_ifp_out
, "source",
3904 json_object_string_add(json_ifp_out
, "group",
3906 json_object_boolean_true_add(json_ifp_out
,
3908 json_object_string_add(json_ifp_out
,
3911 json_object_int_add(
3912 json_ifp_out
, "iVifI",
3913 *oil_parent(&s_route
->c_oil
));
3914 json_object_string_add(json_ifp_out
,
3915 "outboundInterface",
3917 json_object_int_add(json_ifp_out
, "oVifI",
3919 json_object_int_add(json_ifp_out
, "ttl", ttl
);
3920 json_object_string_add(json_ifp_out
, "upTime",
3923 json_oil
= json_object_new_object();
3924 json_object_object_add(json_source
,
3927 json_object_object_add(json_oil
, out_ifname
,
3931 tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3932 &s_route
->source
, &s_route
->group
, "-",
3933 proto
, in_ifname
, out_ifname
, ttl
,
3935 if (first
&& !fill
) {
3938 in_ifname
[0] = '\0';
3944 if (!json
&& !found_oif
) {
3945 ttable_add_row(tt
, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3946 &s_route
->source
, &s_route
->group
, "-",
3947 proto
, in_ifname
, "none", 0, "--:--:--");
3950 /* Dump the generated table. */
3952 table
= ttable_dump(tt
, "\n");
3953 vty_out(vty
, "%s\n", table
);
3954 XFREE(MTYPE_TMP
, table
);
3959 static void show_mroute_count_per_channel_oil(struct channel_oil
*c_oil
,
3963 json_object
*json_group
= NULL
;
3964 json_object
*json_source
= NULL
;
3966 if (!c_oil
->installed
)
3969 pim_mroute_update_counters(c_oil
);
3972 char group_str
[PIM_ADDRSTRLEN
];
3973 char source_str
[PIM_ADDRSTRLEN
];
3975 snprintfrr(group_str
, sizeof(group_str
), "%pPAs",
3976 oil_mcastgrp(c_oil
));
3977 snprintfrr(source_str
, sizeof(source_str
), "%pPAs",
3980 json_object_object_get_ex(json
, group_str
, &json_group
);
3983 json_group
= json_object_new_object();
3984 json_object_object_add(json
, group_str
, json_group
);
3987 json_source
= json_object_new_object();
3988 json_object_object_add(json_group
, source_str
, json_source
);
3989 json_object_int_add(json_source
, "lastUsed",
3990 c_oil
->cc
.lastused
/ 100);
3991 json_object_int_add(json_source
, "packets", c_oil
->cc
.pktcnt
);
3992 json_object_int_add(json_source
, "bytes", c_oil
->cc
.bytecnt
);
3993 json_object_int_add(json_source
, "wrongIf", c_oil
->cc
.wrong_if
);
3996 ttable_add_row(tt
, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
3997 oil_origin(c_oil
), oil_mcastgrp(c_oil
),
3998 c_oil
->cc
.lastused
/ 100,
3999 c_oil
->cc
.pktcnt
- c_oil
->cc
.origpktcnt
,
4000 c_oil
->cc
.bytecnt
- c_oil
->cc
.origbytecnt
,
4001 c_oil
->cc
.wrong_if
- c_oil
->cc
.origwrong_if
);
4005 void show_mroute_count(struct pim_instance
*pim
, struct vty
*vty
,
4008 struct listnode
*node
;
4009 struct channel_oil
*c_oil
;
4010 struct static_route
*sr
;
4011 struct ttable
*tt
= NULL
;
4017 /* Prepare table. */
4018 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4020 "Source|Group|LastUsed|Packets|Bytes|WrongIf");
4021 tt
->style
.cell
.rpad
= 2;
4022 tt
->style
.corner
= '+';
4026 /* Print PIM and IGMP route counts */
4027 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
4028 show_mroute_count_per_channel_oil(c_oil
, json
, tt
);
4030 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
))
4031 show_mroute_count_per_channel_oil(&sr
->c_oil
, json
, tt
);
4033 /* Dump the generated table. */
4035 table
= ttable_dump(tt
, "\n");
4036 vty_out(vty
, "%s\n", table
);
4037 XFREE(MTYPE_TMP
, table
);
4042 void show_mroute_summary(struct pim_instance
*pim
, struct vty
*vty
,
4045 struct listnode
*node
;
4046 struct channel_oil
*c_oil
;
4047 struct static_route
*s_route
;
4048 uint32_t starg_sw_mroute_cnt
= 0;
4049 uint32_t sg_sw_mroute_cnt
= 0;
4050 uint32_t starg_hw_mroute_cnt
= 0;
4051 uint32_t sg_hw_mroute_cnt
= 0;
4052 json_object
*json_starg
= NULL
;
4053 json_object
*json_sg
= NULL
;
4056 vty_out(vty
, "Mroute Type Installed/Total\n");
4058 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4059 if (!c_oil
->installed
) {
4060 if (pim_addr_is_any(*oil_origin(c_oil
)))
4061 starg_sw_mroute_cnt
++;
4065 if (pim_addr_is_any(*oil_origin(c_oil
)))
4066 starg_hw_mroute_cnt
++;
4072 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, s_route
)) {
4073 if (!s_route
->c_oil
.installed
) {
4074 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4075 starg_sw_mroute_cnt
++;
4079 if (pim_addr_is_any(*oil_origin(&s_route
->c_oil
)))
4080 starg_hw_mroute_cnt
++;
4087 vty_out(vty
, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt
,
4088 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4089 vty_out(vty
, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt
,
4090 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4091 vty_out(vty
, "------\n");
4092 vty_out(vty
, "%-20s %u/%u\n", "Total",
4093 (starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
),
4094 (starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4095 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
));
4097 /* (*,G) route details */
4098 json_starg
= json_object_new_object();
4099 json_object_object_add(json
, "wildcardGroup", json_starg
);
4101 json_object_int_add(json_starg
, "installed",
4102 starg_hw_mroute_cnt
);
4103 json_object_int_add(json_starg
, "total",
4104 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
);
4106 /* (S, G) route details */
4107 json_sg
= json_object_new_object();
4108 json_object_object_add(json
, "sourceGroup", json_sg
);
4110 json_object_int_add(json_sg
, "installed", sg_hw_mroute_cnt
);
4111 json_object_int_add(json_sg
, "total",
4112 sg_sw_mroute_cnt
+ sg_hw_mroute_cnt
);
4114 json_object_int_add(json
, "totalNumOfInstalledMroutes",
4115 starg_hw_mroute_cnt
+ sg_hw_mroute_cnt
);
4116 json_object_int_add(json
, "totalNumOfMroutes",
4117 starg_sw_mroute_cnt
+ starg_hw_mroute_cnt
+
4123 int clear_ip_mroute_count_command(struct vty
*vty
, const char *name
)
4125 struct listnode
*node
;
4126 struct channel_oil
*c_oil
;
4127 struct static_route
*sr
;
4128 struct vrf
*v
= pim_cmd_lookup(vty
, name
);
4129 struct pim_instance
*pim
;
4135 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
) {
4136 if (!c_oil
->installed
)
4139 pim_mroute_update_counters(c_oil
);
4140 c_oil
->cc
.origpktcnt
= c_oil
->cc
.pktcnt
;
4141 c_oil
->cc
.origbytecnt
= c_oil
->cc
.bytecnt
;
4142 c_oil
->cc
.origwrong_if
= c_oil
->cc
.wrong_if
;
4145 for (ALL_LIST_ELEMENTS_RO(pim
->static_routes
, node
, sr
)) {
4146 if (!sr
->c_oil
.installed
)
4149 pim_mroute_update_counters(&sr
->c_oil
);
4151 sr
->c_oil
.cc
.origpktcnt
= sr
->c_oil
.cc
.pktcnt
;
4152 sr
->c_oil
.cc
.origbytecnt
= sr
->c_oil
.cc
.bytecnt
;
4153 sr
->c_oil
.cc
.origwrong_if
= sr
->c_oil
.cc
.wrong_if
;
4158 struct vrf
*pim_cmd_lookup(struct vty
*vty
, const char *name
)
4163 vrf
= vrf_lookup_by_name(name
);
4165 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
4168 vty_out(vty
, "Specified VRF: %s does not exist\n", name
);
4173 void clear_mroute(struct pim_instance
*pim
)
4175 struct pim_upstream
*up
;
4176 struct interface
*ifp
;
4178 /* scan interfaces */
4179 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4180 struct pim_interface
*pim_ifp
= ifp
->info
;
4181 struct pim_ifchannel
*ch
;
4186 /* deleting all ifchannels */
4187 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
4188 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
4190 pim_ifchannel_delete(ch
);
4194 /* clean up all igmp groups */
4195 struct gm_group
*grp
;
4197 if (pim_ifp
->gm_group_list
) {
4198 while (pim_ifp
->gm_group_list
->count
) {
4199 grp
= listnode_head(pim_ifp
->gm_group_list
);
4200 igmp_group_delete(grp
);
4204 struct gm_if
*gm_ifp
;
4206 gm_ifp
= pim_ifp
->mld
;
4208 gm_group_delete(gm_ifp
);
4212 /* clean up all upstreams*/
4213 while ((up
= rb_pim_upstream_first(&pim
->upstream_head
)))
4214 pim_upstream_del(pim
, up
, __func__
);
4217 void clear_pim_statistics(struct pim_instance
*pim
)
4219 struct interface
*ifp
;
4223 pim
->bsm_dropped
= 0;
4225 /* scan interfaces */
4226 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4227 struct pim_interface
*pim_ifp
= ifp
->info
;
4232 pim_ifp
->pim_ifstat_bsm_cfg_miss
= 0;
4233 pim_ifp
->pim_ifstat_ucast_bsm_cfg_miss
= 0;
4234 pim_ifp
->pim_ifstat_bsm_invalid_sz
= 0;
4238 int clear_pim_interface_traffic(const char *vrf
, struct vty
*vty
)
4240 struct interface
*ifp
= NULL
;
4241 struct pim_interface
*pim_ifp
= NULL
;
4243 struct vrf
*v
= pim_cmd_lookup(vty
, vrf
);
4248 FOR_ALL_INTERFACES (v
, ifp
) {
4249 pim_ifp
= ifp
->info
;
4254 pim_ifp
->pim_ifstat_hello_recv
= 0;
4255 pim_ifp
->pim_ifstat_hello_sent
= 0;
4256 pim_ifp
->pim_ifstat_join_recv
= 0;
4257 pim_ifp
->pim_ifstat_join_send
= 0;
4258 pim_ifp
->pim_ifstat_prune_recv
= 0;
4259 pim_ifp
->pim_ifstat_prune_send
= 0;
4260 pim_ifp
->pim_ifstat_reg_recv
= 0;
4261 pim_ifp
->pim_ifstat_reg_send
= 0;
4262 pim_ifp
->pim_ifstat_reg_stop_recv
= 0;
4263 pim_ifp
->pim_ifstat_reg_stop_send
= 0;
4264 pim_ifp
->pim_ifstat_assert_recv
= 0;
4265 pim_ifp
->pim_ifstat_assert_send
= 0;
4266 pim_ifp
->pim_ifstat_bsm_rx
= 0;
4267 pim_ifp
->pim_ifstat_bsm_tx
= 0;
4269 pim_ifp
->igmp_ifstat_joins_sent
= 0;
4270 pim_ifp
->igmp_ifstat_joins_failed
= 0;
4271 pim_ifp
->igmp_peak_group_count
= 0;
4278 int pim_debug_pim_cmd(void)
4280 PIM_DO_DEBUG_PIM_EVENTS
;
4281 PIM_DO_DEBUG_PIM_PACKETS
;
4282 PIM_DO_DEBUG_PIM_TRACE
;
4283 PIM_DO_DEBUG_MSDP_EVENTS
;
4284 PIM_DO_DEBUG_MSDP_PACKETS
;
4290 int pim_no_debug_pim_cmd(void)
4292 PIM_DONT_DEBUG_PIM_EVENTS
;
4293 PIM_DONT_DEBUG_PIM_PACKETS
;
4294 PIM_DONT_DEBUG_PIM_TRACE
;
4295 PIM_DONT_DEBUG_MSDP_EVENTS
;
4296 PIM_DONT_DEBUG_MSDP_PACKETS
;
4298 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND
;
4299 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV
;
4301 PIM_DONT_DEBUG_VXLAN
;
4305 int pim_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4306 const char *registers
, struct vty
*vty
)
4309 PIM_DO_DEBUG_PIM_HELLO
;
4310 vty_out(vty
, "PIM Hello debugging is on\n");
4312 PIM_DO_DEBUG_PIM_J_P
;
4313 vty_out(vty
, "PIM Join/Prune debugging is on\n");
4314 } else if (registers
) {
4315 PIM_DO_DEBUG_PIM_REG
;
4316 vty_out(vty
, "PIM Register debugging is on\n");
4318 PIM_DO_DEBUG_PIM_PACKETS
;
4319 vty_out(vty
, "PIM Packet debugging is on\n");
4324 int pim_no_debug_pim_packets_cmd(const char *hello
, const char *joins
,
4325 const char *registers
, struct vty
*vty
)
4328 PIM_DONT_DEBUG_PIM_HELLO
;
4329 vty_out(vty
, "PIM Hello debugging is off\n");
4331 PIM_DONT_DEBUG_PIM_J_P
;
4332 vty_out(vty
, "PIM Join/Prune debugging is off\n");
4333 } else if (registers
) {
4334 PIM_DONT_DEBUG_PIM_REG
;
4335 vty_out(vty
, "PIM Register debugging is off\n");
4337 PIM_DONT_DEBUG_PIM_PACKETS
;
4338 vty_out(vty
, "PIM Packet debugging is off\n");
4344 int pim_show_rpf_helper(const char *vrf
, struct vty
*vty
, bool json
)
4346 struct pim_instance
*pim
;
4348 json_object
*json_parent
= NULL
;
4350 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4358 vty_out(vty
, "%% Unable to find pim instance\n");
4363 json_parent
= json_object_new_object();
4365 pim_show_rpf(pim
, vty
, json_parent
);
4368 vty_json(vty
, json_parent
);
4373 int pim_show_rpf_vrf_all_helper(struct vty
*vty
, bool json
)
4376 json_object
*json_parent
= NULL
;
4377 json_object
*json_vrf
= NULL
;
4380 json_parent
= json_object_new_object();
4382 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4384 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4386 json_vrf
= json_object_new_object();
4387 pim_show_rpf(vrf
->info
, vty
, json_vrf
);
4389 json_object_object_add(json_parent
, vrf
->name
,
4393 vty_json(vty
, json_parent
);
4398 int pim_show_rp_helper(const char *vrf
, struct vty
*vty
, const char *group_str
,
4399 const struct prefix
*group
, bool json
)
4401 struct pim_instance
*pim
;
4403 json_object
*json_parent
= NULL
;
4404 struct prefix
*range
= NULL
;
4406 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4414 vty_out(vty
, "%% Unable to find pim instance\n");
4419 range
= prefix_new();
4420 prefix_copy(range
, group
);
4425 json_parent
= json_object_new_object();
4427 pim_rp_show_information(pim
, range
, vty
, json_parent
);
4430 vty_json(vty
, json_parent
);
4432 prefix_free(&range
);
4437 int pim_show_rp_vrf_all_helper(struct vty
*vty
, const char *group_str
,
4438 const struct prefix
*group
, bool json
)
4441 json_object
*json_parent
= NULL
;
4442 json_object
*json_vrf
= NULL
;
4443 struct prefix
*range
= NULL
;
4446 range
= prefix_new();
4447 prefix_copy(range
, group
);
4452 json_parent
= json_object_new_object();
4454 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4456 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4458 json_vrf
= json_object_new_object();
4459 pim_rp_show_information(vrf
->info
, range
, vty
, json_vrf
);
4461 json_object_object_add(json_parent
, vrf
->name
,
4465 vty_json(vty
, json_parent
);
4467 prefix_free(&range
);
4472 int pim_show_secondary_helper(const char *vrf
, struct vty
*vty
)
4474 struct pim_instance
*pim
;
4477 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4485 vty_out(vty
, "%% Unable to find pim instance\n");
4489 pim_show_neighbors_secondary(pim
, vty
);
4494 int pim_show_statistics_helper(const char *vrf
, struct vty
*vty
,
4495 const char *word
, bool uj
)
4497 struct pim_instance
*pim
;
4500 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4508 vty_out(vty
, "%% Unable to find pim instance\n");
4513 pim_show_statistics(pim
, vty
, word
, uj
);
4515 pim_show_statistics(pim
, vty
, NULL
, uj
);
4520 int pim_show_upstream_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4521 pim_addr g
, bool json
)
4523 pim_sgaddr sg
= {0};
4525 struct pim_instance
*pim
;
4526 json_object
*json_parent
= NULL
;
4528 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4531 vty_out(vty
, "%% Vrf specified: %s does not exist\n", vrf
);
4537 vty_out(vty
, "%% Unable to find pim instance\n");
4542 json_parent
= json_object_new_object();
4544 if (!pim_addr_is_any(s_or_g
)) {
4545 if (!pim_addr_is_any(g
)) {
4552 pim_show_upstream(pim
, vty
, &sg
, json_parent
);
4555 vty_json(vty
, json_parent
);
4560 int pim_show_upstream_vrf_all_helper(struct vty
*vty
, bool json
)
4562 pim_sgaddr sg
= {0};
4564 json_object
*json_parent
= NULL
;
4565 json_object
*json_vrf
= NULL
;
4568 json_parent
= json_object_new_object();
4570 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4572 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4574 json_vrf
= json_object_new_object();
4575 pim_show_upstream(vrf
->info
, vty
, &sg
, json_vrf
);
4577 json_object_object_add(json_parent
, vrf
->name
,
4582 vty_json(vty
, json_parent
);
4587 int pim_show_upstream_join_desired_helper(const char *vrf
, struct vty
*vty
,
4590 struct pim_instance
*pim
;
4593 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4601 vty_out(vty
, "%% Unable to find pim instance\n");
4605 pim_show_join_desired(pim
, vty
, uj
);
4610 int pim_show_upstream_rpf_helper(const char *vrf
, struct vty
*vty
, bool uj
)
4612 struct pim_instance
*pim
;
4615 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4623 vty_out(vty
, "%% Unable to find pim instance\n");
4627 pim_show_upstream_rpf(pim
, vty
, uj
);
4632 int pim_show_state_helper(const char *vrf
, struct vty
*vty
,
4633 const char *s_or_g_str
, const char *g_str
, bool json
)
4635 struct pim_instance
*pim
;
4637 json_object
*json_parent
= NULL
;
4639 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4647 vty_out(vty
, "%% Unable to find pim instance\n");
4652 json_parent
= json_object_new_object();
4654 pim_show_state(pim
, vty
, s_or_g_str
, g_str
, json_parent
);
4657 vty_json(vty
, json_parent
);
4662 int pim_show_state_vrf_all_helper(struct vty
*vty
, const char *s_or_g_str
,
4663 const char *g_str
, bool json
)
4666 json_object
*json_parent
= NULL
;
4667 json_object
*json_vrf
= NULL
;
4670 json_parent
= json_object_new_object();
4672 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4674 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4676 json_vrf
= json_object_new_object();
4677 pim_show_state(vrf
->info
, vty
, s_or_g_str
, g_str
, json_vrf
);
4679 json_object_object_add(json_parent
, vrf
->name
,
4683 vty_json(vty
, json_parent
);
4688 int pim_show_multicast_helper(const char *vrf
, struct vty
*vty
)
4691 struct pim_instance
*pim
;
4693 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4701 vty_out(vty
, "%% Unable to find pim instance\n");
4705 pim_cmd_show_ip_multicast_helper(pim
, vty
);
4710 int pim_show_multicast_vrf_all_helper(struct vty
*vty
)
4714 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4715 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4716 pim_cmd_show_ip_multicast_helper(vrf
->info
, vty
);
4722 int pim_show_multicast_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4724 struct pim_instance
*pim
;
4726 json_object
*json_parent
= NULL
;
4728 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4736 vty_out(vty
, "%% Unable to find pim instance\n");
4741 json_parent
= json_object_new_object();
4743 show_multicast_interfaces(pim
, vty
, json_parent
);
4746 vty_json(vty
, json_parent
);
4751 int pim_show_multicast_count_vrf_all_helper(struct vty
*vty
, bool json
)
4754 json_object
*json_parent
= NULL
;
4755 json_object
*json_vrf
= NULL
;
4758 json_parent
= json_object_new_object();
4760 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4762 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4764 json_vrf
= json_object_new_object();
4766 show_multicast_interfaces(vrf
->info
, vty
, json_vrf
);
4768 json_object_object_add(json_parent
, vrf
->name
,
4772 vty_json(vty
, json_parent
);
4777 int pim_show_mroute_helper(const char *vrf
, struct vty
*vty
, pim_addr s_or_g
,
4778 pim_addr g
, bool fill
, bool json
)
4780 pim_sgaddr sg
= {0};
4781 struct pim_instance
*pim
;
4783 json_object
*json_parent
= NULL
;
4785 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4793 vty_out(vty
, "%% Unable to find pim instance\n");
4798 json_parent
= json_object_new_object();
4800 if (!pim_addr_is_any(s_or_g
)) {
4801 if (!pim_addr_is_any(g
)) {
4808 show_mroute(pim
, vty
, &sg
, fill
, json_parent
);
4811 vty_json(vty
, json_parent
);
4816 int pim_show_mroute_vrf_all_helper(struct vty
*vty
, bool fill
, bool json
)
4818 pim_sgaddr sg
= {0};
4820 json_object
*json_parent
= NULL
;
4821 json_object
*json_vrf
= NULL
;
4824 json_parent
= json_object_new_object();
4826 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4828 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4830 json_vrf
= json_object_new_object();
4831 show_mroute(vrf
->info
, vty
, &sg
, fill
, json_vrf
);
4833 json_object_object_add(json_parent
, vrf
->name
,
4837 vty_json(vty
, json_parent
);
4842 int pim_show_mroute_count_helper(const char *vrf
, struct vty
*vty
, bool json
)
4844 struct pim_instance
*pim
;
4846 json_object
*json_parent
= NULL
;
4848 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4856 vty_out(vty
, "%% Unable to find pim instance\n");
4861 json_parent
= json_object_new_object();
4863 show_mroute_count(pim
, vty
, json_parent
);
4866 vty_json(vty
, json_parent
);
4871 int pim_show_mroute_count_vrf_all_helper(struct vty
*vty
, bool json
)
4874 json_object
*json_parent
= NULL
;
4875 json_object
*json_vrf
= NULL
;
4878 json_parent
= json_object_new_object();
4880 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4882 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4884 json_vrf
= json_object_new_object();
4886 show_mroute_count(vrf
->info
, vty
, json_vrf
);
4889 json_object_object_add(json_parent
, vrf
->name
,
4893 vty_json(vty
, json_parent
);
4898 int pim_show_mroute_summary_helper(const char *vrf
, struct vty
*vty
, bool json
)
4900 struct pim_instance
*pim
;
4902 json_object
*json_parent
= NULL
;
4904 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
4912 vty_out(vty
, "%% Unable to find pim instance\n");
4917 json_parent
= json_object_new_object();
4919 show_mroute_summary(pim
, vty
, json_parent
);
4922 vty_json(vty
, json_parent
);
4927 int pim_show_mroute_summary_vrf_all_helper(struct vty
*vty
, bool json
)
4930 json_object
*json_parent
= NULL
;
4931 json_object
*json_vrf
= NULL
;
4934 json_parent
= json_object_new_object();
4936 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4938 vty_out(vty
, "VRF: %s\n", vrf
->name
);
4940 json_vrf
= json_object_new_object();
4942 show_mroute_summary(vrf
->info
, vty
, json_vrf
);
4945 json_object_object_add(json_parent
, vrf
->name
,
4950 vty_json(vty
, json_parent
);
4955 void pim_show_interface_traffic(struct pim_instance
*pim
, struct vty
*vty
,
4958 struct interface
*ifp
= NULL
;
4959 struct pim_interface
*pim_ifp
= NULL
;
4960 json_object
*json
= NULL
;
4961 json_object
*json_row
= NULL
;
4964 json
= json_object_new_object();
4967 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
4968 "Interface", " HELLO", " JOIN",
4969 " PRUNE", " REGISTER", "REGISTER-STOP",
4971 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
4972 " Rx/Tx", " Rx/Tx", " Rx/Tx",
4973 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
4975 "---------------------------------------------------------------------------------------------------------------\n");
4978 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
4979 pim_ifp
= ifp
->info
;
4985 json_row
= json_object_new_object();
4986 json_object_pim_ifp_add(json_row
, ifp
);
4987 json_object_int_add(json_row
, "helloRx",
4988 pim_ifp
->pim_ifstat_hello_recv
);
4989 json_object_int_add(json_row
, "helloTx",
4990 pim_ifp
->pim_ifstat_hello_sent
);
4991 json_object_int_add(json_row
, "joinRx",
4992 pim_ifp
->pim_ifstat_join_recv
);
4993 json_object_int_add(json_row
, "joinTx",
4994 pim_ifp
->pim_ifstat_join_send
);
4995 json_object_int_add(json_row
, "pruneRx",
4996 pim_ifp
->pim_ifstat_prune_recv
);
4997 json_object_int_add(json_row
, "pruneTx",
4998 pim_ifp
->pim_ifstat_prune_send
);
4999 json_object_int_add(json_row
, "registerRx",
5000 pim_ifp
->pim_ifstat_reg_recv
);
5001 json_object_int_add(json_row
, "registerTx",
5002 pim_ifp
->pim_ifstat_reg_send
);
5003 json_object_int_add(json_row
, "registerStopRx",
5004 pim_ifp
->pim_ifstat_reg_stop_recv
);
5005 json_object_int_add(json_row
, "registerStopTx",
5006 pim_ifp
->pim_ifstat_reg_stop_send
);
5007 json_object_int_add(json_row
, "assertRx",
5008 pim_ifp
->pim_ifstat_assert_recv
);
5009 json_object_int_add(json_row
, "assertTx",
5010 pim_ifp
->pim_ifstat_assert_send
);
5011 json_object_int_add(json_row
, "bsmRx",
5012 pim_ifp
->pim_ifstat_bsm_rx
);
5013 json_object_int_add(json_row
, "bsmTx",
5014 pim_ifp
->pim_ifstat_bsm_tx
);
5015 json_object_object_add(json
, ifp
->name
, json_row
);
5018 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5020 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5021 pim_ifp
->pim_ifstat_hello_sent
,
5022 pim_ifp
->pim_ifstat_join_recv
,
5023 pim_ifp
->pim_ifstat_join_send
,
5024 pim_ifp
->pim_ifstat_prune_recv
,
5025 pim_ifp
->pim_ifstat_prune_send
,
5026 pim_ifp
->pim_ifstat_reg_recv
,
5027 pim_ifp
->pim_ifstat_reg_send
,
5028 pim_ifp
->pim_ifstat_reg_stop_recv
,
5029 pim_ifp
->pim_ifstat_reg_stop_send
,
5030 pim_ifp
->pim_ifstat_assert_recv
,
5031 pim_ifp
->pim_ifstat_assert_send
,
5032 pim_ifp
->pim_ifstat_bsm_rx
,
5033 pim_ifp
->pim_ifstat_bsm_tx
);
5037 vty_json(vty
, json
);
5040 void pim_show_interface_traffic_single(struct pim_instance
*pim
,
5041 struct vty
*vty
, const char *ifname
,
5044 struct interface
*ifp
= NULL
;
5045 struct pim_interface
*pim_ifp
= NULL
;
5046 json_object
*json
= NULL
;
5047 json_object
*json_row
= NULL
;
5048 uint8_t found_ifname
= 0;
5051 json
= json_object_new_object();
5054 vty_out(vty
, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5055 "Interface", " HELLO", " JOIN", " PRUNE",
5056 " REGISTER", " REGISTER-STOP", " ASSERT",
5058 vty_out(vty
, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5059 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
5060 " Rx/Tx", " Rx/Tx", " Rx/Tx");
5062 "-------------------------------------------------------------------------------------------------------------------------------\n");
5065 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5066 if (strcmp(ifname
, ifp
->name
))
5069 pim_ifp
= ifp
->info
;
5076 json_row
= json_object_new_object();
5077 json_object_pim_ifp_add(json_row
, ifp
);
5078 json_object_int_add(json_row
, "helloRx",
5079 pim_ifp
->pim_ifstat_hello_recv
);
5080 json_object_int_add(json_row
, "helloTx",
5081 pim_ifp
->pim_ifstat_hello_sent
);
5082 json_object_int_add(json_row
, "joinRx",
5083 pim_ifp
->pim_ifstat_join_recv
);
5084 json_object_int_add(json_row
, "joinTx",
5085 pim_ifp
->pim_ifstat_join_send
);
5086 json_object_int_add(json_row
, "pruneRx",
5087 pim_ifp
->pim_ifstat_prune_recv
);
5088 json_object_int_add(json_row
, "pruneTx",
5089 pim_ifp
->pim_ifstat_prune_send
);
5090 json_object_int_add(json_row
, "registerRx",
5091 pim_ifp
->pim_ifstat_reg_recv
);
5092 json_object_int_add(json_row
, "registerTx",
5093 pim_ifp
->pim_ifstat_reg_send
);
5094 json_object_int_add(json_row
, "registerStopRx",
5095 pim_ifp
->pim_ifstat_reg_stop_recv
);
5096 json_object_int_add(json_row
, "registerStopTx",
5097 pim_ifp
->pim_ifstat_reg_stop_send
);
5098 json_object_int_add(json_row
, "assertRx",
5099 pim_ifp
->pim_ifstat_assert_recv
);
5100 json_object_int_add(json_row
, "assertTx",
5101 pim_ifp
->pim_ifstat_assert_send
);
5102 json_object_int_add(json_row
, "bsmRx",
5103 pim_ifp
->pim_ifstat_bsm_rx
);
5104 json_object_int_add(json_row
, "bsmTx",
5105 pim_ifp
->pim_ifstat_bsm_tx
);
5107 json_object_object_add(json
, ifp
->name
, json_row
);
5110 "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5112 ifp
->name
, pim_ifp
->pim_ifstat_hello_recv
,
5113 pim_ifp
->pim_ifstat_hello_sent
,
5114 pim_ifp
->pim_ifstat_join_recv
,
5115 pim_ifp
->pim_ifstat_join_send
,
5116 pim_ifp
->pim_ifstat_prune_recv
,
5117 pim_ifp
->pim_ifstat_prune_send
,
5118 pim_ifp
->pim_ifstat_reg_recv
,
5119 pim_ifp
->pim_ifstat_reg_send
,
5120 pim_ifp
->pim_ifstat_reg_stop_recv
,
5121 pim_ifp
->pim_ifstat_reg_stop_send
,
5122 pim_ifp
->pim_ifstat_assert_recv
,
5123 pim_ifp
->pim_ifstat_assert_send
,
5124 pim_ifp
->pim_ifstat_bsm_rx
,
5125 pim_ifp
->pim_ifstat_bsm_tx
);
5129 vty_json(vty
, json
);
5130 else if (!found_ifname
)
5131 vty_out(vty
, "%% No such interface\n");
5134 int pim_show_interface_traffic_helper(const char *vrf
, const char *if_name
,
5135 struct vty
*vty
, bool uj
)
5137 struct pim_instance
*pim
;
5140 v
= vrf_lookup_by_name(vrf
? vrf
: VRF_DEFAULT_NAME
);
5148 vty_out(vty
, "%% Unable to find pim instance\n");
5153 pim_show_interface_traffic_single(v
->info
, vty
, if_name
, uj
);
5155 pim_show_interface_traffic(v
->info
, vty
, uj
);
5160 void clear_pim_interfaces(struct pim_instance
*pim
)
5162 struct interface
*ifp
;
5164 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
5166 pim_neighbor_delete_all(ifp
, "interface cleared");