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