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