Line data Source code
1 : /*
2 : * PIM for IPv6 FRR
3 : * Copyright (C) 2022 Vmware, Inc.
4 : * Mobashshera Rasool <mrasool@vmware.com>
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 2 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "lib/json.h"
24 : #include "command.h"
25 : #include "if.h"
26 : #include "prefix.h"
27 : #include "zclient.h"
28 : #include "plist.h"
29 : #include "hash.h"
30 : #include "nexthop.h"
31 : #include "vrf.h"
32 : #include "ferr.h"
33 : #include "lib/srcdest_table.h"
34 : #include "lib/linklist.h"
35 : #include "termtable.h"
36 :
37 : #include "pimd.h"
38 : #include "pim_instance.h"
39 : #include "pim_vty.h"
40 : #include "lib/northbound_cli.h"
41 : #include "pim_errors.h"
42 : #include "pim_nb.h"
43 : #include "pim_mroute.h"
44 : #include "pim_cmd.h"
45 : #include "pim6_cmd.h"
46 : #include "pim_cmd_common.h"
47 : #include "pim_time.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"
53 : #include "pim_nht.h"
54 : #include "pim_sock.h"
55 : #include "pim_ssm.h"
56 : #include "pim_static.h"
57 : #include "pim_addr.h"
58 : #include "pim_static.h"
59 : #include "pim_util.h"
60 : #include "pim6_mld.h"
61 :
62 : /**
63 : * Get current node VRF name.
64 : *
65 : * NOTE:
66 : * In case of failure it will print error message to user.
67 : *
68 : * \returns name or NULL if failed to get VRF.
69 : */
70 5 : const char *pim_cli_get_vrf_name(struct vty *vty)
71 : {
72 5 : const struct lyd_node *vrf_node;
73 :
74 : /* Not inside any VRF context. */
75 5 : if (vty->xpath_index == 0)
76 5 : return VRF_DEFAULT_NAME;
77 :
78 0 : vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
79 0 : if (vrf_node == NULL) {
80 0 : vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
81 0 : return NULL;
82 : }
83 :
84 0 : return yang_dnode_get_string(vrf_node, "./name");
85 : }
86 :
87 1 : int pim_process_join_prune_cmd(struct vty *vty, const char *jpi_str)
88 : {
89 1 : char xpath[XPATH_MAXLEN];
90 :
91 1 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
92 : FRR_PIM_AF_XPATH_VAL);
93 1 : strlcat(xpath, "/join-prune-interval", sizeof(xpath));
94 :
95 1 : nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, jpi_str);
96 :
97 1 : return nb_cli_apply_changes(vty, NULL);
98 : }
99 :
100 0 : int pim_process_no_join_prune_cmd(struct vty *vty)
101 : {
102 0 : char xpath[XPATH_MAXLEN];
103 :
104 0 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
105 : FRR_PIM_AF_XPATH_VAL);
106 0 : strlcat(xpath, "/join-prune-interval", sizeof(xpath));
107 :
108 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
109 :
110 0 : return nb_cli_apply_changes(vty, NULL);
111 : }
112 :
113 0 : int pim_process_spt_switchover_infinity_cmd(struct vty *vty)
114 : {
115 0 : const char *vrfname;
116 0 : char spt_plist_xpath[XPATH_MAXLEN];
117 0 : char spt_action_xpath[XPATH_MAXLEN];
118 :
119 0 : vrfname = pim_cli_get_vrf_name(vty);
120 0 : if (vrfname == NULL)
121 : return CMD_WARNING_CONFIG_FAILED;
122 :
123 0 : 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 0 : strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
127 : sizeof(spt_plist_xpath));
128 :
129 0 : 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 0 : strlcat(spt_action_xpath, "/spt-switchover/spt-action",
133 : sizeof(spt_action_xpath));
134 :
135 0 : if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
136 0 : nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
137 : NULL);
138 0 : nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
139 : "PIM_SPT_INFINITY");
140 :
141 0 : return nb_cli_apply_changes(vty, NULL);
142 : }
143 :
144 0 : int pim_process_spt_switchover_prefixlist_cmd(struct vty *vty,
145 : const char *plist)
146 : {
147 0 : const char *vrfname;
148 0 : char spt_plist_xpath[XPATH_MAXLEN];
149 0 : char spt_action_xpath[XPATH_MAXLEN];
150 :
151 0 : vrfname = pim_cli_get_vrf_name(vty);
152 0 : if (vrfname == NULL)
153 : return CMD_WARNING_CONFIG_FAILED;
154 :
155 0 : 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 0 : strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
159 : sizeof(spt_plist_xpath));
160 :
161 0 : 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 0 : strlcat(spt_action_xpath, "/spt-switchover/spt-action",
165 : sizeof(spt_action_xpath));
166 :
167 0 : nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
168 : "PIM_SPT_INFINITY");
169 0 : nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
170 : plist);
171 :
172 0 : return nb_cli_apply_changes(vty, NULL);
173 : }
174 :
175 0 : int pim_process_no_spt_switchover_cmd(struct vty *vty)
176 : {
177 0 : const char *vrfname;
178 0 : char spt_plist_xpath[XPATH_MAXLEN];
179 0 : char spt_action_xpath[XPATH_MAXLEN];
180 :
181 0 : vrfname = pim_cli_get_vrf_name(vty);
182 0 : if (vrfname == NULL)
183 : return CMD_WARNING_CONFIG_FAILED;
184 :
185 0 : 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 0 : strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
189 : sizeof(spt_plist_xpath));
190 :
191 0 : 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 0 : strlcat(spt_action_xpath, "/spt-switchover/spt-action",
195 : sizeof(spt_action_xpath));
196 :
197 0 : nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
198 0 : nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
199 : "PIM_SPT_IMMEDIATE");
200 :
201 0 : return nb_cli_apply_changes(vty, NULL);
202 : }
203 :
204 0 : int pim_process_pim_packet_cmd(struct vty *vty, const char *packet)
205 : {
206 0 : char xpath[XPATH_MAXLEN];
207 :
208 0 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
209 : FRR_PIM_AF_XPATH_VAL);
210 0 : strlcat(xpath, "/packets", sizeof(xpath));
211 :
212 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, packet);
213 :
214 0 : return nb_cli_apply_changes(vty, NULL);
215 : }
216 :
217 0 : int pim_process_no_pim_packet_cmd(struct vty *vty)
218 : {
219 0 : char xpath[XPATH_MAXLEN];
220 :
221 0 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
222 : FRR_PIM_AF_XPATH_VAL);
223 0 : strlcat(xpath, "/packets", sizeof(xpath));
224 :
225 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
226 :
227 0 : return nb_cli_apply_changes(vty, NULL);
228 : }
229 :
230 0 : int pim_process_keepalivetimer_cmd(struct vty *vty, const char *kat)
231 : {
232 0 : const char *vrfname;
233 0 : char ka_timer_xpath[XPATH_MAXLEN];
234 :
235 0 : vrfname = pim_cli_get_vrf_name(vty);
236 0 : if (vrfname == NULL)
237 : return CMD_WARNING_CONFIG_FAILED;
238 :
239 0 : snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
240 : "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
241 0 : strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
242 :
243 0 : nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
244 : kat);
245 :
246 0 : return nb_cli_apply_changes(vty, NULL);
247 : }
248 :
249 0 : int pim_process_no_keepalivetimer_cmd(struct vty *vty)
250 : {
251 0 : const char *vrfname;
252 0 : char ka_timer_xpath[XPATH_MAXLEN];
253 :
254 0 : vrfname = pim_cli_get_vrf_name(vty);
255 0 : if (vrfname == NULL)
256 : return CMD_WARNING_CONFIG_FAILED;
257 :
258 0 : snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_VRF_XPATH,
259 : "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL);
260 0 : strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
261 :
262 0 : nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_DESTROY, NULL);
263 :
264 0 : return nb_cli_apply_changes(vty, NULL);
265 : }
266 :
267 0 : int pim_process_rp_kat_cmd(struct vty *vty, const char *rpkat)
268 : {
269 0 : const char *vrfname;
270 0 : char rp_ka_timer_xpath[XPATH_MAXLEN];
271 :
272 0 : vrfname = pim_cli_get_vrf_name(vty);
273 0 : if (vrfname == NULL)
274 : return CMD_WARNING_CONFIG_FAILED;
275 :
276 0 : 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 0 : strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
280 : sizeof(rp_ka_timer_xpath));
281 :
282 0 : nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
283 : rpkat);
284 :
285 0 : return nb_cli_apply_changes(vty, NULL);
286 : }
287 :
288 0 : int pim_process_no_rp_kat_cmd(struct vty *vty)
289 : {
290 0 : const char *vrfname;
291 0 : char rp_ka_timer[6];
292 0 : char rp_ka_timer_xpath[XPATH_MAXLEN];
293 0 : uint v;
294 0 : char rs_timer_xpath[XPATH_MAXLEN];
295 :
296 0 : snprintf(rs_timer_xpath, sizeof(rs_timer_xpath),
297 : FRR_PIM_ROUTER_XPATH, FRR_PIM_AF_XPATH_VAL);
298 0 : strlcat(rs_timer_xpath, "/register-suppress-time",
299 : sizeof(rs_timer_xpath));
300 :
301 : /* RFC4601 */
302 0 : v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
303 : rs_timer_xpath);
304 0 : v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
305 0 : if (v > UINT16_MAX)
306 : v = UINT16_MAX;
307 0 : snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%u", v);
308 :
309 0 : vrfname = pim_cli_get_vrf_name(vty);
310 0 : if (vrfname == NULL)
311 : return CMD_WARNING_CONFIG_FAILED;
312 :
313 0 : 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 0 : strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
317 : sizeof(rp_ka_timer_xpath));
318 :
319 0 : nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
320 : rp_ka_timer);
321 :
322 0 : return nb_cli_apply_changes(vty, NULL);
323 : }
324 :
325 0 : int pim_process_register_suppress_cmd(struct vty *vty, const char *rst)
326 : {
327 0 : char xpath[XPATH_MAXLEN];
328 :
329 0 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
330 : FRR_PIM_AF_XPATH_VAL);
331 0 : strlcat(xpath, "/register-suppress-time", sizeof(xpath));
332 :
333 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rst);
334 :
335 0 : return nb_cli_apply_changes(vty, NULL);
336 : }
337 :
338 0 : int pim_process_no_register_suppress_cmd(struct vty *vty)
339 : {
340 0 : char xpath[XPATH_MAXLEN];
341 :
342 0 : snprintf(xpath, sizeof(xpath), FRR_PIM_ROUTER_XPATH,
343 : FRR_PIM_AF_XPATH_VAL);
344 0 : strlcat(xpath, "/register-suppress-time", sizeof(xpath));
345 :
346 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
347 :
348 0 : return nb_cli_apply_changes(vty, NULL);
349 : }
350 :
351 50 : int pim_process_ip_pim_cmd(struct vty *vty)
352 : {
353 50 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
354 :
355 50 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
356 : FRR_PIM_AF_XPATH_VAL);
357 : }
358 :
359 0 : int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable)
360 : {
361 0 : if (enable)
362 0 : nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
363 : "true");
364 : else
365 0 : nb_cli_enqueue_change(vty, "./pim-passive-enable", NB_OP_MODIFY,
366 : "false");
367 :
368 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
369 : FRR_PIM_AF_XPATH_VAL);
370 : }
371 :
372 0 : int pim_process_no_ip_pim_cmd(struct vty *vty)
373 : {
374 0 : const struct lyd_node *mld_enable_dnode;
375 0 : char mld_if_xpath[XPATH_MAXLEN];
376 :
377 0 : int printed =
378 0 : snprintf(mld_if_xpath, sizeof(mld_if_xpath),
379 : "%s/frr-gmp:gmp/address-family[address-family='%s']",
380 0 : VTY_CURR_XPATH, FRR_PIM_AF_XPATH_VAL);
381 :
382 0 : if (printed >= (int)(sizeof(mld_if_xpath))) {
383 0 : vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
384 : XPATH_MAXLEN);
385 0 : return CMD_WARNING_CONFIG_FAILED;
386 : }
387 :
388 0 : mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
389 0 : FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
390 : FRR_PIM_AF_XPATH_VAL);
391 :
392 0 : if (!mld_enable_dnode) {
393 0 : nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY, NULL);
394 0 : nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
395 : } else {
396 0 : if (!yang_dnode_get_bool(mld_enable_dnode, ".")) {
397 0 : nb_cli_enqueue_change(vty, mld_if_xpath, NB_OP_DESTROY,
398 : NULL);
399 0 : nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
400 : } else
401 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
402 : "false");
403 : }
404 :
405 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
406 : FRR_PIM_AF_XPATH_VAL);
407 : }
408 :
409 0 : int pim_process_ip_pim_drprio_cmd(struct vty *vty, const char *drpriority_str)
410 : {
411 0 : nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
412 : drpriority_str);
413 :
414 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
415 : FRR_PIM_AF_XPATH_VAL);
416 : }
417 :
418 0 : int pim_process_no_ip_pim_drprio_cmd(struct vty *vty)
419 : {
420 0 : nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_DESTROY, NULL);
421 :
422 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
423 : FRR_PIM_AF_XPATH_VAL);
424 : }
425 :
426 34 : int pim_process_ip_pim_hello_cmd(struct vty *vty, const char *hello_str,
427 : const char *hold_str)
428 : {
429 34 : const struct lyd_node *mld_enable_dnode;
430 :
431 68 : mld_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
432 34 : FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
433 : FRR_PIM_AF_XPATH_VAL);
434 :
435 34 : if (!mld_enable_dnode) {
436 25 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
437 : "true");
438 : } else {
439 9 : if (!yang_dnode_get_bool(mld_enable_dnode, "."))
440 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
441 : "true");
442 : }
443 :
444 34 : nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY, hello_str);
445 :
446 34 : if (hold_str)
447 34 : nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
448 : hold_str);
449 :
450 34 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
451 : FRR_PIM_AF_XPATH_VAL);
452 : }
453 :
454 0 : int pim_process_no_ip_pim_hello_cmd(struct vty *vty)
455 : {
456 0 : nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_DESTROY, NULL);
457 0 : nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
458 :
459 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
460 : FRR_PIM_AF_XPATH_VAL);
461 : }
462 :
463 0 : int pim_process_ip_pim_activeactive_cmd(struct vty *vty, const char *no)
464 : {
465 0 : if (no)
466 0 : nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
467 : "false");
468 : else {
469 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
470 : "true");
471 :
472 0 : nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
473 : "true");
474 : }
475 :
476 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
477 : FRR_PIM_AF_XPATH_VAL);
478 : }
479 :
480 0 : int pim_process_ip_pim_boundary_oil_cmd(struct vty *vty, const char *oil)
481 : {
482 0 : nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
483 : oil);
484 :
485 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
486 : FRR_PIM_AF_XPATH_VAL);
487 : }
488 :
489 0 : int pim_process_no_ip_pim_boundary_oil_cmd(struct vty *vty)
490 : {
491 0 : nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
492 : NULL);
493 :
494 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
495 : FRR_PIM_AF_XPATH_VAL);
496 : }
497 :
498 0 : int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
499 : const char *group_str, const char *source_str)
500 : {
501 0 : nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
502 :
503 0 : if (!source_str) {
504 0 : char buf[SRCDEST2STR_BUFFER];
505 :
506 0 : inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
507 0 : return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
508 : FRR_PIM_AF_XPATH_VAL, buf,
509 : group_str);
510 : }
511 :
512 0 : return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
513 : FRR_PIM_AF_XPATH_VAL, source_str,
514 : group_str);
515 : }
516 :
517 0 : int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
518 : const char *group_str, const char *source_str)
519 : {
520 0 : nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
521 :
522 0 : if (!source_str) {
523 0 : char buf[SRCDEST2STR_BUFFER];
524 :
525 0 : inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
526 0 : return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
527 : FRR_PIM_AF_XPATH_VAL, buf,
528 : group_str);
529 : }
530 :
531 0 : return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
532 : FRR_PIM_AF_XPATH_VAL, source_str,
533 : group_str);
534 : }
535 :
536 4 : int pim_process_rp_cmd(struct vty *vty, const char *rp_str,
537 : const char *group_str)
538 : {
539 4 : const char *vrfname;
540 4 : char rp_group_xpath[XPATH_MAXLEN];
541 4 : int result = 0;
542 4 : struct prefix group;
543 4 : pim_addr rp_addr;
544 :
545 4 : result = str2prefix(group_str, &group);
546 4 : if (result) {
547 4 : struct prefix temp;
548 :
549 4 : prefix_copy(&temp, &group);
550 4 : apply_mask(&temp);
551 4 : if (!prefix_same(&group, &temp)) {
552 0 : vty_out(vty, "%% Inconsistent address and mask: %s\n",
553 : group_str);
554 0 : return CMD_WARNING_CONFIG_FAILED;
555 : }
556 : }
557 :
558 4 : if (!result) {
559 0 : vty_out(vty, "%% Bad group address specified: %s\n", group_str);
560 0 : return CMD_WARNING_CONFIG_FAILED;
561 : }
562 :
563 4 : result = inet_pton(PIM_AF, rp_str, &rp_addr);
564 4 : if (result <= 0) {
565 0 : vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
566 0 : return CMD_WARNING_CONFIG_FAILED;
567 : }
568 :
569 4 : if (pim_addr_is_any(rp_addr) || pim_addr_is_multicast(rp_addr)) {
570 0 : vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
571 0 : return CMD_WARNING_CONFIG_FAILED;
572 : }
573 :
574 : #if PIM_IPV == 6
575 2 : if (IN6_IS_ADDR_LINKLOCAL(&rp_addr)) {
576 0 : vty_out(vty, "%% Bad RP address specified: %s\n", rp_str);
577 0 : return CMD_WARNING_CONFIG_FAILED;
578 : }
579 : #endif
580 :
581 4 : vrfname = pim_cli_get_vrf_name(vty);
582 4 : if (vrfname == NULL)
583 : return CMD_WARNING_CONFIG_FAILED;
584 :
585 4 : snprintf(rp_group_xpath, sizeof(rp_group_xpath),
586 : FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
587 : FRR_PIM_AF_XPATH_VAL, rp_str);
588 4 : strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
589 :
590 4 : nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
591 :
592 4 : return nb_cli_apply_changes(vty, NULL);
593 : }
594 :
595 0 : int pim_process_no_rp_cmd(struct vty *vty, const char *rp_str,
596 : const char *group_str)
597 : {
598 0 : char group_list_xpath[XPATH_MAXLEN];
599 0 : char group_xpath[XPATH_MAXLEN];
600 0 : char rp_xpath[XPATH_MAXLEN];
601 0 : int printed;
602 0 : const char *vrfname;
603 0 : const struct lyd_node *group_dnode;
604 :
605 0 : vrfname = pim_cli_get_vrf_name(vty);
606 0 : if (vrfname == NULL)
607 : return CMD_WARNING_CONFIG_FAILED;
608 :
609 0 : snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
610 : "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
611 :
612 0 : printed = snprintf(group_list_xpath, sizeof(group_list_xpath),
613 : "%s/group-list", rp_xpath);
614 :
615 0 : if (printed >= (int)(sizeof(group_list_xpath))) {
616 0 : vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
617 : XPATH_MAXLEN);
618 0 : return CMD_WARNING_CONFIG_FAILED;
619 : }
620 :
621 0 : printed = snprintf(group_xpath, sizeof(group_xpath), "%s[.='%s']",
622 : group_list_xpath, group_str);
623 :
624 0 : if (printed >= (int)(sizeof(group_xpath))) {
625 0 : vty_out(vty, "Xpath too long (%d > %u)", printed + 1,
626 : XPATH_MAXLEN);
627 0 : return CMD_WARNING_CONFIG_FAILED;
628 : }
629 :
630 0 : group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
631 0 : if (!group_dnode) {
632 0 : vty_out(vty, "%% Unable to find specified RP\n");
633 0 : return NB_OK;
634 : }
635 :
636 0 : if (yang_is_last_list_dnode(group_dnode))
637 0 : nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
638 : else
639 0 : nb_cli_enqueue_change(vty, group_list_xpath, NB_OP_DESTROY,
640 : group_str);
641 :
642 0 : return nb_cli_apply_changes(vty, NULL);
643 : }
644 :
645 0 : int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str,
646 : const char *prefix_list)
647 : {
648 0 : const char *vrfname;
649 0 : char rp_plist_xpath[XPATH_MAXLEN];
650 :
651 0 : vrfname = pim_cli_get_vrf_name(vty);
652 0 : if (vrfname == NULL)
653 : return CMD_WARNING_CONFIG_FAILED;
654 :
655 0 : snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
656 : FRR_PIM_STATIC_RP_XPATH, "frr-pim:pimd", "pim", vrfname,
657 : FRR_PIM_AF_XPATH_VAL, rp_str);
658 0 : strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
659 :
660 0 : nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY, prefix_list);
661 :
662 0 : return nb_cli_apply_changes(vty, NULL);
663 : }
664 :
665 0 : int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str,
666 : const char *prefix_list)
667 : {
668 0 : char rp_xpath[XPATH_MAXLEN];
669 0 : char plist_xpath[XPATH_MAXLEN];
670 0 : const char *vrfname;
671 0 : const struct lyd_node *plist_dnode;
672 0 : const char *plist;
673 :
674 0 : vrfname = pim_cli_get_vrf_name(vty);
675 0 : if (vrfname == NULL)
676 : return CMD_WARNING_CONFIG_FAILED;
677 :
678 0 : snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
679 : "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
680 :
681 0 : snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
682 : "frr-pim:pimd", "pim", vrfname, FRR_PIM_AF_XPATH_VAL, rp_str);
683 0 : strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
684 :
685 0 : plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
686 0 : if (!plist_dnode) {
687 0 : vty_out(vty, "%% Unable to find specified RP\n");
688 0 : return NB_OK;
689 : }
690 :
691 0 : plist = yang_dnode_get_string(plist_dnode, "%s", plist_xpath);
692 0 : if (strcmp(prefix_list, plist)) {
693 0 : vty_out(vty, "%% Unable to find specified RP\n");
694 0 : return NB_OK;
695 : }
696 :
697 0 : nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
698 :
699 0 : return nb_cli_apply_changes(vty, NULL);
700 : }
701 :
702 25 : bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
703 : {
704 25 : return (pim_addr_is_any(match.grp) ||
705 25 : !pim_addr_cmp(match.grp, item.grp)) &&
706 25 : (pim_addr_is_any(match.src) ||
707 0 : !pim_addr_cmp(match.src, item.src));
708 : }
709 :
710 17 : void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp)
711 : {
712 17 : struct pim_interface *pim_ifp;
713 :
714 17 : pim_ifp = ifp->info;
715 17 : json_object_string_add(json, "name", ifp->name);
716 17 : json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down");
717 17 : json_object_string_addf(json, "address", "%pPA",
718 : &pim_ifp->primary_address);
719 17 : json_object_int_add(json, "index", ifp->ifindex);
720 :
721 17 : if (if_is_multicast(ifp))
722 17 : json_object_boolean_true_add(json, "flagMulticast");
723 :
724 17 : if (if_is_broadcast(ifp))
725 17 : json_object_boolean_true_add(json, "flagBroadcast");
726 :
727 17 : if (ifp->flags & IFF_ALLMULTI)
728 0 : json_object_boolean_true_add(json, "flagAllMulticast");
729 :
730 17 : if (ifp->flags & IFF_PROMISC)
731 0 : json_object_boolean_true_add(json, "flagPromiscuous");
732 :
733 17 : if (PIM_IF_IS_DELETED(ifp))
734 0 : json_object_boolean_true_add(json, "flagDeleted");
735 :
736 17 : if (pim_if_lan_delay_enabled(ifp))
737 17 : json_object_boolean_true_add(json, "lanDelayEnabled");
738 17 : }
739 :
740 0 : void pim_print_ifp_flags(struct vty *vty, struct interface *ifp)
741 : {
742 0 : vty_out(vty, "Flags\n");
743 0 : vty_out(vty, "-----\n");
744 0 : vty_out(vty, "All Multicast : %s\n",
745 0 : (ifp->flags & IFF_ALLMULTI) ? "yes" : "no");
746 0 : vty_out(vty, "Broadcast : %s\n",
747 0 : if_is_broadcast(ifp) ? "yes" : "no");
748 0 : vty_out(vty, "Deleted : %s\n",
749 0 : PIM_IF_IS_DELETED(ifp) ? "yes" : "no");
750 0 : vty_out(vty, "Interface Index : %d\n", ifp->ifindex);
751 0 : vty_out(vty, "Multicast : %s\n",
752 0 : if_is_multicast(ifp) ? "yes" : "no");
753 0 : vty_out(vty, "Promiscuous : %s\n",
754 0 : (ifp->flags & IFF_PROMISC) ? "yes" : "no");
755 0 : vty_out(vty, "\n");
756 0 : vty_out(vty, "\n");
757 0 : }
758 :
759 8 : void json_object_pim_upstream_add(json_object *json, struct pim_upstream *up)
760 : {
761 8 : json_object_boolean_add(
762 : json, "drJoinDesired",
763 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED));
764 8 : json_object_boolean_add(
765 : json, "drJoinDesiredUpdated",
766 8 : CHECK_FLAG(up->flags,
767 : PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED));
768 8 : json_object_boolean_add(
769 : json, "firstHopRouter",
770 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FHR));
771 8 : json_object_boolean_add(
772 : json, "sourceIgmp",
773 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP));
774 8 : json_object_boolean_add(
775 : json, "sourcePim",
776 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_PIM));
777 8 : json_object_boolean_add(
778 : json, "sourceStream",
779 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM));
780 : /* XXX: need to print ths flag in the plain text display as well */
781 8 : json_object_boolean_add(
782 : json, "sourceMsdp",
783 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_MSDP));
784 8 : json_object_boolean_add(
785 : json, "sendSGRptPrune",
786 8 : CHECK_FLAG(up->flags,
787 : PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE));
788 8 : json_object_boolean_add(
789 : json, "lastHopRouter",
790 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_LHR));
791 8 : json_object_boolean_add(
792 : json, "disableKATExpiry",
793 8 : CHECK_FLAG(up->flags,
794 : PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY));
795 8 : json_object_boolean_add(
796 : json, "staticIncomingInterface",
797 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_STATIC_IIF));
798 8 : json_object_boolean_add(
799 : json, "allowIncomingInterfaceinOil",
800 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL));
801 8 : json_object_boolean_add(
802 : json, "noPimRegistrationData",
803 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA));
804 8 : json_object_boolean_add(
805 : json, "forcePimRegistration",
806 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG));
807 8 : json_object_boolean_add(
808 : json, "sourceVxlanOrigination",
809 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG));
810 8 : json_object_boolean_add(
811 : json, "sourceVxlanTermination",
812 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM));
813 8 : json_object_boolean_add(
814 : json, "mlagVxlan",
815 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN));
816 8 : json_object_boolean_add(
817 : json, "mlagNonDesignatedForwarder",
818 8 : CHECK_FLAG(up->flags, PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF));
819 8 : }
820 :
821 : static const char *
822 8 : pim_upstream_state2brief_str(enum pim_upstream_state join_state,
823 : char *state_str, size_t state_str_len)
824 : {
825 8 : switch (join_state) {
826 7 : case PIM_UPSTREAM_NOTJOINED:
827 7 : strlcpy(state_str, "NotJ", state_str_len);
828 7 : break;
829 1 : case PIM_UPSTREAM_JOINED:
830 1 : strlcpy(state_str, "J", state_str_len);
831 1 : break;
832 0 : default:
833 0 : strlcpy(state_str, "Unk", state_str_len);
834 : }
835 8 : return state_str;
836 : }
837 :
838 6 : static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state,
839 : char *state_str,
840 : size_t state_str_len)
841 : {
842 6 : switch (reg_state) {
843 0 : case PIM_REG_NOINFO:
844 0 : strlcpy(state_str, "RegNI", state_str_len);
845 0 : break;
846 0 : case PIM_REG_JOIN:
847 0 : strlcpy(state_str, "RegJ", state_str_len);
848 0 : break;
849 6 : case PIM_REG_JOIN_PENDING:
850 : case PIM_REG_PRUNE:
851 6 : strlcpy(state_str, "RegP", state_str_len);
852 6 : break;
853 : }
854 6 : return state_str;
855 : }
856 :
857 0 : void pim_show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
858 : time_t now, json_object *json)
859 : {
860 0 : char refresh_uptime[10];
861 :
862 0 : pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
863 : pim->rpf_cache_refresh_last);
864 :
865 0 : if (json) {
866 0 : json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
867 0 : router->rpf_cache_refresh_delay_msec);
868 0 : json_object_int_add(
869 : json, "rpfCacheRefreshTimer",
870 : pim_time_timer_remain_msec(pim->rpf_cache_refresher));
871 0 : json_object_int_add(json, "rpfCacheRefreshRequests",
872 : pim->rpf_cache_refresh_requests);
873 0 : json_object_int_add(json, "rpfCacheRefreshEvents",
874 : pim->rpf_cache_refresh_events);
875 0 : json_object_string_add(json, "rpfCacheRefreshLast",
876 : refresh_uptime);
877 0 : json_object_int_add(json, "nexthopLookups",
878 : pim->nexthop_lookups);
879 0 : json_object_int_add(json, "nexthopLookupsAvoided",
880 : pim->nexthop_lookups_avoided);
881 : } else {
882 0 : vty_out(vty,
883 : "RPF Cache Refresh Delay: %ld msecs\n"
884 : "RPF Cache Refresh Timer: %ld msecs\n"
885 : "RPF Cache Refresh Requests: %lld\n"
886 : "RPF Cache Refresh Events: %lld\n"
887 : "RPF Cache Refresh Last: %s\n"
888 : "Nexthop Lookups: %lld\n"
889 : "Nexthop Lookups Avoided: %lld\n",
890 0 : router->rpf_cache_refresh_delay_msec,
891 : pim_time_timer_remain_msec(pim->rpf_cache_refresher),
892 0 : (long long)pim->rpf_cache_refresh_requests,
893 0 : (long long)pim->rpf_cache_refresh_events,
894 0 : refresh_uptime, (long long)pim->nexthop_lookups,
895 0 : (long long)pim->nexthop_lookups_avoided);
896 : }
897 0 : }
898 :
899 0 : void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
900 : {
901 0 : struct pim_upstream *up;
902 0 : time_t now = pim_time_monotonic_sec();
903 0 : struct ttable *tt = NULL;
904 0 : char *table = NULL;
905 0 : json_object *json_group = NULL;
906 0 : json_object *json_row = NULL;
907 :
908 0 : pim_show_rpf_refresh_stats(vty, pim, now, json);
909 :
910 0 : if (!json) {
911 0 : vty_out(vty, "\n");
912 :
913 : /* Prepare table. */
914 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
915 0 : ttable_add_row(
916 : tt,
917 : "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
918 0 : tt->style.cell.rpad = 2;
919 0 : tt->style.corner = '+';
920 0 : ttable_restyle(tt);
921 : }
922 :
923 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
924 0 : const char *rpf_ifname;
925 0 : struct pim_rpf *rpf = &up->rpf;
926 :
927 0 : rpf_ifname =
928 0 : rpf->source_nexthop.interface ? rpf->source_nexthop
929 : .interface->name
930 0 : : "<ifname?>";
931 :
932 0 : if (json) {
933 0 : char grp_str[PIM_ADDRSTRLEN];
934 0 : char src_str[PIM_ADDRSTRLEN];
935 :
936 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
937 : &up->sg.grp);
938 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
939 : &up->sg.src);
940 :
941 0 : json_object_object_get_ex(json, grp_str, &json_group);
942 :
943 0 : if (!json_group) {
944 0 : json_group = json_object_new_object();
945 0 : json_object_object_add(json, grp_str,
946 : json_group);
947 : }
948 :
949 0 : json_row = json_object_new_object();
950 0 : json_object_string_add(json_row, "source", src_str);
951 0 : json_object_string_add(json_row, "group", grp_str);
952 0 : json_object_string_add(json_row, "rpfInterface",
953 : rpf_ifname);
954 0 : json_object_string_addf(json_row, "rpfAddress", "%pPA",
955 : &rpf->rpf_addr);
956 0 : json_object_string_addf(
957 : json_row, "ribNexthop", "%pPAs",
958 : &rpf->source_nexthop.mrib_nexthop_addr);
959 0 : json_object_int_add(
960 : json_row, "routeMetric",
961 0 : rpf->source_nexthop.mrib_route_metric);
962 0 : json_object_int_add(
963 : json_row, "routePreference",
964 0 : rpf->source_nexthop.mrib_metric_preference);
965 0 : json_object_object_add(json_group, src_str, json_row);
966 :
967 : } else {
968 0 : ttable_add_row(
969 : tt, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
970 : &up->sg.src, &up->sg.grp, rpf_ifname,
971 : &rpf->rpf_addr,
972 : &rpf->source_nexthop.mrib_nexthop_addr,
973 : rpf->source_nexthop.mrib_route_metric,
974 : rpf->source_nexthop.mrib_metric_preference);
975 : }
976 : }
977 : /* Dump the generated table. */
978 0 : if (!json) {
979 0 : table = ttable_dump(tt, "\n");
980 0 : vty_out(vty, "%s\n", table);
981 0 : XFREE(MTYPE_TMP, table);
982 0 : ttable_del(tt);
983 : }
984 0 : }
985 :
986 0 : void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
987 : {
988 0 : struct interface *ifp;
989 0 : struct ttable *tt = NULL;
990 0 : char *table = NULL;
991 :
992 : /* Prepare table. */
993 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
994 0 : ttable_add_row(tt, "Interface|Address|Neighbor|Secondary");
995 0 : tt->style.cell.rpad = 2;
996 0 : tt->style.corner = '+';
997 0 : ttable_restyle(tt);
998 :
999 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
1000 0 : struct pim_interface *pim_ifp;
1001 0 : pim_addr ifaddr;
1002 0 : struct listnode *neighnode;
1003 0 : struct pim_neighbor *neigh;
1004 :
1005 0 : pim_ifp = ifp->info;
1006 :
1007 0 : if (!pim_ifp)
1008 0 : continue;
1009 :
1010 0 : if (pim_ifp->pim_sock_fd < 0)
1011 0 : continue;
1012 :
1013 0 : ifaddr = pim_ifp->primary_address;
1014 :
1015 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1016 : neigh)) {
1017 0 : struct listnode *prefix_node;
1018 0 : struct prefix *p;
1019 :
1020 0 : if (!neigh->prefix_list)
1021 0 : continue;
1022 :
1023 0 : for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
1024 : prefix_node, p))
1025 0 : ttable_add_row(tt, "%s|%pPAs|%pPAs|%pFX",
1026 0 : ifp->name, &ifaddr,
1027 : &neigh->source_addr, p);
1028 : }
1029 : }
1030 : /* Dump the generated table. */
1031 0 : table = ttable_dump(tt, "\n");
1032 0 : vty_out(vty, "%s\n", table);
1033 0 : XFREE(MTYPE_TMP, table);
1034 0 : ttable_del(tt);
1035 0 : }
1036 :
1037 0 : void pim_show_state(struct pim_instance *pim, struct vty *vty,
1038 : const char *src_or_group, const char *group,
1039 : json_object *json)
1040 : {
1041 0 : struct channel_oil *c_oil;
1042 : #if PIM_IPV != 4
1043 0 : struct ttable *tt = NULL;
1044 0 : char *table = NULL;
1045 : #endif
1046 0 : char flag[50];
1047 0 : json_object *json_group = NULL;
1048 0 : json_object *json_ifp_in = NULL;
1049 0 : json_object *json_ifp_out = NULL;
1050 0 : json_object *json_source = NULL;
1051 0 : time_t now;
1052 0 : int first_oif;
1053 :
1054 0 : now = pim_time_monotonic_sec();
1055 :
1056 0 : if (!json) {
1057 0 : vty_out(vty,
1058 : "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
1059 : #if PIM_IPV == 4
1060 0 : vty_out(vty,
1061 : "Active Source Group RPT IIF OIL\n");
1062 : #else
1063 : /* Prepare table. */
1064 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1065 0 : ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL");
1066 0 : tt->style.cell.rpad = 2;
1067 0 : tt->style.corner = '+';
1068 0 : ttable_restyle(tt);
1069 : #endif
1070 : }
1071 :
1072 0 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
1073 0 : char src_str[PIM_ADDRSTRLEN];
1074 0 : char grp_str[PIM_ADDRSTRLEN];
1075 0 : char in_ifname[INTERFACE_NAMSIZ + 1];
1076 0 : char out_ifname[INTERFACE_NAMSIZ + 1];
1077 0 : int oif_vif_index;
1078 0 : struct interface *ifp_in;
1079 0 : bool isRpt;
1080 :
1081 0 : first_oif = 1;
1082 :
1083 0 : if ((c_oil->up &&
1084 0 : PIM_UPSTREAM_FLAG_TEST_USE_RPT(c_oil->up->flags)) ||
1085 0 : pim_addr_is_any(*oil_origin(c_oil)))
1086 : isRpt = true;
1087 : else
1088 : isRpt = false;
1089 :
1090 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1091 : oil_mcastgrp(c_oil));
1092 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
1093 : oil_origin(c_oil));
1094 0 : ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
1095 :
1096 0 : if (ifp_in)
1097 0 : strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
1098 : else
1099 0 : strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
1100 :
1101 0 : if (src_or_group) {
1102 0 : if (strcmp(src_or_group, src_str) &&
1103 0 : strcmp(src_or_group, grp_str))
1104 0 : continue;
1105 :
1106 0 : if (group && strcmp(group, grp_str))
1107 0 : continue;
1108 : }
1109 :
1110 0 : if (json) {
1111 :
1112 : /* Find the group, create it if it doesn't exist */
1113 0 : json_object_object_get_ex(json, grp_str, &json_group);
1114 :
1115 0 : if (!json_group) {
1116 0 : json_group = json_object_new_object();
1117 0 : json_object_object_add(json, grp_str,
1118 : json_group);
1119 : }
1120 :
1121 : /* Find the source nested under the group, create it if
1122 : * it doesn't exist
1123 : */
1124 0 : json_object_object_get_ex(json_group, src_str,
1125 : &json_source);
1126 :
1127 0 : if (!json_source) {
1128 0 : json_source = json_object_new_object();
1129 0 : json_object_object_add(json_group, src_str,
1130 : json_source);
1131 : }
1132 :
1133 : /* Find the inbound interface nested under the source,
1134 : * create it if it doesn't exist
1135 : */
1136 0 : json_object_object_get_ex(json_source, in_ifname,
1137 : &json_ifp_in);
1138 :
1139 0 : if (!json_ifp_in) {
1140 0 : json_ifp_in = json_object_new_object();
1141 0 : json_object_object_add(json_source, in_ifname,
1142 : json_ifp_in);
1143 0 : json_object_int_add(json_source, "installed",
1144 0 : c_oil->installed);
1145 0 : json_object_boolean_add(json_source, "isRpt",
1146 : isRpt);
1147 0 : json_object_int_add(json_source, "refCount",
1148 0 : c_oil->oil_ref_count);
1149 0 : json_object_int_add(json_source, "oilListSize",
1150 0 : c_oil->oil_size);
1151 0 : json_object_int_add(
1152 : json_source, "oilRescan",
1153 0 : c_oil->oil_inherited_rescan);
1154 0 : json_object_int_add(json_source, "lastUsed",
1155 0 : c_oil->cc.lastused);
1156 0 : json_object_int_add(json_source, "packetCount",
1157 0 : c_oil->cc.pktcnt);
1158 0 : json_object_int_add(json_source, "byteCount",
1159 0 : c_oil->cc.bytecnt);
1160 0 : json_object_int_add(json_source,
1161 : "wrongInterface",
1162 0 : c_oil->cc.wrong_if);
1163 : }
1164 : }
1165 : #if PIM_IPV == 4
1166 : else
1167 0 : vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
1168 : c_oil->installed, oil_origin(c_oil),
1169 : oil_mcastgrp(c_oil), isRpt ? "y" : "n",
1170 : in_ifname);
1171 : #endif
1172 :
1173 0 : for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
1174 0 : ++oif_vif_index) {
1175 0 : struct interface *ifp_out;
1176 0 : char oif_uptime[10];
1177 0 : int ttl;
1178 :
1179 0 : ttl = oil_if_has(c_oil, oif_vif_index);
1180 0 : if (ttl < 1)
1181 0 : continue;
1182 :
1183 0 : ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
1184 0 : pim_time_uptime(
1185 : oif_uptime, sizeof(oif_uptime),
1186 0 : now - c_oil->oif_creation[oif_vif_index]);
1187 :
1188 0 : if (ifp_out)
1189 0 : strlcpy(out_ifname, ifp_out->name,
1190 : sizeof(out_ifname));
1191 : else
1192 0 : strlcpy(out_ifname, "<oif?>",
1193 : sizeof(out_ifname));
1194 :
1195 0 : if (json) {
1196 0 : json_ifp_out = json_object_new_object();
1197 0 : json_object_string_add(json_ifp_out, "source",
1198 : src_str);
1199 0 : json_object_string_add(json_ifp_out, "group",
1200 : grp_str);
1201 0 : json_object_string_add(json_ifp_out,
1202 : "inboundInterface",
1203 : in_ifname);
1204 0 : json_object_string_add(json_ifp_out,
1205 : "outboundInterface",
1206 : out_ifname);
1207 0 : json_object_int_add(json_ifp_out, "installed",
1208 0 : c_oil->installed);
1209 :
1210 0 : json_object_object_add(json_ifp_in, out_ifname,
1211 : json_ifp_out);
1212 : } else {
1213 0 : flag[0] = '\0';
1214 0 : snprintf(flag, sizeof(flag), "(%c%c%c%c%c)",
1215 0 : (c_oil->oif_flags[oif_vif_index] &
1216 : PIM_OIF_FLAG_PROTO_GM)
1217 : ? 'I'
1218 : : ' ',
1219 0 : (c_oil->oif_flags[oif_vif_index] &
1220 : PIM_OIF_FLAG_PROTO_PIM)
1221 : ? 'J'
1222 : : ' ',
1223 0 : (c_oil->oif_flags[oif_vif_index] &
1224 : PIM_OIF_FLAG_PROTO_VXLAN)
1225 : ? 'V'
1226 : : ' ',
1227 0 : (c_oil->oif_flags[oif_vif_index] &
1228 : PIM_OIF_FLAG_PROTO_STAR)
1229 : ? '*'
1230 : : ' ',
1231 0 : (c_oil->oif_flags[oif_vif_index] &
1232 : PIM_OIF_FLAG_MUTE)
1233 : ? 'M'
1234 : : ' ');
1235 :
1236 0 : if (first_oif) {
1237 0 : first_oif = 0;
1238 : #if PIM_IPV == 4
1239 0 : vty_out(vty, "%s%s", out_ifname, flag);
1240 : #else
1241 0 : ttable_add_row(
1242 : tt, "%d|%pPAs|%pPAs|%s|%s|%s%s",
1243 : c_oil->installed,
1244 : oil_origin(c_oil),
1245 : oil_mcastgrp(c_oil),
1246 : isRpt ? "y" : "n", in_ifname,
1247 : out_ifname, flag);
1248 : #endif
1249 : } else {
1250 : #if PIM_IPV == 4
1251 0 : vty_out(vty, ", %s%s", out_ifname,
1252 : flag);
1253 : #else
1254 0 : ttable_add_row(tt,
1255 : "%c|%c|%c|%c|%c|%s%s",
1256 : ' ', ' ', ' ', ' ', ' ',
1257 : out_ifname, flag);
1258 : #endif
1259 : }
1260 : }
1261 : }
1262 : #if PIM_IPV == 4
1263 0 : if (!json)
1264 0 : vty_out(vty, "\n");
1265 : #endif
1266 : }
1267 :
1268 : /* Dump the generated table. */
1269 0 : if (!json) {
1270 : #if PIM_IPV == 4
1271 0 : vty_out(vty, "\n");
1272 : #else
1273 0 : table = ttable_dump(tt, "\n");
1274 0 : vty_out(vty, "%s\n", table);
1275 0 : XFREE(MTYPE_TMP, table);
1276 0 : ttable_del(tt);
1277 : #endif
1278 : }
1279 0 : }
1280 :
1281 : /* pim statistics - just adding only bsm related now.
1282 : * We can continue to add all pim related stats here.
1283 : */
1284 0 : void pim_show_statistics(struct pim_instance *pim, struct vty *vty,
1285 : const char *ifname, bool uj)
1286 : {
1287 0 : json_object *json = NULL;
1288 0 : struct interface *ifp;
1289 :
1290 0 : if (uj) {
1291 0 : json = json_object_new_object();
1292 0 : json_object_int_add(json, "bsmRx", pim->bsm_rcvd);
1293 0 : json_object_int_add(json, "bsmTx", pim->bsm_sent);
1294 0 : json_object_int_add(json, "bsmDropped", pim->bsm_dropped);
1295 : } else {
1296 0 : vty_out(vty, "BSM Statistics :\n");
1297 0 : vty_out(vty, "----------------\n");
1298 0 : vty_out(vty, "Number of Received BSMs : %" PRIu64 "\n",
1299 : pim->bsm_rcvd);
1300 0 : vty_out(vty, "Number of Forwared BSMs : %" PRIu64 "\n",
1301 : pim->bsm_sent);
1302 0 : vty_out(vty, "Number of Dropped BSMs : %" PRIu64 "\n",
1303 : pim->bsm_dropped);
1304 : }
1305 :
1306 0 : vty_out(vty, "\n");
1307 :
1308 : /* scan interfaces */
1309 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
1310 0 : struct pim_interface *pim_ifp = ifp->info;
1311 :
1312 0 : if (ifname && strcmp(ifname, ifp->name))
1313 0 : continue;
1314 :
1315 0 : if (!pim_ifp)
1316 0 : continue;
1317 :
1318 0 : if (!uj) {
1319 0 : vty_out(vty, "Interface : %s\n", ifp->name);
1320 0 : vty_out(vty, "-------------------\n");
1321 0 : vty_out(vty,
1322 : "Number of BSMs dropped due to config miss : %u\n",
1323 : pim_ifp->pim_ifstat_bsm_cfg_miss);
1324 0 : vty_out(vty, "Number of unicast BSMs dropped : %u\n",
1325 : pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1326 0 : vty_out(vty,
1327 : "Number of BSMs dropped due to invalid scope zone : %u\n",
1328 : pim_ifp->pim_ifstat_bsm_invalid_sz);
1329 : } else {
1330 :
1331 0 : json_object *json_row = NULL;
1332 :
1333 0 : json_row = json_object_new_object();
1334 :
1335 0 : json_object_string_add(json_row, "If Name", ifp->name);
1336 0 : json_object_int_add(json_row, "bsmDroppedConfig",
1337 0 : pim_ifp->pim_ifstat_bsm_cfg_miss);
1338 0 : json_object_int_add(
1339 : json_row, "bsmDroppedUnicast",
1340 0 : pim_ifp->pim_ifstat_ucast_bsm_cfg_miss);
1341 0 : json_object_int_add(json_row,
1342 : "bsmDroppedInvalidScopeZone",
1343 0 : pim_ifp->pim_ifstat_bsm_invalid_sz);
1344 0 : json_object_object_add(json, ifp->name, json_row);
1345 : }
1346 0 : vty_out(vty, "\n");
1347 : }
1348 :
1349 0 : if (uj)
1350 0 : vty_json(vty, json);
1351 0 : }
1352 :
1353 4 : void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
1354 : pim_sgaddr *sg, json_object *json)
1355 : {
1356 4 : struct pim_upstream *up;
1357 4 : struct ttable *tt = NULL;
1358 4 : char *table = NULL;
1359 4 : time_t now;
1360 4 : json_object *json_group = NULL;
1361 4 : json_object *json_row = NULL;
1362 :
1363 4 : now = pim_time_monotonic_sec();
1364 :
1365 4 : if (!json) {
1366 : /* Prepare table. */
1367 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1368 0 : ttable_add_row(
1369 : tt,
1370 : "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
1371 0 : tt->style.cell.rpad = 2;
1372 0 : tt->style.corner = '+';
1373 0 : ttable_restyle(tt);
1374 : }
1375 :
1376 24 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1377 8 : char uptime[10];
1378 8 : char join_timer[10];
1379 8 : char rs_timer[10];
1380 8 : char ka_timer[10];
1381 8 : char msdp_reg_timer[10];
1382 8 : char state_str[PIM_REG_STATE_STR_LEN];
1383 :
1384 8 : if (!pim_sgaddr_match(up->sg, *sg))
1385 0 : continue;
1386 :
1387 8 : pim_time_uptime(uptime, sizeof(uptime),
1388 8 : now - up->state_transition);
1389 8 : pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer),
1390 : up->t_join_timer);
1391 :
1392 : /*
1393 : * If the upstream is not dummy and it has a J/P timer for the
1394 : * neighbor display that
1395 : */
1396 8 : if (!up->t_join_timer && up->rpf.source_nexthop.interface) {
1397 8 : struct pim_neighbor *nbr;
1398 :
1399 8 : nbr = pim_neighbor_find(
1400 : up->rpf.source_nexthop.interface,
1401 : up->rpf.rpf_addr);
1402 8 : if (nbr)
1403 2 : pim_time_timer_to_hhmmss(join_timer,
1404 : sizeof(join_timer),
1405 : nbr->jp_timer);
1406 : }
1407 :
1408 8 : pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer),
1409 : up->t_rs_timer);
1410 8 : pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer),
1411 : up->t_ka_timer);
1412 8 : pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer),
1413 : up->t_msdp_reg_timer);
1414 :
1415 8 : pim_upstream_state2brief_str(up->join_state, state_str,
1416 : sizeof(state_str));
1417 8 : if (up->reg_state != PIM_REG_NOINFO) {
1418 6 : char tmp_str[PIM_REG_STATE_STR_LEN];
1419 6 : char tmp[sizeof(state_str) + 1];
1420 :
1421 6 : snprintf(tmp, sizeof(tmp), ",%s",
1422 : pim_reg_state2brief_str(up->reg_state, tmp_str,
1423 : sizeof(tmp_str)));
1424 6 : strlcat(state_str, tmp, sizeof(state_str));
1425 : }
1426 :
1427 8 : if (json) {
1428 8 : char grp_str[PIM_ADDRSTRLEN];
1429 8 : char src_str[PIM_ADDRSTRLEN];
1430 :
1431 8 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1432 : &up->sg.grp);
1433 8 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
1434 : &up->sg.src);
1435 :
1436 8 : json_object_object_get_ex(json, grp_str, &json_group);
1437 :
1438 8 : if (!json_group) {
1439 5 : json_group = json_object_new_object();
1440 5 : json_object_object_add(json, grp_str,
1441 : json_group);
1442 : }
1443 :
1444 8 : json_row = json_object_new_object();
1445 8 : json_object_pim_upstream_add(json_row, up);
1446 8 : json_object_string_add(
1447 : json_row, "inboundInterface",
1448 8 : up->rpf.source_nexthop.interface
1449 : ? up->rpf.source_nexthop.interface->name
1450 : : "Unknown");
1451 :
1452 : /*
1453 : * The RPF address we use is slightly different
1454 : * based upon what we are looking up.
1455 : * If we have a S, list that unless
1456 : * we are the FHR, else we just put
1457 : * the RP as the rpfAddress
1458 : */
1459 8 : if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR ||
1460 9 : pim_addr_is_any(up->sg.src)) {
1461 7 : struct pim_rpf *rpg;
1462 :
1463 7 : rpg = RP(pim, up->sg.grp);
1464 7 : json_object_string_addf(json_row, "rpfAddress",
1465 : "%pPA", &rpg->rpf_addr);
1466 : } else {
1467 1 : json_object_string_add(json_row, "rpfAddress",
1468 : src_str);
1469 : }
1470 :
1471 8 : json_object_string_add(json_row, "source", src_str);
1472 8 : json_object_string_add(json_row, "group", grp_str);
1473 8 : json_object_string_add(json_row, "state", state_str);
1474 8 : json_object_string_add(
1475 : json_row, "joinState",
1476 : pim_upstream_state2str(up->join_state));
1477 8 : json_object_string_add(
1478 : json_row, "regState",
1479 : pim_reg_state2str(up->reg_state, state_str,
1480 : sizeof(state_str)));
1481 8 : json_object_string_add(json_row, "upTime", uptime);
1482 8 : json_object_string_add(json_row, "joinTimer",
1483 : join_timer);
1484 8 : json_object_string_add(json_row, "resetTimer",
1485 : rs_timer);
1486 8 : json_object_string_add(json_row, "keepaliveTimer",
1487 : ka_timer);
1488 8 : json_object_string_add(json_row, "msdpRegTimer",
1489 : msdp_reg_timer);
1490 8 : json_object_int_add(json_row, "refCount",
1491 8 : up->ref_count);
1492 8 : json_object_int_add(json_row, "sptBit", up->sptbit);
1493 8 : json_object_object_add(json_group, src_str, json_row);
1494 : } else {
1495 0 : ttable_add_row(tt,
1496 : "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
1497 0 : up->rpf.source_nexthop.interface
1498 : ? up->rpf.source_nexthop.interface->name
1499 : : "Unknown",
1500 : &up->sg.src, &up->sg.grp, state_str, uptime,
1501 : join_timer, rs_timer, ka_timer, up->ref_count);
1502 : }
1503 : }
1504 : /* Dump the generated table. */
1505 4 : if (!json) {
1506 0 : table = ttable_dump(tt, "\n");
1507 0 : vty_out(vty, "%s\n", table);
1508 0 : XFREE(MTYPE_TMP, table);
1509 0 : ttable_del(tt);
1510 : }
1511 4 : }
1512 :
1513 0 : static void pim_show_join_desired_helper(struct pim_instance *pim,
1514 : struct vty *vty,
1515 : struct pim_upstream *up,
1516 : json_object *json, bool uj,
1517 : struct ttable *tt)
1518 : {
1519 0 : json_object *json_group = NULL;
1520 0 : json_object *json_row = NULL;
1521 :
1522 0 : if (uj) {
1523 0 : char grp_str[PIM_ADDRSTRLEN];
1524 0 : char src_str[PIM_ADDRSTRLEN];
1525 :
1526 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
1527 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs", &up->sg.src);
1528 :
1529 0 : json_object_object_get_ex(json, grp_str, &json_group);
1530 :
1531 0 : if (!json_group) {
1532 0 : json_group = json_object_new_object();
1533 0 : json_object_object_add(json, grp_str, json_group);
1534 : }
1535 :
1536 0 : json_row = json_object_new_object();
1537 0 : json_object_pim_upstream_add(json_row, up);
1538 0 : json_object_string_add(json_row, "source", src_str);
1539 0 : json_object_string_add(json_row, "group", grp_str);
1540 :
1541 0 : if (pim_upstream_evaluate_join_desired(pim, up))
1542 0 : json_object_boolean_true_add(json_row,
1543 : "evaluateJoinDesired");
1544 :
1545 0 : json_object_object_add(json_group, src_str, json_row);
1546 :
1547 : } else {
1548 0 : ttable_add_row(tt, "%pPAs|%pPAs|%s", &up->sg.src, &up->sg.grp,
1549 0 : pim_upstream_evaluate_join_desired(pim, up)
1550 : ? "yes"
1551 : : "no");
1552 : }
1553 0 : }
1554 :
1555 0 : void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
1556 : {
1557 0 : struct pim_upstream *up;
1558 0 : struct ttable *tt = NULL;
1559 0 : char *table = NULL;
1560 :
1561 0 : json_object *json = NULL;
1562 :
1563 0 : if (uj)
1564 0 : json = json_object_new_object();
1565 : else {
1566 : /* Prepare table. */
1567 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1568 0 : ttable_add_row(tt, "Source|Group|EvalJD");
1569 0 : tt->style.cell.rpad = 2;
1570 0 : tt->style.corner = '+';
1571 0 : ttable_restyle(tt);
1572 : }
1573 :
1574 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1575 : /* scan all interfaces */
1576 0 : pim_show_join_desired_helper(pim, vty, up, json, uj, tt);
1577 : }
1578 :
1579 0 : if (uj)
1580 0 : vty_json(vty, json);
1581 : else {
1582 : /* Dump the generated table. */
1583 0 : table = ttable_dump(tt, "\n");
1584 0 : vty_out(vty, "%s\n", table);
1585 0 : XFREE(MTYPE_TMP, table);
1586 0 : ttable_del(tt);
1587 : }
1588 0 : }
1589 :
1590 0 : void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
1591 : {
1592 0 : struct pim_upstream *up;
1593 0 : struct ttable *tt = NULL;
1594 0 : char *table = NULL;
1595 0 : json_object *json = NULL;
1596 0 : json_object *json_group = NULL;
1597 0 : json_object *json_row = NULL;
1598 :
1599 0 : if (uj)
1600 0 : json = json_object_new_object();
1601 : else {
1602 : /* Prepare table. */
1603 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1604 0 : ttable_add_row(tt,
1605 : "Source|Group|RpfIface|RibNextHop|RpfAddress");
1606 0 : tt->style.cell.rpad = 2;
1607 0 : tt->style.corner = '+';
1608 0 : ttable_restyle(tt);
1609 : }
1610 :
1611 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
1612 0 : struct pim_rpf *rpf;
1613 0 : const char *rpf_ifname;
1614 :
1615 0 : rpf = &up->rpf;
1616 :
1617 0 : rpf_ifname =
1618 0 : rpf->source_nexthop.interface ? rpf->source_nexthop
1619 : .interface->name
1620 0 : : "<ifname?>";
1621 :
1622 0 : if (uj) {
1623 0 : char grp_str[PIM_ADDRSTRLEN];
1624 0 : char src_str[PIM_ADDRSTRLEN];
1625 :
1626 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
1627 : &up->sg.grp);
1628 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
1629 : &up->sg.src);
1630 0 : json_object_object_get_ex(json, grp_str, &json_group);
1631 :
1632 0 : if (!json_group) {
1633 0 : json_group = json_object_new_object();
1634 0 : json_object_object_add(json, grp_str,
1635 : json_group);
1636 : }
1637 :
1638 0 : json_row = json_object_new_object();
1639 0 : json_object_pim_upstream_add(json_row, up);
1640 0 : json_object_string_add(json_row, "source", src_str);
1641 0 : json_object_string_add(json_row, "group", grp_str);
1642 0 : json_object_string_add(json_row, "rpfInterface",
1643 : rpf_ifname);
1644 0 : json_object_string_addf(
1645 : json_row, "ribNexthop", "%pPAs",
1646 : &rpf->source_nexthop.mrib_nexthop_addr);
1647 0 : json_object_string_addf(json_row, "rpfAddress", "%pPA",
1648 : &rpf->rpf_addr);
1649 0 : json_object_object_add(json_group, src_str, json_row);
1650 : } else {
1651 0 : ttable_add_row(tt, "%pPAs|%pPAs|%s|%pPA|%pPA",
1652 : &up->sg.src, &up->sg.grp, rpf_ifname,
1653 : &rpf->source_nexthop.mrib_nexthop_addr,
1654 : &rpf->rpf_addr);
1655 : }
1656 : }
1657 :
1658 0 : if (uj)
1659 0 : vty_json(vty, json);
1660 : else {
1661 : /* Dump the generated table. */
1662 0 : table = ttable_dump(tt, "\n");
1663 0 : vty_out(vty, "%s\n", table);
1664 0 : XFREE(MTYPE_TMP, table);
1665 0 : ttable_del(tt);
1666 : }
1667 0 : }
1668 :
1669 17 : static void pim_show_join_helper(struct pim_interface *pim_ifp,
1670 : struct pim_ifchannel *ch, json_object *json,
1671 : time_t now, struct ttable *tt)
1672 : {
1673 17 : json_object *json_iface = NULL;
1674 17 : json_object *json_row = NULL;
1675 17 : json_object *json_grp = NULL;
1676 17 : pim_addr ifaddr;
1677 17 : char uptime[10];
1678 17 : char expire[10];
1679 17 : char prune[10];
1680 :
1681 17 : ifaddr = pim_ifp->primary_address;
1682 :
1683 17 : pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
1684 17 : pim_time_timer_to_mmss(expire, sizeof(expire),
1685 : ch->t_ifjoin_expiry_timer);
1686 17 : pim_time_timer_to_mmss(prune, sizeof(prune),
1687 : ch->t_ifjoin_prune_pending_timer);
1688 :
1689 17 : if (json) {
1690 17 : char ch_grp_str[PIM_ADDRSTRLEN];
1691 :
1692 17 : json_object_object_get_ex(json, ch->interface->name,
1693 : &json_iface);
1694 :
1695 17 : if (!json_iface) {
1696 17 : json_iface = json_object_new_object();
1697 17 : json_object_pim_ifp_add(json_iface, ch->interface);
1698 17 : json_object_object_add(json, ch->interface->name,
1699 : json_iface);
1700 : }
1701 :
1702 17 : json_row = json_object_new_object();
1703 17 : json_object_string_addf(json_row, "source", "%pPAs",
1704 : &ch->sg.src);
1705 17 : json_object_string_addf(json_row, "group", "%pPAs",
1706 : &ch->sg.grp);
1707 17 : json_object_string_add(json_row, "upTime", uptime);
1708 17 : json_object_string_add(json_row, "expire", expire);
1709 17 : json_object_string_add(json_row, "prune", prune);
1710 17 : json_object_string_add(
1711 : json_row, "channelJoinName",
1712 17 : pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
1713 17 : if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
1714 0 : json_object_int_add(json_row, "sgRpt", 1);
1715 17 : if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
1716 15 : json_object_int_add(json_row, "protocolPim", 1);
1717 17 : if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
1718 1 : json_object_int_add(json_row, "protocolIgmp", 1);
1719 17 : snprintfrr(ch_grp_str, sizeof(ch_grp_str), "%pPAs",
1720 : &ch->sg.grp);
1721 17 : json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
1722 17 : if (!json_grp) {
1723 17 : json_grp = json_object_new_object();
1724 17 : json_object_object_addf(json_grp, json_row, "%pPAs",
1725 : &ch->sg.src);
1726 17 : json_object_object_addf(json_iface, json_grp, "%pPAs",
1727 : &ch->sg.grp);
1728 : } else
1729 0 : json_object_object_addf(json_grp, json_row, "%pPAs",
1730 : &ch->sg.src);
1731 : } else {
1732 0 : ttable_add_row(
1733 : tt, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
1734 0 : ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
1735 0 : pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
1736 : uptime, expire, prune);
1737 : }
1738 17 : }
1739 :
1740 18 : int pim_show_join_cmd_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
1741 : pim_addr g, const char *json)
1742 : {
1743 18 : pim_sgaddr sg = {};
1744 18 : struct vrf *v;
1745 18 : struct pim_instance *pim;
1746 18 : json_object *json_parent = NULL;
1747 :
1748 18 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1749 :
1750 18 : if (!v) {
1751 0 : vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
1752 0 : return CMD_WARNING;
1753 : }
1754 18 : pim = v->info;
1755 :
1756 18 : if (!pim) {
1757 0 : vty_out(vty, "%% Unable to find pim instance\n");
1758 0 : return CMD_WARNING;
1759 : }
1760 :
1761 18 : if (!pim_addr_is_any(s_or_g)) {
1762 0 : if (!pim_addr_is_any(g)) {
1763 0 : sg.src = s_or_g;
1764 0 : sg.grp = g;
1765 : } else
1766 0 : sg.grp = s_or_g;
1767 : }
1768 :
1769 18 : if (json)
1770 18 : json_parent = json_object_new_object();
1771 :
1772 18 : pim_show_join(pim, vty, &sg, json_parent);
1773 :
1774 18 : if (json)
1775 18 : vty_json(vty, json_parent);
1776 :
1777 : return CMD_SUCCESS;
1778 : }
1779 :
1780 0 : int pim_show_join_vrf_all_cmd_helper(struct vty *vty, const char *json)
1781 : {
1782 0 : pim_sgaddr sg = {0};
1783 0 : struct vrf *vrf_struct;
1784 0 : json_object *json_parent = NULL;
1785 0 : json_object *json_vrf = NULL;
1786 :
1787 0 : if (json)
1788 0 : json_parent = json_object_new_object();
1789 :
1790 0 : RB_FOREACH (vrf_struct, vrf_name_head, &vrfs_by_name) {
1791 0 : if (!json_parent)
1792 0 : vty_out(vty, "VRF: %s\n", vrf_struct->name);
1793 : else
1794 0 : json_vrf = json_object_new_object();
1795 0 : pim_show_join(vrf_struct->info, vty, &sg, json_vrf);
1796 :
1797 0 : if (json)
1798 0 : json_object_object_add(json_parent, vrf_struct->name,
1799 : json_vrf);
1800 : }
1801 0 : if (json)
1802 0 : vty_json(vty, json_parent);
1803 :
1804 0 : return CMD_WARNING;
1805 : }
1806 :
1807 18 : void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
1808 : json_object *json)
1809 : {
1810 18 : struct pim_interface *pim_ifp;
1811 18 : struct pim_ifchannel *ch;
1812 18 : struct interface *ifp;
1813 18 : time_t now;
1814 18 : struct ttable *tt = NULL;
1815 18 : char *table = NULL;
1816 :
1817 18 : now = pim_time_monotonic_sec();
1818 :
1819 18 : if (!json) {
1820 : /* Prepare table. */
1821 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1822 0 : ttable_add_row(
1823 : tt,
1824 : "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
1825 0 : tt->style.cell.rpad = 2;
1826 0 : tt->style.corner = '+';
1827 0 : ttable_restyle(tt);
1828 : }
1829 :
1830 108 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
1831 72 : pim_ifp = ifp->info;
1832 72 : if (!pim_ifp)
1833 18 : continue;
1834 :
1835 125 : RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1836 17 : if (!pim_sgaddr_match(ch->sg, *sg))
1837 0 : continue;
1838 :
1839 17 : pim_show_join_helper(pim_ifp, ch, json, now, tt);
1840 : } /* scan interface channels */
1841 : }
1842 : /* Dump the generated table. */
1843 18 : if (!json) {
1844 0 : table = ttable_dump(tt, "\n");
1845 0 : vty_out(vty, "%s\n", table);
1846 0 : XFREE(MTYPE_TMP, table);
1847 0 : ttable_del(tt);
1848 : }
1849 18 : }
1850 :
1851 0 : static void pim_show_jp_agg_helper(struct interface *ifp,
1852 : struct pim_neighbor *neigh,
1853 : struct pim_upstream *up, int is_join,
1854 : struct ttable *tt)
1855 : {
1856 0 : ttable_add_row(tt, "%s|%pPAs|%pPAs|%pPAs|%s", ifp->name,
1857 : &neigh->source_addr, &up->sg.src, &up->sg.grp,
1858 : is_join ? "J" : "P");
1859 0 : }
1860 :
1861 0 : int pim_show_jp_agg_list_cmd_helper(const char *vrf, struct vty *vty)
1862 : {
1863 0 : struct vrf *v;
1864 0 : struct pim_instance *pim;
1865 :
1866 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1867 :
1868 0 : if (!v) {
1869 0 : vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
1870 0 : return CMD_WARNING;
1871 : }
1872 0 : pim = v->info;
1873 :
1874 0 : if (!pim) {
1875 0 : vty_out(vty, "%% Unable to find pim instance\n");
1876 0 : return CMD_WARNING;
1877 : }
1878 :
1879 0 : pim_show_jp_agg_list(pim, vty);
1880 :
1881 0 : return CMD_SUCCESS;
1882 : }
1883 :
1884 0 : void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
1885 : {
1886 0 : struct interface *ifp;
1887 0 : struct pim_interface *pim_ifp;
1888 0 : struct listnode *n_node;
1889 0 : struct pim_neighbor *neigh;
1890 0 : struct listnode *jag_node;
1891 0 : struct pim_jp_agg_group *jag;
1892 0 : struct listnode *js_node;
1893 0 : struct pim_jp_sources *js;
1894 0 : struct ttable *tt;
1895 0 : char *table;
1896 :
1897 : /* Prepare table. */
1898 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1899 0 : ttable_add_row(tt, "Interface|RPF Nbr|Source|Group|State");
1900 0 : tt->style.cell.rpad = 2;
1901 0 : tt->style.corner = '+';
1902 0 : ttable_restyle(tt);
1903 :
1904 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
1905 0 : pim_ifp = ifp->info;
1906 0 : if (!pim_ifp)
1907 0 : continue;
1908 :
1909 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, n_node,
1910 : neigh)) {
1911 0 : for (ALL_LIST_ELEMENTS_RO(neigh->upstream_jp_agg,
1912 : jag_node, jag)) {
1913 0 : for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
1914 : js)) {
1915 0 : pim_show_jp_agg_helper(ifp, neigh,
1916 : js->up,
1917 : js->is_join, tt);
1918 : }
1919 : }
1920 : }
1921 : }
1922 :
1923 : /* Dump the generated table. */
1924 0 : table = ttable_dump(tt, "\n");
1925 0 : vty_out(vty, "%s\n", table);
1926 0 : XFREE(MTYPE_TMP, table);
1927 0 : ttable_del(tt);
1928 0 : }
1929 :
1930 0 : int pim_show_membership_cmd_helper(const char *vrf, struct vty *vty, bool uj)
1931 : {
1932 0 : struct vrf *v;
1933 :
1934 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
1935 :
1936 0 : if (!v)
1937 : return CMD_WARNING;
1938 :
1939 0 : pim_show_membership(v->info, vty, uj);
1940 :
1941 0 : return CMD_SUCCESS;
1942 : }
1943 :
1944 0 : static void pim_show_membership_helper(struct vty *vty,
1945 : struct pim_interface *pim_ifp,
1946 : struct pim_ifchannel *ch,
1947 : struct json_object *json)
1948 : {
1949 0 : json_object *json_iface = NULL;
1950 0 : json_object *json_row = NULL;
1951 :
1952 0 : json_object_object_get_ex(json, ch->interface->name, &json_iface);
1953 0 : if (!json_iface) {
1954 0 : json_iface = json_object_new_object();
1955 0 : json_object_pim_ifp_add(json_iface, ch->interface);
1956 0 : json_object_object_add(json, ch->interface->name, json_iface);
1957 : }
1958 :
1959 0 : json_row = json_object_new_object();
1960 0 : json_object_string_addf(json_row, "source", "%pPAs", &ch->sg.src);
1961 0 : json_object_string_addf(json_row, "group", "%pPAs", &ch->sg.grp);
1962 0 : json_object_string_add(json_row, "localMembership",
1963 0 : ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO
1964 : ? "NOINFO"
1965 : : "INCLUDE");
1966 0 : json_object_object_addf(json_iface, json_row, "%pPAs", &ch->sg.grp);
1967 0 : }
1968 :
1969 0 : void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
1970 : {
1971 0 : struct pim_interface *pim_ifp;
1972 0 : struct pim_ifchannel *ch;
1973 0 : struct interface *ifp;
1974 0 : enum json_type type;
1975 0 : json_object *json = NULL;
1976 0 : json_object *json_tmp = NULL;
1977 0 : struct ttable *tt = NULL;
1978 0 : char *table = NULL;
1979 :
1980 0 : json = json_object_new_object();
1981 :
1982 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
1983 0 : pim_ifp = ifp->info;
1984 0 : if (!pim_ifp)
1985 0 : continue;
1986 :
1987 0 : RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1988 0 : pim_show_membership_helper(vty, pim_ifp, ch, json);
1989 : } /* scan interface channels */
1990 : }
1991 :
1992 0 : if (uj) {
1993 0 : vty_json(vty, json);
1994 : } else {
1995 : /* Prepare table. */
1996 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
1997 0 : ttable_add_row(tt, "Interface|Address|Source|Group|Membership");
1998 0 : tt->style.cell.rpad = 2;
1999 0 : tt->style.corner = '+';
2000 0 : ttable_restyle(tt);
2001 :
2002 : /*
2003 : * Example of the json data we are traversing
2004 : *
2005 : * {
2006 : * "swp3":{
2007 : * "name":"swp3",
2008 : * "state":"up",
2009 : * "address":"10.1.20.1",
2010 : * "index":5,
2011 : * "flagMulticast":true,
2012 : * "flagBroadcast":true,
2013 : * "lanDelayEnabled":true,
2014 : * "226.10.10.10":{
2015 : * "source":"*",
2016 : * "group":"226.10.10.10",
2017 : * "localMembership":"INCLUDE"
2018 : * }
2019 : * }
2020 : * }
2021 : */
2022 :
2023 : /* foreach interface */
2024 0 : json_object_object_foreach(json, key, val)
2025 : {
2026 :
2027 : /* Find all of the keys where the val is an object. In
2028 : * the example
2029 : * above the only one is 226.10.10.10
2030 : */
2031 0 : json_object_object_foreach(val, if_field_key,
2032 : if_field_val)
2033 : {
2034 0 : type = json_object_get_type(if_field_val);
2035 :
2036 0 : if (type == json_type_object) {
2037 0 : const char *address, *source,
2038 : *localMembership;
2039 :
2040 0 : json_object_object_get_ex(
2041 : val, "address", &json_tmp);
2042 0 : address = json_object_get_string(
2043 : json_tmp);
2044 :
2045 0 : json_object_object_get_ex(if_field_val,
2046 : "source",
2047 : &json_tmp);
2048 0 : source = json_object_get_string(
2049 : json_tmp);
2050 :
2051 0 : json_object_object_get_ex(
2052 : if_field_val, "localMembership",
2053 : &json_tmp);
2054 0 : localMembership =
2055 0 : json_object_get_string(
2056 : json_tmp);
2057 :
2058 0 : ttable_add_row(tt, "%s|%s|%s|%s|%s",
2059 : key, address, source,
2060 : if_field_key,
2061 : localMembership);
2062 : }
2063 : }
2064 : }
2065 0 : json_object_free(json);
2066 : /* Dump the generated table. */
2067 0 : table = ttable_dump(tt, "\n");
2068 0 : vty_out(vty, "%s\n", table);
2069 0 : XFREE(MTYPE_TMP, table);
2070 0 : ttable_del(tt);
2071 : }
2072 0 : }
2073 :
2074 0 : static void pim_show_channel_helper(struct pim_instance *pim,
2075 : struct pim_interface *pim_ifp,
2076 : struct pim_ifchannel *ch, json_object *json,
2077 : bool uj, struct ttable *tt)
2078 : {
2079 0 : struct pim_upstream *up = ch->upstream;
2080 0 : json_object *json_group = NULL;
2081 0 : json_object *json_row = NULL;
2082 :
2083 0 : if (uj) {
2084 0 : char grp_str[PIM_ADDRSTRLEN];
2085 :
2086 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &up->sg.grp);
2087 0 : json_object_object_get_ex(json, grp_str, &json_group);
2088 :
2089 0 : if (!json_group) {
2090 0 : json_group = json_object_new_object();
2091 0 : json_object_object_add(json, grp_str, json_group);
2092 : }
2093 :
2094 0 : json_row = json_object_new_object();
2095 0 : json_object_pim_upstream_add(json_row, up);
2096 0 : json_object_string_add(json_row, "interface",
2097 0 : ch->interface->name);
2098 0 : json_object_string_addf(json_row, "source", "%pPAs",
2099 : &up->sg.src);
2100 0 : json_object_string_addf(json_row, "group", "%pPAs",
2101 : &up->sg.grp);
2102 :
2103 0 : if (pim_macro_ch_lost_assert(ch))
2104 0 : json_object_boolean_true_add(json_row, "lostAssert");
2105 :
2106 0 : if (pim_macro_chisin_joins(ch))
2107 0 : json_object_boolean_true_add(json_row, "joins");
2108 :
2109 0 : if (pim_macro_chisin_pim_include(ch))
2110 0 : json_object_boolean_true_add(json_row, "pimInclude");
2111 :
2112 0 : if (pim_upstream_evaluate_join_desired(pim, up))
2113 0 : json_object_boolean_true_add(json_row,
2114 : "evaluateJoinDesired");
2115 :
2116 0 : json_object_object_addf(json_group, json_row, "%pPAs",
2117 : &up->sg.src);
2118 :
2119 : } else {
2120 0 : ttable_add_row(tt, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
2121 0 : ch->interface->name, &up->sg.src, &up->sg.grp,
2122 0 : pim_macro_ch_lost_assert(ch) ? "yes" : "no",
2123 0 : pim_macro_chisin_joins(ch) ? "yes" : "no",
2124 0 : pim_macro_chisin_pim_include(ch) ? "yes" : "no",
2125 0 : PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
2126 : ? "yes"
2127 : : "no",
2128 0 : pim_upstream_evaluate_join_desired(pim, up)
2129 : ? "yes"
2130 : : "no");
2131 : }
2132 0 : }
2133 :
2134 0 : void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
2135 : {
2136 0 : struct pim_interface *pim_ifp;
2137 0 : struct pim_ifchannel *ch;
2138 0 : struct interface *ifp;
2139 0 : struct ttable *tt = NULL;
2140 0 : json_object *json = NULL;
2141 0 : char *table = NULL;
2142 :
2143 0 : if (uj)
2144 0 : json = json_object_new_object();
2145 : else {
2146 : /* Prepare table. */
2147 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2148 0 : ttable_add_row(
2149 : tt,
2150 : "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
2151 0 : tt->style.cell.rpad = 2;
2152 0 : tt->style.corner = '+';
2153 0 : ttable_restyle(tt);
2154 : }
2155 :
2156 : /* scan per-interface (S,G) state */
2157 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
2158 0 : pim_ifp = ifp->info;
2159 0 : if (!pim_ifp)
2160 0 : continue;
2161 :
2162 0 : RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
2163 : /* scan all interfaces */
2164 0 : pim_show_channel_helper(pim, pim_ifp, ch, json, uj, tt);
2165 : }
2166 : }
2167 :
2168 0 : if (uj)
2169 0 : vty_json(vty, json);
2170 : else {
2171 : /* Dump the generated table. */
2172 0 : table = ttable_dump(tt, "\n");
2173 0 : vty_out(vty, "%s\n", table);
2174 0 : XFREE(MTYPE_TMP, table);
2175 0 : ttable_del(tt);
2176 : }
2177 0 : }
2178 :
2179 0 : int pim_show_channel_cmd_helper(const char *vrf, struct vty *vty, bool uj)
2180 : {
2181 0 : struct vrf *v;
2182 :
2183 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2184 :
2185 0 : if (!v)
2186 : return CMD_WARNING;
2187 :
2188 0 : pim_show_channel(v->info, vty, uj);
2189 :
2190 0 : return CMD_SUCCESS;
2191 : }
2192 :
2193 0 : int pim_show_interface_cmd_helper(const char *vrf, struct vty *vty, bool uj,
2194 : bool mlag, const char *interface)
2195 : {
2196 0 : struct vrf *v;
2197 0 : json_object *json_parent = NULL;
2198 :
2199 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2200 :
2201 0 : if (!v)
2202 : return CMD_WARNING;
2203 :
2204 0 : if (uj)
2205 0 : json_parent = json_object_new_object();
2206 :
2207 0 : if (interface)
2208 0 : pim_show_interfaces_single(v->info, vty, interface, mlag,
2209 : json_parent);
2210 : else
2211 0 : pim_show_interfaces(v->info, vty, mlag, json_parent);
2212 :
2213 0 : if (uj)
2214 0 : vty_json(vty, json_parent);
2215 :
2216 : return CMD_SUCCESS;
2217 : }
2218 :
2219 0 : int pim_show_interface_vrf_all_cmd_helper(struct vty *vty, bool uj, bool mlag,
2220 : const char *interface)
2221 : {
2222 0 : struct vrf *v;
2223 0 : json_object *json_parent = NULL;
2224 0 : json_object *json_vrf = NULL;
2225 :
2226 0 : if (uj)
2227 0 : json_parent = json_object_new_object();
2228 :
2229 0 : RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
2230 0 : if (!uj)
2231 0 : vty_out(vty, "VRF: %s\n", v->name);
2232 : else
2233 0 : json_vrf = json_object_new_object();
2234 :
2235 0 : if (interface)
2236 0 : pim_show_interfaces_single(v->info, vty, interface,
2237 : mlag, json_vrf);
2238 : else
2239 0 : pim_show_interfaces(v->info, vty, mlag, json_vrf);
2240 :
2241 0 : if (uj)
2242 0 : json_object_object_add(json_parent, v->name, json_vrf);
2243 : }
2244 0 : if (uj)
2245 0 : vty_json(vty, json_parent);
2246 :
2247 0 : return CMD_SUCCESS;
2248 : }
2249 :
2250 0 : void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
2251 : json_object *json)
2252 : {
2253 0 : struct interface *ifp;
2254 0 : struct pim_interface *pim_ifp;
2255 0 : struct pim_upstream *up;
2256 0 : int fhr = 0;
2257 0 : int pim_nbrs = 0;
2258 0 : int pim_ifchannels = 0;
2259 0 : bool uj = true;
2260 0 : struct ttable *tt = NULL;
2261 0 : char *table = NULL;
2262 0 : json_object *json_row = NULL;
2263 0 : json_object *json_tmp;
2264 :
2265 0 : if (!json) {
2266 0 : uj = false;
2267 0 : json = json_object_new_object();
2268 : }
2269 :
2270 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
2271 0 : pim_ifp = ifp->info;
2272 :
2273 0 : if (!pim_ifp)
2274 0 : continue;
2275 :
2276 0 : if (mlag == true && pim_ifp->activeactive == false)
2277 0 : continue;
2278 :
2279 0 : pim_nbrs = pim_ifp->pim_neighbor_list->count;
2280 0 : pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
2281 0 : fhr = 0;
2282 :
2283 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up)
2284 0 : if (ifp == up->rpf.source_nexthop.interface)
2285 0 : if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR)
2286 0 : fhr++;
2287 :
2288 0 : json_row = json_object_new_object();
2289 0 : json_object_pim_ifp_add(json_row, ifp);
2290 0 : json_object_int_add(json_row, "pimNeighbors", pim_nbrs);
2291 0 : json_object_int_add(json_row, "pimIfChannels", pim_ifchannels);
2292 0 : json_object_int_add(json_row, "firstHopRouterCount", fhr);
2293 0 : json_object_string_addf(json_row, "pimDesignatedRouter",
2294 : "%pPAs", &pim_ifp->pim_dr_addr);
2295 :
2296 0 : if (!pim_addr_cmp(pim_ifp->pim_dr_addr,
2297 : pim_ifp->primary_address))
2298 0 : json_object_boolean_true_add(
2299 : json_row, "pimDesignatedRouterLocal");
2300 :
2301 0 : json_object_object_add(json, ifp->name, json_row);
2302 : }
2303 :
2304 0 : if (!uj) {
2305 :
2306 : /* Prepare table. */
2307 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2308 0 : ttable_add_row(
2309 : tt,
2310 : "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
2311 0 : tt->style.cell.rpad = 2;
2312 0 : tt->style.corner = '+';
2313 0 : ttable_restyle(tt);
2314 :
2315 0 : json_object_object_foreach(json, key, val)
2316 : {
2317 0 : const char *state, *address, *pimdr;
2318 0 : int neighbors, firsthpr, pimifchnl;
2319 :
2320 0 : json_object_object_get_ex(val, "state", &json_tmp);
2321 0 : state = json_object_get_string(json_tmp);
2322 :
2323 0 : json_object_object_get_ex(val, "address", &json_tmp);
2324 0 : address = json_object_get_string(json_tmp);
2325 :
2326 0 : json_object_object_get_ex(val, "pimNeighbors",
2327 : &json_tmp);
2328 0 : neighbors = json_object_get_int(json_tmp);
2329 :
2330 0 : if (json_object_object_get_ex(
2331 : val, "pimDesignatedRouterLocal",
2332 : &json_tmp)) {
2333 : pimdr = "local";
2334 : } else {
2335 0 : json_object_object_get_ex(
2336 : val, "pimDesignatedRouter", &json_tmp);
2337 0 : pimdr = json_object_get_string(json_tmp);
2338 : }
2339 :
2340 0 : json_object_object_get_ex(val, "firstHopRouter",
2341 : &json_tmp);
2342 0 : firsthpr = json_object_get_int(json_tmp);
2343 :
2344 0 : json_object_object_get_ex(val, "pimIfChannels",
2345 : &json_tmp);
2346 0 : pimifchnl = json_object_get_int(json_tmp);
2347 :
2348 0 : ttable_add_row(tt, "%s|%s|%s|%d|%s|%d|%d", key, state,
2349 : address, neighbors, pimdr, firsthpr,
2350 : pimifchnl);
2351 : }
2352 0 : json_object_free(json);
2353 :
2354 : /* Dump the generated table. */
2355 0 : table = ttable_dump(tt, "\n");
2356 0 : vty_out(vty, "%s\n", table);
2357 0 : XFREE(MTYPE_TMP, table);
2358 :
2359 0 : ttable_del(tt);
2360 : }
2361 0 : }
2362 :
2363 0 : void pim_show_interfaces_single(struct pim_instance *pim, struct vty *vty,
2364 : const char *ifname, bool mlag,
2365 : json_object *json)
2366 : {
2367 0 : pim_addr ifaddr;
2368 0 : struct interface *ifp;
2369 0 : struct listnode *neighnode;
2370 0 : struct pim_interface *pim_ifp;
2371 0 : struct pim_neighbor *neigh;
2372 0 : struct pim_upstream *up;
2373 0 : time_t now;
2374 0 : char dr_str[PIM_ADDRSTRLEN];
2375 0 : char dr_uptime[10];
2376 0 : char expire[10];
2377 0 : char grp_str[PIM_ADDRSTRLEN];
2378 0 : char hello_period[10];
2379 0 : char hello_timer[10];
2380 0 : char neigh_src_str[PIM_ADDRSTRLEN];
2381 0 : char src_str[PIM_ADDRSTRLEN];
2382 0 : char stat_uptime[10];
2383 0 : char uptime[10];
2384 0 : int found_ifname = 0;
2385 0 : int print_header;
2386 0 : json_object *json_row = NULL;
2387 0 : json_object *json_pim_neighbor = NULL;
2388 0 : json_object *json_pim_neighbors = NULL;
2389 0 : json_object *json_group = NULL;
2390 0 : json_object *json_group_source = NULL;
2391 0 : json_object *json_fhr_sources = NULL;
2392 0 : struct pim_secondary_addr *sec_addr;
2393 0 : struct listnode *sec_node;
2394 :
2395 0 : now = pim_time_monotonic_sec();
2396 :
2397 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
2398 0 : pim_ifp = ifp->info;
2399 :
2400 0 : if (!pim_ifp)
2401 0 : continue;
2402 :
2403 0 : if (mlag == true && pim_ifp->activeactive == false)
2404 0 : continue;
2405 :
2406 0 : if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
2407 0 : continue;
2408 :
2409 0 : found_ifname = 1;
2410 0 : ifaddr = pim_ifp->primary_address;
2411 0 : snprintfrr(dr_str, sizeof(dr_str), "%pPAs",
2412 : &pim_ifp->pim_dr_addr);
2413 0 : pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now,
2414 : pim_ifp->pim_dr_election_last);
2415 0 : pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer),
2416 : pim_ifp->t_pim_hello_timer);
2417 0 : pim_time_mmss(hello_period, sizeof(hello_period),
2418 0 : pim_ifp->pim_hello_period);
2419 0 : pim_time_uptime(stat_uptime, sizeof(stat_uptime),
2420 0 : now - pim_ifp->pim_ifstat_start);
2421 :
2422 0 : if (json) {
2423 0 : json_row = json_object_new_object();
2424 0 : json_object_pim_ifp_add(json_row, ifp);
2425 :
2426 0 : if (!pim_addr_is_any(pim_ifp->update_source)) {
2427 0 : json_object_string_addf(
2428 : json_row, "useSource", "%pPAs",
2429 : &pim_ifp->update_source);
2430 : }
2431 0 : if (pim_ifp->sec_addr_list) {
2432 0 : json_object *sec_list = NULL;
2433 :
2434 0 : sec_list = json_object_new_array();
2435 0 : for (ALL_LIST_ELEMENTS_RO(
2436 : pim_ifp->sec_addr_list, sec_node,
2437 : sec_addr)) {
2438 0 : json_object_array_add(
2439 : sec_list,
2440 : json_object_new_stringf(
2441 : "%pFXh",
2442 : &sec_addr->addr));
2443 : }
2444 0 : json_object_object_add(json_row,
2445 : "secondaryAddressList",
2446 : sec_list);
2447 : }
2448 :
2449 0 : if (pim_ifp->pim_passive_enable)
2450 0 : json_object_boolean_true_add(json_row,
2451 : "passive");
2452 :
2453 : /* PIM neighbors */
2454 0 : if (pim_ifp->pim_neighbor_list->count) {
2455 0 : json_pim_neighbors = json_object_new_object();
2456 :
2457 0 : for (ALL_LIST_ELEMENTS_RO(
2458 : pim_ifp->pim_neighbor_list,
2459 : neighnode, neigh)) {
2460 0 : json_pim_neighbor =
2461 0 : json_object_new_object();
2462 0 : snprintfrr(neigh_src_str,
2463 : sizeof(neigh_src_str),
2464 : "%pPAs",
2465 : &neigh->source_addr);
2466 0 : pim_time_uptime(uptime, sizeof(uptime),
2467 0 : now - neigh->creation);
2468 0 : pim_time_timer_to_hhmmss(
2469 : expire, sizeof(expire),
2470 : neigh->t_expire_timer);
2471 :
2472 0 : json_object_string_add(
2473 : json_pim_neighbor, "address",
2474 : neigh_src_str);
2475 0 : json_object_string_add(
2476 : json_pim_neighbor, "upTime",
2477 : uptime);
2478 0 : json_object_string_add(
2479 : json_pim_neighbor, "holdtime",
2480 : expire);
2481 :
2482 0 : json_object_object_add(
2483 : json_pim_neighbors,
2484 : neigh_src_str,
2485 : json_pim_neighbor);
2486 : }
2487 :
2488 0 : json_object_object_add(json_row, "neighbors",
2489 : json_pim_neighbors);
2490 : }
2491 :
2492 0 : json_object_string_add(json_row, "drAddress", dr_str);
2493 0 : json_object_int_add(json_row, "drPriority",
2494 0 : pim_ifp->pim_dr_priority);
2495 0 : json_object_string_add(json_row, "drUptime", dr_uptime);
2496 0 : json_object_int_add(json_row, "drElections",
2497 0 : pim_ifp->pim_dr_election_count);
2498 0 : json_object_int_add(json_row, "drChanges",
2499 0 : pim_ifp->pim_dr_election_changes);
2500 :
2501 : /* FHR */
2502 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2503 0 : if (ifp != up->rpf.source_nexthop.interface)
2504 0 : continue;
2505 :
2506 0 : if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2507 0 : continue;
2508 :
2509 0 : if (!json_fhr_sources)
2510 0 : json_fhr_sources =
2511 0 : json_object_new_object();
2512 :
2513 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
2514 : &up->sg.grp);
2515 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
2516 : &up->sg.src);
2517 0 : pim_time_uptime(uptime, sizeof(uptime),
2518 0 : now - up->state_transition);
2519 :
2520 : /*
2521 : * Does this group live in json_fhr_sources?
2522 : * If not create it.
2523 : */
2524 0 : json_object_object_get_ex(json_fhr_sources,
2525 : grp_str, &json_group);
2526 :
2527 0 : if (!json_group) {
2528 0 : json_group = json_object_new_object();
2529 0 : json_object_object_add(json_fhr_sources,
2530 : grp_str,
2531 : json_group);
2532 : }
2533 :
2534 0 : json_group_source = json_object_new_object();
2535 0 : json_object_string_add(json_group_source,
2536 : "source", src_str);
2537 0 : json_object_string_add(json_group_source,
2538 : "group", grp_str);
2539 0 : json_object_string_add(json_group_source,
2540 : "upTime", uptime);
2541 0 : json_object_object_add(json_group, src_str,
2542 : json_group_source);
2543 : }
2544 :
2545 0 : if (json_fhr_sources) {
2546 0 : json_object_object_add(json_row,
2547 : "firstHopRouter",
2548 : json_fhr_sources);
2549 : }
2550 :
2551 0 : json_object_int_add(json_row, "helloPeriod",
2552 0 : pim_ifp->pim_hello_period);
2553 0 : json_object_int_add(json_row, "holdTime",
2554 0 : PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2555 0 : json_object_string_add(json_row, "helloTimer",
2556 : hello_timer);
2557 0 : json_object_string_add(json_row, "helloStatStart",
2558 : stat_uptime);
2559 0 : json_object_int_add(json_row, "helloReceived",
2560 0 : pim_ifp->pim_ifstat_hello_recv);
2561 0 : json_object_int_add(json_row, "helloReceivedFailed",
2562 0 : pim_ifp->pim_ifstat_hello_recvfail);
2563 0 : json_object_int_add(json_row, "helloSend",
2564 0 : pim_ifp->pim_ifstat_hello_sent);
2565 0 : json_object_int_add(json_row, "hellosendFailed",
2566 0 : pim_ifp->pim_ifstat_hello_sendfail);
2567 0 : json_object_int_add(json_row, "helloGenerationId",
2568 0 : pim_ifp->pim_generation_id);
2569 :
2570 0 : json_object_int_add(
2571 : json_row, "effectivePropagationDelay",
2572 0 : pim_if_effective_propagation_delay_msec(ifp));
2573 0 : json_object_int_add(
2574 : json_row, "effectiveOverrideInterval",
2575 0 : pim_if_effective_override_interval_msec(ifp));
2576 0 : json_object_int_add(
2577 : json_row, "joinPruneOverrideInterval",
2578 0 : pim_if_jp_override_interval_msec(ifp));
2579 :
2580 0 : json_object_int_add(
2581 : json_row, "propagationDelay",
2582 0 : pim_ifp->pim_propagation_delay_msec);
2583 0 : json_object_int_add(
2584 : json_row, "propagationDelayHighest",
2585 0 : pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2586 0 : json_object_int_add(
2587 : json_row, "overrideInterval",
2588 0 : pim_ifp->pim_override_interval_msec);
2589 0 : json_object_int_add(
2590 : json_row, "overrideIntervalHighest",
2591 0 : pim_ifp->pim_neighbors_highest_override_interval_msec);
2592 0 : if (pim_ifp->bsm_enable)
2593 0 : json_object_boolean_true_add(json_row,
2594 : "bsmEnabled");
2595 0 : if (pim_ifp->ucast_bsm_accept)
2596 0 : json_object_boolean_true_add(json_row,
2597 : "ucastBsmEnabled");
2598 0 : json_object_object_add(json, ifp->name, json_row);
2599 :
2600 : } else {
2601 0 : vty_out(vty, "Interface : %s\n", ifp->name);
2602 0 : vty_out(vty, "State : %s\n",
2603 0 : if_is_up(ifp) ? "up" : "down");
2604 0 : if (!pim_addr_is_any(pim_ifp->update_source)) {
2605 0 : vty_out(vty, "Use Source : %pPAs\n",
2606 : &pim_ifp->update_source);
2607 : }
2608 0 : if (pim_ifp->sec_addr_list) {
2609 0 : vty_out(vty, "Address : %pPAs (primary)\n",
2610 : &ifaddr);
2611 0 : for (ALL_LIST_ELEMENTS_RO(
2612 : pim_ifp->sec_addr_list, sec_node,
2613 : sec_addr))
2614 0 : vty_out(vty, " %pFX\n",
2615 : &sec_addr->addr);
2616 : } else {
2617 0 : vty_out(vty, "Address : %pPAs\n", &ifaddr);
2618 : }
2619 :
2620 0 : if (pim_ifp->pim_passive_enable)
2621 0 : vty_out(vty, "Passive : %s\n",
2622 : (pim_ifp->pim_passive_enable) ? "yes"
2623 : : "no");
2624 :
2625 0 : vty_out(vty, "\n");
2626 :
2627 : /* PIM neighbors */
2628 0 : print_header = 1;
2629 :
2630 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
2631 : neighnode, neigh)) {
2632 :
2633 0 : if (print_header) {
2634 0 : vty_out(vty, "PIM Neighbors\n");
2635 0 : vty_out(vty, "-------------\n");
2636 0 : print_header = 0;
2637 : }
2638 :
2639 0 : snprintfrr(neigh_src_str, sizeof(neigh_src_str),
2640 : "%pPAs", &neigh->source_addr);
2641 0 : pim_time_uptime(uptime, sizeof(uptime),
2642 0 : now - neigh->creation);
2643 0 : pim_time_timer_to_hhmmss(expire, sizeof(expire),
2644 : neigh->t_expire_timer);
2645 0 : vty_out(vty,
2646 : "%-15s : up for %s, holdtime expires in %s\n",
2647 : neigh_src_str, uptime, expire);
2648 : }
2649 :
2650 0 : if (!print_header) {
2651 0 : vty_out(vty, "\n");
2652 0 : vty_out(vty, "\n");
2653 : }
2654 :
2655 0 : vty_out(vty, "Designated Router\n");
2656 0 : vty_out(vty, "-----------------\n");
2657 0 : vty_out(vty, "Address : %s\n", dr_str);
2658 0 : vty_out(vty, "Priority : %u(%d)\n",
2659 : pim_ifp->pim_dr_priority,
2660 : pim_ifp->pim_dr_num_nondrpri_neighbors);
2661 0 : vty_out(vty, "Uptime : %s\n", dr_uptime);
2662 0 : vty_out(vty, "Elections : %d\n",
2663 : pim_ifp->pim_dr_election_count);
2664 0 : vty_out(vty, "Changes : %d\n",
2665 : pim_ifp->pim_dr_election_changes);
2666 0 : vty_out(vty, "\n");
2667 0 : vty_out(vty, "\n");
2668 :
2669 : /* FHR */
2670 0 : print_header = 1;
2671 0 : frr_each (rb_pim_upstream, &pim->upstream_head, up) {
2672 0 : if (!up->rpf.source_nexthop.interface)
2673 0 : continue;
2674 :
2675 0 : if (strcmp(ifp->name,
2676 : up->rpf.source_nexthop
2677 0 : .interface->name) != 0)
2678 0 : continue;
2679 :
2680 0 : if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_FHR))
2681 0 : continue;
2682 :
2683 0 : if (print_header) {
2684 0 : vty_out(vty,
2685 : "FHR - First Hop Router\n");
2686 0 : vty_out(vty,
2687 : "----------------------\n");
2688 0 : print_header = 0;
2689 : }
2690 :
2691 0 : pim_time_uptime(uptime, sizeof(uptime),
2692 0 : now - up->state_transition);
2693 0 : vty_out(vty,
2694 : "%pPAs : %pPAs is a source, uptime is %s\n",
2695 : &up->sg.grp, &up->sg.src, uptime);
2696 : }
2697 :
2698 0 : if (!print_header) {
2699 0 : vty_out(vty, "\n");
2700 0 : vty_out(vty, "\n");
2701 : }
2702 :
2703 0 : vty_out(vty, "Hellos\n");
2704 0 : vty_out(vty, "------\n");
2705 0 : vty_out(vty, "Period : %d\n",
2706 : pim_ifp->pim_hello_period);
2707 0 : vty_out(vty, "HoldTime : %d\n",
2708 0 : PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
2709 0 : vty_out(vty, "Timer : %s\n", hello_timer);
2710 0 : vty_out(vty, "StatStart : %s\n", stat_uptime);
2711 0 : vty_out(vty, "Receive : %d\n",
2712 : pim_ifp->pim_ifstat_hello_recv);
2713 0 : vty_out(vty, "Receive Failed : %d\n",
2714 : pim_ifp->pim_ifstat_hello_recvfail);
2715 0 : vty_out(vty, "Send : %d\n",
2716 : pim_ifp->pim_ifstat_hello_sent);
2717 0 : vty_out(vty, "Send Failed : %d\n",
2718 : pim_ifp->pim_ifstat_hello_sendfail);
2719 0 : vty_out(vty, "Generation ID : %08x\n",
2720 : pim_ifp->pim_generation_id);
2721 0 : vty_out(vty, "\n");
2722 0 : vty_out(vty, "\n");
2723 :
2724 0 : pim_print_ifp_flags(vty, ifp);
2725 :
2726 0 : vty_out(vty, "Join Prune Interval\n");
2727 0 : vty_out(vty, "-------------------\n");
2728 0 : vty_out(vty, "LAN Delay : %s\n",
2729 0 : pim_if_lan_delay_enabled(ifp) ? "yes" : "no");
2730 0 : vty_out(vty, "Effective Propagation Delay : %d msec\n",
2731 0 : pim_if_effective_propagation_delay_msec(ifp));
2732 0 : vty_out(vty, "Effective Override Interval : %d msec\n",
2733 0 : pim_if_effective_override_interval_msec(ifp));
2734 0 : vty_out(vty, "Join Prune Override Interval : %d msec\n",
2735 0 : pim_if_jp_override_interval_msec(ifp));
2736 0 : vty_out(vty, "\n");
2737 0 : vty_out(vty, "\n");
2738 :
2739 0 : vty_out(vty, "LAN Prune Delay\n");
2740 0 : vty_out(vty, "---------------\n");
2741 0 : vty_out(vty, "Propagation Delay : %d msec\n",
2742 0 : pim_ifp->pim_propagation_delay_msec);
2743 0 : vty_out(vty, "Propagation Delay (Highest) : %d msec\n",
2744 0 : pim_ifp->pim_neighbors_highest_propagation_delay_msec);
2745 0 : vty_out(vty, "Override Interval : %d msec\n",
2746 0 : pim_ifp->pim_override_interval_msec);
2747 0 : vty_out(vty, "Override Interval (Highest) : %d msec\n",
2748 0 : pim_ifp->pim_neighbors_highest_override_interval_msec);
2749 0 : vty_out(vty, "\n");
2750 0 : vty_out(vty, "\n");
2751 :
2752 0 : vty_out(vty, "BSM Status\n");
2753 0 : vty_out(vty, "----------\n");
2754 0 : vty_out(vty, "Bsm Enabled : %s\n",
2755 0 : pim_ifp->bsm_enable ? "yes" : "no");
2756 0 : vty_out(vty, "Unicast Bsm Enabled : %s\n",
2757 0 : pim_ifp->ucast_bsm_accept ? "yes" : "no");
2758 0 : vty_out(vty, "\n");
2759 0 : vty_out(vty, "\n");
2760 : }
2761 : }
2762 :
2763 0 : if (!found_ifname)
2764 0 : vty_out(vty, "%% No such interface\n");
2765 0 : }
2766 :
2767 0 : void ip_pim_ssm_show_group_range(struct pim_instance *pim, struct vty *vty,
2768 : bool uj)
2769 : {
2770 0 : struct pim_ssm *ssm = pim->ssm_info;
2771 0 : const char *range_str =
2772 0 : ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE;
2773 :
2774 0 : if (uj) {
2775 0 : json_object *json;
2776 :
2777 0 : json = json_object_new_object();
2778 0 : json_object_string_add(json, "ssmGroups", range_str);
2779 0 : vty_json(vty, json);
2780 : } else
2781 0 : vty_out(vty, "SSM group range : %s\n", range_str);
2782 0 : }
2783 :
2784 : struct vty_pnc_cache_walk_data {
2785 : struct vty *vty;
2786 : struct pim_instance *pim;
2787 : };
2788 :
2789 : struct json_pnc_cache_walk_data {
2790 : json_object *json_obj;
2791 : struct pim_instance *pim;
2792 : };
2793 :
2794 0 : static int pim_print_vty_pnc_cache_walkcb(struct hash_bucket *bucket, void *arg)
2795 : {
2796 0 : struct pim_nexthop_cache *pnc = bucket->data;
2797 0 : struct vty_pnc_cache_walk_data *cwd = arg;
2798 0 : struct vty *vty = cwd->vty;
2799 0 : struct pim_instance *pim = cwd->pim;
2800 0 : struct nexthop *nh_node = NULL;
2801 0 : ifindex_t first_ifindex;
2802 0 : struct interface *ifp = NULL;
2803 0 : struct ttable *tt = NULL;
2804 0 : char *table = NULL;
2805 :
2806 : /* Prepare table. */
2807 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
2808 0 : ttable_add_row(tt, "Address|Interface|Nexthop");
2809 0 : tt->style.cell.rpad = 2;
2810 0 : tt->style.corner = '+';
2811 0 : ttable_restyle(tt);
2812 :
2813 0 : for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2814 0 : first_ifindex = nh_node->ifindex;
2815 :
2816 0 : ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2817 :
2818 : #if PIM_IPV == 4
2819 0 : ttable_add_row(tt, "%pPA|%s|%pI4", &pnc->rpf.rpf_addr,
2820 : ifp ? ifp->name : "NULL", &nh_node->gate.ipv4);
2821 : #else
2822 0 : ttable_add_row(tt, "%pPA|%s|%pI6", &pnc->rpf.rpf_addr,
2823 : ifp ? ifp->name : "NULL", &nh_node->gate.ipv6);
2824 : #endif
2825 : }
2826 : /* Dump the generated table. */
2827 0 : table = ttable_dump(tt, "\n");
2828 0 : vty_out(vty, "%s\n", table);
2829 0 : XFREE(MTYPE_TMP, table);
2830 0 : ttable_del(tt);
2831 :
2832 0 : return CMD_SUCCESS;
2833 : }
2834 :
2835 0 : static int pim_print_json_pnc_cache_walkcb(struct hash_bucket *backet,
2836 : void *arg)
2837 : {
2838 0 : struct pim_nexthop_cache *pnc = backet->data;
2839 0 : struct json_pnc_cache_walk_data *cwd = arg;
2840 0 : struct pim_instance *pim = cwd->pim;
2841 0 : struct nexthop *nh_node = NULL;
2842 0 : ifindex_t first_ifindex;
2843 0 : struct interface *ifp = NULL;
2844 0 : char addr_str[PIM_ADDRSTRLEN];
2845 0 : json_object *json_row = NULL;
2846 0 : json_object *json_ifp = NULL;
2847 0 : json_object *json_arr = NULL;
2848 :
2849 0 : for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
2850 0 : first_ifindex = nh_node->ifindex;
2851 0 : ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
2852 0 : snprintfrr(addr_str, sizeof(addr_str), "%pPA",
2853 : &pnc->rpf.rpf_addr);
2854 0 : json_object_object_get_ex(cwd->json_obj, addr_str, &json_row);
2855 0 : if (!json_row) {
2856 0 : json_row = json_object_new_object();
2857 0 : json_object_string_addf(json_row, "address", "%pPA",
2858 : &pnc->rpf.rpf_addr);
2859 0 : json_object_object_addf(cwd->json_obj, json_row, "%pPA",
2860 : &pnc->rpf.rpf_addr);
2861 0 : json_arr = json_object_new_array();
2862 0 : json_object_object_add(json_row, "nexthops", json_arr);
2863 : }
2864 0 : json_ifp = json_object_new_object();
2865 0 : json_object_string_add(json_ifp, "interface",
2866 : ifp ? ifp->name : "NULL");
2867 : #if PIM_IPV == 4
2868 0 : json_object_string_addf(json_ifp, "nexthop", "%pI4",
2869 : &nh_node->gate.ipv4);
2870 : #else
2871 0 : json_object_string_addf(json_ifp, "nexthop", "%pI6",
2872 : &nh_node->gate.ipv6);
2873 : #endif
2874 0 : json_object_array_add(json_arr, json_ifp);
2875 : }
2876 0 : return CMD_SUCCESS;
2877 : }
2878 :
2879 0 : int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
2880 : pim_addr source, pim_addr group)
2881 : {
2882 0 : int result = 0;
2883 0 : pim_addr vif_source;
2884 0 : struct prefix grp;
2885 0 : struct pim_nexthop nexthop;
2886 0 : struct vrf *v;
2887 0 : char grp_str[PREFIX_STRLEN];
2888 :
2889 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2890 :
2891 0 : if (!v)
2892 : return CMD_WARNING;
2893 :
2894 : #if PIM_IPV == 4
2895 0 : if (pim_is_group_224_4(source)) {
2896 0 : vty_out(vty,
2897 : "Invalid argument. Expected Valid Source Address.\n");
2898 0 : return CMD_WARNING;
2899 : }
2900 :
2901 0 : if (!pim_is_group_224_4(group)) {
2902 0 : vty_out(vty,
2903 : "Invalid argument. Expected Valid Multicast Group Address.\n");
2904 0 : return CMD_WARNING;
2905 : }
2906 : #endif
2907 :
2908 0 : if (!pim_rp_set_upstream_addr(v->info, &vif_source, source, group))
2909 : return CMD_SUCCESS;
2910 :
2911 0 : pim_addr_to_prefix(&grp, group);
2912 0 : memset(&nexthop, 0, sizeof(nexthop));
2913 :
2914 0 : result =
2915 0 : pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
2916 :
2917 0 : if (!result) {
2918 0 : vty_out(vty,
2919 : "Nexthop Lookup failed, no usable routes returned.\n");
2920 0 : return CMD_SUCCESS;
2921 : }
2922 :
2923 0 : pim_addr_dump("<grp?>", &grp, grp_str, sizeof(grp_str));
2924 :
2925 0 : vty_out(vty, "Group %s --- Nexthop %pPAs Interface %s\n", grp_str,
2926 0 : &nexthop.mrib_nexthop_addr, nexthop.interface->name);
2927 :
2928 0 : return CMD_SUCCESS;
2929 : }
2930 :
2931 0 : int pim_show_nexthop_cmd_helper(const char *vrf, struct vty *vty, bool uj)
2932 : {
2933 0 : struct vrf *v;
2934 :
2935 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2936 :
2937 0 : if (!v)
2938 : return CMD_WARNING;
2939 :
2940 0 : pim_show_nexthop(v->info, vty, uj);
2941 :
2942 0 : return CMD_SUCCESS;
2943 : }
2944 :
2945 0 : void pim_show_nexthop(struct pim_instance *pim, struct vty *vty, bool uj)
2946 : {
2947 0 : struct vty_pnc_cache_walk_data cwd;
2948 0 : struct json_pnc_cache_walk_data jcwd;
2949 :
2950 0 : cwd.vty = vty;
2951 0 : cwd.pim = pim;
2952 0 : jcwd.pim = pim;
2953 :
2954 0 : if (uj) {
2955 0 : jcwd.json_obj = json_object_new_object();
2956 : } else {
2957 0 : vty_out(vty, "Number of registered addresses: %lu\n",
2958 0 : pim->rpf_hash->count);
2959 : }
2960 :
2961 0 : if (uj) {
2962 0 : hash_walk(pim->rpf_hash, pim_print_json_pnc_cache_walkcb,
2963 : &jcwd);
2964 0 : vty_json(vty, jcwd.json_obj);
2965 : } else
2966 0 : hash_walk(pim->rpf_hash, pim_print_vty_pnc_cache_walkcb, &cwd);
2967 0 : }
2968 :
2969 47 : int pim_show_neighbors_cmd_helper(const char *vrf, struct vty *vty,
2970 : const char *json, const char *interface)
2971 : {
2972 47 : struct vrf *v;
2973 47 : json_object *json_parent = NULL;
2974 :
2975 47 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
2976 :
2977 47 : if (!v)
2978 : return CMD_WARNING;
2979 :
2980 47 : if (json)
2981 46 : json_parent = json_object_new_object();
2982 :
2983 47 : if (interface)
2984 0 : pim_show_neighbors_single(v->info, vty, interface, json_parent);
2985 : else
2986 47 : pim_show_neighbors(v->info, vty, json_parent);
2987 :
2988 47 : if (json)
2989 46 : vty_json(vty, json_parent);
2990 :
2991 : return CMD_SUCCESS;
2992 : }
2993 :
2994 0 : int pim_show_neighbors_vrf_all_cmd_helper(struct vty *vty, const char *json,
2995 : const char *interface)
2996 : {
2997 0 : struct vrf *v;
2998 0 : json_object *json_parent = NULL;
2999 0 : json_object *json_vrf = NULL;
3000 :
3001 0 : if (json)
3002 0 : json_parent = json_object_new_object();
3003 0 : RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
3004 0 : if (!json)
3005 0 : vty_out(vty, "VRF: %s\n", v->name);
3006 : else
3007 0 : json_vrf = json_object_new_object();
3008 :
3009 0 : if (interface)
3010 0 : pim_show_neighbors_single(v->info, vty, interface,
3011 : json_vrf);
3012 : else
3013 0 : pim_show_neighbors(v->info, vty, json_vrf);
3014 :
3015 0 : if (json)
3016 0 : json_object_object_add(json_parent, v->name, json_vrf);
3017 : }
3018 0 : if (json)
3019 0 : vty_json(vty, json_parent);
3020 :
3021 0 : return CMD_SUCCESS;
3022 : }
3023 :
3024 0 : void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
3025 : const char *neighbor, json_object *json)
3026 : {
3027 0 : struct listnode *neighnode;
3028 0 : struct interface *ifp;
3029 0 : struct pim_interface *pim_ifp;
3030 0 : struct pim_neighbor *neigh;
3031 0 : time_t now;
3032 0 : int found_neighbor = 0;
3033 0 : int option_address_list;
3034 0 : int option_dr_priority;
3035 0 : int option_generation_id;
3036 0 : int option_holdtime;
3037 0 : int option_lan_prune_delay;
3038 0 : int option_t_bit;
3039 0 : char uptime[10];
3040 0 : char expire[10];
3041 0 : char neigh_src_str[PIM_ADDRSTRLEN];
3042 :
3043 0 : json_object *json_ifp = NULL;
3044 0 : json_object *json_row = NULL;
3045 :
3046 0 : now = pim_time_monotonic_sec();
3047 :
3048 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
3049 0 : pim_ifp = ifp->info;
3050 :
3051 0 : if (!pim_ifp)
3052 0 : continue;
3053 :
3054 0 : if (pim_ifp->pim_sock_fd < 0)
3055 0 : continue;
3056 :
3057 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
3058 : neigh)) {
3059 0 : snprintfrr(neigh_src_str, sizeof(neigh_src_str),
3060 : "%pPAs", &neigh->source_addr);
3061 :
3062 : /*
3063 : * The user can specify either the interface name or the
3064 : * PIM neighbor IP.
3065 : * If this pim_ifp matches neither then skip.
3066 : */
3067 0 : if (strcmp(neighbor, "detail") &&
3068 0 : strcmp(neighbor, ifp->name) &&
3069 0 : strcmp(neighbor, neigh_src_str))
3070 0 : continue;
3071 :
3072 0 : found_neighbor = 1;
3073 0 : pim_time_uptime(uptime, sizeof(uptime),
3074 0 : now - neigh->creation);
3075 0 : pim_time_timer_to_hhmmss(expire, sizeof(expire),
3076 : neigh->t_expire_timer);
3077 :
3078 0 : option_address_list = 0;
3079 0 : option_dr_priority = 0;
3080 0 : option_generation_id = 0;
3081 0 : option_holdtime = 0;
3082 0 : option_lan_prune_delay = 0;
3083 0 : option_t_bit = 0;
3084 :
3085 0 : if (PIM_OPTION_IS_SET(neigh->hello_options,
3086 : PIM_OPTION_MASK_ADDRESS_LIST))
3087 0 : option_address_list = 1;
3088 :
3089 0 : if (PIM_OPTION_IS_SET(neigh->hello_options,
3090 : PIM_OPTION_MASK_DR_PRIORITY))
3091 0 : option_dr_priority = 1;
3092 :
3093 0 : if (PIM_OPTION_IS_SET(neigh->hello_options,
3094 : PIM_OPTION_MASK_GENERATION_ID))
3095 0 : option_generation_id = 1;
3096 :
3097 0 : if (PIM_OPTION_IS_SET(neigh->hello_options,
3098 : PIM_OPTION_MASK_HOLDTIME))
3099 0 : option_holdtime = 1;
3100 :
3101 0 : if (PIM_OPTION_IS_SET(neigh->hello_options,
3102 : PIM_OPTION_MASK_LAN_PRUNE_DELAY))
3103 0 : option_lan_prune_delay = 1;
3104 :
3105 0 : if (PIM_OPTION_IS_SET(
3106 : neigh->hello_options,
3107 : PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION))
3108 0 : option_t_bit = 1;
3109 :
3110 0 : if (json) {
3111 :
3112 : /* Does this ifp live in json? If not create it
3113 : */
3114 0 : json_object_object_get_ex(json, ifp->name,
3115 : &json_ifp);
3116 :
3117 0 : if (!json_ifp) {
3118 0 : json_ifp = json_object_new_object();
3119 0 : json_object_pim_ifp_add(json_ifp, ifp);
3120 0 : json_object_object_add(json, ifp->name,
3121 : json_ifp);
3122 : }
3123 :
3124 0 : json_row = json_object_new_object();
3125 0 : json_object_string_add(json_row, "interface",
3126 : ifp->name);
3127 0 : json_object_string_add(json_row, "address",
3128 : neigh_src_str);
3129 0 : json_object_string_add(json_row, "upTime",
3130 : uptime);
3131 0 : json_object_string_add(json_row, "holdtime",
3132 : expire);
3133 0 : json_object_int_add(json_row, "drPriority",
3134 0 : neigh->dr_priority);
3135 0 : json_object_int_add(json_row, "generationId",
3136 0 : neigh->generation_id);
3137 :
3138 0 : if (option_address_list)
3139 0 : json_object_boolean_true_add(
3140 : json_row,
3141 : "helloOptionAddressList");
3142 :
3143 0 : if (option_dr_priority)
3144 0 : json_object_boolean_true_add(
3145 : json_row,
3146 : "helloOptionDrPriority");
3147 :
3148 0 : if (option_generation_id)
3149 0 : json_object_boolean_true_add(
3150 : json_row,
3151 : "helloOptionGenerationId");
3152 :
3153 0 : if (option_holdtime)
3154 0 : json_object_boolean_true_add(
3155 : json_row,
3156 : "helloOptionHoldtime");
3157 :
3158 0 : if (option_lan_prune_delay)
3159 0 : json_object_boolean_true_add(
3160 : json_row,
3161 : "helloOptionLanPruneDelay");
3162 :
3163 0 : if (option_t_bit)
3164 0 : json_object_boolean_true_add(
3165 : json_row, "helloOptionTBit");
3166 :
3167 0 : json_object_object_add(json_ifp, neigh_src_str,
3168 : json_row);
3169 :
3170 : } else {
3171 0 : vty_out(vty, "Interface : %s\n", ifp->name);
3172 0 : vty_out(vty, "Neighbor : %s\n", neigh_src_str);
3173 0 : vty_out(vty,
3174 : " Uptime : %s\n",
3175 : uptime);
3176 0 : vty_out(vty,
3177 : " Holdtime : %s\n",
3178 : expire);
3179 0 : vty_out(vty,
3180 : " DR Priority : %d\n",
3181 : neigh->dr_priority);
3182 0 : vty_out(vty,
3183 : " Generation ID : %08x\n",
3184 : neigh->generation_id);
3185 0 : vty_out(vty,
3186 : " Override Interval (msec) : %d\n",
3187 0 : neigh->override_interval_msec);
3188 0 : vty_out(vty,
3189 : " Propagation Delay (msec) : %d\n",
3190 0 : neigh->propagation_delay_msec);
3191 0 : vty_out(vty,
3192 : " Hello Option - Address List : %s\n",
3193 : option_address_list ? "yes" : "no");
3194 0 : vty_out(vty,
3195 : " Hello Option - DR Priority : %s\n",
3196 : option_dr_priority ? "yes" : "no");
3197 0 : vty_out(vty,
3198 : " Hello Option - Generation ID : %s\n",
3199 : option_generation_id ? "yes" : "no");
3200 0 : vty_out(vty,
3201 : " Hello Option - Holdtime : %s\n",
3202 : option_holdtime ? "yes" : "no");
3203 0 : vty_out(vty,
3204 : " Hello Option - LAN Prune Delay : %s\n",
3205 : option_lan_prune_delay ? "yes" : "no");
3206 0 : vty_out(vty,
3207 : " Hello Option - T-bit : %s\n",
3208 : option_t_bit ? "yes" : "no");
3209 0 : bfd_sess_show(vty, json_ifp,
3210 : neigh->bfd_session);
3211 0 : vty_out(vty, "\n");
3212 : }
3213 : }
3214 : }
3215 :
3216 0 : if (!found_neighbor)
3217 0 : vty_out(vty, "%% No such interface or neighbor\n");
3218 0 : }
3219 :
3220 47 : void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
3221 : json_object *json)
3222 : {
3223 47 : struct listnode *neighnode;
3224 47 : struct interface *ifp;
3225 47 : struct pim_interface *pim_ifp;
3226 47 : struct pim_neighbor *neigh;
3227 47 : struct ttable *tt = NULL;
3228 47 : char *table = NULL;
3229 47 : time_t now;
3230 47 : char uptime[10];
3231 47 : char expire[10];
3232 47 : char neigh_src_str[PIM_ADDRSTRLEN];
3233 47 : json_object *json_ifp_rows = NULL;
3234 47 : json_object *json_row = NULL;
3235 :
3236 47 : now = pim_time_monotonic_sec();
3237 :
3238 47 : if (!json) {
3239 : /* Prepare table. */
3240 1 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3241 1 : ttable_add_row(tt, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
3242 1 : tt->style.cell.rpad = 2;
3243 1 : tt->style.corner = '+';
3244 1 : ttable_restyle(tt);
3245 : }
3246 :
3247 289 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
3248 195 : pim_ifp = ifp->info;
3249 :
3250 195 : if (!pim_ifp)
3251 46 : continue;
3252 :
3253 149 : if (pim_ifp->pim_sock_fd < 0)
3254 49 : continue;
3255 :
3256 100 : if (json)
3257 98 : json_ifp_rows = json_object_new_object();
3258 :
3259 274 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
3260 : neigh)) {
3261 74 : snprintfrr(neigh_src_str, sizeof(neigh_src_str),
3262 : "%pPAs", &neigh->source_addr);
3263 74 : pim_time_uptime(uptime, sizeof(uptime),
3264 74 : now - neigh->creation);
3265 74 : pim_time_timer_to_hhmmss(expire, sizeof(expire),
3266 : neigh->t_expire_timer);
3267 :
3268 74 : if (json) {
3269 74 : json_row = json_object_new_object();
3270 74 : json_object_string_add(json_row, "interface",
3271 74 : ifp->name);
3272 74 : json_object_string_add(json_row, "neighbor",
3273 : neigh_src_str);
3274 74 : json_object_string_add(json_row, "upTime",
3275 : uptime);
3276 74 : json_object_string_add(json_row, "holdTime",
3277 : expire);
3278 74 : json_object_int_add(json_row, "holdTimeMax",
3279 74 : neigh->holdtime);
3280 74 : json_object_int_add(json_row, "drPriority",
3281 74 : neigh->dr_priority);
3282 74 : json_object_object_add(json_ifp_rows,
3283 : neigh_src_str, json_row);
3284 :
3285 : } else {
3286 0 : ttable_add_row(tt, "%s|%pPAs|%s|%s|%d",
3287 0 : ifp->name, &neigh->source_addr,
3288 : uptime, expire,
3289 : neigh->dr_priority);
3290 : }
3291 : }
3292 :
3293 100 : if (json) {
3294 98 : json_object_object_add(json, ifp->name, json_ifp_rows);
3295 98 : json_ifp_rows = NULL;
3296 : }
3297 : }
3298 : /* Dump the generated table. */
3299 47 : if (!json) {
3300 1 : table = ttable_dump(tt, "\n");
3301 1 : vty_out(vty, "%s\n", table);
3302 1 : XFREE(MTYPE_TMP, table);
3303 1 : ttable_del(tt);
3304 : }
3305 47 : }
3306 :
3307 8 : int gm_process_query_max_response_time_cmd(struct vty *vty,
3308 : const char *qmrt_str)
3309 : {
3310 8 : const struct lyd_node *pim_enable_dnode;
3311 :
3312 16 : pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3313 8 : FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3314 : FRR_PIM_AF_XPATH_VAL);
3315 :
3316 8 : if (!pim_enable_dnode) {
3317 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3318 : } else {
3319 8 : if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3320 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3321 : "true");
3322 : }
3323 :
3324 8 : nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
3325 : qmrt_str);
3326 8 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3327 : FRR_PIM_AF_XPATH_VAL);
3328 : }
3329 :
3330 0 : int gm_process_no_query_max_response_time_cmd(struct vty *vty)
3331 : {
3332 0 : nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_DESTROY,
3333 : NULL);
3334 0 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3335 : FRR_PIM_AF_XPATH_VAL);
3336 : }
3337 :
3338 0 : int gm_process_last_member_query_count_cmd(struct vty *vty,
3339 : const char *lmqc_str)
3340 : {
3341 0 : const struct lyd_node *pim_enable_dnode;
3342 :
3343 0 : pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3344 0 : FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3345 : FRR_PIM_AF_XPATH_VAL);
3346 0 : if (!pim_enable_dnode) {
3347 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3348 : } else {
3349 0 : if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3350 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3351 : "true");
3352 : }
3353 :
3354 0 : nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
3355 : lmqc_str);
3356 0 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3357 : FRR_PIM_AF_XPATH_VAL);
3358 : }
3359 :
3360 0 : int gm_process_no_last_member_query_count_cmd(struct vty *vty)
3361 : {
3362 0 : nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_DESTROY,
3363 : NULL);
3364 0 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3365 : FRR_PIM_AF_XPATH_VAL);
3366 : }
3367 :
3368 0 : int gm_process_last_member_query_interval_cmd(struct vty *vty,
3369 : const char *lmqi_str)
3370 : {
3371 0 : const struct lyd_node *pim_enable_dnode;
3372 :
3373 0 : pim_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3374 0 : FRR_PIM_ENABLE_XPATH, VTY_CURR_XPATH,
3375 : FRR_PIM_AF_XPATH_VAL);
3376 0 : if (!pim_enable_dnode) {
3377 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
3378 : } else {
3379 0 : if (!yang_dnode_get_bool(pim_enable_dnode, "."))
3380 0 : nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY,
3381 : "true");
3382 : }
3383 :
3384 0 : nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
3385 : lmqi_str);
3386 0 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3387 : FRR_PIM_AF_XPATH_VAL);
3388 : }
3389 :
3390 0 : int gm_process_no_last_member_query_interval_cmd(struct vty *vty)
3391 : {
3392 0 : nb_cli_enqueue_change(vty, "./last-member-query-interval",
3393 : NB_OP_DESTROY, NULL);
3394 0 : return nb_cli_apply_changes(vty, FRR_GMP_INTERFACE_XPATH,
3395 : FRR_PIM_AF_XPATH_VAL);
3396 : }
3397 :
3398 0 : int pim_process_ssmpingd_cmd(struct vty *vty, enum nb_operation operation,
3399 : const char *src_str)
3400 : {
3401 0 : const char *vrfname;
3402 0 : char ssmpingd_ip_xpath[XPATH_MAXLEN];
3403 :
3404 0 : vrfname = pim_cli_get_vrf_name(vty);
3405 0 : if (vrfname == NULL)
3406 : return CMD_WARNING_CONFIG_FAILED;
3407 :
3408 0 : snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
3409 : FRR_PIM_VRF_XPATH, "frr-pim:pimd", "pim", vrfname,
3410 : FRR_PIM_AF_XPATH_VAL);
3411 0 : strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
3412 : sizeof(ssmpingd_ip_xpath));
3413 :
3414 0 : nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, operation, src_str);
3415 :
3416 0 : return nb_cli_apply_changes(vty, NULL);
3417 : }
3418 :
3419 0 : int pim_process_bsm_cmd(struct vty *vty)
3420 : {
3421 0 : const struct lyd_node *gm_enable_dnode;
3422 :
3423 0 : gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3424 0 : FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
3425 : FRR_PIM_AF_XPATH_VAL);
3426 0 : if (!gm_enable_dnode)
3427 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3428 : "true");
3429 : else {
3430 0 : if (!yang_dnode_get_bool(gm_enable_dnode, "."))
3431 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3432 : "true");
3433 : }
3434 :
3435 0 : nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
3436 :
3437 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3438 : FRR_PIM_AF_XPATH_VAL);
3439 : }
3440 :
3441 0 : int pim_process_no_bsm_cmd(struct vty *vty)
3442 : {
3443 0 : nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
3444 :
3445 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3446 : FRR_PIM_AF_XPATH_VAL);
3447 : }
3448 :
3449 0 : int pim_process_unicast_bsm_cmd(struct vty *vty)
3450 : {
3451 0 : const struct lyd_node *gm_enable_dnode;
3452 :
3453 0 : gm_enable_dnode = yang_dnode_getf(vty->candidate_config->dnode,
3454 0 : FRR_GMP_ENABLE_XPATH, VTY_CURR_XPATH,
3455 : FRR_PIM_AF_XPATH_VAL);
3456 0 : if (!gm_enable_dnode)
3457 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3458 : "true");
3459 : else {
3460 0 : if (!yang_dnode_get_bool(gm_enable_dnode, "."))
3461 0 : nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
3462 : "true");
3463 : }
3464 :
3465 0 : nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
3466 :
3467 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3468 : FRR_PIM_AF_XPATH_VAL);
3469 : }
3470 :
3471 0 : int pim_process_no_unicast_bsm_cmd(struct vty *vty)
3472 : {
3473 0 : nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
3474 :
3475 0 : return nb_cli_apply_changes(vty, FRR_PIM_INTERFACE_XPATH,
3476 : FRR_PIM_AF_XPATH_VAL);
3477 : }
3478 :
3479 0 : static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
3480 : time_t now)
3481 : {
3482 0 : char uptime_scan_oil[10];
3483 0 : char uptime_mroute_add[10];
3484 0 : char uptime_mroute_del[10];
3485 :
3486 0 : pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
3487 : pim->scan_oil_last);
3488 0 : pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
3489 : pim->mroute_add_last);
3490 0 : pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
3491 : pim->mroute_del_last);
3492 :
3493 0 : vty_out(vty,
3494 : "Scan OIL - Last: %s Events: %lld\n"
3495 : "MFC Add - Last: %s Events: %lld\n"
3496 : "MFC Del - Last: %s Events: %lld\n",
3497 0 : uptime_scan_oil, (long long)pim->scan_oil_events,
3498 0 : uptime_mroute_add, (long long)pim->mroute_add_events,
3499 0 : uptime_mroute_del, (long long)pim->mroute_del_events);
3500 0 : }
3501 :
3502 0 : void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
3503 : json_object *json)
3504 : {
3505 0 : struct interface *ifp;
3506 0 : struct ttable *tt = NULL;
3507 0 : char *table = NULL;
3508 0 : json_object *json_row = NULL;
3509 :
3510 0 : vty_out(vty, "\n");
3511 :
3512 0 : if (!json) {
3513 : /* Prepare table. */
3514 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3515 0 : ttable_add_row(
3516 : tt,
3517 : "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
3518 0 : tt->style.cell.rpad = 2;
3519 0 : tt->style.corner = '+';
3520 0 : ttable_restyle(tt);
3521 : }
3522 :
3523 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
3524 0 : struct pim_interface *pim_ifp;
3525 : #if PIM_IPV == 4
3526 0 : struct sioc_vif_req vreq;
3527 : #else
3528 0 : struct sioc_mif_req6 vreq;
3529 : #endif
3530 :
3531 0 : pim_ifp = ifp->info;
3532 :
3533 0 : if (!pim_ifp)
3534 0 : continue;
3535 :
3536 0 : memset(&vreq, 0, sizeof(vreq));
3537 : #if PIM_IPV == 4
3538 0 : vreq.vifi = pim_ifp->mroute_vif_index;
3539 0 : if (ioctl(pim->mroute_socket, SIOCGETVIFCNT, &vreq)) {
3540 0 : zlog_warn(
3541 : "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3542 : (unsigned long)SIOCGETVIFCNT, ifp->name,
3543 : pim_ifp->mroute_vif_index, errno,
3544 : safe_strerror(errno));
3545 : }
3546 : #else
3547 0 : vreq.mifi = pim_ifp->mroute_vif_index;
3548 0 : if (ioctl(pim->mroute_socket, SIOCGETMIFCNT_IN6, &vreq)) {
3549 0 : zlog_warn(
3550 : "ioctl(SIOCGETMIFCNT_IN6=%lu) failure for interface %s vif_index=%d: errno=%d: %s",
3551 : (unsigned long)SIOCGETMIFCNT_IN6, ifp->name,
3552 : pim_ifp->mroute_vif_index, errno,
3553 : safe_strerror(errno));
3554 : }
3555 : #endif
3556 :
3557 0 : if (json) {
3558 0 : json_row = json_object_new_object();
3559 0 : json_object_string_add(json_row, "name", ifp->name);
3560 0 : json_object_string_add(json_row, "state",
3561 0 : if_is_up(ifp) ? "up" : "down");
3562 0 : json_object_string_addf(json_row, "address", "%pPA",
3563 : &pim_ifp->primary_address);
3564 0 : json_object_int_add(json_row, "ifIndex", ifp->ifindex);
3565 0 : json_object_int_add(json_row, "vif",
3566 0 : pim_ifp->mroute_vif_index);
3567 0 : json_object_int_add(json_row, "pktsIn",
3568 0 : (unsigned long)vreq.icount);
3569 0 : json_object_int_add(json_row, "pktsOut",
3570 0 : (unsigned long)vreq.ocount);
3571 0 : json_object_int_add(json_row, "bytesIn",
3572 0 : (unsigned long)vreq.ibytes);
3573 0 : json_object_int_add(json_row, "bytesOut",
3574 0 : (unsigned long)vreq.obytes);
3575 0 : json_object_object_add(json, ifp->name, json_row);
3576 : } else {
3577 0 : ttable_add_row(tt, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
3578 0 : ifp->name, &pim_ifp->primary_address,
3579 : ifp->ifindex, pim_ifp->mroute_vif_index,
3580 : (unsigned long)vreq.icount,
3581 : (unsigned long)vreq.ocount,
3582 : (unsigned long)vreq.ibytes,
3583 : (unsigned long)vreq.obytes);
3584 : }
3585 : }
3586 : /* Dump the generated table. */
3587 0 : if (!json) {
3588 0 : table = ttable_dump(tt, "\n");
3589 0 : vty_out(vty, "%s\n", table);
3590 0 : XFREE(MTYPE_TMP, table);
3591 0 : ttable_del(tt);
3592 : }
3593 0 : }
3594 :
3595 0 : void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
3596 : {
3597 0 : struct vrf *vrf = pim->vrf;
3598 0 : time_t now = pim_time_monotonic_sec();
3599 0 : char uptime[10];
3600 0 : char mlag_role[80];
3601 :
3602 0 : pim = vrf->info;
3603 :
3604 0 : vty_out(vty, "Router MLAG Role: %s\n",
3605 0 : mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
3606 0 : vty_out(vty, "Mroute socket descriptor:");
3607 :
3608 0 : vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
3609 0 : vty_out(vty, "PIM Register socket descriptor:");
3610 0 : vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name);
3611 :
3612 0 : pim_time_uptime(uptime, sizeof(uptime),
3613 0 : now - pim->mroute_socket_creation);
3614 0 : vty_out(vty, "Mroute socket uptime: %s\n", uptime);
3615 :
3616 0 : vty_out(vty, "\n");
3617 :
3618 0 : pim_zebra_zclient_update(vty);
3619 0 : pim_zlookup_show_ip_multicast(vty);
3620 :
3621 0 : vty_out(vty, "\n");
3622 0 : vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
3623 :
3624 0 : vty_out(vty, "\n");
3625 0 : vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
3626 0 : vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
3627 0 : vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
3628 0 : vty_out(vty, "PIM ECMP Rebalance: %s\n",
3629 0 : pim->ecmp_rebalance_enable ? "Enable" : "Disable");
3630 :
3631 0 : vty_out(vty, "\n");
3632 :
3633 0 : pim_show_rpf_refresh_stats(vty, pim, now, NULL);
3634 :
3635 0 : vty_out(vty, "\n");
3636 :
3637 0 : show_scan_oil_stats(pim, vty, now);
3638 :
3639 0 : show_multicast_interfaces(pim, vty, NULL);
3640 0 : }
3641 :
3642 13 : void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
3643 : bool fill, json_object *json)
3644 : {
3645 13 : struct listnode *node;
3646 13 : struct channel_oil *c_oil;
3647 13 : struct static_route *s_route;
3648 13 : struct ttable *tt = NULL;
3649 13 : char *table = NULL;
3650 13 : time_t now;
3651 13 : json_object *json_group = NULL;
3652 13 : json_object *json_source = NULL;
3653 13 : json_object *json_oil = NULL;
3654 13 : json_object *json_ifp_out = NULL;
3655 13 : int found_oif;
3656 13 : int first;
3657 13 : char grp_str[PIM_ADDRSTRLEN];
3658 13 : char src_str[PIM_ADDRSTRLEN];
3659 13 : char in_ifname[INTERFACE_NAMSIZ + 1];
3660 13 : char out_ifname[INTERFACE_NAMSIZ + 1];
3661 13 : int oif_vif_index;
3662 13 : struct interface *ifp_in;
3663 13 : char proto[100];
3664 13 : char state_str[PIM_REG_STATE_STR_LEN];
3665 13 : char mroute_uptime[10];
3666 :
3667 13 : if (!json) {
3668 0 : vty_out(vty, "IP Multicast Routing Table\n");
3669 0 : vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
3670 0 : vty_out(vty,
3671 : " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
3672 :
3673 : /* Prepare table. */
3674 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
3675 0 : ttable_add_row(
3676 : tt, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
3677 0 : tt->style.cell.rpad = 2;
3678 0 : tt->style.corner = '+';
3679 0 : ttable_restyle(tt);
3680 : }
3681 :
3682 13 : now = pim_time_monotonic_sec();
3683 :
3684 : /* print list of PIM and IGMP routes */
3685 52 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
3686 13 : found_oif = 0;
3687 13 : first = 1;
3688 13 : if (!c_oil->installed)
3689 1 : continue;
3690 :
3691 12 : if (!pim_addr_is_any(sg->grp) &&
3692 0 : pim_addr_cmp(sg->grp, *oil_mcastgrp(c_oil)))
3693 0 : continue;
3694 12 : if (!pim_addr_is_any(sg->src) &&
3695 0 : pim_addr_cmp(sg->src, *oil_origin(c_oil)))
3696 0 : continue;
3697 :
3698 12 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs",
3699 : oil_mcastgrp(c_oil));
3700 12 : snprintfrr(src_str, sizeof(src_str), "%pPAs",
3701 : oil_origin(c_oil));
3702 :
3703 12 : strlcpy(state_str, "S", sizeof(state_str));
3704 : /* When a non DR receives a igmp join, it creates a (*,G)
3705 : * channel_oil without any upstream creation
3706 : */
3707 12 : if (c_oil->up) {
3708 12 : if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags))
3709 0 : strlcat(state_str, "C", sizeof(state_str));
3710 12 : if (pim_upstream_is_sg_rpt(c_oil->up))
3711 0 : strlcat(state_str, "R", sizeof(state_str));
3712 12 : if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags))
3713 1 : strlcat(state_str, "F", sizeof(state_str));
3714 12 : if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
3715 12 : strlcat(state_str, "T", sizeof(state_str));
3716 : }
3717 12 : if (pim_channel_oil_empty(c_oil))
3718 10 : strlcat(state_str, "P", sizeof(state_str));
3719 :
3720 12 : ifp_in = pim_if_find_by_vif_index(pim, *oil_parent(c_oil));
3721 :
3722 12 : if (ifp_in)
3723 12 : strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3724 : else
3725 0 : strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3726 :
3727 :
3728 12 : pim_time_uptime(mroute_uptime, sizeof(mroute_uptime),
3729 12 : now - c_oil->mroute_creation);
3730 :
3731 12 : if (json) {
3732 :
3733 : /* Find the group, create it if it doesn't exist */
3734 12 : json_object_object_get_ex(json, grp_str, &json_group);
3735 :
3736 12 : if (!json_group) {
3737 12 : json_group = json_object_new_object();
3738 12 : json_object_object_add(json, grp_str,
3739 : json_group);
3740 : }
3741 :
3742 : /* Find the source nested under the group, create it if
3743 : * it doesn't exist
3744 : */
3745 12 : json_object_object_get_ex(json_group, src_str,
3746 : &json_source);
3747 :
3748 12 : if (!json_source) {
3749 12 : json_source = json_object_new_object();
3750 12 : json_object_object_add(json_group, src_str,
3751 : json_source);
3752 : }
3753 :
3754 : /* Find the inbound interface nested under the source,
3755 : * create it if it doesn't exist
3756 : */
3757 12 : json_object_string_add(json_source, "source", src_str);
3758 12 : json_object_string_add(json_source, "group", grp_str);
3759 12 : json_object_int_add(json_source, "installed",
3760 12 : c_oil->installed);
3761 12 : json_object_int_add(json_source, "refCount",
3762 12 : c_oil->oil_ref_count);
3763 12 : json_object_int_add(json_source, "oilSize",
3764 12 : c_oil->oil_size);
3765 12 : json_object_int_add(json_source, "oilInheritedRescan",
3766 12 : c_oil->oil_inherited_rescan);
3767 12 : json_object_string_add(json_source, "iif", in_ifname);
3768 12 : json_object_string_add(json_source, "upTime",
3769 : mroute_uptime);
3770 12 : json_oil = NULL;
3771 : }
3772 :
3773 3084 : for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3774 3072 : ++oif_vif_index) {
3775 3072 : struct interface *ifp_out;
3776 3072 : int ttl;
3777 :
3778 3072 : ttl = oil_if_has(c_oil, oif_vif_index);
3779 3072 : if (ttl < 1)
3780 3070 : continue;
3781 :
3782 : /* do not display muted OIFs */
3783 2 : if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_MUTE)
3784 0 : continue;
3785 :
3786 2 : if (*oil_parent(c_oil) == oif_vif_index &&
3787 0 : !pim_mroute_allow_iif_in_oil(c_oil, oif_vif_index))
3788 0 : continue;
3789 :
3790 2 : ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3791 2 : found_oif = 1;
3792 :
3793 2 : if (ifp_out)
3794 2 : strlcpy(out_ifname, ifp_out->name,
3795 : sizeof(out_ifname));
3796 : else
3797 0 : strlcpy(out_ifname, "<oif?>",
3798 : sizeof(out_ifname));
3799 :
3800 2 : if (json) {
3801 2 : json_ifp_out = json_object_new_object();
3802 2 : json_object_string_add(json_ifp_out, "source",
3803 : src_str);
3804 2 : json_object_string_add(json_ifp_out, "group",
3805 : grp_str);
3806 :
3807 2 : if (c_oil->oif_flags[oif_vif_index] &
3808 : PIM_OIF_FLAG_PROTO_PIM)
3809 2 : json_object_boolean_true_add(
3810 : json_ifp_out, "protocolPim");
3811 :
3812 2 : if (c_oil->oif_flags[oif_vif_index] &
3813 : PIM_OIF_FLAG_PROTO_GM)
3814 : #if PIM_IPV == 4
3815 0 : json_object_boolean_true_add(
3816 : json_ifp_out, "protocolIgmp");
3817 : #else
3818 0 : json_object_boolean_true_add(
3819 : json_ifp_out, "protocolMld");
3820 : #endif
3821 :
3822 2 : if (c_oil->oif_flags[oif_vif_index] &
3823 : PIM_OIF_FLAG_PROTO_VXLAN)
3824 0 : json_object_boolean_true_add(
3825 : json_ifp_out, "protocolVxlan");
3826 :
3827 2 : if (c_oil->oif_flags[oif_vif_index] &
3828 : PIM_OIF_FLAG_PROTO_STAR)
3829 0 : json_object_boolean_true_add(
3830 : json_ifp_out,
3831 : "protocolInherited");
3832 :
3833 2 : json_object_string_add(json_ifp_out,
3834 : "inboundInterface",
3835 : in_ifname);
3836 2 : json_object_int_add(json_ifp_out, "iVifI",
3837 2 : *oil_parent(c_oil));
3838 2 : json_object_string_add(json_ifp_out,
3839 : "outboundInterface",
3840 : out_ifname);
3841 2 : json_object_int_add(json_ifp_out, "oVifI",
3842 : oif_vif_index);
3843 2 : json_object_int_add(json_ifp_out, "ttl", ttl);
3844 2 : json_object_string_add(json_ifp_out, "upTime",
3845 : mroute_uptime);
3846 2 : json_object_string_add(json_source, "flags",
3847 : state_str);
3848 2 : if (!json_oil) {
3849 2 : json_oil = json_object_new_object();
3850 2 : json_object_object_add(json_source,
3851 : "oil", json_oil);
3852 : }
3853 2 : json_object_object_add(json_oil, out_ifname,
3854 : json_ifp_out);
3855 : } else {
3856 0 : proto[0] = '\0';
3857 0 : if (c_oil->oif_flags[oif_vif_index] &
3858 : PIM_OIF_FLAG_PROTO_PIM) {
3859 0 : strlcpy(proto, "PIM", sizeof(proto));
3860 : }
3861 :
3862 0 : if (c_oil->oif_flags[oif_vif_index] &
3863 : PIM_OIF_FLAG_PROTO_GM) {
3864 : #if PIM_IPV == 4
3865 0 : strlcpy(proto, "IGMP", sizeof(proto));
3866 : #else
3867 0 : strlcpy(proto, "MLD", sizeof(proto));
3868 : #endif
3869 : }
3870 :
3871 0 : if (c_oil->oif_flags[oif_vif_index] &
3872 : PIM_OIF_FLAG_PROTO_VXLAN) {
3873 0 : strlcpy(proto, "VxLAN", sizeof(proto));
3874 : }
3875 :
3876 0 : if (c_oil->oif_flags[oif_vif_index] &
3877 : PIM_OIF_FLAG_PROTO_STAR) {
3878 0 : strlcpy(proto, "STAR", sizeof(proto));
3879 : }
3880 :
3881 0 : ttable_add_row(tt, "%s|%s|%s|%s|%s|%s|%d|%s",
3882 : src_str, grp_str, state_str,
3883 : proto, in_ifname, out_ifname,
3884 : ttl, mroute_uptime);
3885 :
3886 0 : if (first) {
3887 0 : src_str[0] = '\0';
3888 0 : grp_str[0] = '\0';
3889 0 : in_ifname[0] = '\0';
3890 0 : state_str[0] = '\0';
3891 0 : mroute_uptime[0] = '\0';
3892 0 : first = 0;
3893 : }
3894 : }
3895 : }
3896 :
3897 12 : if (!json && !found_oif) {
3898 0 : ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
3899 : oil_origin(c_oil), oil_mcastgrp(c_oil),
3900 : state_str, "none", in_ifname, "none", 0,
3901 : "--:--:--");
3902 : }
3903 : }
3904 :
3905 : /* Print list of static routes */
3906 26 : for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
3907 0 : first = 1;
3908 :
3909 0 : if (!s_route->c_oil.installed)
3910 0 : continue;
3911 :
3912 0 : snprintfrr(grp_str, sizeof(grp_str), "%pPAs", &s_route->group);
3913 0 : snprintfrr(src_str, sizeof(src_str), "%pPAs", &s_route->source);
3914 0 : ifp_in = pim_if_find_by_vif_index(pim, s_route->iif);
3915 0 : found_oif = 0;
3916 :
3917 0 : if (ifp_in)
3918 0 : strlcpy(in_ifname, ifp_in->name, sizeof(in_ifname));
3919 : else
3920 0 : strlcpy(in_ifname, "<iif?>", sizeof(in_ifname));
3921 :
3922 0 : if (json) {
3923 :
3924 : /* Find the group, create it if it doesn't exist */
3925 0 : json_object_object_get_ex(json, grp_str, &json_group);
3926 :
3927 0 : if (!json_group) {
3928 0 : json_group = json_object_new_object();
3929 0 : json_object_object_add(json, grp_str,
3930 : json_group);
3931 : }
3932 :
3933 : /* Find the source nested under the group, create it if
3934 : * it doesn't exist
3935 : */
3936 0 : json_object_object_get_ex(json_group, src_str,
3937 : &json_source);
3938 :
3939 0 : if (!json_source) {
3940 0 : json_source = json_object_new_object();
3941 0 : json_object_object_add(json_group, src_str,
3942 : json_source);
3943 : }
3944 :
3945 0 : json_object_string_add(json_source, "iif", in_ifname);
3946 0 : json_oil = NULL;
3947 : } else {
3948 0 : strlcpy(proto, "STATIC", sizeof(proto));
3949 : }
3950 :
3951 0 : for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
3952 0 : ++oif_vif_index) {
3953 0 : struct interface *ifp_out;
3954 0 : char oif_uptime[10];
3955 0 : int ttl;
3956 :
3957 0 : ttl = s_route->oif_ttls[oif_vif_index];
3958 0 : if (ttl < 1)
3959 0 : continue;
3960 :
3961 0 : ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index);
3962 0 : pim_time_uptime(
3963 : oif_uptime, sizeof(oif_uptime),
3964 : now - s_route->c_oil
3965 0 : .oif_creation[oif_vif_index]);
3966 0 : found_oif = 1;
3967 :
3968 0 : if (ifp_out)
3969 0 : strlcpy(out_ifname, ifp_out->name,
3970 : sizeof(out_ifname));
3971 : else
3972 0 : strlcpy(out_ifname, "<oif?>",
3973 : sizeof(out_ifname));
3974 :
3975 0 : if (json) {
3976 0 : json_ifp_out = json_object_new_object();
3977 0 : json_object_string_add(json_ifp_out, "source",
3978 : src_str);
3979 0 : json_object_string_add(json_ifp_out, "group",
3980 : grp_str);
3981 0 : json_object_boolean_true_add(json_ifp_out,
3982 : "protocolStatic");
3983 0 : json_object_string_add(json_ifp_out,
3984 : "inboundInterface",
3985 : in_ifname);
3986 0 : json_object_int_add(
3987 : json_ifp_out, "iVifI",
3988 0 : *oil_parent(&s_route->c_oil));
3989 0 : json_object_string_add(json_ifp_out,
3990 : "outboundInterface",
3991 : out_ifname);
3992 0 : json_object_int_add(json_ifp_out, "oVifI",
3993 : oif_vif_index);
3994 0 : json_object_int_add(json_ifp_out, "ttl", ttl);
3995 0 : json_object_string_add(json_ifp_out, "upTime",
3996 : oif_uptime);
3997 0 : if (!json_oil) {
3998 0 : json_oil = json_object_new_object();
3999 0 : json_object_object_add(json_source,
4000 : "oil", json_oil);
4001 : }
4002 0 : json_object_object_add(json_oil, out_ifname,
4003 : json_ifp_out);
4004 : } else {
4005 0 : ttable_add_row(
4006 : tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4007 : &s_route->source, &s_route->group, "-",
4008 : proto, in_ifname, out_ifname, ttl,
4009 : oif_uptime);
4010 0 : if (first && !fill) {
4011 0 : src_str[0] = '\0';
4012 0 : grp_str[0] = '\0';
4013 0 : in_ifname[0] = '\0';
4014 0 : first = 0;
4015 : }
4016 : }
4017 : }
4018 :
4019 0 : if (!json && !found_oif) {
4020 0 : ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
4021 : &s_route->source, &s_route->group, "-",
4022 : proto, in_ifname, "none", 0, "--:--:--");
4023 : }
4024 : }
4025 : /* Dump the generated table. */
4026 13 : if (!json) {
4027 0 : table = ttable_dump(tt, "\n");
4028 0 : vty_out(vty, "%s\n", table);
4029 0 : XFREE(MTYPE_TMP, table);
4030 0 : ttable_del(tt);
4031 : }
4032 13 : }
4033 :
4034 0 : static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
4035 : json_object *json,
4036 : struct ttable *tt)
4037 : {
4038 0 : json_object *json_group = NULL;
4039 0 : json_object *json_source = NULL;
4040 :
4041 0 : if (!c_oil->installed)
4042 0 : return;
4043 :
4044 0 : pim_mroute_update_counters(c_oil);
4045 :
4046 0 : if (json) {
4047 0 : char group_str[PIM_ADDRSTRLEN];
4048 0 : char source_str[PIM_ADDRSTRLEN];
4049 :
4050 0 : snprintfrr(group_str, sizeof(group_str), "%pPAs",
4051 : oil_mcastgrp(c_oil));
4052 0 : snprintfrr(source_str, sizeof(source_str), "%pPAs",
4053 : oil_origin(c_oil));
4054 :
4055 0 : json_object_object_get_ex(json, group_str, &json_group);
4056 :
4057 0 : if (!json_group) {
4058 0 : json_group = json_object_new_object();
4059 0 : json_object_object_add(json, group_str, json_group);
4060 : }
4061 :
4062 0 : json_source = json_object_new_object();
4063 0 : json_object_object_add(json_group, source_str, json_source);
4064 0 : json_object_int_add(json_source, "lastUsed",
4065 0 : c_oil->cc.lastused / 100);
4066 0 : json_object_int_add(json_source, "packets", c_oil->cc.pktcnt);
4067 0 : json_object_int_add(json_source, "bytes", c_oil->cc.bytecnt);
4068 0 : json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
4069 :
4070 : } else {
4071 0 : ttable_add_row(tt, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
4072 : oil_origin(c_oil), oil_mcastgrp(c_oil),
4073 0 : c_oil->cc.lastused / 100,
4074 0 : c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
4075 0 : c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
4076 0 : c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
4077 : }
4078 : }
4079 :
4080 0 : void show_mroute_count(struct pim_instance *pim, struct vty *vty,
4081 : json_object *json)
4082 : {
4083 0 : struct listnode *node;
4084 0 : struct channel_oil *c_oil;
4085 0 : struct static_route *sr;
4086 0 : struct ttable *tt = NULL;
4087 0 : char *table = NULL;
4088 :
4089 0 : if (!json) {
4090 0 : vty_out(vty, "\n");
4091 :
4092 : /* Prepare table. */
4093 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
4094 0 : ttable_add_row(tt,
4095 : "Source|Group|LastUsed|Packets|Bytes|WrongIf");
4096 0 : tt->style.cell.rpad = 2;
4097 0 : tt->style.corner = '+';
4098 0 : ttable_restyle(tt);
4099 : }
4100 :
4101 : /* Print PIM and IGMP route counts */
4102 0 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
4103 0 : show_mroute_count_per_channel_oil(c_oil, json, tt);
4104 :
4105 0 : for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
4106 0 : show_mroute_count_per_channel_oil(&sr->c_oil, json, tt);
4107 :
4108 : /* Dump the generated table. */
4109 0 : if (!json) {
4110 0 : table = ttable_dump(tt, "\n");
4111 0 : vty_out(vty, "%s\n", table);
4112 0 : XFREE(MTYPE_TMP, table);
4113 0 : ttable_del(tt);
4114 : }
4115 0 : }
4116 :
4117 0 : void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
4118 : json_object *json)
4119 : {
4120 0 : struct listnode *node;
4121 0 : struct channel_oil *c_oil;
4122 0 : struct static_route *s_route;
4123 0 : uint32_t starg_sw_mroute_cnt = 0;
4124 0 : uint32_t sg_sw_mroute_cnt = 0;
4125 0 : uint32_t starg_hw_mroute_cnt = 0;
4126 0 : uint32_t sg_hw_mroute_cnt = 0;
4127 0 : json_object *json_starg = NULL;
4128 0 : json_object *json_sg = NULL;
4129 :
4130 0 : if (!json)
4131 0 : vty_out(vty, "Mroute Type Installed/Total\n");
4132 :
4133 0 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
4134 0 : if (!c_oil->installed) {
4135 0 : if (pim_addr_is_any(*oil_origin(c_oil)))
4136 0 : starg_sw_mroute_cnt++;
4137 : else
4138 0 : sg_sw_mroute_cnt++;
4139 : } else {
4140 0 : if (pim_addr_is_any(*oil_origin(c_oil)))
4141 0 : starg_hw_mroute_cnt++;
4142 : else
4143 0 : sg_hw_mroute_cnt++;
4144 : }
4145 : }
4146 :
4147 0 : for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
4148 0 : if (!s_route->c_oil.installed) {
4149 0 : if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
4150 0 : starg_sw_mroute_cnt++;
4151 : else
4152 0 : sg_sw_mroute_cnt++;
4153 : } else {
4154 0 : if (pim_addr_is_any(*oil_origin(&s_route->c_oil)))
4155 0 : starg_hw_mroute_cnt++;
4156 : else
4157 0 : sg_hw_mroute_cnt++;
4158 : }
4159 : }
4160 :
4161 0 : if (!json) {
4162 0 : vty_out(vty, "%-20s %u/%u\n", "(*, G)", starg_hw_mroute_cnt,
4163 : starg_sw_mroute_cnt + starg_hw_mroute_cnt);
4164 0 : vty_out(vty, "%-20s %u/%u\n", "(S, G)", sg_hw_mroute_cnt,
4165 : sg_sw_mroute_cnt + sg_hw_mroute_cnt);
4166 0 : vty_out(vty, "------\n");
4167 0 : vty_out(vty, "%-20s %u/%u\n", "Total",
4168 : (starg_hw_mroute_cnt + sg_hw_mroute_cnt),
4169 0 : (starg_sw_mroute_cnt + starg_hw_mroute_cnt +
4170 : sg_sw_mroute_cnt + sg_hw_mroute_cnt));
4171 : } else {
4172 : /* (*,G) route details */
4173 0 : json_starg = json_object_new_object();
4174 0 : json_object_object_add(json, "wildcardGroup", json_starg);
4175 :
4176 0 : json_object_int_add(json_starg, "installed",
4177 : starg_hw_mroute_cnt);
4178 0 : json_object_int_add(json_starg, "total",
4179 0 : starg_sw_mroute_cnt + starg_hw_mroute_cnt);
4180 :
4181 : /* (S, G) route details */
4182 0 : json_sg = json_object_new_object();
4183 0 : json_object_object_add(json, "sourceGroup", json_sg);
4184 :
4185 0 : json_object_int_add(json_sg, "installed", sg_hw_mroute_cnt);
4186 0 : json_object_int_add(json_sg, "total",
4187 0 : sg_sw_mroute_cnt + sg_hw_mroute_cnt);
4188 :
4189 0 : json_object_int_add(json, "totalNumOfInstalledMroutes",
4190 0 : starg_hw_mroute_cnt + sg_hw_mroute_cnt);
4191 0 : json_object_int_add(json, "totalNumOfMroutes",
4192 0 : starg_sw_mroute_cnt + starg_hw_mroute_cnt +
4193 0 : sg_sw_mroute_cnt +
4194 : sg_hw_mroute_cnt);
4195 : }
4196 0 : }
4197 :
4198 0 : int clear_ip_mroute_count_command(struct vty *vty, const char *name)
4199 : {
4200 0 : struct listnode *node;
4201 0 : struct channel_oil *c_oil;
4202 0 : struct static_route *sr;
4203 0 : struct vrf *v = pim_cmd_lookup(vty, name);
4204 0 : struct pim_instance *pim;
4205 :
4206 0 : if (!v)
4207 : return CMD_WARNING;
4208 :
4209 0 : pim = v->info;
4210 0 : frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
4211 0 : if (!c_oil->installed)
4212 0 : continue;
4213 :
4214 0 : pim_mroute_update_counters(c_oil);
4215 0 : c_oil->cc.origpktcnt = c_oil->cc.pktcnt;
4216 0 : c_oil->cc.origbytecnt = c_oil->cc.bytecnt;
4217 0 : c_oil->cc.origwrong_if = c_oil->cc.wrong_if;
4218 : }
4219 :
4220 0 : for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr)) {
4221 0 : if (!sr->c_oil.installed)
4222 0 : continue;
4223 :
4224 0 : pim_mroute_update_counters(&sr->c_oil);
4225 :
4226 0 : sr->c_oil.cc.origpktcnt = sr->c_oil.cc.pktcnt;
4227 0 : sr->c_oil.cc.origbytecnt = sr->c_oil.cc.bytecnt;
4228 0 : sr->c_oil.cc.origwrong_if = sr->c_oil.cc.wrong_if;
4229 : }
4230 : return CMD_SUCCESS;
4231 : }
4232 :
4233 0 : struct vrf *pim_cmd_lookup(struct vty *vty, const char *name)
4234 : {
4235 0 : struct vrf *vrf;
4236 :
4237 0 : if (name)
4238 0 : vrf = vrf_lookup_by_name(name);
4239 : else
4240 0 : vrf = vrf_lookup_by_id(VRF_DEFAULT);
4241 :
4242 0 : if (!vrf)
4243 0 : vty_out(vty, "Specified VRF: %s does not exist\n", name);
4244 :
4245 0 : return vrf;
4246 : }
4247 :
4248 0 : void clear_mroute(struct pim_instance *pim)
4249 : {
4250 0 : struct pim_upstream *up;
4251 0 : struct interface *ifp;
4252 :
4253 : /* scan interfaces */
4254 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
4255 0 : struct pim_interface *pim_ifp = ifp->info;
4256 0 : struct pim_ifchannel *ch;
4257 :
4258 0 : if (!pim_ifp)
4259 0 : continue;
4260 :
4261 : /* deleting all ifchannels */
4262 0 : while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
4263 0 : ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
4264 :
4265 0 : pim_ifchannel_delete(ch);
4266 : }
4267 :
4268 : #if PIM_IPV == 4
4269 : /* clean up all igmp groups */
4270 0 : struct gm_group *grp;
4271 :
4272 0 : if (pim_ifp->gm_group_list) {
4273 0 : while (pim_ifp->gm_group_list->count) {
4274 0 : grp = listnode_head(pim_ifp->gm_group_list);
4275 0 : igmp_group_delete(grp);
4276 : }
4277 : }
4278 : #else
4279 0 : struct gm_if *gm_ifp;
4280 :
4281 0 : gm_ifp = pim_ifp->mld;
4282 0 : if (gm_ifp)
4283 0 : gm_group_delete(gm_ifp);
4284 : #endif
4285 : }
4286 :
4287 : /* clean up all upstreams*/
4288 0 : while ((up = rb_pim_upstream_first(&pim->upstream_head)))
4289 0 : pim_upstream_del(pim, up, __func__);
4290 0 : }
4291 :
4292 0 : void clear_pim_statistics(struct pim_instance *pim)
4293 : {
4294 0 : struct interface *ifp;
4295 :
4296 0 : pim->bsm_rcvd = 0;
4297 0 : pim->bsm_sent = 0;
4298 0 : pim->bsm_dropped = 0;
4299 :
4300 : /* scan interfaces */
4301 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
4302 0 : struct pim_interface *pim_ifp = ifp->info;
4303 :
4304 0 : if (!pim_ifp)
4305 0 : continue;
4306 :
4307 0 : pim_ifp->pim_ifstat_bsm_cfg_miss = 0;
4308 0 : pim_ifp->pim_ifstat_ucast_bsm_cfg_miss = 0;
4309 0 : pim_ifp->pim_ifstat_bsm_invalid_sz = 0;
4310 : }
4311 0 : }
4312 :
4313 0 : int clear_pim_interface_traffic(const char *vrf, struct vty *vty)
4314 : {
4315 0 : struct interface *ifp = NULL;
4316 0 : struct pim_interface *pim_ifp = NULL;
4317 :
4318 0 : struct vrf *v = pim_cmd_lookup(vty, vrf);
4319 :
4320 0 : if (!v)
4321 : return CMD_WARNING;
4322 :
4323 0 : FOR_ALL_INTERFACES (v, ifp) {
4324 0 : pim_ifp = ifp->info;
4325 :
4326 0 : if (!pim_ifp)
4327 0 : continue;
4328 :
4329 0 : pim_ifp->pim_ifstat_hello_recv = 0;
4330 0 : pim_ifp->pim_ifstat_hello_sent = 0;
4331 0 : pim_ifp->pim_ifstat_join_recv = 0;
4332 0 : pim_ifp->pim_ifstat_join_send = 0;
4333 0 : pim_ifp->pim_ifstat_prune_recv = 0;
4334 0 : pim_ifp->pim_ifstat_prune_send = 0;
4335 0 : pim_ifp->pim_ifstat_reg_recv = 0;
4336 0 : pim_ifp->pim_ifstat_reg_send = 0;
4337 0 : pim_ifp->pim_ifstat_reg_stop_recv = 0;
4338 0 : pim_ifp->pim_ifstat_reg_stop_send = 0;
4339 0 : pim_ifp->pim_ifstat_assert_recv = 0;
4340 0 : pim_ifp->pim_ifstat_assert_send = 0;
4341 0 : pim_ifp->pim_ifstat_bsm_rx = 0;
4342 0 : pim_ifp->pim_ifstat_bsm_tx = 0;
4343 : #if PIM_IPV == 4
4344 0 : pim_ifp->igmp_ifstat_joins_sent = 0;
4345 0 : pim_ifp->igmp_ifstat_joins_failed = 0;
4346 0 : pim_ifp->igmp_peak_group_count = 0;
4347 : #endif
4348 : }
4349 :
4350 : return CMD_SUCCESS;
4351 : }
4352 :
4353 0 : int pim_debug_pim_cmd(void)
4354 : {
4355 0 : PIM_DO_DEBUG_PIM_EVENTS;
4356 0 : PIM_DO_DEBUG_PIM_PACKETS;
4357 0 : PIM_DO_DEBUG_PIM_TRACE;
4358 0 : PIM_DO_DEBUG_MSDP_EVENTS;
4359 0 : PIM_DO_DEBUG_MSDP_PACKETS;
4360 0 : PIM_DO_DEBUG_BSM;
4361 0 : PIM_DO_DEBUG_VXLAN;
4362 0 : return CMD_SUCCESS;
4363 : }
4364 :
4365 0 : int pim_no_debug_pim_cmd(void)
4366 : {
4367 0 : PIM_DONT_DEBUG_PIM_EVENTS;
4368 0 : PIM_DONT_DEBUG_PIM_PACKETS;
4369 0 : PIM_DONT_DEBUG_PIM_TRACE;
4370 0 : PIM_DONT_DEBUG_MSDP_EVENTS;
4371 0 : PIM_DONT_DEBUG_MSDP_PACKETS;
4372 :
4373 0 : PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
4374 0 : PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
4375 0 : PIM_DONT_DEBUG_BSM;
4376 0 : PIM_DONT_DEBUG_VXLAN;
4377 0 : return CMD_SUCCESS;
4378 : }
4379 :
4380 0 : int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
4381 : const char *registers, struct vty *vty)
4382 : {
4383 0 : if (hello) {
4384 0 : PIM_DO_DEBUG_PIM_HELLO;
4385 0 : vty_out(vty, "PIM Hello debugging is on\n");
4386 0 : } else if (joins) {
4387 0 : PIM_DO_DEBUG_PIM_J_P;
4388 0 : vty_out(vty, "PIM Join/Prune debugging is on\n");
4389 0 : } else if (registers) {
4390 0 : PIM_DO_DEBUG_PIM_REG;
4391 0 : vty_out(vty, "PIM Register debugging is on\n");
4392 : } else {
4393 0 : PIM_DO_DEBUG_PIM_PACKETS;
4394 0 : vty_out(vty, "PIM Packet debugging is on\n");
4395 : }
4396 0 : return CMD_SUCCESS;
4397 : }
4398 :
4399 0 : int pim_no_debug_pim_packets_cmd(const char *hello, const char *joins,
4400 : const char *registers, struct vty *vty)
4401 : {
4402 0 : if (hello) {
4403 0 : PIM_DONT_DEBUG_PIM_HELLO;
4404 0 : vty_out(vty, "PIM Hello debugging is off\n");
4405 0 : } else if (joins) {
4406 0 : PIM_DONT_DEBUG_PIM_J_P;
4407 0 : vty_out(vty, "PIM Join/Prune debugging is off\n");
4408 0 : } else if (registers) {
4409 0 : PIM_DONT_DEBUG_PIM_REG;
4410 0 : vty_out(vty, "PIM Register debugging is off\n");
4411 : } else {
4412 0 : PIM_DONT_DEBUG_PIM_PACKETS;
4413 0 : vty_out(vty, "PIM Packet debugging is off\n");
4414 : }
4415 :
4416 0 : return CMD_SUCCESS;
4417 : }
4418 :
4419 0 : int pim_show_rpf_helper(const char *vrf, struct vty *vty, bool json)
4420 : {
4421 0 : struct pim_instance *pim;
4422 0 : struct vrf *v;
4423 0 : json_object *json_parent = NULL;
4424 :
4425 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4426 :
4427 0 : if (!v)
4428 : return CMD_WARNING;
4429 :
4430 0 : pim = v->info;
4431 :
4432 0 : if (!pim) {
4433 0 : vty_out(vty, "%% Unable to find pim instance\n");
4434 0 : return CMD_WARNING;
4435 : }
4436 :
4437 0 : if (json)
4438 0 : json_parent = json_object_new_object();
4439 :
4440 0 : pim_show_rpf(pim, vty, json_parent);
4441 :
4442 0 : if (json)
4443 0 : vty_json(vty, json_parent);
4444 :
4445 : return CMD_SUCCESS;
4446 : }
4447 :
4448 0 : int pim_show_rpf_vrf_all_helper(struct vty *vty, bool json)
4449 : {
4450 0 : struct vrf *vrf;
4451 0 : json_object *json_parent = NULL;
4452 0 : json_object *json_vrf = NULL;
4453 :
4454 0 : if (json)
4455 0 : json_parent = json_object_new_object();
4456 :
4457 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4458 0 : if (!json)
4459 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4460 : else
4461 0 : json_vrf = json_object_new_object();
4462 0 : pim_show_rpf(vrf->info, vty, json_vrf);
4463 0 : if (json)
4464 0 : json_object_object_add(json_parent, vrf->name,
4465 : json_vrf);
4466 : }
4467 0 : if (json)
4468 0 : vty_json(vty, json_parent);
4469 :
4470 0 : return CMD_SUCCESS;
4471 : }
4472 :
4473 4 : int pim_show_rp_helper(const char *vrf, struct vty *vty, const char *group_str,
4474 : const struct prefix *group, bool json)
4475 : {
4476 4 : struct pim_instance *pim;
4477 4 : struct vrf *v;
4478 4 : json_object *json_parent = NULL;
4479 4 : struct prefix *range = NULL;
4480 :
4481 4 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4482 :
4483 4 : if (!v)
4484 : return CMD_WARNING;
4485 :
4486 4 : pim = v->info;
4487 :
4488 4 : if (!pim) {
4489 0 : vty_out(vty, "%% Unable to find pim instance\n");
4490 0 : return CMD_WARNING;
4491 : }
4492 :
4493 4 : if (group_str) {
4494 0 : range = prefix_new();
4495 0 : prefix_copy(range, group);
4496 0 : apply_mask(range);
4497 : }
4498 :
4499 4 : if (json)
4500 1 : json_parent = json_object_new_object();
4501 :
4502 4 : pim_rp_show_information(pim, range, vty, json_parent);
4503 :
4504 4 : if (json)
4505 1 : vty_json(vty, json_parent);
4506 :
4507 4 : prefix_free(&range);
4508 :
4509 4 : return CMD_SUCCESS;
4510 : }
4511 :
4512 0 : int pim_show_rp_vrf_all_helper(struct vty *vty, const char *group_str,
4513 : const struct prefix *group, bool json)
4514 : {
4515 0 : struct vrf *vrf;
4516 0 : json_object *json_parent = NULL;
4517 0 : json_object *json_vrf = NULL;
4518 0 : struct prefix *range = NULL;
4519 :
4520 0 : if (group_str) {
4521 0 : range = prefix_new();
4522 0 : prefix_copy(range, group);
4523 0 : apply_mask(range);
4524 : }
4525 :
4526 0 : if (json)
4527 0 : json_parent = json_object_new_object();
4528 :
4529 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4530 0 : if (!json)
4531 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4532 : else
4533 0 : json_vrf = json_object_new_object();
4534 0 : pim_rp_show_information(vrf->info, range, vty, json_vrf);
4535 0 : if (json)
4536 0 : json_object_object_add(json_parent, vrf->name,
4537 : json_vrf);
4538 : }
4539 0 : if (json)
4540 0 : vty_json(vty, json_parent);
4541 :
4542 0 : prefix_free(&range);
4543 :
4544 0 : return CMD_SUCCESS;
4545 : }
4546 :
4547 0 : int pim_show_secondary_helper(const char *vrf, struct vty *vty)
4548 : {
4549 0 : struct pim_instance *pim;
4550 0 : struct vrf *v;
4551 :
4552 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4553 :
4554 0 : if (!v)
4555 : return CMD_WARNING;
4556 :
4557 0 : pim = v->info;
4558 :
4559 0 : if (!pim) {
4560 0 : vty_out(vty, "%% Unable to find pim instance\n");
4561 0 : return CMD_WARNING;
4562 : }
4563 :
4564 0 : pim_show_neighbors_secondary(pim, vty);
4565 :
4566 0 : return CMD_SUCCESS;
4567 : }
4568 :
4569 0 : int pim_show_statistics_helper(const char *vrf, struct vty *vty,
4570 : const char *word, bool uj)
4571 : {
4572 0 : struct pim_instance *pim;
4573 0 : struct vrf *v;
4574 :
4575 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4576 :
4577 0 : if (!v)
4578 : return CMD_WARNING;
4579 :
4580 0 : pim = v->info;
4581 :
4582 0 : if (!pim) {
4583 0 : vty_out(vty, "%% Unable to find pim instance\n");
4584 0 : return CMD_WARNING;
4585 : }
4586 :
4587 0 : if (word)
4588 0 : pim_show_statistics(pim, vty, word, uj);
4589 : else
4590 0 : pim_show_statistics(pim, vty, NULL, uj);
4591 :
4592 : return CMD_SUCCESS;
4593 : }
4594 :
4595 4 : int pim_show_upstream_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
4596 : pim_addr g, bool json)
4597 : {
4598 4 : pim_sgaddr sg = {0};
4599 4 : struct vrf *v;
4600 4 : struct pim_instance *pim;
4601 4 : json_object *json_parent = NULL;
4602 :
4603 4 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4604 :
4605 4 : if (!v) {
4606 0 : vty_out(vty, "%% Vrf specified: %s does not exist\n", vrf);
4607 0 : return CMD_WARNING;
4608 : }
4609 4 : pim = v->info;
4610 :
4611 4 : if (!pim) {
4612 0 : vty_out(vty, "%% Unable to find pim instance\n");
4613 0 : return CMD_WARNING;
4614 : }
4615 :
4616 4 : if (json)
4617 4 : json_parent = json_object_new_object();
4618 :
4619 4 : if (!pim_addr_is_any(s_or_g)) {
4620 0 : if (!pim_addr_is_any(g)) {
4621 0 : sg.src = s_or_g;
4622 0 : sg.grp = g;
4623 : } else
4624 0 : sg.grp = s_or_g;
4625 : }
4626 :
4627 4 : pim_show_upstream(pim, vty, &sg, json_parent);
4628 :
4629 4 : if (json)
4630 4 : vty_json(vty, json_parent);
4631 :
4632 : return CMD_SUCCESS;
4633 : }
4634 :
4635 0 : int pim_show_upstream_vrf_all_helper(struct vty *vty, bool json)
4636 : {
4637 0 : pim_sgaddr sg = {0};
4638 0 : struct vrf *vrf;
4639 0 : json_object *json_parent = NULL;
4640 0 : json_object *json_vrf = NULL;
4641 :
4642 0 : if (json)
4643 0 : json_parent = json_object_new_object();
4644 :
4645 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4646 0 : if (!json)
4647 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4648 : else
4649 0 : json_vrf = json_object_new_object();
4650 0 : pim_show_upstream(vrf->info, vty, &sg, json_vrf);
4651 0 : if (json)
4652 0 : json_object_object_add(json_parent, vrf->name,
4653 : json_vrf);
4654 : }
4655 :
4656 0 : if (json)
4657 0 : vty_json(vty, json_parent);
4658 :
4659 0 : return CMD_SUCCESS;
4660 : }
4661 :
4662 0 : int pim_show_upstream_join_desired_helper(const char *vrf, struct vty *vty,
4663 : bool uj)
4664 : {
4665 0 : struct pim_instance *pim;
4666 0 : struct vrf *v;
4667 :
4668 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4669 :
4670 0 : if (!v)
4671 : return CMD_WARNING;
4672 :
4673 0 : pim = v->info;
4674 :
4675 0 : if (!pim) {
4676 0 : vty_out(vty, "%% Unable to find pim instance\n");
4677 0 : return CMD_WARNING;
4678 : }
4679 :
4680 0 : pim_show_join_desired(pim, vty, uj);
4681 :
4682 0 : return CMD_SUCCESS;
4683 : }
4684 :
4685 0 : int pim_show_upstream_rpf_helper(const char *vrf, struct vty *vty, bool uj)
4686 : {
4687 0 : struct pim_instance *pim;
4688 0 : struct vrf *v;
4689 :
4690 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4691 :
4692 0 : if (!v)
4693 : return CMD_WARNING;
4694 :
4695 0 : pim = v->info;
4696 :
4697 0 : if (!pim) {
4698 0 : vty_out(vty, "%% Unable to find pim instance\n");
4699 0 : return CMD_WARNING;
4700 : }
4701 :
4702 0 : pim_show_upstream_rpf(pim, vty, uj);
4703 :
4704 0 : return CMD_SUCCESS;
4705 : }
4706 :
4707 0 : int pim_show_state_helper(const char *vrf, struct vty *vty,
4708 : const char *s_or_g_str, const char *g_str, bool json)
4709 : {
4710 0 : struct pim_instance *pim;
4711 0 : struct vrf *v;
4712 0 : json_object *json_parent = NULL;
4713 :
4714 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4715 :
4716 0 : if (!v)
4717 : return CMD_WARNING;
4718 :
4719 0 : pim = v->info;
4720 :
4721 0 : if (!pim) {
4722 0 : vty_out(vty, "%% Unable to find pim instance\n");
4723 0 : return CMD_WARNING;
4724 : }
4725 :
4726 0 : if (json)
4727 0 : json_parent = json_object_new_object();
4728 :
4729 0 : pim_show_state(pim, vty, s_or_g_str, g_str, json_parent);
4730 :
4731 0 : if (json)
4732 0 : vty_json(vty, json_parent);
4733 :
4734 : return CMD_SUCCESS;
4735 : }
4736 :
4737 0 : int pim_show_state_vrf_all_helper(struct vty *vty, const char *s_or_g_str,
4738 : const char *g_str, bool json)
4739 : {
4740 0 : struct vrf *vrf;
4741 0 : json_object *json_parent = NULL;
4742 0 : json_object *json_vrf = NULL;
4743 :
4744 0 : if (json)
4745 0 : json_parent = json_object_new_object();
4746 :
4747 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4748 0 : if (!json)
4749 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4750 : else
4751 0 : json_vrf = json_object_new_object();
4752 0 : pim_show_state(vrf->info, vty, s_or_g_str, g_str, json_vrf);
4753 0 : if (json)
4754 0 : json_object_object_add(json_parent, vrf->name,
4755 : json_vrf);
4756 : }
4757 0 : if (json)
4758 0 : vty_json(vty, json_parent);
4759 :
4760 0 : return CMD_SUCCESS;
4761 : }
4762 :
4763 0 : int pim_show_multicast_helper(const char *vrf, struct vty *vty)
4764 : {
4765 0 : struct vrf *v;
4766 0 : struct pim_instance *pim;
4767 :
4768 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4769 :
4770 0 : if (!v)
4771 : return CMD_WARNING;
4772 :
4773 0 : pim = v->info;
4774 :
4775 0 : if (!pim) {
4776 0 : vty_out(vty, "%% Unable to find pim instance\n");
4777 0 : return CMD_WARNING;
4778 : }
4779 :
4780 0 : pim_cmd_show_ip_multicast_helper(pim, vty);
4781 :
4782 0 : return CMD_SUCCESS;
4783 : }
4784 :
4785 0 : int pim_show_multicast_vrf_all_helper(struct vty *vty)
4786 : {
4787 0 : struct vrf *vrf;
4788 :
4789 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4790 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4791 0 : pim_cmd_show_ip_multicast_helper(vrf->info, vty);
4792 : }
4793 :
4794 0 : return CMD_SUCCESS;
4795 : }
4796 :
4797 0 : int pim_show_multicast_count_helper(const char *vrf, struct vty *vty, bool json)
4798 : {
4799 0 : struct pim_instance *pim;
4800 0 : struct vrf *v;
4801 0 : json_object *json_parent = NULL;
4802 :
4803 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4804 :
4805 0 : if (!v)
4806 : return CMD_WARNING;
4807 :
4808 0 : pim = v->info;
4809 :
4810 0 : if (!pim) {
4811 0 : vty_out(vty, "%% Unable to find pim instance\n");
4812 0 : return CMD_WARNING;
4813 : }
4814 :
4815 0 : if (json)
4816 0 : json_parent = json_object_new_object();
4817 :
4818 0 : show_multicast_interfaces(pim, vty, json_parent);
4819 :
4820 0 : if (json)
4821 0 : vty_json(vty, json_parent);
4822 :
4823 : return CMD_SUCCESS;
4824 : }
4825 :
4826 0 : int pim_show_multicast_count_vrf_all_helper(struct vty *vty, bool json)
4827 : {
4828 0 : struct vrf *vrf;
4829 0 : json_object *json_parent = NULL;
4830 0 : json_object *json_vrf = NULL;
4831 :
4832 0 : if (json)
4833 0 : json_parent = json_object_new_object();
4834 :
4835 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4836 0 : if (!json)
4837 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4838 : else
4839 0 : json_vrf = json_object_new_object();
4840 :
4841 0 : show_multicast_interfaces(vrf->info, vty, json_vrf);
4842 0 : if (json)
4843 0 : json_object_object_add(json_parent, vrf->name,
4844 : json_vrf);
4845 : }
4846 0 : if (json)
4847 0 : vty_json(vty, json_parent);
4848 :
4849 0 : return CMD_SUCCESS;
4850 : }
4851 :
4852 13 : int pim_show_mroute_helper(const char *vrf, struct vty *vty, pim_addr s_or_g,
4853 : pim_addr g, bool fill, bool json)
4854 : {
4855 13 : pim_sgaddr sg = {0};
4856 13 : struct pim_instance *pim;
4857 13 : struct vrf *v;
4858 13 : json_object *json_parent = NULL;
4859 :
4860 13 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4861 :
4862 13 : if (!v)
4863 : return CMD_WARNING;
4864 :
4865 13 : pim = v->info;
4866 :
4867 13 : if (!pim) {
4868 0 : vty_out(vty, "%% Unable to find pim instance\n");
4869 0 : return CMD_WARNING;
4870 : }
4871 :
4872 13 : if (json)
4873 13 : json_parent = json_object_new_object();
4874 :
4875 13 : if (!pim_addr_is_any(s_or_g)) {
4876 0 : if (!pim_addr_is_any(g)) {
4877 0 : sg.src = s_or_g;
4878 0 : sg.grp = g;
4879 : } else
4880 0 : sg.grp = s_or_g;
4881 : }
4882 :
4883 13 : show_mroute(pim, vty, &sg, fill, json_parent);
4884 :
4885 13 : if (json)
4886 13 : vty_json(vty, json_parent);
4887 :
4888 : return CMD_SUCCESS;
4889 : }
4890 :
4891 0 : int pim_show_mroute_vrf_all_helper(struct vty *vty, bool fill, bool json)
4892 : {
4893 0 : pim_sgaddr sg = {0};
4894 0 : struct vrf *vrf;
4895 0 : json_object *json_parent = NULL;
4896 0 : json_object *json_vrf = NULL;
4897 :
4898 0 : if (json)
4899 0 : json_parent = json_object_new_object();
4900 :
4901 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4902 0 : if (!json)
4903 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4904 : else
4905 0 : json_vrf = json_object_new_object();
4906 0 : show_mroute(vrf->info, vty, &sg, fill, json_vrf);
4907 0 : if (json)
4908 0 : json_object_object_add(json_parent, vrf->name,
4909 : json_vrf);
4910 : }
4911 0 : if (json)
4912 0 : vty_json(vty, json_parent);
4913 :
4914 0 : return CMD_SUCCESS;
4915 : }
4916 :
4917 0 : int pim_show_mroute_count_helper(const char *vrf, struct vty *vty, bool json)
4918 : {
4919 0 : struct pim_instance *pim;
4920 0 : struct vrf *v;
4921 0 : json_object *json_parent = NULL;
4922 :
4923 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4924 :
4925 0 : if (!v)
4926 : return CMD_WARNING;
4927 :
4928 0 : pim = v->info;
4929 :
4930 0 : if (!pim) {
4931 0 : vty_out(vty, "%% Unable to find pim instance\n");
4932 0 : return CMD_WARNING;
4933 : }
4934 :
4935 0 : if (json)
4936 0 : json_parent = json_object_new_object();
4937 :
4938 0 : show_mroute_count(pim, vty, json_parent);
4939 :
4940 0 : if (json)
4941 0 : vty_json(vty, json_parent);
4942 :
4943 : return CMD_SUCCESS;
4944 : }
4945 :
4946 0 : int pim_show_mroute_count_vrf_all_helper(struct vty *vty, bool json)
4947 : {
4948 0 : struct vrf *vrf;
4949 0 : json_object *json_parent = NULL;
4950 0 : json_object *json_vrf = NULL;
4951 :
4952 0 : if (json)
4953 0 : json_parent = json_object_new_object();
4954 :
4955 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
4956 0 : if (!json)
4957 0 : vty_out(vty, "VRF: %s\n", vrf->name);
4958 : else
4959 0 : json_vrf = json_object_new_object();
4960 :
4961 0 : show_mroute_count(vrf->info, vty, json_vrf);
4962 :
4963 0 : if (json)
4964 0 : json_object_object_add(json_parent, vrf->name,
4965 : json_vrf);
4966 : }
4967 0 : if (json)
4968 0 : vty_json(vty, json_parent);
4969 :
4970 0 : return CMD_SUCCESS;
4971 : }
4972 :
4973 0 : int pim_show_mroute_summary_helper(const char *vrf, struct vty *vty, bool json)
4974 : {
4975 0 : struct pim_instance *pim;
4976 0 : struct vrf *v;
4977 0 : json_object *json_parent = NULL;
4978 :
4979 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
4980 :
4981 0 : if (!v)
4982 : return CMD_WARNING;
4983 :
4984 0 : pim = v->info;
4985 :
4986 0 : if (!pim) {
4987 0 : vty_out(vty, "%% Unable to find pim instance\n");
4988 0 : return CMD_WARNING;
4989 : }
4990 :
4991 0 : if (json)
4992 0 : json_parent = json_object_new_object();
4993 :
4994 0 : show_mroute_summary(pim, vty, json_parent);
4995 :
4996 0 : if (json)
4997 0 : vty_json(vty, json_parent);
4998 :
4999 : return CMD_SUCCESS;
5000 : }
5001 :
5002 0 : int pim_show_mroute_summary_vrf_all_helper(struct vty *vty, bool json)
5003 : {
5004 0 : struct vrf *vrf;
5005 0 : json_object *json_parent = NULL;
5006 0 : json_object *json_vrf = NULL;
5007 :
5008 0 : if (json)
5009 0 : json_parent = json_object_new_object();
5010 :
5011 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5012 0 : if (!json)
5013 0 : vty_out(vty, "VRF: %s\n", vrf->name);
5014 : else
5015 0 : json_vrf = json_object_new_object();
5016 :
5017 0 : show_mroute_summary(vrf->info, vty, json_vrf);
5018 :
5019 0 : if (json)
5020 0 : json_object_object_add(json_parent, vrf->name,
5021 : json_vrf);
5022 : }
5023 :
5024 0 : if (json)
5025 0 : vty_json(vty, json_parent);
5026 :
5027 0 : return CMD_SUCCESS;
5028 : }
5029 :
5030 0 : void pim_show_interface_traffic(struct pim_instance *pim, struct vty *vty,
5031 : bool uj)
5032 : {
5033 0 : struct interface *ifp = NULL;
5034 0 : struct pim_interface *pim_ifp = NULL;
5035 0 : json_object *json = NULL;
5036 0 : json_object *json_row = NULL;
5037 :
5038 0 : if (uj)
5039 0 : json = json_object_new_object();
5040 : else {
5041 0 : vty_out(vty, "\n");
5042 0 : vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5043 : "Interface", " HELLO", " JOIN",
5044 : " PRUNE", " REGISTER", "REGISTER-STOP",
5045 : " ASSERT", " BSM");
5046 0 : vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5047 : " Rx/Tx", " Rx/Tx", " Rx/Tx",
5048 : " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx");
5049 0 : vty_out(vty,
5050 : "---------------------------------------------------------------------------------------------------------------\n");
5051 : }
5052 :
5053 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
5054 0 : pim_ifp = ifp->info;
5055 :
5056 0 : if (!pim_ifp)
5057 0 : continue;
5058 :
5059 0 : if (uj) {
5060 0 : json_row = json_object_new_object();
5061 0 : json_object_pim_ifp_add(json_row, ifp);
5062 0 : json_object_int_add(json_row, "helloRx",
5063 0 : pim_ifp->pim_ifstat_hello_recv);
5064 0 : json_object_int_add(json_row, "helloTx",
5065 0 : pim_ifp->pim_ifstat_hello_sent);
5066 0 : json_object_int_add(json_row, "joinRx",
5067 0 : pim_ifp->pim_ifstat_join_recv);
5068 0 : json_object_int_add(json_row, "joinTx",
5069 0 : pim_ifp->pim_ifstat_join_send);
5070 0 : json_object_int_add(json_row, "pruneRx",
5071 0 : pim_ifp->pim_ifstat_prune_recv);
5072 0 : json_object_int_add(json_row, "pruneTx",
5073 0 : pim_ifp->pim_ifstat_prune_send);
5074 0 : json_object_int_add(json_row, "registerRx",
5075 0 : pim_ifp->pim_ifstat_reg_recv);
5076 0 : json_object_int_add(json_row, "registerTx",
5077 0 : pim_ifp->pim_ifstat_reg_send);
5078 0 : json_object_int_add(json_row, "registerStopRx",
5079 0 : pim_ifp->pim_ifstat_reg_stop_recv);
5080 0 : json_object_int_add(json_row, "registerStopTx",
5081 0 : pim_ifp->pim_ifstat_reg_stop_send);
5082 0 : json_object_int_add(json_row, "assertRx",
5083 0 : pim_ifp->pim_ifstat_assert_recv);
5084 0 : json_object_int_add(json_row, "assertTx",
5085 0 : pim_ifp->pim_ifstat_assert_send);
5086 0 : json_object_int_add(json_row, "bsmRx",
5087 0 : pim_ifp->pim_ifstat_bsm_rx);
5088 0 : json_object_int_add(json_row, "bsmTx",
5089 0 : pim_ifp->pim_ifstat_bsm_tx);
5090 0 : json_object_object_add(json, ifp->name, json_row);
5091 : } else {
5092 0 : vty_out(vty,
5093 : "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5094 : "/%-7" PRIu64 "\n",
5095 0 : ifp->name, pim_ifp->pim_ifstat_hello_recv,
5096 : pim_ifp->pim_ifstat_hello_sent,
5097 : pim_ifp->pim_ifstat_join_recv,
5098 : pim_ifp->pim_ifstat_join_send,
5099 : pim_ifp->pim_ifstat_prune_recv,
5100 : pim_ifp->pim_ifstat_prune_send,
5101 : pim_ifp->pim_ifstat_reg_recv,
5102 : pim_ifp->pim_ifstat_reg_send,
5103 : pim_ifp->pim_ifstat_reg_stop_recv,
5104 : pim_ifp->pim_ifstat_reg_stop_send,
5105 : pim_ifp->pim_ifstat_assert_recv,
5106 : pim_ifp->pim_ifstat_assert_send,
5107 : pim_ifp->pim_ifstat_bsm_rx,
5108 : pim_ifp->pim_ifstat_bsm_tx);
5109 : }
5110 : }
5111 0 : if (uj)
5112 0 : vty_json(vty, json);
5113 0 : }
5114 :
5115 0 : void pim_show_interface_traffic_single(struct pim_instance *pim,
5116 : struct vty *vty, const char *ifname,
5117 : bool uj)
5118 : {
5119 0 : struct interface *ifp = NULL;
5120 0 : struct pim_interface *pim_ifp = NULL;
5121 0 : json_object *json = NULL;
5122 0 : json_object *json_row = NULL;
5123 0 : uint8_t found_ifname = 0;
5124 :
5125 0 : if (uj)
5126 0 : json = json_object_new_object();
5127 : else {
5128 0 : vty_out(vty, "\n");
5129 0 : vty_out(vty, "%-16s%-17s%-17s%-17s%-17s%-17s%-17s%-17s\n",
5130 : "Interface", " HELLO", " JOIN", " PRUNE",
5131 : " REGISTER", " REGISTER-STOP", " ASSERT",
5132 : " BSM");
5133 0 : vty_out(vty, "%-14s%-18s%-17s%-17s%-17s%-17s%-17s%-17s\n", "",
5134 : " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
5135 : " Rx/Tx", " Rx/Tx", " Rx/Tx");
5136 0 : vty_out(vty,
5137 : "-------------------------------------------------------------------------------------------------------------------------------\n");
5138 : }
5139 :
5140 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
5141 0 : if (strcmp(ifname, ifp->name))
5142 0 : continue;
5143 :
5144 0 : pim_ifp = ifp->info;
5145 :
5146 0 : if (!pim_ifp)
5147 0 : continue;
5148 :
5149 0 : found_ifname = 1;
5150 0 : if (uj) {
5151 0 : json_row = json_object_new_object();
5152 0 : json_object_pim_ifp_add(json_row, ifp);
5153 0 : json_object_int_add(json_row, "helloRx",
5154 0 : pim_ifp->pim_ifstat_hello_recv);
5155 0 : json_object_int_add(json_row, "helloTx",
5156 0 : pim_ifp->pim_ifstat_hello_sent);
5157 0 : json_object_int_add(json_row, "joinRx",
5158 0 : pim_ifp->pim_ifstat_join_recv);
5159 0 : json_object_int_add(json_row, "joinTx",
5160 0 : pim_ifp->pim_ifstat_join_send);
5161 0 : json_object_int_add(json_row, "pruneRx",
5162 0 : pim_ifp->pim_ifstat_prune_recv);
5163 0 : json_object_int_add(json_row, "pruneTx",
5164 0 : pim_ifp->pim_ifstat_prune_send);
5165 0 : json_object_int_add(json_row, "registerRx",
5166 0 : pim_ifp->pim_ifstat_reg_recv);
5167 0 : json_object_int_add(json_row, "registerTx",
5168 0 : pim_ifp->pim_ifstat_reg_send);
5169 0 : json_object_int_add(json_row, "registerStopRx",
5170 0 : pim_ifp->pim_ifstat_reg_stop_recv);
5171 0 : json_object_int_add(json_row, "registerStopTx",
5172 0 : pim_ifp->pim_ifstat_reg_stop_send);
5173 0 : json_object_int_add(json_row, "assertRx",
5174 0 : pim_ifp->pim_ifstat_assert_recv);
5175 0 : json_object_int_add(json_row, "assertTx",
5176 0 : pim_ifp->pim_ifstat_assert_send);
5177 0 : json_object_int_add(json_row, "bsmRx",
5178 0 : pim_ifp->pim_ifstat_bsm_rx);
5179 0 : json_object_int_add(json_row, "bsmTx",
5180 0 : pim_ifp->pim_ifstat_bsm_tx);
5181 :
5182 0 : json_object_object_add(json, ifp->name, json_row);
5183 : } else {
5184 0 : vty_out(vty,
5185 : "%-16s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7" PRIu64
5186 : "/%-7" PRIu64 "\n",
5187 : ifp->name, pim_ifp->pim_ifstat_hello_recv,
5188 : pim_ifp->pim_ifstat_hello_sent,
5189 : pim_ifp->pim_ifstat_join_recv,
5190 : pim_ifp->pim_ifstat_join_send,
5191 : pim_ifp->pim_ifstat_prune_recv,
5192 : pim_ifp->pim_ifstat_prune_send,
5193 : pim_ifp->pim_ifstat_reg_recv,
5194 : pim_ifp->pim_ifstat_reg_send,
5195 : pim_ifp->pim_ifstat_reg_stop_recv,
5196 : pim_ifp->pim_ifstat_reg_stop_send,
5197 : pim_ifp->pim_ifstat_assert_recv,
5198 : pim_ifp->pim_ifstat_assert_send,
5199 : pim_ifp->pim_ifstat_bsm_rx,
5200 : pim_ifp->pim_ifstat_bsm_tx);
5201 : }
5202 : }
5203 0 : if (uj)
5204 0 : vty_json(vty, json);
5205 0 : else if (!found_ifname)
5206 0 : vty_out(vty, "%% No such interface\n");
5207 0 : }
5208 :
5209 0 : int pim_show_interface_traffic_helper(const char *vrf, const char *if_name,
5210 : struct vty *vty, bool uj)
5211 : {
5212 0 : struct pim_instance *pim;
5213 0 : struct vrf *v;
5214 :
5215 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5216 :
5217 0 : if (!v)
5218 : return CMD_WARNING;
5219 :
5220 0 : pim = v->info;
5221 :
5222 0 : if (!pim) {
5223 0 : vty_out(vty, "%% Unable to find pim instance\n");
5224 0 : return CMD_WARNING;
5225 : }
5226 :
5227 0 : if (if_name)
5228 0 : pim_show_interface_traffic_single(v->info, vty, if_name, uj);
5229 : else
5230 0 : pim_show_interface_traffic(v->info, vty, uj);
5231 :
5232 : return CMD_SUCCESS;
5233 : }
5234 :
5235 0 : void clear_pim_interfaces(struct pim_instance *pim)
5236 : {
5237 0 : struct interface *ifp;
5238 :
5239 0 : FOR_ALL_INTERFACES (pim->vrf, ifp) {
5240 0 : if (ifp->info)
5241 0 : pim_neighbor_delete_all(ifp, "interface cleared");
5242 : }
5243 0 : }
5244 :
5245 10 : void pim_show_bsr(struct pim_instance *pim, struct vty *vty, bool uj)
5246 : {
5247 10 : char uptime[10];
5248 10 : char last_bsm_seen[10];
5249 10 : time_t now;
5250 10 : char bsr_state[20];
5251 10 : json_object *json = NULL;
5252 :
5253 10 : if (pim_addr_is_any(pim->global_scope.current_bsr)) {
5254 6 : pim_time_uptime(uptime, sizeof(uptime),
5255 : pim->global_scope.current_bsr_first_ts);
5256 6 : pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
5257 : pim->global_scope.current_bsr_last_ts);
5258 : }
5259 :
5260 : else {
5261 4 : now = pim_time_monotonic_sec();
5262 4 : pim_time_uptime(uptime, sizeof(uptime),
5263 4 : (now - pim->global_scope.current_bsr_first_ts));
5264 4 : pim_time_uptime(last_bsm_seen, sizeof(last_bsm_seen),
5265 4 : now - pim->global_scope.current_bsr_last_ts);
5266 : }
5267 :
5268 10 : switch (pim->global_scope.state) {
5269 6 : case NO_INFO:
5270 6 : strlcpy(bsr_state, "NO_INFO", sizeof(bsr_state));
5271 6 : break;
5272 0 : case ACCEPT_ANY:
5273 0 : strlcpy(bsr_state, "ACCEPT_ANY", sizeof(bsr_state));
5274 0 : break;
5275 4 : case ACCEPT_PREFERRED:
5276 4 : strlcpy(bsr_state, "ACCEPT_PREFERRED", sizeof(bsr_state));
5277 4 : break;
5278 0 : default:
5279 0 : strlcpy(bsr_state, "", sizeof(bsr_state));
5280 : }
5281 :
5282 :
5283 10 : if (uj) {
5284 10 : json = json_object_new_object();
5285 10 : json_object_string_addf(json, "bsr", "%pPA",
5286 : &pim->global_scope.current_bsr);
5287 10 : json_object_int_add(json, "priority",
5288 10 : pim->global_scope.current_bsr_prio);
5289 10 : json_object_int_add(json, "fragmentTag",
5290 10 : pim->global_scope.bsm_frag_tag);
5291 10 : json_object_string_add(json, "state", bsr_state);
5292 10 : json_object_string_add(json, "upTime", uptime);
5293 10 : json_object_string_add(json, "lastBsmSeen", last_bsm_seen);
5294 : }
5295 :
5296 : else {
5297 0 : vty_out(vty, "PIMv2 Bootstrap information\n");
5298 0 : vty_out(vty, "Current preferred BSR address: %pPA\n",
5299 : &pim->global_scope.current_bsr);
5300 0 : vty_out(vty,
5301 : "Priority Fragment-Tag State UpTime\n");
5302 0 : vty_out(vty, " %-12d %-12d %-13s %7s\n",
5303 : pim->global_scope.current_bsr_prio,
5304 0 : pim->global_scope.bsm_frag_tag, bsr_state, uptime);
5305 0 : vty_out(vty, "Last BSM seen: %s\n", last_bsm_seen);
5306 : }
5307 :
5308 10 : if (uj)
5309 10 : vty_json(vty, json);
5310 10 : }
5311 :
5312 10 : int pim_show_bsr_helper(const char *vrf, struct vty *vty, bool uj)
5313 : {
5314 10 : struct pim_instance *pim;
5315 10 : struct vrf *v;
5316 :
5317 10 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5318 :
5319 10 : if (!v)
5320 : return CMD_WARNING;
5321 :
5322 10 : pim = pim_get_pim_instance(v->vrf_id);
5323 :
5324 10 : if (!pim) {
5325 0 : vty_out(vty, "%% Unable to find pim instance\n");
5326 0 : return CMD_WARNING;
5327 : }
5328 :
5329 10 : pim_show_bsr(v->info, vty, uj);
5330 :
5331 10 : return CMD_SUCCESS;
5332 : }
5333 :
5334 : /*Display the group-rp mappings */
5335 0 : static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
5336 : struct vty *vty, bool uj)
5337 : {
5338 0 : struct bsgrp_node *bsgrp;
5339 0 : struct bsm_rpinfo *bsm_rp;
5340 0 : struct route_node *rn;
5341 0 : json_object *json = NULL;
5342 0 : json_object *json_group = NULL;
5343 0 : json_object *json_row = NULL;
5344 0 : struct ttable *tt = NULL;
5345 :
5346 0 : if (uj) {
5347 0 : json = json_object_new_object();
5348 0 : json_object_string_addf(json, "BSR Address", "%pPA",
5349 : &pim->global_scope.current_bsr);
5350 : } else
5351 0 : vty_out(vty, "BSR Address %pPA\n",
5352 : &pim->global_scope.current_bsr);
5353 :
5354 0 : for (rn = route_top(pim->global_scope.bsrp_table); rn;
5355 0 : rn = route_next(rn)) {
5356 0 : bsgrp = (struct bsgrp_node *)rn->info;
5357 :
5358 0 : if (!bsgrp)
5359 0 : continue;
5360 :
5361 0 : char grp_str[PREFIX_STRLEN];
5362 :
5363 0 : prefix2str(&bsgrp->group, grp_str, sizeof(grp_str));
5364 :
5365 0 : if (uj) {
5366 0 : json_object_object_get_ex(json, grp_str, &json_group);
5367 0 : if (!json_group) {
5368 0 : json_group = json_object_new_object();
5369 0 : json_object_object_add(json, grp_str,
5370 : json_group);
5371 : }
5372 : } else {
5373 0 : vty_out(vty, "Group Address %pFX\n", &bsgrp->group);
5374 0 : vty_out(vty, "--------------------------\n");
5375 : /* Prepare table. */
5376 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
5377 0 : ttable_add_row(tt, "Rp Address|priority|Holdtime|Hash");
5378 0 : tt->style.cell.rpad = 2;
5379 0 : tt->style.corner = '+';
5380 0 : ttable_restyle(tt);
5381 :
5382 0 : ttable_add_row(tt, "%s|%c|%c|%c", "(ACTIVE)", ' ', ' ',
5383 : ' ');
5384 : }
5385 :
5386 0 : frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) {
5387 0 : if (uj) {
5388 0 : json_row = json_object_new_object();
5389 0 : json_object_string_addf(json_row, "Rp Address",
5390 : "%pPA",
5391 : &bsm_rp->rp_address);
5392 0 : json_object_int_add(json_row, "Rp HoldTime",
5393 0 : bsm_rp->rp_holdtime);
5394 0 : json_object_int_add(json_row, "Rp Priority",
5395 0 : bsm_rp->rp_prio);
5396 0 : json_object_int_add(json_row, "Hash Val",
5397 0 : bsm_rp->hash);
5398 0 : json_object_object_addf(json_group, json_row,
5399 : "%pPA",
5400 : &bsm_rp->rp_address);
5401 :
5402 : } else {
5403 0 : ttable_add_row(
5404 : tt, "%pPA|%u|%u|%u",
5405 0 : &bsm_rp->rp_address, bsm_rp->rp_prio,
5406 0 : bsm_rp->rp_holdtime, bsm_rp->hash);
5407 : }
5408 : }
5409 : /* Dump the generated table. */
5410 0 : if (tt) {
5411 0 : char *table = NULL;
5412 :
5413 0 : table = ttable_dump(tt, "\n");
5414 0 : vty_out(vty, "%s\n", table);
5415 0 : XFREE(MTYPE_TMP, table);
5416 0 : ttable_del(tt);
5417 0 : tt = NULL;
5418 : }
5419 0 : if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj)
5420 0 : vty_out(vty, "Active List is empty.\n");
5421 :
5422 0 : if (uj) {
5423 0 : json_object_int_add(json_group, "Pending RP count",
5424 0 : bsgrp->pend_rp_cnt);
5425 : } else {
5426 0 : vty_out(vty, "(PENDING)\n");
5427 0 : vty_out(vty, "Pending RP count :%d\n",
5428 : bsgrp->pend_rp_cnt);
5429 0 : if (bsgrp->pend_rp_cnt) {
5430 : /* Prepare table. */
5431 0 : tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
5432 0 : ttable_add_row(
5433 : tt,
5434 : "Rp Address|priority|Holdtime|Hash");
5435 0 : tt->style.cell.rpad = 2;
5436 0 : tt->style.corner = '+';
5437 0 : ttable_restyle(tt);
5438 : }
5439 : }
5440 :
5441 0 : frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) {
5442 0 : if (uj) {
5443 0 : json_row = json_object_new_object();
5444 0 : json_object_string_addf(json_row, "Rp Address",
5445 : "%pPA",
5446 : &bsm_rp->rp_address);
5447 0 : json_object_int_add(json_row, "Rp HoldTime",
5448 0 : bsm_rp->rp_holdtime);
5449 0 : json_object_int_add(json_row, "Rp Priority",
5450 0 : bsm_rp->rp_prio);
5451 0 : json_object_int_add(json_row, "Hash Val",
5452 0 : bsm_rp->hash);
5453 0 : json_object_object_addf(json_group, json_row,
5454 : "%pPA",
5455 : &bsm_rp->rp_address);
5456 : } else {
5457 0 : ttable_add_row(
5458 : tt, "%pPA|%u|%u|%u",
5459 0 : &bsm_rp->rp_address, bsm_rp->rp_prio,
5460 0 : bsm_rp->rp_holdtime, bsm_rp->hash);
5461 : }
5462 : }
5463 : /* Dump the generated table. */
5464 0 : if (tt) {
5465 0 : char *table = NULL;
5466 :
5467 0 : table = ttable_dump(tt, "\n");
5468 0 : vty_out(vty, "%s\n", table);
5469 0 : XFREE(MTYPE_TMP, table);
5470 0 : ttable_del(tt);
5471 : }
5472 0 : if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj)
5473 0 : vty_out(vty, "Partial List is empty\n");
5474 :
5475 0 : if (!uj)
5476 0 : vty_out(vty, "\n");
5477 : }
5478 :
5479 0 : if (uj)
5480 0 : vty_json(vty, json);
5481 0 : }
5482 :
5483 0 : int pim_show_group_rp_mappings_info_helper(const char *vrf, struct vty *vty,
5484 : bool uj)
5485 : {
5486 0 : struct pim_instance *pim;
5487 0 : struct vrf *v;
5488 :
5489 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5490 :
5491 0 : if (!v)
5492 : return CMD_WARNING;
5493 :
5494 0 : pim = v->info;
5495 :
5496 0 : if (!pim) {
5497 0 : vty_out(vty, "%% Unable to find pim instance\n");
5498 0 : return CMD_WARNING;
5499 : }
5500 :
5501 0 : pim_show_group_rp_mappings_info(v->info, vty, uj);
5502 :
5503 0 : return CMD_SUCCESS;
5504 : }
5505 :
5506 : /* Display the bsm database details */
5507 0 : static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
5508 : {
5509 0 : int count = 0;
5510 0 : int fragment = 1;
5511 0 : struct bsm_frag *bsfrag;
5512 0 : json_object *json = NULL;
5513 0 : json_object *json_group = NULL;
5514 0 : json_object *json_row = NULL;
5515 :
5516 0 : count = bsm_frags_count(pim->global_scope.bsm_frags);
5517 :
5518 0 : if (uj) {
5519 0 : json = json_object_new_object();
5520 0 : json_object_int_add(json, "Number of the fragments", count);
5521 : } else {
5522 0 : vty_out(vty, "Scope Zone: Global\n");
5523 0 : vty_out(vty, "Number of the fragments: %d\n", count);
5524 0 : vty_out(vty, "\n");
5525 : }
5526 :
5527 0 : frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) {
5528 0 : char grp_str[PREFIX_STRLEN];
5529 0 : struct bsmmsg_grpinfo *group;
5530 0 : struct bsmmsg_rpinfo *bsm_rpinfo;
5531 0 : struct prefix grp;
5532 0 : struct bsm_hdr *hdr;
5533 0 : pim_addr bsr_addr;
5534 0 : uint32_t offset = 0;
5535 0 : uint8_t *buf;
5536 0 : uint32_t len = 0;
5537 0 : uint32_t frag_rp_cnt = 0;
5538 :
5539 0 : buf = bsfrag->data;
5540 0 : len = bsfrag->size;
5541 :
5542 : /* skip pim header */
5543 0 : buf += PIM_MSG_HEADER_LEN;
5544 0 : len -= PIM_MSG_HEADER_LEN;
5545 :
5546 0 : hdr = (struct bsm_hdr *)buf;
5547 : /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */
5548 0 : memcpy(&bsr_addr, &hdr->bsr_addr.addr, sizeof(bsr_addr));
5549 :
5550 : /* BSM starts with bsr header */
5551 0 : buf += sizeof(struct bsm_hdr);
5552 0 : len -= sizeof(struct bsm_hdr);
5553 :
5554 0 : if (uj) {
5555 0 : json_object_string_addf(json, "BSR address", "%pPA",
5556 : &bsr_addr);
5557 0 : json_object_int_add(json, "BSR priority",
5558 0 : hdr->bsr_prio);
5559 0 : json_object_int_add(json, "Hashmask Length",
5560 0 : hdr->hm_len);
5561 0 : json_object_int_add(json, "Fragment Tag",
5562 0 : ntohs(hdr->frag_tag));
5563 : } else {
5564 0 : vty_out(vty, "BSM Fragment : %d\n", fragment);
5565 0 : vty_out(vty, "------------------\n");
5566 0 : vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address",
5567 : "BSR-Priority", "Hashmask-len", "Fragment-Tag");
5568 0 : vty_out(vty, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr,
5569 0 : hdr->bsr_prio, hdr->hm_len,
5570 0 : ntohs(hdr->frag_tag));
5571 : }
5572 :
5573 0 : vty_out(vty, "\n");
5574 :
5575 0 : while (offset < len) {
5576 0 : group = (struct bsmmsg_grpinfo *)buf;
5577 :
5578 0 : if (group->group.family == PIM_MSG_ADDRESS_FAMILY_IPV4)
5579 0 : grp.family = AF_INET;
5580 0 : else if (group->group.family ==
5581 : PIM_MSG_ADDRESS_FAMILY_IPV6)
5582 0 : grp.family = AF_INET6;
5583 :
5584 0 : grp.prefixlen = group->group.mask;
5585 : #if PIM_IPV == 4
5586 0 : grp.u.prefix4 = group->group.addr;
5587 : #else
5588 0 : grp.u.prefix6 = group->group.addr;
5589 : #endif
5590 :
5591 0 : prefix2str(&grp, grp_str, sizeof(grp_str));
5592 :
5593 0 : buf += sizeof(struct bsmmsg_grpinfo);
5594 0 : offset += sizeof(struct bsmmsg_grpinfo);
5595 :
5596 0 : if (uj) {
5597 0 : json_object_object_get_ex(json, grp_str,
5598 : &json_group);
5599 0 : if (!json_group) {
5600 0 : json_group = json_object_new_object();
5601 0 : json_object_int_add(json_group,
5602 : "Rp Count",
5603 0 : group->rp_count);
5604 0 : json_object_int_add(
5605 : json_group, "Fragment Rp count",
5606 0 : group->frag_rp_count);
5607 0 : json_object_object_add(json, grp_str,
5608 : json_group);
5609 : }
5610 : } else {
5611 0 : vty_out(vty, "Group : %s\n", grp_str);
5612 0 : vty_out(vty, "-------------------\n");
5613 0 : vty_out(vty, "Rp Count:%d\n", group->rp_count);
5614 0 : vty_out(vty, "Fragment Rp Count : %d\n",
5615 0 : group->frag_rp_count);
5616 : }
5617 :
5618 0 : frag_rp_cnt = group->frag_rp_count;
5619 :
5620 0 : if (!frag_rp_cnt)
5621 0 : continue;
5622 :
5623 0 : if (!uj)
5624 0 : vty_out(vty,
5625 : "RpAddress HoldTime Priority\n");
5626 :
5627 0 : while (frag_rp_cnt--) {
5628 0 : pim_addr rp_addr;
5629 :
5630 0 : bsm_rpinfo = (struct bsmmsg_rpinfo *)buf;
5631 : /* unaligned, again */
5632 0 : memcpy(&rp_addr, &bsm_rpinfo->rpaddr.addr,
5633 : sizeof(rp_addr));
5634 :
5635 0 : buf += sizeof(struct bsmmsg_rpinfo);
5636 0 : offset += sizeof(struct bsmmsg_rpinfo);
5637 :
5638 0 : if (uj) {
5639 0 : json_row = json_object_new_object();
5640 0 : json_object_string_addf(
5641 : json_row, "Rp Address", "%pPA",
5642 : &rp_addr);
5643 0 : json_object_int_add(
5644 : json_row, "Rp HoldTime",
5645 0 : ntohs(bsm_rpinfo->rp_holdtime));
5646 0 : json_object_int_add(json_row,
5647 : "Rp Priority",
5648 0 : bsm_rpinfo->rp_pri);
5649 0 : json_object_object_addf(
5650 : json_group, json_row, "%pPA",
5651 : &rp_addr);
5652 : } else {
5653 0 : vty_out(vty, "%-15pPA %-12d %d\n",
5654 : &rp_addr,
5655 0 : ntohs(bsm_rpinfo->rp_holdtime),
5656 0 : bsm_rpinfo->rp_pri);
5657 : }
5658 : }
5659 0 : vty_out(vty, "\n");
5660 : }
5661 :
5662 0 : fragment++;
5663 : }
5664 :
5665 0 : if (uj)
5666 0 : vty_json(vty, json);
5667 0 : }
5668 :
5669 0 : int pim_show_bsm_db_helper(const char *vrf, struct vty *vty, bool uj)
5670 : {
5671 0 : struct pim_instance *pim;
5672 0 : struct vrf *v;
5673 :
5674 0 : v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME);
5675 :
5676 0 : if (!v)
5677 : return CMD_WARNING;
5678 :
5679 0 : pim = v->info;
5680 :
5681 0 : if (!pim) {
5682 0 : vty_out(vty, "%% Unable to find pim instance\n");
5683 0 : return CMD_WARNING;
5684 : }
5685 :
5686 0 : pim_show_bsm_db(v->info, vty, uj);
5687 :
5688 0 : return CMD_SUCCESS;
5689 : }
|