blob: b1349ed3bca9ef311e7058cbca43db19b1d0d3c3 [file] [log] [blame]
Everton Marques871dbcf2009-08-11 15:43:05 -03001/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19
20 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include <sys/ioctl.h>
24
25#include <zebra.h>
26
27#include "command.h"
28#include "if.h"
29#include "prefix.h"
30
31#include "pimd.h"
32#include "pim_cmd.h"
33#include "pim_iface.h"
34#include "pim_vty.h"
35#include "pim_mroute.h"
36#include "pim_str.h"
37#include "pim_igmpv3.h"
38#include "pim_sock.h"
39#include "pim_time.h"
40#include "pim_util.h"
41#include "pim_oil.h"
42#include "pim_neighbor.h"
43#include "pim_pim.h"
44#include "pim_ifchannel.h"
45#include "pim_hello.h"
46#include "pim_msg.h"
47#include "pim_upstream.h"
48#include "pim_rpf.h"
49#include "pim_macro.h"
50
51static struct cmd_node pim_global_node = {
52 PIM_NODE,
53 "",
54 1 /* vtysh ? yes */
55};
56
57static struct cmd_node pim_interface_node = {
58 INTERFACE_NODE,
59 "%s(config-if-pim)# ",
60 1 /* vtysh ? yes */
61};
62
63static void pim_if_membership_clear(struct interface *ifp)
64{
65 struct pim_interface *pim_ifp;
66
67 pim_ifp = ifp->info;
68 zassert(pim_ifp);
69
70 if (PIM_IF_TEST_PIM(pim_ifp->options) &&
71 PIM_IF_TEST_IGMP(pim_ifp->options)) {
72 return;
73 }
74
75 pim_ifchannel_membership_clear(ifp);
76}
77
78/*
79 When PIM is disabled on interface, IGMPv3 local membership
80 information is not injected into PIM interface state.
81
82 The function pim_if_membership_refresh() fetches all IGMPv3 local
83 membership information into PIM. It is intented to be called
84 whenever PIM is enabled on the interface in order to collect missed
85 local membership information.
86 */
87static void pim_if_membership_refresh(struct interface *ifp)
88{
89 struct pim_interface *pim_ifp;
90 struct listnode *sock_node;
91 struct igmp_sock *igmp;
92
93 pim_ifp = ifp->info;
94 zassert(pim_ifp);
95
96 if (!PIM_IF_TEST_PIM(pim_ifp->options))
97 return;
98 if (!PIM_IF_TEST_IGMP(pim_ifp->options))
99 return;
100
101 /*
102 First clear off membership from all PIM (S,G) entries on the
103 interface
104 */
105
106 pim_ifchannel_membership_clear(ifp);
107
108 /*
109 Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
110 the interface
111 */
112
113 /* scan igmp sockets */
114 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
115 struct listnode *grpnode;
116 struct igmp_group *grp;
117
118 /* scan igmp groups */
119 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
120 struct listnode *srcnode;
121 struct igmp_source *src;
122
123 /* scan group sources */
124 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
125
126 if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
127 pim_ifchannel_local_membership_add(ifp,
128 src->source_addr,
129 grp->group_addr);
130 }
131
132 } /* scan group sources */
133 } /* scan igmp groups */
134 } /* scan igmp sockets */
135
136 /*
137 Finally delete every PIM (S,G) entry lacking all state info
138 */
139
140 pim_ifchannel_delete_on_noinfo(ifp);
141
142}
143
144static void pim_show_assert(struct vty *vty)
145{
146 struct listnode *ifnode;
147 struct interface *ifp;
148 time_t now;
149
150 now = pim_time_monotonic_sec();
151
152 vty_out(vty,
153 "Interface Address Source Group State Winner Uptime Timer%s",
154 VTY_NEWLINE);
155
156 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
157 struct pim_interface *pim_ifp;
158 struct in_addr ifaddr;
159 struct listnode *ch_node;
160 struct pim_ifchannel *ch;
161
162 pim_ifp = ifp->info;
163
164 if (!pim_ifp)
165 continue;
166
167 ifaddr = pim_ifp->primary_address;
168
169 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
170 char ch_src_str[100];
171 char ch_grp_str[100];
172 char winner_str[100];
173 char uptime[10];
174 char timer[10];
175
176 pim_inet4_dump("<ch_src?>", ch->source_addr,
177 ch_src_str, sizeof(ch_src_str));
178 pim_inet4_dump("<ch_grp?>", ch->group_addr,
179 ch_grp_str, sizeof(ch_grp_str));
180 pim_inet4_dump("<assrt_win?>", ch->ifassert_winner,
181 winner_str, sizeof(winner_str));
182
183 pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
184 pim_time_timer_to_mmss(timer, sizeof(timer),
185 ch->t_ifassert_timer);
186
187 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s",
188 ifp->name,
189 inet_ntoa(ifaddr),
190 ch_src_str,
191 ch_grp_str,
192 pim_ifchannel_ifassert_name(ch->ifassert_state),
193 winner_str,
194 uptime,
195 timer,
196 VTY_NEWLINE);
197 } /* scan interface channels */
198 } /* scan interfaces */
199}
200
201static void pim_show_assert_internal(struct vty *vty)
202{
203 struct listnode *ifnode;
204 struct interface *ifp;
205
206 vty_out(vty,
207 "CA: CouldAssert%s"
208 "ECA: Evaluate CouldAssert%s"
209 "ATD: AssertTrackingDesired%s"
210 "eATD: Evaluate AssertTrackingDesired%s%s",
211 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
212
213 vty_out(vty,
214 "Interface Address Source Group CA eCA ATD eATD%s",
215 VTY_NEWLINE);
216
217 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
218 struct pim_interface *pim_ifp;
219 struct in_addr ifaddr;
220 struct listnode *ch_node;
221 struct pim_ifchannel *ch;
222
223 pim_ifp = ifp->info;
224
225 if (!pim_ifp)
226 continue;
227
228 ifaddr = pim_ifp->primary_address;
229
230 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
231 char ch_src_str[100];
232 char ch_grp_str[100];
233
234 pim_inet4_dump("<ch_src?>", ch->source_addr,
235 ch_src_str, sizeof(ch_src_str));
236 pim_inet4_dump("<ch_grp?>", ch->group_addr,
237 ch_grp_str, sizeof(ch_grp_str));
238 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s",
239 ifp->name,
240 inet_ntoa(ifaddr),
241 ch_src_str,
242 ch_grp_str,
243 PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
244 pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
245 PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no",
246 pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no",
247 VTY_NEWLINE);
248 } /* scan interface channels */
249 } /* scan interfaces */
250}
251
252static void pim_show_assert_metric(struct vty *vty)
253{
254 struct listnode *ifnode;
255 struct interface *ifp;
256
257 vty_out(vty,
258 "Interface Address Source Group RPT Pref Metric Address %s",
259 VTY_NEWLINE);
260
261 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
262 struct pim_interface *pim_ifp;
263 struct in_addr ifaddr;
264 struct listnode *ch_node;
265 struct pim_ifchannel *ch;
266
267 pim_ifp = ifp->info;
268
269 if (!pim_ifp)
270 continue;
271
272 ifaddr = pim_ifp->primary_address;
273
274 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
275 char ch_src_str[100];
276 char ch_grp_str[100];
277 char addr_str[100];
278 struct pim_assert_metric am;
279
280 am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address);
281
282 pim_inet4_dump("<ch_src?>", ch->source_addr,
283 ch_src_str, sizeof(ch_src_str));
284 pim_inet4_dump("<ch_grp?>", ch->group_addr,
285 ch_grp_str, sizeof(ch_grp_str));
286 pim_inet4_dump("<addr?>", am.ip_address,
287 addr_str, sizeof(addr_str));
288
289 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s",
290 ifp->name,
291 inet_ntoa(ifaddr),
292 ch_src_str,
293 ch_grp_str,
294 am.rpt_bit_flag ? "yes" : "no",
295 am.metric_preference,
296 am.route_metric,
297 addr_str,
298 VTY_NEWLINE);
299 } /* scan interface channels */
300 } /* scan interfaces */
301}
302
303static void pim_show_assert_winner_metric(struct vty *vty)
304{
305 struct listnode *ifnode;
306 struct interface *ifp;
307
308 vty_out(vty,
309 "Interface Address Source Group RPT Pref Metric Address %s",
310 VTY_NEWLINE);
311
312 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
313 struct pim_interface *pim_ifp;
314 struct in_addr ifaddr;
315 struct listnode *ch_node;
316 struct pim_ifchannel *ch;
317
318 pim_ifp = ifp->info;
319
320 if (!pim_ifp)
321 continue;
322
323 ifaddr = pim_ifp->primary_address;
324
325 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
326 char ch_src_str[100];
327 char ch_grp_str[100];
328 char addr_str[100];
329 struct pim_assert_metric *am;
330 char pref_str[5];
331 char metr_str[7];
332
333 am = &ch->ifassert_winner_metric;
334
335 pim_inet4_dump("<ch_src?>", ch->source_addr,
336 ch_src_str, sizeof(ch_src_str));
337 pim_inet4_dump("<ch_grp?>", ch->group_addr,
338 ch_grp_str, sizeof(ch_grp_str));
339 pim_inet4_dump("<addr?>", am->ip_address,
340 addr_str, sizeof(addr_str));
341
342 if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
343 snprintf(pref_str, sizeof(pref_str), "INFI");
344 else
345 snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference);
346
347 if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
348 snprintf(metr_str, sizeof(metr_str), "INFI");
349 else
350 snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
351
352 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s",
353 ifp->name,
354 inet_ntoa(ifaddr),
355 ch_src_str,
356 ch_grp_str,
357 am->rpt_bit_flag ? "yes" : "no",
358 pref_str,
359 metr_str,
360 addr_str,
361 VTY_NEWLINE);
362 } /* scan interface channels */
363 } /* scan interfaces */
364}
365
366static void pim_show_membership(struct vty *vty)
367{
368 struct listnode *ifnode;
369 struct interface *ifp;
370
371 vty_out(vty,
372 "Interface Address Source Group Membership%s",
373 VTY_NEWLINE);
374
375 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
376 struct pim_interface *pim_ifp;
377 struct in_addr ifaddr;
378 struct listnode *ch_node;
379 struct pim_ifchannel *ch;
380
381 pim_ifp = ifp->info;
382
383 if (!pim_ifp)
384 continue;
385
386 ifaddr = pim_ifp->primary_address;
387
388 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
389 char ch_src_str[100];
390 char ch_grp_str[100];
391
392 pim_inet4_dump("<ch_src?>", ch->source_addr,
393 ch_src_str, sizeof(ch_src_str));
394 pim_inet4_dump("<ch_grp?>", ch->group_addr,
395 ch_grp_str, sizeof(ch_grp_str));
396
397 vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s",
398 ifp->name,
399 inet_ntoa(ifaddr),
400 ch_src_str,
401 ch_grp_str,
402 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ?
403 "NOINFO" : "INCLUDE",
404 VTY_NEWLINE);
405 } /* scan interface channels */
406 } /* scan interfaces */
407
408}
409
410static void igmp_show_interfaces(struct vty *vty)
411{
412 struct listnode *node;
413 struct interface *ifp;
414 time_t now;
415
416 now = pim_time_monotonic_sec();
417
418 vty_out(vty,
419 "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s",
420 VTY_NEWLINE);
421
422 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
423 struct pim_interface *pim_ifp;
424 struct listnode *sock_node;
425 struct igmp_sock *igmp;
426
427 pim_ifp = ifp->info;
428
429 if (!pim_ifp)
430 continue;
431
432 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
433 char uptime[10];
434 int mloop;
435
436 pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation);
437
438 mloop = pim_socket_mcastloop_get(igmp->fd);
439
440 vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
441 ifp->name,
442 inet_ntoa(igmp->ifaddr),
443 ifp->ifindex,
444 igmp->fd,
445 uptime,
446 if_is_multicast(ifp) ? "yes" : "no",
447 if_is_broadcast(ifp) ? "yes" : "no",
448 (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
449 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
450 (ifp->flags & IFF_PROMISC) ? "yes" : "no",
451 PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
452 VTY_NEWLINE);
453 }
454 }
455}
456
457static void show_interface_address(struct vty *vty)
458{
459 struct listnode *ifpnode;
460 struct interface *ifp;
461
462 vty_out(vty,
463 "Interface Primary Secondary %s",
464 VTY_NEWLINE);
465
466 for (ALL_LIST_ELEMENTS_RO(iflist, ifpnode, ifp)) {
467 struct listnode *ifcnode;
468 struct connected *ifc;
469 struct in_addr pri_addr;
470 char pri_addr_str[100];
471
472 pri_addr = pim_find_primary_addr(ifp);
473
474 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
475
476 for (ALL_LIST_ELEMENTS_RO(ifp->connected, ifcnode, ifc)) {
477 char sec_addr_str[100];
478 struct prefix *p = ifc->address;
479
480 if (p->family != AF_INET)
481 continue;
482
483 if (p->u.prefix4.s_addr == pri_addr.s_addr) {
484 sec_addr_str[0] = '\0';
485 }
486 else {
487 pim_inet4_dump("<sec?>", p->u.prefix4, sec_addr_str, sizeof(sec_addr_str));
488 }
489
490 vty_out(vty, "%-9s %-15s %-15s%s",
491 ifp->name,
492 pri_addr_str,
493 sec_addr_str,
494 VTY_NEWLINE);
495 }
496 }
497}
498
499static void pim_show_dr(struct vty *vty)
500{
501 struct listnode *node;
502 struct interface *ifp;
503 time_t now;
504
505 now = pim_time_monotonic_sec();
506
507 vty_out(vty,
508 "NonPri: Number of neighbors missing DR Priority hello option%s%s",
509 VTY_NEWLINE, VTY_NEWLINE);
510
511 vty_out(vty, "Interface Address DR Uptime Elections NonPri%s", VTY_NEWLINE);
512
513 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
514 struct pim_interface *pim_ifp;
515 struct in_addr ifaddr;
516 char dr_str[100];
517 char dr_uptime[10];
518
519 pim_ifp = ifp->info;
520
521 if (!pim_ifp)
522 continue;
523
524 if (pim_ifp->pim_sock_fd < 0)
525 continue;
526
527 ifaddr = pim_ifp->primary_address;
528
529 pim_time_uptime(dr_uptime, sizeof(dr_uptime),
530 now - pim_ifp->pim_dr_election_last);
531
532 pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr,
533 dr_str, sizeof(dr_str));
534
535 vty_out(vty, "%-9s %-15s %-15s %8s %9d %6d%s",
536 ifp->name,
537 inet_ntoa(ifaddr),
538 dr_str,
539 dr_uptime,
540 pim_ifp->pim_dr_election_count,
541 pim_ifp->pim_dr_num_nondrpri_neighbors,
542 VTY_NEWLINE);
543 }
544}
545
546static void pim_show_hello(struct vty *vty)
547{
548 struct listnode *node;
549 struct interface *ifp;
550 time_t now;
551
552 now = pim_time_monotonic_sec();
553
554 vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail%s", VTY_NEWLINE);
555
556 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
557 struct pim_interface *pim_ifp;
558 struct in_addr ifaddr;
559 char hello_period[10];
560 char hello_timer[10];
561 char stat_uptime[10];
562
563 pim_ifp = ifp->info;
564
565 if (!pim_ifp)
566 continue;
567
568 if (pim_ifp->pim_sock_fd < 0)
569 continue;
570
571 ifaddr = pim_ifp->primary_address;
572
573 pim_time_timer_to_mmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer);
574 pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period);
575 pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start);
576
577 vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u%s",
578 ifp->name,
579 inet_ntoa(ifaddr),
580 hello_period,
581 hello_timer,
582 stat_uptime,
583 pim_ifp->pim_ifstat_hello_recv,
584 pim_ifp->pim_ifstat_hello_recvfail,
585 pim_ifp->pim_ifstat_hello_sent,
586 pim_ifp->pim_ifstat_hello_sendfail,
587 VTY_NEWLINE);
588 }
589}
590
591static void pim_show_interfaces(struct vty *vty)
592{
593 struct listnode *node;
594 struct interface *ifp;
595 time_t now;
596
597 now = pim_time_monotonic_sec();
598
599 vty_out(vty, "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE);
600
601 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
602 struct pim_interface *pim_ifp;
603 struct in_addr ifaddr;
604 char uptime[10];
605 int mloop;
606
607 pim_ifp = ifp->info;
608
609 if (!pim_ifp)
610 continue;
611
612 if (pim_ifp->pim_sock_fd < 0)
613 continue;
614
615 ifaddr = pim_ifp->primary_address;
616
617 pim_time_uptime(uptime, sizeof(uptime), now - pim_ifp->pim_sock_creation);
618
619 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
620
621 vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
622 ifp->name,
623 inet_ntoa(ifaddr),
624 ifp->ifindex,
625 pim_ifp->pim_sock_fd,
626 uptime,
627 if_is_multicast(ifp) ? "yes" : "no",
628 if_is_broadcast(ifp) ? "yes" : "no",
629 (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
630 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
631 (ifp->flags & IFF_PROMISC) ? "yes" : "no",
632 PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
633 VTY_NEWLINE);
634 }
635}
636
637static void pim_show_join(struct vty *vty)
638{
639 struct listnode *ifnode;
640 struct interface *ifp;
641 time_t now;
642
643 now = pim_time_monotonic_sec();
644
645 vty_out(vty,
646 "Interface Address Source Group State Uptime Expire Prune%s",
647 VTY_NEWLINE);
648
649 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
650 struct pim_interface *pim_ifp;
651 struct in_addr ifaddr;
652 struct listnode *ch_node;
653 struct pim_ifchannel *ch;
654
655 pim_ifp = ifp->info;
656
657 if (!pim_ifp)
658 continue;
659
660 ifaddr = pim_ifp->primary_address;
661
662 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
663 char ch_src_str[100];
664 char ch_grp_str[100];
665 char uptime[10];
666 char expire[10];
667 char prune[10];
668
669 pim_inet4_dump("<ch_src?>", ch->source_addr,
670 ch_src_str, sizeof(ch_src_str));
671 pim_inet4_dump("<ch_grp?>", ch->group_addr,
672 ch_grp_str, sizeof(ch_grp_str));
673
674 pim_time_uptime(uptime, sizeof(uptime), now - ch->ifjoin_creation);
675 pim_time_timer_to_mmss(expire, sizeof(expire),
676 ch->t_ifjoin_expiry_timer);
677 pim_time_timer_to_mmss(prune, sizeof(prune),
678 ch->t_ifjoin_prune_pending_timer);
679
680 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s",
681 ifp->name,
682 inet_ntoa(ifaddr),
683 ch_src_str,
684 ch_grp_str,
685 pim_ifchannel_ifjoin_name(ch->ifjoin_state),
686 uptime,
687 expire,
688 prune,
689 VTY_NEWLINE);
690 } /* scan interface channels */
691 } /* scan interfaces */
692
693}
694
695static void pim_show_neighbors(struct vty *vty)
696{
697 struct listnode *node;
698 struct interface *ifp;
699 time_t now;
700
701 now = pim_time_monotonic_sec();
702
703 vty_out(vty,
704 "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s"
705 " T=can_disable_join_suppression%s%s",
706 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
707
708 vty_out(vty, "Interface Address Neighbor Uptime Timer Holdt DrPri GenId Recv %s", VTY_NEWLINE);
709
710 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
711 struct pim_interface *pim_ifp;
712 struct in_addr ifaddr;
713 struct listnode *neighnode;
714 struct pim_neighbor *neigh;
715
716 pim_ifp = ifp->info;
717
718 if (!pim_ifp)
719 continue;
720
721 if (pim_ifp->pim_sock_fd < 0)
722 continue;
723
724 ifaddr = pim_ifp->primary_address;
725
726 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
727 char uptime[10];
728 char holdtime[10];
729 char expire[10];
730 char neigh_src_str[100];
731 char recv[7];
732
733 pim_inet4_dump("<src?>", neigh->source_addr,
734 neigh_src_str, sizeof(neigh_src_str));
735 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
736 pim_time_mmss(holdtime, sizeof(holdtime), neigh->holdtime);
737 pim_time_timer_to_mmss(expire, sizeof(expire), neigh->t_expire_timer);
738
739 recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME) ? 'H' : ' ';
740 recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? 'L' : ' ';
741 recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ? 'P' : ' ';
742 recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ? 'G' : ' ';
743 recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST) ? 'A' : ' ';
744 recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' ';
745 recv[6] = '\0';
746
747 vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s",
748 ifp->name,
749 inet_ntoa(ifaddr),
750 neigh_src_str,
751 uptime,
752 expire,
753 holdtime,
754 neigh->dr_priority,
755 neigh->generation_id,
756 recv,
757 VTY_NEWLINE);
758 }
759
760
761 }
762}
763
764static void pim_show_lan_prune_delay(struct vty *vty)
765{
766 struct listnode *node;
767 struct interface *ifp;
768
769 vty_out(vty,
770 "PrDly=propagation_delay (msec) OvInt=override_interval (msec)%s"
771 "HiDly=highest_propagation_delay (msec) HiInt=highest_override_interval (msec)%s"
772 "NoDly=number_of_non_lan_delay_neighbors%s"
773 "T=t_bit LPD=lan_prune_delay_hello_option%s%s",
774 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
775
776 vty_out(vty, "Interface Address PrDly OvInt NoDly HiDly HiInt T Neighbor LPD PrDly OvInt T%s", VTY_NEWLINE);
777
778 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
779 struct pim_interface *pim_ifp;
780 struct in_addr ifaddr;
781 struct listnode *neighnode;
782 struct pim_neighbor *neigh;
783
784 pim_ifp = ifp->info;
785
786 if (!pim_ifp)
787 continue;
788
789 if (pim_ifp->pim_sock_fd < 0)
790 continue;
791
792 ifaddr = pim_ifp->primary_address;
793
794 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
795 char neigh_src_str[100];
796
797 pim_inet4_dump("<src?>", neigh->source_addr,
798 neigh_src_str, sizeof(neigh_src_str));
799
800 vty_out(vty, "%-9s %-15s %5u %5u %5u %5u %5u %1u %-15s %s %5u %5u %1u%s",
801 ifp->name,
802 inet_ntoa(ifaddr),
803 pim_ifp->pim_propagation_delay_msec,
804 pim_ifp->pim_override_interval_msec,
805 pim_ifp->pim_number_of_nonlandelay_neighbors,
806 pim_ifp->pim_neighbors_highest_propagation_delay_msec,
807 pim_ifp->pim_neighbors_highest_override_interval_msec,
808 PIM_FORCE_BOOLEAN(PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)),
809 neigh_src_str,
810 PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? "yes" : "no",
811 neigh->propagation_delay_msec,
812 neigh->override_interval_msec,
813 PIM_FORCE_BOOLEAN(PIM_OPTION_IS_SET(neigh->hello_options,
814 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)),
815 VTY_NEWLINE);
816 }
817
818 }
819}
820
821static void pim_show_jp_override_interval(struct vty *vty)
822{
823 struct listnode *node;
824 struct interface *ifp;
825
826 vty_out(vty,
827 "EffPDelay=effective_propagation_delay (msec)%s"
828 "EffOvrInt=override_interval (msec)%s"
829 "JPOvrInt=jp_override_interval (msec)%s%s",
830 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
831
832 vty_out(vty, "Interface Address LAN_Delay EffPDelay EffOvrInt JPOvrInt%s", VTY_NEWLINE);
833
834 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
835 struct pim_interface *pim_ifp;
836 struct in_addr ifaddr;
837
838 pim_ifp = ifp->info;
839
840 if (!pim_ifp)
841 continue;
842
843 if (pim_ifp->pim_sock_fd < 0)
844 continue;
845
846 ifaddr = pim_ifp->primary_address;
847
848 vty_out(vty, "%-9s %-15s %-9s %9u %9u %8u%s",
849 ifp->name,
850 inet_ntoa(ifaddr),
851 pim_if_lan_delay_enabled(ifp) ? "enabled" : "disabled",
852 pim_if_effective_propagation_delay_msec(ifp),
853 pim_if_effective_override_interval_msec(ifp),
854 pim_if_jp_override_interval_msec(ifp),
855 VTY_NEWLINE);
856 }
857}
858
859static void pim_show_neighbors_secondary(struct vty *vty)
860{
861 struct listnode *node;
862 struct interface *ifp;
863
864 vty_out(vty, "Interface Address Neighbor Secondary %s", VTY_NEWLINE);
865
866 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
867 struct pim_interface *pim_ifp;
868 struct in_addr ifaddr;
869 struct listnode *neighnode;
870 struct pim_neighbor *neigh;
871
872 pim_ifp = ifp->info;
873
874 if (!pim_ifp)
875 continue;
876
877 if (pim_ifp->pim_sock_fd < 0)
878 continue;
879
880 ifaddr = pim_ifp->primary_address;
881
882 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
883 char neigh_src_str[100];
884 struct listnode *prefix_node;
885 struct prefix *p;
886
887 if (!neigh->prefix_list)
888 continue;
889
890 pim_inet4_dump("<src?>", neigh->source_addr,
891 neigh_src_str, sizeof(neigh_src_str));
892
893 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
894 char neigh_sec_str[100];
895
896 if (p->family != AF_INET)
897 continue;
898
899 pim_inet4_dump("<src?>", p->u.prefix4,
900 neigh_sec_str, sizeof(neigh_sec_str));
901
902 vty_out(vty, "%-9s %-15s %-15s %-15s%s",
903 ifp->name,
904 inet_ntoa(ifaddr),
905 neigh_src_str,
906 neigh_sec_str,
907 VTY_NEWLINE);
908 }
909 }
910 }
911}
912
913static void pim_show_upstream(struct vty *vty)
914{
915 struct listnode *upnode;
916 struct pim_upstream *up;
917 time_t now;
918
919 now = pim_time_monotonic_sec();
920
921 vty_out(vty, "Source Group State Uptime JoinTimer RefCnt%s", VTY_NEWLINE);
922
923 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
924 char src_str[100];
925 char grp_str[100];
926 char uptime[10];
927 char join_timer[10];
928
929 pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
930 pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
931 pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
932 pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer);
933
934 vty_out(vty, "%-15s %-15s %-5s %-8s %-9s %6d%s",
935 src_str,
936 grp_str,
937 up->join_state == PIM_UPSTREAM_JOINED ? "Jnd" : "NtJnd",
938 uptime,
939 join_timer,
940 up->ref_count,
941 VTY_NEWLINE);
942 }
943}
944
945static void pim_show_join_desired(struct vty *vty)
946{
947 struct listnode *ifnode;
948 struct listnode *chnode;
949 struct interface *ifp;
950 struct pim_interface *pim_ifp;
951 struct pim_ifchannel *ch;
952 struct in_addr me_ifaddr;
953 char src_str[100];
954 char grp_str[100];
955
956 vty_out(vty,
957 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s",
958 VTY_NEWLINE);
959
960 /* scan all interfaces */
961 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
962 pim_ifp = ifp->info;
963 if (!pim_ifp)
964 continue;
965
966 me_ifaddr = pim_ifp->primary_address;
967
968 /* scan per-interface (S,G) state */
969 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) {
970 struct pim_upstream *up = ch->upstream;
971
972 pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
973 pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
974
975 vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s",
976 ifp->name,
977 src_str,
978 grp_str,
979 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
980 pim_macro_chisin_joins(ch) ? "yes" : "no",
981 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
982 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no",
983 pim_upstream_evaluate_join_desired(up) ? "yes" : "no",
984 VTY_NEWLINE);
985 }
986 }
987}
988
989static void pim_show_upstream_rpf(struct vty *vty)
990{
991 struct listnode *upnode;
992 struct pim_upstream *up;
993
994 vty_out(vty,
995 "Source Group RpfIface RibNextHop RpfAddress %s",
996 VTY_NEWLINE);
997
998 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
999 char src_str[100];
1000 char grp_str[100];
1001 char rpf_nexthop_str[100];
1002 char rpf_addr_str[100];
1003 struct pim_rpf *rpf;
1004 const char *rpf_ifname;
1005
1006 rpf = &up->rpf;
1007
1008 pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
1009 pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
1010 pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str));
1011 pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1012
1013 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1014
1015 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s",
1016 src_str,
1017 grp_str,
1018 rpf_ifname,
1019 rpf_nexthop_str,
1020 rpf_addr_str,
1021 VTY_NEWLINE);
1022 }
1023}
1024
1025static void pim_show_rpf(struct vty *vty)
1026{
1027 struct listnode *up_node;
1028 struct pim_upstream *up;
1029
1030 vty_out(vty,
1031 "Source Group RpfIface RpfAddress RibNextHop Metric Pref%s",
1032 VTY_NEWLINE);
1033
1034
1035 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) {
1036 char src_str[100];
1037 char grp_str[100];
1038 char rpf_addr_str[100];
1039 char rib_nexthop_str[100];
1040 const char *rpf_ifname;
1041 struct pim_rpf *rpf = &up->rpf;
1042
1043 pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
1044 pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
1045 pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1046 pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str));
1047
1048 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1049
1050 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s",
1051 src_str,
1052 grp_str,
1053 rpf_ifname,
1054 rpf_addr_str,
1055 rib_nexthop_str,
1056 rpf->source_nexthop.mrib_route_metric,
1057 rpf->source_nexthop.mrib_metric_preference,
1058 VTY_NEWLINE);
1059 }
1060}
1061
1062static void igmp_show_querier(struct vty *vty)
1063{
1064 struct listnode *node;
1065 struct interface *ifp;
1066 time_t now;
1067
1068 now = pim_time_monotonic_sec();
1069
1070 vty_out(vty, "Interface Address Querier StartCount Query-Timer Other-Timer%s", VTY_NEWLINE);
1071
1072 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
1073 struct pim_interface *pim_ifp = ifp->info;
1074 struct listnode *sock_node;
1075 struct igmp_sock *igmp;
1076
1077 if (!pim_ifp)
1078 continue;
1079
1080 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1081 char query_hhmmss[10];
1082 char other_hhmmss[10];
1083
1084 pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer);
1085 pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer);
1086
1087 vty_out(vty, "%-9s %-15s %7s %10d %11s %11s%s",
1088 ifp->name,
1089 inet_ntoa(igmp->ifaddr),
1090 igmp->t_igmp_query_timer ? "THIS" : "OTHER",
1091 igmp->startup_query_count,
1092 query_hhmmss,
1093 other_hhmmss,
1094 VTY_NEWLINE);
1095 }
1096 }
1097}
1098
1099static void igmp_show_groups(struct vty *vty)
1100{
1101 struct listnode *ifnode;
1102 struct interface *ifp;
1103 time_t now;
1104
1105 now = pim_time_monotonic_sec();
1106
1107 vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime %s", VTY_NEWLINE);
1108
1109 /* scan interfaces */
1110 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1111 struct pim_interface *pim_ifp = ifp->info;
1112 struct listnode *sock_node;
1113 struct igmp_sock *igmp;
1114
1115 if (!pim_ifp)
1116 continue;
1117
1118 /* scan igmp sockets */
1119 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1120 char ifaddr_str[100];
1121 struct listnode *grpnode;
1122 struct igmp_group *grp;
1123
1124 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1125
1126 /* scan igmp groups */
1127 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1128 char group_str[100];
1129 char hhmmss[10];
1130 char uptime[10];
1131
1132 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1133 pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer);
1134 pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation);
1135
1136 vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s",
1137 ifp->name,
1138 ifaddr_str,
1139 group_str,
1140 grp->group_filtermode_isexcl ? "EXCL" : "INCL",
1141 hhmmss,
1142 grp->group_source_list ? listcount(grp->group_source_list) : 0,
1143 igmp_group_compat_mode(igmp, grp),
1144 uptime,
1145 VTY_NEWLINE);
1146
1147 } /* scan igmp groups */
1148 } /* scan igmp sockets */
1149 } /* scan interfaces */
1150}
1151
1152static void igmp_show_group_retransmission(struct vty *vty)
1153{
1154 struct listnode *ifnode;
1155 struct interface *ifp;
1156 time_t now;
1157
1158 now = pim_time_monotonic_sec();
1159
1160 vty_out(vty, "Interface Address Group RetTimer Counter RetSrcs%s", VTY_NEWLINE);
1161
1162 /* scan interfaces */
1163 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1164 struct pim_interface *pim_ifp = ifp->info;
1165 struct listnode *sock_node;
1166 struct igmp_sock *igmp;
1167
1168 if (!pim_ifp)
1169 continue;
1170
1171 /* scan igmp sockets */
1172 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1173 char ifaddr_str[100];
1174 struct listnode *grpnode;
1175 struct igmp_group *grp;
1176
1177 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1178
1179 /* scan igmp groups */
1180 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1181 char group_str[100];
1182 char grp_retr_mmss[10];
1183 struct listnode *src_node;
1184 struct igmp_source *src;
1185 int grp_retr_sources = 0;
1186
1187 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1188 pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer);
1189
1190
1191 /* count group sources with retransmission state */
1192 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
1193 if (src->source_query_retransmit_count > 0) {
1194 ++grp_retr_sources;
1195 }
1196 }
1197
1198 vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d%s",
1199 ifp->name,
1200 ifaddr_str,
1201 group_str,
1202 grp_retr_mmss,
1203 grp->group_specific_query_retransmit_count,
1204 grp_retr_sources,
1205 VTY_NEWLINE);
1206
1207 } /* scan igmp groups */
1208 } /* scan igmp sockets */
1209 } /* scan interfaces */
1210}
1211
1212static void igmp_show_parameters(struct vty *vty)
1213{
1214 struct listnode *ifnode;
1215 struct interface *ifp;
1216
1217 vty_out(vty,
1218 "QRV: Robustness Variable SQI: Startup Query Interval%s"
1219 "QQI: Query Interval OQPI: Other Querier Present Interval%s"
1220 "QRI: Query Response Interval LMQT: Last Member Query Time%s"
1221 "GMI: Group Membership Interval OHPI: Older Host Present Interval%s%s",
1222 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1223
1224 vty_out(vty,
1225 "Interface Address QRV QQI QRI GMI SQI OQPI LMQT OHPI %s",
1226 VTY_NEWLINE);
1227
1228 /* scan interfaces */
1229 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1230 struct pim_interface *pim_ifp = ifp->info;
1231 struct listnode *sock_node;
1232 struct igmp_sock *igmp;
1233
1234 if (!pim_ifp)
1235 continue;
1236
1237 /* scan igmp sockets */
1238 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1239 char ifaddr_str[100];
1240 long gmi_dsec; /* Group Membership Interval */
1241 long oqpi_dsec; /* Other Querier Present Interval */
1242 int sqi;
1243 long lmqt_dsec;
1244 long ohpi_dsec;
1245 long qri_dsec;
1246
1247 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1248
1249 gmi_dsec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
1250 igmp->querier_query_interval,
1251 pim_ifp->igmp_query_max_response_time_dsec) / 100;
1252
1253 sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval);
1254
1255 oqpi_dsec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable,
1256 igmp->querier_query_interval,
1257 pim_ifp->igmp_query_max_response_time_dsec) / 100;
1258
1259 lmqt_dsec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec,
1260 igmp->querier_robustness_variable) / 100;
1261
1262 ohpi_dsec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable,
1263 igmp->querier_query_interval,
1264 pim_ifp->igmp_query_max_response_time_dsec);
1265
1266 qri_dsec = pim_ifp->igmp_query_max_response_time_dsec;
1267
1268 vty_out(vty,
1269 "%-9s %-15s %3d %3d %3ld.%ld %3ld.%ld %3d %3ld.%ld %3ld.%ld %3ld.%ld%s",
1270 ifp->name,
1271 ifaddr_str,
1272 igmp->querier_robustness_variable,
1273 igmp->querier_query_interval,
1274 qri_dsec / 10, qri_dsec % 10,
1275 gmi_dsec / 10, gmi_dsec % 10,
1276 sqi,
1277 oqpi_dsec / 10, oqpi_dsec % 10,
1278 lmqt_dsec / 10, lmqt_dsec % 10,
1279 ohpi_dsec / 10, ohpi_dsec % 10,
1280 VTY_NEWLINE);
1281
1282 } /* scan igmp sockets */
1283 } /* scan interfaces */
1284}
1285
1286static void igmp_show_sources(struct vty *vty)
1287{
1288 struct listnode *ifnode;
1289 struct interface *ifp;
1290 time_t now;
1291
1292 now = pim_time_monotonic_sec();
1293
1294 vty_out(vty, "Interface Address Group Source Timer Fwd Uptime %s", VTY_NEWLINE);
1295
1296 /* scan interfaces */
1297 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1298 struct pim_interface *pim_ifp = ifp->info;
1299 struct listnode *sock_node;
1300 struct igmp_sock *igmp;
1301
1302 if (!pim_ifp)
1303 continue;
1304
1305 /* scan igmp sockets */
1306 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1307 char ifaddr_str[100];
1308 struct listnode *grpnode;
1309 struct igmp_group *grp;
1310
1311 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1312
1313 /* scan igmp groups */
1314 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1315 char group_str[100];
1316 struct listnode *srcnode;
1317 struct igmp_source *src;
1318
1319 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1320
1321 /* scan group sources */
1322 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1323 char source_str[100];
1324 char mmss[10];
1325 char uptime[10];
1326
1327 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1328
1329 pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer);
1330
1331 pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation);
1332
1333 vty_out(vty, "%-9s %-15s %-15s %-15s %5s %3s %8s%s",
1334 ifp->name,
1335 ifaddr_str,
1336 group_str,
1337 source_str,
1338 mmss,
1339 IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N",
1340 uptime,
1341 VTY_NEWLINE);
1342
1343 } /* scan group sources */
1344 } /* scan igmp groups */
1345 } /* scan igmp sockets */
1346 } /* scan interfaces */
1347}
1348
1349static void igmp_show_source_retransmission(struct vty *vty)
1350{
1351 struct listnode *ifnode;
1352 struct interface *ifp;
1353 time_t now;
1354
1355 now = pim_time_monotonic_sec();
1356
1357 vty_out(vty, "Interface Address Group Source Counter%s", VTY_NEWLINE);
1358
1359 /* scan interfaces */
1360 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1361 struct pim_interface *pim_ifp = ifp->info;
1362 struct listnode *sock_node;
1363 struct igmp_sock *igmp;
1364
1365 if (!pim_ifp)
1366 continue;
1367
1368 /* scan igmp sockets */
1369 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1370 char ifaddr_str[100];
1371 struct listnode *grpnode;
1372 struct igmp_group *grp;
1373
1374 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1375
1376 /* scan igmp groups */
1377 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1378 char group_str[100];
1379 struct listnode *srcnode;
1380 struct igmp_source *src;
1381
1382 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1383
1384 /* scan group sources */
1385 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1386 char source_str[100];
1387
1388 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1389
1390 vty_out(vty, "%-9s %-15s %-15s %-15s %7d%s",
1391 ifp->name,
1392 ifaddr_str,
1393 group_str,
1394 source_str,
1395 src->source_query_retransmit_count,
1396 VTY_NEWLINE);
1397
1398 } /* scan group sources */
1399 } /* scan igmp groups */
1400 } /* scan igmp sockets */
1401 } /* scan interfaces */
1402}
1403
1404static void clear_igmp_interfaces()
1405{
1406 struct listnode *ifnode;
1407 struct listnode *ifnextnode;
1408 struct interface *ifp;
1409
1410 for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1411 pim_if_addr_del_all_igmp(ifp);
1412 }
1413
1414 for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1415 pim_if_addr_add_all(ifp);
1416 }
1417}
1418
1419static void clear_pim_interfaces()
1420{
1421 struct listnode *ifnode;
1422 struct listnode *ifnextnode;
1423 struct interface *ifp;
1424
1425 for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1426 if (ifp->info) {
1427 pim_neighbor_delete_all(ifp, "interface cleared");
1428 }
1429 }
1430}
1431
1432static void clear_interfaces()
1433{
1434 clear_igmp_interfaces();
1435 clear_pim_interfaces();
1436}
1437
1438DEFUN (pim_interface,
1439 pim_interface_cmd,
1440 "interface IFNAME",
1441 "Select an interface to configure\n"
1442 "Interface's name\n")
1443{
1444 struct interface *ifp;
1445 const char *ifname = argv[0];
1446 size_t sl;
1447
1448 sl = strlen(ifname);
1449 if (sl > INTERFACE_NAMSIZ) {
1450 vty_out(vty, "%% Interface name %s is invalid: length exceeds "
1451 "%d characters%s",
1452 ifname, INTERFACE_NAMSIZ, VTY_NEWLINE);
1453 return CMD_WARNING;
1454 }
1455
1456 ifp = if_lookup_by_name_len(ifname, sl);
1457 if (!ifp) {
1458 vty_out(vty, "%% Interface %s does not exist%s", ifname, VTY_NEWLINE);
1459
1460 /* Returning here would prevent pimd from booting when there are
1461 interface commands in pimd.conf, since all interfaces are
1462 unknown at pimd boot time (the zebra daemon has not been
1463 contacted for interface discovery). */
1464
1465 ifp = if_get_by_name_len(ifname, sl);
1466 if (!ifp) {
1467 vty_out(vty, "%% Could not create interface %s%s", ifname, VTY_NEWLINE);
1468 return CMD_WARNING;
1469 }
1470 }
1471
1472 vty->index = ifp;
1473 vty->node = INTERFACE_NODE;
1474
1475 return CMD_SUCCESS;
1476}
1477
1478DEFUN (clear_ip_interfaces,
1479 clear_ip_interfaces_cmd,
1480 "clear ip interfaces",
1481 CLEAR_STR
1482 IP_STR
1483 "Reset interfaces\n")
1484{
1485 clear_interfaces();
1486
1487 return CMD_SUCCESS;
1488}
1489
1490DEFUN (clear_ip_igmp_interfaces,
1491 clear_ip_igmp_interfaces_cmd,
1492 "clear ip igmp interfaces",
1493 CLEAR_STR
1494 IP_STR
1495 CLEAR_IP_IGMP_STR
1496 "Reset IGMP interfaces\n")
1497{
1498 clear_igmp_interfaces();
1499
1500 return CMD_SUCCESS;
1501}
1502
1503DEFUN (clear_ip_pim_interfaces,
1504 clear_ip_pim_interfaces_cmd,
1505 "clear ip pim interfaces",
1506 CLEAR_STR
1507 IP_STR
1508 CLEAR_IP_PIM_STR
1509 "Reset PIM interfaces\n")
1510{
1511 clear_pim_interfaces();
1512
1513 return CMD_SUCCESS;
1514}
1515
1516DEFUN (show_ip_igmp_interface,
1517 show_ip_igmp_interface_cmd,
1518 "show ip igmp interface",
1519 SHOW_STR
1520 IP_STR
1521 IGMP_STR
1522 "IGMP interface information\n")
1523{
1524 igmp_show_interfaces(vty);
1525
1526 return CMD_SUCCESS;
1527}
1528
1529DEFUN (show_ip_igmp_groups,
1530 show_ip_igmp_groups_cmd,
1531 "show ip igmp groups",
1532 SHOW_STR
1533 IP_STR
1534 IGMP_STR
1535 IGMP_GROUP_STR)
1536{
1537 igmp_show_groups(vty);
1538
1539 return CMD_SUCCESS;
1540}
1541
1542DEFUN (show_ip_igmp_groups_retransmissions,
1543 show_ip_igmp_groups_retransmissions_cmd,
1544 "show ip igmp groups retransmissions",
1545 SHOW_STR
1546 IP_STR
1547 IGMP_STR
1548 IGMP_GROUP_STR
1549 "IGMP group retransmissions\n")
1550{
1551 igmp_show_group_retransmission(vty);
1552
1553 return CMD_SUCCESS;
1554}
1555
1556DEFUN (show_ip_igmp_parameters,
1557 show_ip_igmp_parameters_cmd,
1558 "show ip igmp parameters",
1559 SHOW_STR
1560 IP_STR
1561 IGMP_STR
1562 "IGMP parameters information\n")
1563{
1564 igmp_show_parameters(vty);
1565
1566 return CMD_SUCCESS;
1567}
1568
1569DEFUN (show_ip_igmp_sources,
1570 show_ip_igmp_sources_cmd,
1571 "show ip igmp sources",
1572 SHOW_STR
1573 IP_STR
1574 IGMP_STR
1575 IGMP_SOURCE_STR)
1576{
1577 igmp_show_sources(vty);
1578
1579 return CMD_SUCCESS;
1580}
1581
1582DEFUN (show_ip_igmp_sources_retransmissions,
1583 show_ip_igmp_sources_retransmissions_cmd,
1584 "show ip igmp sources retransmissions",
1585 SHOW_STR
1586 IP_STR
1587 IGMP_STR
1588 IGMP_SOURCE_STR
1589 "IGMP source retransmissions\n")
1590{
1591 igmp_show_source_retransmission(vty);
1592
1593 return CMD_SUCCESS;
1594}
1595
1596DEFUN (show_ip_igmp_querier,
1597 show_ip_igmp_querier_cmd,
1598 "show ip igmp querier",
1599 SHOW_STR
1600 IP_STR
1601 IGMP_STR
1602 "IGMP querier information\n")
1603{
1604 igmp_show_querier(vty);
1605
1606 return CMD_SUCCESS;
1607}
1608
1609DEFUN (show_ip_pim_address,
1610 show_ip_pim_address_cmd,
1611 "show ip pim address",
1612 SHOW_STR
1613 IP_STR
1614 PIM_STR
1615 "PIM interface address\n")
1616{
1617 show_interface_address(vty);
1618
1619 return CMD_SUCCESS;
1620}
1621
1622DEFUN (show_ip_pim_assert,
1623 show_ip_pim_assert_cmd,
1624 "show ip pim assert",
1625 SHOW_STR
1626 IP_STR
1627 PIM_STR
1628 "PIM interface assert\n")
1629{
1630 pim_show_assert(vty);
1631
1632 return CMD_SUCCESS;
1633}
1634
1635DEFUN (show_ip_pim_assert_internal,
1636 show_ip_pim_assert_internal_cmd,
1637 "show ip pim assert-internal",
1638 SHOW_STR
1639 IP_STR
1640 PIM_STR
1641 "PIM interface internal assert state\n")
1642{
1643 pim_show_assert_internal(vty);
1644
1645 return CMD_SUCCESS;
1646}
1647
1648DEFUN (show_ip_pim_assert_metric,
1649 show_ip_pim_assert_metric_cmd,
1650 "show ip pim assert-metric",
1651 SHOW_STR
1652 IP_STR
1653 PIM_STR
1654 "PIM interface assert metric\n")
1655{
1656 pim_show_assert_metric(vty);
1657
1658 return CMD_SUCCESS;
1659}
1660
1661DEFUN (show_ip_pim_assert_winner_metric,
1662 show_ip_pim_assert_winner_metric_cmd,
1663 "show ip pim assert-winner-metric",
1664 SHOW_STR
1665 IP_STR
1666 PIM_STR
1667 "PIM interface assert winner metric\n")
1668{
1669 pim_show_assert_winner_metric(vty);
1670
1671 return CMD_SUCCESS;
1672}
1673
1674DEFUN (show_ip_pim_dr,
1675 show_ip_pim_dr_cmd,
1676 "show ip pim designated-router",
1677 SHOW_STR
1678 IP_STR
1679 PIM_STR
1680 "PIM interface designated router\n")
1681{
1682 pim_show_dr(vty);
1683
1684 return CMD_SUCCESS;
1685}
1686
1687DEFUN (show_ip_pim_hello,
1688 show_ip_pim_hello_cmd,
1689 "show ip pim hello",
1690 SHOW_STR
1691 IP_STR
1692 PIM_STR
1693 "PIM interface hello information\n")
1694{
1695 pim_show_hello(vty);
1696
1697 return CMD_SUCCESS;
1698}
1699
1700DEFUN (show_ip_pim_interface,
1701 show_ip_pim_interface_cmd,
1702 "show ip pim interface",
1703 SHOW_STR
1704 IP_STR
1705 PIM_STR
1706 "PIM interface information\n")
1707{
1708 pim_show_interfaces(vty);
1709
1710 return CMD_SUCCESS;
1711}
1712
1713DEFUN (show_ip_pim_join,
1714 show_ip_pim_join_cmd,
1715 "show ip pim join",
1716 SHOW_STR
1717 IP_STR
1718 PIM_STR
1719 "PIM interface join information\n")
1720{
1721 pim_show_join(vty);
1722
1723 return CMD_SUCCESS;
1724}
1725
1726DEFUN (show_ip_pim_lan_prune_delay,
1727 show_ip_pim_lan_prune_delay_cmd,
1728 "show ip pim lan-prune-delay",
1729 SHOW_STR
1730 IP_STR
1731 PIM_STR
1732 "PIM neighbors LAN prune delay parameters\n")
1733{
1734 pim_show_lan_prune_delay(vty);
1735
1736 return CMD_SUCCESS;
1737}
1738
1739DEFUN (show_ip_pim_local_membership,
1740 show_ip_pim_local_membership_cmd,
1741 "show ip pim local-membership",
1742 SHOW_STR
1743 IP_STR
1744 PIM_STR
1745 "PIM interface local-membership\n")
1746{
1747 pim_show_membership(vty);
1748
1749 return CMD_SUCCESS;
1750}
1751
1752DEFUN (show_ip_pim_jp_override_interval,
1753 show_ip_pim_jp_override_interval_cmd,
1754 "show ip pim jp-override-interval",
1755 SHOW_STR
1756 IP_STR
1757 PIM_STR
1758 "PIM interface J/P override interval\n")
1759{
1760 pim_show_jp_override_interval(vty);
1761
1762 return CMD_SUCCESS;
1763}
1764
1765DEFUN (show_ip_pim_neighbor,
1766 show_ip_pim_neighbor_cmd,
1767 "show ip pim neighbor",
1768 SHOW_STR
1769 IP_STR
1770 PIM_STR
1771 "PIM neighbor information\n")
1772{
1773 pim_show_neighbors(vty);
1774
1775 return CMD_SUCCESS;
1776}
1777
1778DEFUN (show_ip_pim_secondary,
1779 show_ip_pim_secondary_cmd,
1780 "show ip pim secondary",
1781 SHOW_STR
1782 IP_STR
1783 PIM_STR
1784 "PIM neighbor addresses\n")
1785{
1786 pim_show_neighbors_secondary(vty);
1787
1788 return CMD_SUCCESS;
1789}
1790
1791DEFUN (show_ip_pim_upstream,
1792 show_ip_pim_upstream_cmd,
1793 "show ip pim upstream",
1794 SHOW_STR
1795 IP_STR
1796 PIM_STR
1797 "PIM upstream information\n")
1798{
1799 pim_show_upstream(vty);
1800
1801 return CMD_SUCCESS;
1802}
1803
1804DEFUN (show_ip_pim_upstream_join_desired,
1805 show_ip_pim_upstream_join_desired_cmd,
1806 "show ip pim upstream-join-desired",
1807 SHOW_STR
1808 IP_STR
1809 PIM_STR
1810 "PIM upstream join-desired\n")
1811{
1812 pim_show_join_desired(vty);
1813
1814 return CMD_SUCCESS;
1815}
1816
1817DEFUN (show_ip_pim_upstream_rpf,
1818 show_ip_pim_upstream_rpf_cmd,
1819 "show ip pim upstream-rpf",
1820 SHOW_STR
1821 IP_STR
1822 PIM_STR
1823 "PIM upstream source rpf\n")
1824{
1825 pim_show_upstream_rpf(vty);
1826
1827 return CMD_SUCCESS;
1828}
1829
1830DEFUN (show_ip_pim_rpf,
1831 show_ip_pim_rpf_cmd,
1832 "show ip pim rpf",
1833 SHOW_STR
1834 IP_STR
1835 PIM_STR
1836 "PIM cached source rpf information\n")
1837{
1838 pim_show_rpf(vty);
1839
1840 return CMD_SUCCESS;
1841}
1842
1843static void show_multicast_interfaces(struct vty *vty)
1844{
1845 struct listnode *node;
1846 struct interface *ifp;
1847
1848 vty_out(vty, "%s", VTY_NEWLINE);
1849
1850 vty_out(vty, "Interface Address ifIndex VifIndex PktsIn PktsOut BytesIn BytesOut%s",
1851 VTY_NEWLINE);
1852
1853 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
1854 struct pim_interface *pim_ifp;
1855 struct in_addr ifaddr;
1856 struct sioc_vif_req vreq;
1857
1858 pim_ifp = ifp->info;
1859
1860 if (!pim_ifp)
1861 continue;
1862
1863 memset(&vreq, 0, sizeof(vreq));
1864 vreq.vifi = pim_ifp->mroute_vif_index;
1865
1866 if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) {
1867 int e = errno;
1868 vty_out(vty,
1869 "ioctl(SIOCGETVIFCNT=%d) failure for interface %s vif_index=%d: errno=%d: %s%s",
1870 SIOCGETVIFCNT,
1871 ifp->name,
1872 pim_ifp->mroute_vif_index,
1873 e,
1874 strerror(e),
1875 VTY_NEWLINE);
1876 continue;
1877 }
1878
1879 ifaddr = pim_ifp->primary_address;
1880
1881 vty_out(vty, "%-9s %-15s %7d %8d %6lu %7lu %7lu %8lu%s",
1882 ifp->name,
1883 inet_ntoa(ifaddr),
1884 ifp->ifindex,
1885 pim_ifp->mroute_vif_index,
1886 vreq.icount,
1887 vreq.ocount,
1888 vreq.ibytes,
1889 vreq.obytes,
1890 VTY_NEWLINE);
1891 }
1892}
1893
1894DEFUN (show_ip_multicast,
1895 show_ip_multicast_cmd,
1896 "show ip multicast",
1897 SHOW_STR
1898 IP_STR
1899 "Multicast global information\n")
1900{
1901 if (PIM_MROUTE_IS_ENABLED) {
1902 time_t now;
1903 char uptime[10];
1904
1905 vty_out(vty, "Mroute socket descriptor: %d%s",
1906 qpim_mroute_socket_fd,
1907 VTY_NEWLINE);
1908
1909 now = pim_time_monotonic_sec();
1910 pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
1911 vty_out(vty, "Mroute socket uptime: %s%s",
1912 uptime,
1913 VTY_NEWLINE);
1914 }
1915 else {
1916 vty_out(vty, "Multicast disabled%s",
1917 VTY_NEWLINE);
1918 }
1919
1920 vty_out(vty, "%s", VTY_NEWLINE);
1921 vty_out(vty, "Current highest VifIndex: %d%s",
1922 qpim_mroute_oif_highest_vif_index,
1923 VTY_NEWLINE);
1924 vty_out(vty, "Maximum highest VifIndex: %d%s",
1925 MAXVIFS - 1,
1926 VTY_NEWLINE);
1927
1928 vty_out(vty, "%s", VTY_NEWLINE);
1929 vty_out(vty, "Upstream Join Timer: %d secs%s",
1930 qpim_t_periodic,
1931 VTY_NEWLINE);
1932 vty_out(vty, "Join/Prune Holdtime: %d secs%s",
1933 PIM_JP_HOLDTIME,
1934 VTY_NEWLINE);
1935
1936 vty_out(vty, "%s", VTY_NEWLINE);
1937 vty_out(vty, "RPF Cache Refresh Delay: %ld msecs%s",
1938 qpim_rpf_cache_refresh_delay_msec,
1939 VTY_NEWLINE);
1940 vty_out(vty, "RPF Cache Refresh Timer: %ld msecs%s",
1941 pim_time_timer_remain_msec(qpim_rpf_cache_refresher),
1942 VTY_NEWLINE);
1943
1944 show_multicast_interfaces(vty);
1945
1946 return CMD_SUCCESS;
1947}
1948
1949static void show_mroute(struct vty *vty)
1950{
1951 struct listnode *node;
1952 struct channel_oil *c_oil;
1953 time_t now;
1954
1955 vty_out(vty, "Proto: I=IGMP P=PIM%s%s", VTY_NEWLINE, VTY_NEWLINE);
1956
1957 vty_out(vty, "Source Group Proto Input iVifI Output oVifI TTL Uptime %s",
1958 VTY_NEWLINE);
1959
1960 now = pim_time_monotonic_sec();
1961
1962 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
1963 char group_str[100];
1964 char source_str[100];
1965 int oif_vif_index;
1966
1967 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1968 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
1969
1970 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
1971 struct interface *ifp_in;
1972 struct interface *ifp_out;
1973 char oif_uptime[10];
1974 int ttl;
1975 char proto[5];
1976
1977 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
1978 if (ttl < 1)
1979 continue;
1980
1981 ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
1982 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
1983
1984 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]);
1985
1986 proto[0] = '\0';
1987 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) {
1988 strcat(proto, "P");
1989 }
1990 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) {
1991 strcat(proto, "I");
1992 }
1993
1994 vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s",
1995 source_str,
1996 group_str,
1997 proto,
1998 ifp_in ? ifp_in->name : "<iif?>",
1999 c_oil->oil.mfcc_parent,
2000 ifp_out ? ifp_out->name : "<oif?>",
2001 oif_vif_index,
2002 ttl,
2003 oif_uptime,
2004 VTY_NEWLINE);
2005 }
2006 }
2007}
2008
2009DEFUN (show_ip_mroute,
2010 show_ip_mroute_cmd,
2011 "show ip mroute",
2012 SHOW_STR
2013 IP_STR
2014 MROUTE_STR)
2015{
2016 show_mroute(vty);
2017 return CMD_SUCCESS;
2018}
2019
2020static void show_mroute_count(struct vty *vty)
2021{
2022 struct listnode *node;
2023 struct channel_oil *c_oil;
2024
2025 vty_out(vty, "%s", VTY_NEWLINE);
2026
2027 vty_out(vty, "Source Group Packets Bytes WrongIf %s",
2028 VTY_NEWLINE);
2029
2030 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2031 char group_str[100];
2032 char source_str[100];
2033 struct sioc_sg_req sgreq;
2034
2035 memset(&sgreq, 0, sizeof(sgreq));
2036 sgreq.src = c_oil->oil.mfcc_origin;
2037 sgreq.grp = c_oil->oil.mfcc_mcastgrp;
2038
2039 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2040 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2041
2042 if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
2043 int e = errno;
2044 vty_out(vty,
2045 "ioctl(SIOCGETSGCNT=%d) failure for (S,G)=(%s,%s): errno=%d: %s%s",
2046 SIOCGETSGCNT,
2047 source_str,
2048 group_str,
2049 e,
2050 strerror(e),
2051 VTY_NEWLINE);
2052 continue;
2053 }
2054
2055 vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
2056 source_str,
2057 group_str,
2058 sgreq.pktcnt,
2059 sgreq.bytecnt,
2060 sgreq.wrong_if,
2061 VTY_NEWLINE);
2062
2063 }
2064}
2065
2066DEFUN (show_ip_mroute_count,
2067 show_ip_mroute_count_cmd,
2068 "show ip mroute count",
2069 SHOW_STR
2070 IP_STR
2071 MROUTE_STR
2072 "Route and packet count data\n")
2073{
2074 show_mroute_count(vty);
2075 return CMD_SUCCESS;
2076}
2077
2078DEFUN (show_ip_route,
2079 show_ip_route_cmd,
2080 "show ip route A.B.C.D",
2081 SHOW_STR
2082 IP_STR
2083 ROUTE_STR
2084 "Unicast address\n")
2085{
2086 struct in_addr addr;
2087 const char *addr_str;
2088 struct pim_nexthop nexthop;
2089 char nexthop_addr_str[100];
2090 int result;
2091
2092 addr_str = argv[0];
2093 result = inet_pton(AF_INET, addr_str, &addr);
2094 if (result <= 0) {
2095 vty_out(vty, "Bad unicast address %s: errno=%d: %s%s",
2096 addr_str, errno, strerror(errno), VTY_NEWLINE);
2097 return CMD_WARNING;
2098 }
2099
2100 if (pim_nexthop_lookup(&nexthop, addr)) {
2101 vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s",
2102 addr_str, VTY_NEWLINE);
2103 return CMD_WARNING;
2104 }
2105
2106 vty_out(vty, "Address NextHop Interface Metric Preference%s",
2107 VTY_NEWLINE);
2108
2109 pim_inet4_dump("<nexthop?>", nexthop.mrib_nexthop_addr,
2110 nexthop_addr_str, sizeof(nexthop_addr_str));
2111
2112 vty_out(vty, "%-15s %-15s %-9s %6d %10d%s",
2113 addr_str,
2114 nexthop_addr_str,
2115 nexthop.interface ? nexthop.interface->name : "<ifname?>",
2116 nexthop.mrib_route_metric,
2117 nexthop.mrib_metric_preference,
2118 VTY_NEWLINE);
2119
2120 return CMD_SUCCESS;
2121}
2122
2123static void mroute_add_all()
2124{
2125 struct listnode *node;
2126 struct channel_oil *c_oil;
2127
2128 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2129 if (pim_mroute_add(&c_oil->oil)) {
2130 /* just log warning */
2131 char source_str[100];
2132 char group_str[100];
2133 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2134 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2135 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
2136 __FILE__, __PRETTY_FUNCTION__,
2137 source_str, group_str);
2138 }
2139 }
2140}
2141
2142static void mroute_del_all()
2143{
2144 struct listnode *node;
2145 struct channel_oil *c_oil;
2146
2147 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2148 if (pim_mroute_del(&c_oil->oil)) {
2149 /* just log warning */
2150 char source_str[100];
2151 char group_str[100];
2152 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2153 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2154 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
2155 __FILE__, __PRETTY_FUNCTION__,
2156 source_str, group_str);
2157 }
2158 }
2159}
2160
2161DEFUN (ip_multicast_routing,
2162 ip_multicast_routing_cmd,
2163 PIM_CMD_IP_MULTICAST_ROUTING,
2164 IP_STR
2165 "Enable IP multicast forwarding\n")
2166{
2167 pim_mroute_socket_enable();
2168 pim_if_add_vif_all();
2169 mroute_add_all();
2170 return CMD_SUCCESS;
2171}
2172
2173DEFUN (no_ip_multicast_routing,
2174 no_ip_multicast_routing_cmd,
2175 PIM_CMD_NO " " PIM_CMD_IP_MULTICAST_ROUTING,
2176 NO_STR
2177 IP_STR
2178 "Global IP configuration subcommands\n"
2179 "Enable IP multicast forwarding\n")
2180{
2181 mroute_del_all();
2182 pim_if_del_vif_all();
2183 pim_mroute_socket_disable();
2184 return CMD_SUCCESS;
2185}
2186
2187DEFUN (interface_ip_igmp,
2188 interface_ip_igmp_cmd,
2189 "ip igmp",
2190 IP_STR
2191 IFACE_IGMP_STR)
2192{
2193 struct interface *ifp;
2194 struct pim_interface *pim_ifp;
2195
2196 ifp = vty->index;
2197 pim_ifp = ifp->info;
2198
2199 if (!pim_ifp) {
2200 pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
2201 if (!pim_ifp) {
2202 vty_out(vty, "Could not enable IGMP on interface %s%s",
2203 ifp->name, VTY_NEWLINE);
2204 return CMD_WARNING;
2205 }
2206 }
2207 else {
2208 PIM_IF_DO_IGMP(pim_ifp->options);
2209 }
2210
2211 pim_if_addr_add_all(ifp);
2212 pim_if_membership_refresh(ifp);
2213
2214 return CMD_SUCCESS;
2215}
2216
2217DEFUN (interface_no_ip_igmp,
2218 interface_no_ip_igmp_cmd,
2219 "no ip igmp",
2220 NO_STR
2221 IP_STR
2222 IFACE_IGMP_STR)
2223{
2224 struct interface *ifp;
2225 struct pim_interface *pim_ifp;
2226
2227 ifp = vty->index;
2228 pim_ifp = ifp->info;
2229 if (!pim_ifp)
2230 return CMD_SUCCESS;
2231
2232 PIM_IF_DONT_IGMP(pim_ifp->options);
2233
2234 pim_if_membership_clear(ifp);
2235
2236 pim_if_addr_del_all(ifp);
2237
2238 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
2239 pim_if_delete(ifp);
2240 }
2241
2242 return CMD_SUCCESS;
2243}
2244
2245DEFUN (interface_ip_igmp_join,
2246 interface_ip_igmp_join_cmd,
2247 "ip igmp join A.B.C.D A.B.C.D",
2248 IP_STR
2249 IFACE_IGMP_STR
2250 "IGMP join multicast group\n"
2251 "Multicast group address\n"
2252 "Source address\n")
2253{
2254 struct interface *ifp;
2255 const char *group_str;
2256 const char *source_str;
2257 struct in_addr group_addr;
2258 struct in_addr source_addr;
2259 int result;
2260
2261 ifp = vty->index;
2262
2263 /* Group address */
2264 group_str = argv[0];
2265 result = inet_pton(AF_INET, group_str, &group_addr);
2266 if (result <= 0) {
2267 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2268 group_str, errno, strerror(errno), VTY_NEWLINE);
2269 return CMD_WARNING;
2270 }
2271
2272 /* Source address */
2273 source_str = argv[1];
2274 result = inet_pton(AF_INET, source_str, &source_addr);
2275 if (result <= 0) {
2276 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2277 source_str, errno, strerror(errno), VTY_NEWLINE);
2278 return CMD_WARNING;
2279 }
2280
2281 result = pim_if_igmp_join_add(ifp, group_addr, source_addr);
2282 if (result) {
2283 vty_out(vty, "%% Failure joining IGMP group %s source %s on interface %s: %d%s",
2284 group_str, source_str, ifp->name, result, VTY_NEWLINE);
2285 return CMD_WARNING;
2286 }
2287
2288 return CMD_SUCCESS;
2289}
2290
2291DEFUN (interface_no_ip_igmp_join,
2292 interface_no_ip_igmp_join_cmd,
2293 "no ip igmp join A.B.C.D A.B.C.D",
2294 NO_STR
2295 IP_STR
2296 IFACE_IGMP_STR
2297 "IGMP join multicast group\n"
2298 "Multicast group address\n"
2299 "Source address\n")
2300{
2301 struct interface *ifp;
2302 const char *group_str;
2303 const char *source_str;
2304 struct in_addr group_addr;
2305 struct in_addr source_addr;
2306 int result;
2307
2308 ifp = vty->index;
2309
2310 /* Group address */
2311 group_str = argv[0];
2312 result = inet_pton(AF_INET, group_str, &group_addr);
2313 if (result <= 0) {
2314 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2315 group_str, errno, strerror(errno), VTY_NEWLINE);
2316 return CMD_WARNING;
2317 }
2318
2319 /* Source address */
2320 source_str = argv[1];
2321 result = inet_pton(AF_INET, source_str, &source_addr);
2322 if (result <= 0) {
2323 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2324 source_str, errno, strerror(errno), VTY_NEWLINE);
2325 return CMD_WARNING;
2326 }
2327
2328 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
2329 if (result) {
2330 vty_out(vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d%s",
2331 group_str, source_str, ifp->name, result, VTY_NEWLINE);
2332 return CMD_WARNING;
2333 }
2334
2335 return CMD_SUCCESS;
2336}
2337
2338/*
2339 CLI reconfiguration affects the interface level (struct pim_interface).
2340 This function propagates the reconfiguration to every active socket
2341 for that interface.
2342 */
2343static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
2344{
2345 struct interface *ifp;
2346 struct pim_interface *pim_ifp;
2347
2348 zassert(igmp);
2349
2350 /* other querier present? */
2351
2352 if (igmp->t_other_querier_timer)
2353 return;
2354
2355 /* this is the querier */
2356
2357 zassert(igmp->interface);
2358 zassert(igmp->interface->info);
2359
2360 ifp = igmp->interface;
2361 pim_ifp = ifp->info;
2362
2363 if (PIM_DEBUG_IGMP_TRACE) {
2364 char ifaddr_str[100];
2365 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2366 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
2367 __PRETTY_FUNCTION__,
2368 ifaddr_str,
2369 ifp->name,
2370 pim_ifp->igmp_default_query_interval);
2371 }
2372
2373 /*
2374 igmp_startup_mode_on() will reset QQI:
2375
2376 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
2377 */
2378 igmp_startup_mode_on(igmp);
2379}
2380
2381static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
2382{
2383 if (igmp->t_igmp_query_timer) {
2384 /* other querier present */
2385 zassert(igmp->t_igmp_query_timer);
2386 zassert(!igmp->t_other_querier_timer);
2387
2388 pim_igmp_general_query_off(igmp);
2389 pim_igmp_general_query_on(igmp);
2390
2391 zassert(igmp->t_igmp_query_timer);
2392 zassert(!igmp->t_other_querier_timer);
2393 }
2394 else {
2395 /* this is the querier */
2396
2397 zassert(!igmp->t_igmp_query_timer);
2398 zassert(igmp->t_other_querier_timer);
2399
2400 pim_igmp_other_querier_timer_off(igmp);
2401 pim_igmp_other_querier_timer_on(igmp);
2402
2403 zassert(!igmp->t_igmp_query_timer);
2404 zassert(igmp->t_other_querier_timer);
2405 }
2406}
2407
2408static void change_query_interval(struct pim_interface *pim_ifp,
2409 int query_interval)
2410{
2411 struct listnode *sock_node;
2412 struct igmp_sock *igmp;
2413
2414 pim_ifp->igmp_default_query_interval = query_interval;
2415
2416 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2417 igmp_sock_query_interval_reconfig(igmp);
2418 igmp_sock_query_reschedule(igmp);
2419 }
2420}
2421
2422static void change_query_max_response_time(struct pim_interface *pim_ifp,
2423 int query_max_response_time_dsec)
2424{
2425 struct listnode *sock_node;
2426 struct igmp_sock *igmp;
2427
2428 pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec;
2429
2430 /*
2431 Below we modify socket/group/source timers in order to quickly
2432 reflect the change. Otherwise, those timers would eventually catch
2433 up.
2434 */
2435
2436 /* scan all sockets */
2437 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2438 struct listnode *grp_node;
2439 struct igmp_group *grp;
2440
2441 /* reschedule socket general query */
2442 igmp_sock_query_reschedule(igmp);
2443
2444 /* scan socket groups */
2445 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) {
2446 struct listnode *src_node;
2447 struct igmp_source *src;
2448
2449 /* reset group timers for groups in EXCLUDE mode */
2450 if (grp->group_filtermode_isexcl) {
2451 igmp_group_reset_gmi(grp);
2452 }
2453
2454 /* scan group sources */
2455 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
2456
2457 /* reset source timers for sources with running timers */
2458 if (src->t_source_timer) {
2459 igmp_source_reset_gmi(igmp, grp, src);
2460 }
2461 }
2462 }
2463 }
2464}
2465
2466#define IGMP_QUERY_INTERVAL_MIN (1)
2467#define IGMP_QUERY_INTERVAL_MAX (1800)
2468
2469DEFUN (interface_ip_igmp_query_interval,
2470 interface_ip_igmp_query_interval_cmd,
2471 PIM_CMD_IP_IGMP_QUERY_INTERVAL " <1-1800>",
2472 IP_STR
2473 IFACE_IGMP_STR
2474 IFACE_IGMP_QUERY_INTERVAL_STR
2475 "Query interval in seconds\n")
2476{
2477 struct interface *ifp;
2478 struct pim_interface *pim_ifp;
2479 int query_interval;
2480 int query_interval_dsec;
2481
2482 ifp = vty->index;
2483 pim_ifp = ifp->info;
2484
2485 if (!pim_ifp) {
2486 vty_out(vty,
2487 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2488 ifp->name,
2489 VTY_NEWLINE);
2490 return CMD_WARNING;
2491 }
2492
2493 query_interval = atoi(argv[0]);
2494 query_interval_dsec = 10 * query_interval;
2495
2496 /*
2497 It seems we don't need to check bounds since command.c does it
2498 already, but we verify them anyway for extra safety.
2499 */
2500 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
2501 vty_out(vty, "General query interval %d lower than minimum %d%s",
2502 query_interval,
2503 IGMP_QUERY_INTERVAL_MIN,
2504 VTY_NEWLINE);
2505 return CMD_WARNING;
2506 }
2507 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
2508 vty_out(vty, "General query interval %d higher than maximum %d%s",
2509 query_interval,
2510 IGMP_QUERY_INTERVAL_MAX,
2511 VTY_NEWLINE);
2512 return CMD_WARNING;
2513 }
2514
2515 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2516 vty_out(vty,
2517 "Can't set general query interval %d dsec <= query max response time %d dsec.%s",
2518 query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2519 VTY_NEWLINE);
2520 return CMD_WARNING;
2521 }
2522
2523 change_query_interval(pim_ifp, query_interval);
2524
2525 return CMD_SUCCESS;
2526}
2527
2528DEFUN (interface_no_ip_igmp_query_interval,
2529 interface_no_ip_igmp_query_interval_cmd,
2530 PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_INTERVAL,
2531 NO_STR
2532 IP_STR
2533 IFACE_IGMP_STR
2534 IFACE_IGMP_QUERY_INTERVAL_STR)
2535{
2536 struct interface *ifp;
2537 struct pim_interface *pim_ifp;
2538 int default_query_interval_dsec;
2539
2540 ifp = vty->index;
2541 pim_ifp = ifp->info;
2542
2543 if (!pim_ifp)
2544 return CMD_SUCCESS;
2545
2546 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
2547
2548 if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2549 vty_out(vty,
2550 "Can't set default general query interval %d dsec <= query max response time %d dsec.%s",
2551 default_query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2552 VTY_NEWLINE);
2553 return CMD_WARNING;
2554 }
2555
2556 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
2557
2558 return CMD_SUCCESS;
2559}
2560
2561#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1)
2562#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25)
2563
2564DEFUN (interface_ip_igmp_query_max_response_time,
2565 interface_ip_igmp_query_max_response_time_cmd,
2566 PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME " <1-25>",
2567 IP_STR
2568 IFACE_IGMP_STR
2569 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
2570 "Query response value in seconds\n")
2571{
2572 struct interface *ifp;
2573 struct pim_interface *pim_ifp;
2574 int query_max_response_time;
2575
2576 ifp = vty->index;
2577 pim_ifp = ifp->info;
2578
2579 if (!pim_ifp) {
2580 vty_out(vty,
2581 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2582 ifp->name,
2583 VTY_NEWLINE);
2584 return CMD_WARNING;
2585 }
2586
2587 query_max_response_time = atoi(argv[0]);
2588
2589 /*
2590 It seems we don't need to check bounds since command.c does it
2591 already, but we verify them anyway for extra safety.
2592 */
2593 if (query_max_response_time < IGMP_QUERY_MAX_RESPONSE_TIME_MIN) {
2594 vty_out(vty, "Query max response time %d sec lower than minimum %d sec%s",
2595 query_max_response_time,
2596 IGMP_QUERY_MAX_RESPONSE_TIME_MIN,
2597 VTY_NEWLINE);
2598 return CMD_WARNING;
2599 }
2600 if (query_max_response_time > IGMP_QUERY_MAX_RESPONSE_TIME_MAX) {
2601 vty_out(vty, "Query max response time %d sec higher than maximum %d sec%s",
2602 query_max_response_time,
2603 IGMP_QUERY_MAX_RESPONSE_TIME_MAX,
2604 VTY_NEWLINE);
2605 return CMD_WARNING;
2606 }
2607
2608 if (query_max_response_time >= pim_ifp->igmp_default_query_interval) {
2609 vty_out(vty,
2610 "Can't set query max response time %d sec >= general query interval %d sec%s",
2611 query_max_response_time, pim_ifp->igmp_default_query_interval,
2612 VTY_NEWLINE);
2613 return CMD_WARNING;
2614 }
2615
2616 change_query_max_response_time(pim_ifp, 10 * query_max_response_time);
2617
2618 return CMD_SUCCESS;
2619}
2620
2621DEFUN (interface_no_ip_igmp_query_max_response_time,
2622 interface_no_ip_igmp_query_max_response_time_cmd,
2623 PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME,
2624 NO_STR
2625 IP_STR
2626 IFACE_IGMP_STR
2627 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR)
2628{
2629 struct interface *ifp;
2630 struct pim_interface *pim_ifp;
2631 int default_query_interval_dsec;
2632
2633 ifp = vty->index;
2634 pim_ifp = ifp->info;
2635
2636 if (!pim_ifp)
2637 return CMD_SUCCESS;
2638
2639 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
2640
2641 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
2642 vty_out(vty,
2643 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
2644 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
2645 VTY_NEWLINE);
2646 return CMD_WARNING;
2647 }
2648
2649 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
2650
2651 return CMD_SUCCESS;
2652}
2653
2654#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
2655#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
2656
2657DEFUN (interface_ip_igmp_query_max_response_time_dsec,
2658 interface_ip_igmp_query_max_response_time_dsec_cmd,
2659 PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC " <10-250>",
2660 IP_STR
2661 IFACE_IGMP_STR
2662 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
2663 "Query response value in deciseconds\n")
2664{
2665 struct interface *ifp;
2666 struct pim_interface *pim_ifp;
2667 int query_max_response_time_dsec;
2668 int default_query_interval_dsec;
2669
2670 ifp = vty->index;
2671 pim_ifp = ifp->info;
2672
2673 if (!pim_ifp) {
2674 vty_out(vty,
2675 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2676 ifp->name,
2677 VTY_NEWLINE);
2678 return CMD_WARNING;
2679 }
2680
2681 query_max_response_time_dsec = atoi(argv[0]);
2682
2683 /*
2684 It seems we don't need to check bounds since command.c does it
2685 already, but we verify them anyway for extra safety.
2686 */
2687 if (query_max_response_time_dsec < IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC) {
2688 vty_out(vty, "Query max response time %d dsec lower than minimum %d dsec%s",
2689 query_max_response_time_dsec,
2690 IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC,
2691 VTY_NEWLINE);
2692 return CMD_WARNING;
2693 }
2694 if (query_max_response_time_dsec > IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC) {
2695 vty_out(vty, "Query max response time %d dsec higher than maximum %d dsec%s",
2696 query_max_response_time_dsec,
2697 IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC,
2698 VTY_NEWLINE);
2699 return CMD_WARNING;
2700 }
2701
2702 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
2703
2704 if (query_max_response_time_dsec >= default_query_interval_dsec) {
2705 vty_out(vty,
2706 "Can't set query max response time %d dsec >= general query interval %d dsec%s",
2707 query_max_response_time_dsec, default_query_interval_dsec,
2708 VTY_NEWLINE);
2709 return CMD_WARNING;
2710 }
2711
2712 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
2713
2714 return CMD_SUCCESS;
2715}
2716
2717DEFUN (interface_no_ip_igmp_query_max_response_time_dsec,
2718 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
2719 PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC,
2720 NO_STR
2721 IP_STR
2722 IFACE_IGMP_STR
2723 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
2724{
2725 struct interface *ifp;
2726 struct pim_interface *pim_ifp;
2727 int default_query_interval_dsec;
2728
2729 ifp = vty->index;
2730 pim_ifp = ifp->info;
2731
2732 if (!pim_ifp)
2733 return CMD_SUCCESS;
2734
2735 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
2736
2737 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
2738 vty_out(vty,
2739 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
2740 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
2741 VTY_NEWLINE);
2742 return CMD_WARNING;
2743 }
2744
2745 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
2746
2747 return CMD_SUCCESS;
2748}
2749
2750DEFUN (interface_ip_pim_ssm,
2751 interface_ip_pim_ssm_cmd,
2752 "ip pim ssm",
2753 IP_STR
2754 PIM_STR
2755 IFACE_PIM_STR)
2756{
2757 struct interface *ifp;
2758 struct pim_interface *pim_ifp;
2759
2760 ifp = vty->index;
2761 pim_ifp = ifp->info;
2762
2763 if (!pim_ifp) {
2764 pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
2765 if (!pim_ifp) {
2766 vty_out(vty, "Could not enable PIM on interface%s", VTY_NEWLINE);
2767 return CMD_WARNING;
2768 }
2769 }
2770 else {
2771 PIM_IF_DO_PIM(pim_ifp->options);
2772 }
2773
2774 pim_if_addr_add_all(ifp);
2775 pim_if_membership_refresh(ifp);
2776
2777 return CMD_SUCCESS;
2778}
2779
2780DEFUN (interface_no_ip_pim_ssm,
2781 interface_no_ip_pim_ssm_cmd,
2782 "no ip pim ssm",
2783 NO_STR
2784 IP_STR
2785 PIM_STR
2786 IFACE_PIM_STR)
2787{
2788 struct interface *ifp;
2789 struct pim_interface *pim_ifp;
2790
2791 ifp = vty->index;
2792 pim_ifp = ifp->info;
2793 if (!pim_ifp)
2794 return CMD_SUCCESS;
2795
2796 PIM_IF_DONT_PIM(pim_ifp->options);
2797
2798 pim_if_membership_clear(ifp);
2799
2800 /*
2801 pim_if_addr_del_all() removes all sockets from
2802 pim_ifp->igmp_socket_list.
2803 */
2804 pim_if_addr_del_all(ifp);
2805
2806 /*
2807 pim_sock_delete() removes all neighbors from
2808 pim_ifp->pim_neighbor_list.
2809 */
2810 pim_sock_delete(ifp, "pim unconfigured on interface");
2811
2812 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
2813 pim_if_delete(ifp);
2814 }
2815
2816 return CMD_SUCCESS;
2817}
2818
2819DEFUN (debug_igmp,
2820 debug_igmp_cmd,
2821 "debug igmp",
2822 DEBUG_STR
2823 DEBUG_IGMP_STR)
2824{
2825 PIM_DO_DEBUG_IGMP_EVENTS;
2826 PIM_DO_DEBUG_IGMP_PACKETS;
2827 PIM_DO_DEBUG_IGMP_TRACE;
2828 return CMD_SUCCESS;
2829}
2830
2831DEFUN (no_debug_igmp,
2832 no_debug_igmp_cmd,
2833 "no debug igmp",
2834 NO_STR
2835 DEBUG_STR
2836 DEBUG_IGMP_STR)
2837{
2838 PIM_DONT_DEBUG_IGMP_EVENTS;
2839 PIM_DONT_DEBUG_IGMP_PACKETS;
2840 PIM_DONT_DEBUG_IGMP_TRACE;
2841 return CMD_SUCCESS;
2842}
2843
2844ALIAS (no_debug_igmp,
2845 undebug_igmp_cmd,
2846 "undebug igmp",
2847 UNDEBUG_STR
2848 DEBUG_IGMP_STR)
2849
2850DEFUN (debug_igmp_events,
2851 debug_igmp_events_cmd,
2852 "debug igmp events",
2853 DEBUG_STR
2854 DEBUG_IGMP_STR
2855 DEBUG_IGMP_EVENTS_STR)
2856{
2857 PIM_DO_DEBUG_IGMP_EVENTS;
2858 return CMD_SUCCESS;
2859}
2860
2861DEFUN (no_debug_igmp_events,
2862 no_debug_igmp_events_cmd,
2863 "no debug igmp events",
2864 NO_STR
2865 DEBUG_STR
2866 DEBUG_IGMP_STR
2867 DEBUG_IGMP_EVENTS_STR)
2868{
2869 PIM_DONT_DEBUG_IGMP_EVENTS;
2870 return CMD_SUCCESS;
2871}
2872
2873ALIAS (no_debug_igmp_events,
2874 undebug_igmp_events_cmd,
2875 "undebug igmp events",
2876 UNDEBUG_STR
2877 DEBUG_IGMP_STR
2878 DEBUG_IGMP_EVENTS_STR)
2879
2880DEFUN (debug_igmp_packets,
2881 debug_igmp_packets_cmd,
2882 "debug igmp packets",
2883 DEBUG_STR
2884 DEBUG_IGMP_STR
2885 DEBUG_IGMP_PACKETS_STR)
2886{
2887 PIM_DO_DEBUG_IGMP_PACKETS;
2888 return CMD_SUCCESS;
2889}
2890
2891DEFUN (no_debug_igmp_packets,
2892 no_debug_igmp_packets_cmd,
2893 "no debug igmp packets",
2894 NO_STR
2895 DEBUG_STR
2896 DEBUG_IGMP_STR
2897 DEBUG_IGMP_PACKETS_STR)
2898{
2899 PIM_DONT_DEBUG_IGMP_PACKETS;
2900 return CMD_SUCCESS;
2901}
2902
2903ALIAS (no_debug_igmp_packets,
2904 undebug_igmp_packets_cmd,
2905 "undebug igmp packets",
2906 UNDEBUG_STR
2907 DEBUG_IGMP_STR
2908 DEBUG_IGMP_PACKETS_STR)
2909
2910DEFUN (debug_igmp_trace,
2911 debug_igmp_trace_cmd,
2912 "debug igmp trace",
2913 DEBUG_STR
2914 DEBUG_IGMP_STR
2915 DEBUG_IGMP_TRACE_STR)
2916{
2917 PIM_DO_DEBUG_IGMP_TRACE;
2918 return CMD_SUCCESS;
2919}
2920
2921DEFUN (no_debug_igmp_trace,
2922 no_debug_igmp_trace_cmd,
2923 "no debug igmp trace",
2924 NO_STR
2925 DEBUG_STR
2926 DEBUG_IGMP_STR
2927 DEBUG_IGMP_TRACE_STR)
2928{
2929 PIM_DONT_DEBUG_IGMP_TRACE;
2930 return CMD_SUCCESS;
2931}
2932
2933ALIAS (no_debug_igmp_trace,
2934 undebug_igmp_trace_cmd,
2935 "undebug igmp trace",
2936 UNDEBUG_STR
2937 DEBUG_IGMP_STR
2938 DEBUG_IGMP_TRACE_STR)
2939
2940DEFUN (debug_pim,
2941 debug_pim_cmd,
2942 "debug pim",
2943 DEBUG_STR
2944 DEBUG_PIM_STR)
2945{
2946 PIM_DO_DEBUG_PIM_EVENTS;
2947 PIM_DO_DEBUG_PIM_PACKETS;
2948 PIM_DO_DEBUG_PIM_TRACE;
2949 return CMD_SUCCESS;
2950}
2951
2952DEFUN (no_debug_pim,
2953 no_debug_pim_cmd,
2954 "no debug pim",
2955 NO_STR
2956 DEBUG_STR
2957 DEBUG_PIM_STR)
2958{
2959 PIM_DONT_DEBUG_PIM_EVENTS;
2960 PIM_DONT_DEBUG_PIM_PACKETS;
2961 PIM_DONT_DEBUG_PIM_TRACE;
2962 return CMD_SUCCESS;
2963}
2964
2965ALIAS (no_debug_pim,
2966 undebug_pim_cmd,
2967 "undebug pim",
2968 UNDEBUG_STR
2969 DEBUG_PIM_STR)
2970
2971DEFUN (debug_pim_events,
2972 debug_pim_events_cmd,
2973 "debug pim events",
2974 DEBUG_STR
2975 DEBUG_PIM_STR
2976 DEBUG_PIM_EVENTS_STR)
2977{
2978 PIM_DO_DEBUG_PIM_EVENTS;
2979 return CMD_SUCCESS;
2980}
2981
2982DEFUN (no_debug_pim_events,
2983 no_debug_pim_events_cmd,
2984 "no debug pim events",
2985 NO_STR
2986 DEBUG_STR
2987 DEBUG_PIM_STR
2988 DEBUG_PIM_EVENTS_STR)
2989{
2990 PIM_DONT_DEBUG_PIM_EVENTS;
2991 return CMD_SUCCESS;
2992}
2993
2994ALIAS (no_debug_pim_events,
2995 undebug_pim_events_cmd,
2996 "undebug pim events",
2997 UNDEBUG_STR
2998 DEBUG_PIM_STR
2999 DEBUG_PIM_EVENTS_STR)
3000
3001DEFUN (debug_pim_packets,
3002 debug_pim_packets_cmd,
3003 "debug pim packets",
3004 DEBUG_STR
3005 DEBUG_PIM_STR
3006 DEBUG_PIM_PACKETS_STR)
3007{
3008 PIM_DO_DEBUG_PIM_PACKETS;
3009 return CMD_SUCCESS;
3010}
3011
3012DEFUN (no_debug_pim_packets,
3013 no_debug_pim_packets_cmd,
3014 "no debug pim packets",
3015 NO_STR
3016 DEBUG_STR
3017 DEBUG_PIM_STR
3018 DEBUG_PIM_PACKETS_STR)
3019{
3020 PIM_DONT_DEBUG_PIM_PACKETS;
3021 return CMD_SUCCESS;
3022}
3023
3024ALIAS (no_debug_pim_packets,
3025 undebug_pim_packets_cmd,
3026 "undebug pim packets",
3027 UNDEBUG_STR
3028 DEBUG_PIM_STR
3029 DEBUG_PIM_PACKETS_STR)
3030
3031DEFUN (debug_pim_trace,
3032 debug_pim_trace_cmd,
3033 "debug pim trace",
3034 DEBUG_STR
3035 DEBUG_PIM_STR
3036 DEBUG_PIM_TRACE_STR)
3037{
3038 PIM_DO_DEBUG_PIM_TRACE;
3039 return CMD_SUCCESS;
3040}
3041
3042DEFUN (no_debug_pim_trace,
3043 no_debug_pim_trace_cmd,
3044 "no debug pim trace",
3045 NO_STR
3046 DEBUG_STR
3047 DEBUG_PIM_STR
3048 DEBUG_PIM_TRACE_STR)
3049{
3050 PIM_DONT_DEBUG_PIM_TRACE;
3051 return CMD_SUCCESS;
3052}
3053
3054ALIAS (no_debug_pim_trace,
3055 undebug_pim_trace_cmd,
3056 "undebug pim trace",
3057 UNDEBUG_STR
3058 DEBUG_PIM_STR
3059 DEBUG_PIM_TRACE_STR)
3060
3061DEFUN (debug_pim_zebra,
3062 debug_pim_zebra_cmd,
3063 "debug pim zebra",
3064 DEBUG_STR
3065 DEBUG_PIM_STR
3066 DEBUG_PIM_ZEBRA_STR)
3067{
3068 PIM_DO_DEBUG_ZEBRA;
3069 return CMD_SUCCESS;
3070}
3071
3072DEFUN (no_debug_pim_zebra,
3073 no_debug_pim_zebra_cmd,
3074 "no debug pim zebra",
3075 NO_STR
3076 DEBUG_STR
3077 DEBUG_PIM_STR
3078 DEBUG_PIM_ZEBRA_STR)
3079{
3080 PIM_DONT_DEBUG_ZEBRA;
3081 return CMD_SUCCESS;
3082}
3083
3084ALIAS (no_debug_pim_zebra,
3085 undebug_pim_zebra_cmd,
3086 "undebug pim zebra",
3087 UNDEBUG_STR
3088 DEBUG_PIM_STR
3089 DEBUG_PIM_ZEBRA_STR)
3090
3091DEFUN (show_debugging,
3092 show_debugging_cmd,
3093 "show debugging",
3094 SHOW_STR
3095 "State of each debugging option\n")
3096{
3097 pim_debug_config_write(vty);
3098 return CMD_SUCCESS;
3099}
3100
3101static struct igmp_sock *find_igmp_sock_by_fd(int fd)
3102{
3103 struct listnode *ifnode;
3104 struct interface *ifp;
3105
3106 /* scan all interfaces */
3107 for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
3108 struct pim_interface *pim_ifp;
3109 struct igmp_sock *igmp;
3110
3111 if (!ifp->info)
3112 continue;
3113
3114 pim_ifp = ifp->info;
3115
3116 /* lookup igmp socket under current interface */
3117 igmp = igmp_sock_lookup_by_fd(pim_ifp->igmp_socket_list, fd);
3118 if (igmp)
3119 return igmp;
3120 }
3121
3122 return 0;
3123}
3124
3125DEFUN (test_igmp_receive_report,
3126 test_igmp_receive_report_cmd,
3127 "test igmp receive report <0-65535> A.B.C.D <1-6> .LINE",
3128 "Test\n"
3129 "Test IGMP protocol\n"
3130 "Test IGMP message\n"
3131 "Test IGMP report\n"
3132 "Socket\n"
3133 "IGMP group address\n"
3134 "Record type\n"
3135 "Sources\n")
3136{
3137 char buf[1000];
3138 char *igmp_msg;
3139 struct ip *ip_hdr;
3140 size_t ip_hlen; /* ip header length in bytes */
3141 int ip_msg_len;
3142 int igmp_msg_len;
3143 const char *socket;
3144 int socket_fd;
3145 const char *grp_str;
3146 struct in_addr grp_addr;
3147 const char *record_type_str;
3148 int record_type;
3149 const char *src_str;
3150 int result;
3151 struct igmp_sock *igmp;
3152 char *group_record;
3153 int num_sources;
3154 struct in_addr *sources;
3155 struct in_addr *src_addr;
3156 int argi;
3157
3158 socket = argv[0];
3159 socket_fd = atoi(socket);
3160 igmp = find_igmp_sock_by_fd(socket_fd);
3161 if (!igmp) {
3162 vty_out(vty, "Could not find IGMP socket %s: fd=%d%s",
3163 socket, socket_fd, VTY_NEWLINE);
3164 return CMD_WARNING;
3165 }
3166
3167 grp_str = argv[1];
3168 result = inet_pton(AF_INET, grp_str, &grp_addr);
3169 if (result <= 0) {
3170 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3171 grp_str, errno, strerror(errno), VTY_NEWLINE);
3172 return CMD_WARNING;
3173 }
3174
3175 record_type_str = argv[2];
3176 record_type = atoi(record_type_str);
3177
3178 /*
3179 Tweak IP header
3180 */
3181 ip_hdr = (struct ip *) buf;
3182 ip_hdr->ip_p = PIM_IP_PROTO_IGMP;
3183 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
3184 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
3185 ip_hdr->ip_src = igmp->ifaddr;
3186 ip_hdr->ip_dst = igmp->ifaddr;
3187
3188 /*
3189 Build IGMP v3 report message
3190 */
3191 igmp_msg = buf + ip_hlen;
3192 group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
3193 *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */
3194 *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; /* for computing checksum */
3195 *(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */
3196 *(uint8_t *) (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type;
3197 *(struct in_addr *)(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET) = grp_addr;
3198
3199 /* Scan LINE sources */
3200 sources = (struct in_addr *) (group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET);
3201 src_addr = sources;
3202 for (argi = 3; argi < argc; ++argi,++src_addr) {
3203 src_str = argv[argi];
3204 result = inet_pton(AF_INET, src_str, src_addr);
3205 if (result <= 0) {
3206 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3207 src_str, errno, strerror(errno), VTY_NEWLINE);
3208 return CMD_WARNING;
3209 }
3210 }
3211 num_sources = src_addr - sources;
3212
3213 *(uint16_t *)(group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET) = htons(num_sources);
3214
3215 igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4); /* v3 report for one single group record */
3216
3217 /* compute checksum */
3218 *(uint16_t *)(igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = pim_inet_checksum(igmp_msg, igmp_msg_len);
3219
3220 /* "receive" message */
3221
3222 ip_msg_len = ip_hlen + igmp_msg_len;
3223 result = pim_igmp_packet(igmp, buf, ip_msg_len);
3224 if (result) {
3225 vty_out(vty, "pim_igmp_packet(len=%d) returned: %d%s",
3226 ip_msg_len, result, VTY_NEWLINE);
3227 return CMD_WARNING;
3228 }
3229
3230 return CMD_SUCCESS;
3231}
3232
3233DEFUN (test_pim_receive_hello,
3234 test_pim_receive_hello_cmd,
3235 "test pim receive hello INTERFACE A.B.C.D <0-65535> <0-65535> <0-65535> <0-32767> <0-65535> <0-1>[LINE]",
3236 "Test\n"
3237 "Test PIM protocol\n"
3238 "Test PIM message reception\n"
3239 "Test PIM hello reception from neighbor\n"
3240 "Interface\n"
3241 "Neighbor address\n"
3242 "Neighbor holdtime\n"
3243 "Neighbor DR priority\n"
3244 "Neighbor generation ID\n"
3245 "Neighbor propagation delay (msec)\n"
3246 "Neighbor override interval (msec)\n"
3247 "Neighbor LAN prune delay T-bit\n"
3248 "Neighbor secondary addresses\n")
3249{
3250 char buf[1000];
3251 char *pim_msg;
3252 struct ip *ip_hdr;
3253 size_t ip_hlen; /* ip header length in bytes */
3254 int ip_msg_len;
3255 int pim_tlv_size;
3256 int pim_msg_size;
3257 const char *neigh_str;
3258 struct in_addr neigh_addr;
3259 const char *ifname;
3260 struct interface *ifp;
3261 uint16_t neigh_holdtime;
3262 uint16_t neigh_propagation_delay;
3263 uint16_t neigh_override_interval;
3264 int neigh_can_disable_join_suppression;
3265 uint32_t neigh_dr_priority;
3266 uint32_t neigh_generation_id;
3267 int argi;
3268 int result;
3269
3270 /* Find interface */
3271 ifname = argv[0];
3272 ifp = if_lookup_by_name(ifname);
3273 if (!ifp) {
3274 vty_out(vty, "No such interface name %s%s",
3275 ifname, VTY_NEWLINE);
3276 return CMD_WARNING;
3277 }
3278
3279 /* Neighbor address */
3280 neigh_str = argv[1];
3281 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
3282 if (result <= 0) {
3283 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
3284 neigh_str, errno, strerror(errno), VTY_NEWLINE);
3285 return CMD_WARNING;
3286 }
3287
3288 neigh_holdtime = atoi(argv[2]);
3289 neigh_dr_priority = atoi(argv[3]);
3290 neigh_generation_id = atoi(argv[4]);
3291 neigh_propagation_delay = atoi(argv[5]);
3292 neigh_override_interval = atoi(argv[6]);
3293 neigh_can_disable_join_suppression = atoi(argv[7]);
3294
3295 /*
3296 Tweak IP header
3297 */
3298 ip_hdr = (struct ip *) buf;
3299 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
3300 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
3301 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
3302 ip_hdr->ip_src = neigh_addr;
3303 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
3304
3305 /*
3306 Build PIM hello message
3307 */
3308 pim_msg = buf + ip_hlen;
3309
3310 /* Scan LINE addresses */
3311 for (argi = 8; argi < argc; ++argi) {
3312 const char *sec_str = argv[argi];
3313 struct in_addr sec_addr;
3314 result = inet_pton(AF_INET, sec_str, &sec_addr);
3315 if (result <= 0) {
3316 vty_out(vty, "Bad neighbor secondary address %s: errno=%d: %s%s",
3317 sec_str, errno, strerror(errno), VTY_NEWLINE);
3318 return CMD_WARNING;
3319 }
3320
3321 vty_out(vty,
3322 "FIXME WRITEME consider neighbor secondary address %s%s",
3323 sec_str, VTY_NEWLINE);
3324 }
3325
3326 pim_tlv_size = pim_hello_build_tlv(ifp->name,
3327 pim_msg + PIM_PIM_MIN_LEN,
3328 sizeof(buf) - ip_hlen - PIM_PIM_MIN_LEN,
3329 neigh_holdtime,
3330 neigh_dr_priority,
3331 neigh_generation_id,
3332 neigh_propagation_delay,
3333 neigh_override_interval,
3334 neigh_can_disable_join_suppression,
3335 0 /* FIXME secondary address list */);
3336 if (pim_tlv_size < 0) {
3337 vty_out(vty, "pim_hello_build_tlv() returned failure: %d%s",
3338 pim_tlv_size, VTY_NEWLINE);
3339 return CMD_WARNING;
3340 }
3341
3342 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
3343
3344 pim_msg_build_header(pim_msg, pim_msg_size,
3345 PIM_MSG_TYPE_HELLO);
3346
3347 /* "receive" message */
3348
3349 ip_msg_len = ip_hlen + pim_msg_size;
3350 result = pim_pim_packet(ifp, buf, ip_msg_len);
3351 if (result) {
3352 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
3353 ip_msg_len, result, VTY_NEWLINE);
3354 return CMD_WARNING;
3355 }
3356
3357 return CMD_SUCCESS;
3358}
3359
3360DEFUN (test_pim_receive_assert,
3361 test_pim_receive_assert_cmd,
3362 "test pim receive assert INTERFACE A.B.C.D A.B.C.D A.B.C.D <0-65535> <0-65535> <0-1>",
3363 "Test\n"
3364 "Test PIM protocol\n"
3365 "Test PIM message reception\n"
3366 "Test reception of PIM assert\n"
3367 "Interface\n"
3368 "Neighbor address\n"
3369 "Assert multicast group address\n"
3370 "Assert unicast source address\n"
3371 "Assert metric preference\n"
3372 "Assert route metric\n"
3373 "Assert RPT bit flag\n")
3374{
3375 char buf[1000];
3376 char *buf_pastend = buf + sizeof(buf);
3377 char *pim_msg;
3378 struct ip *ip_hdr;
3379 size_t ip_hlen; /* ip header length in bytes */
3380 int ip_msg_len;
3381 int pim_msg_size;
3382 const char *neigh_str;
3383 struct in_addr neigh_addr;
3384 const char *group_str;
3385 struct in_addr group_addr;
3386 const char *source_str;
3387 struct in_addr source_addr;
3388 const char *ifname;
3389 struct interface *ifp;
3390 uint32_t assert_metric_preference;
3391 uint32_t assert_route_metric;
3392 uint32_t assert_rpt_bit_flag;
3393 int remain;
3394 int result;
3395
3396 /* Find interface */
3397 ifname = argv[0];
3398 ifp = if_lookup_by_name(ifname);
3399 if (!ifp) {
3400 vty_out(vty, "No such interface name %s%s",
3401 ifname, VTY_NEWLINE);
3402 return CMD_WARNING;
3403 }
3404
3405 /* Neighbor address */
3406 neigh_str = argv[1];
3407 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
3408 if (result <= 0) {
3409 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
3410 neigh_str, errno, strerror(errno), VTY_NEWLINE);
3411 return CMD_WARNING;
3412 }
3413
3414 /* Group address */
3415 group_str = argv[2];
3416 result = inet_pton(AF_INET, group_str, &group_addr);
3417 if (result <= 0) {
3418 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3419 group_str, errno, strerror(errno), VTY_NEWLINE);
3420 return CMD_WARNING;
3421 }
3422
3423 /* Source address */
3424 source_str = argv[3];
3425 result = inet_pton(AF_INET, source_str, &source_addr);
3426 if (result <= 0) {
3427 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3428 source_str, errno, strerror(errno), VTY_NEWLINE);
3429 return CMD_WARNING;
3430 }
3431
3432 assert_metric_preference = atoi(argv[4]);
3433 assert_route_metric = atoi(argv[5]);
3434 assert_rpt_bit_flag = atoi(argv[6]);
3435
3436 remain = buf_pastend - buf;
3437 if (remain < (int) sizeof(struct ip)) {
3438 vty_out(vty, "No room for ip header: buf_size=%d < ip_header_size=%d%s",
3439 remain, sizeof(struct ip), VTY_NEWLINE);
3440 return CMD_WARNING;
3441 }
3442
3443 /*
3444 Tweak IP header
3445 */
3446 ip_hdr = (struct ip *) buf;
3447 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
3448 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
3449 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
3450 ip_hdr->ip_src = neigh_addr;
3451 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
3452
3453 /*
3454 Build PIM assert message
3455 */
3456 pim_msg = buf + ip_hlen; /* skip ip header */
3457
3458 pim_msg_size = pim_assert_build_msg(pim_msg, buf_pastend - pim_msg, ifp,
3459 group_addr, source_addr,
3460 assert_metric_preference,
3461 assert_route_metric,
3462 assert_rpt_bit_flag);
3463 if (pim_msg_size < 0) {
3464 vty_out(vty, "Failure building PIM assert message: size=%d%s",
3465 pim_msg_size, VTY_NEWLINE);
3466 return CMD_WARNING;
3467 }
3468
3469 /* "receive" message */
3470
3471 ip_msg_len = ip_hlen + pim_msg_size;
3472 result = pim_pim_packet(ifp, buf, ip_msg_len);
3473 if (result) {
3474 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
3475 ip_msg_len, result, VTY_NEWLINE);
3476 return CMD_WARNING;
3477 }
3478
3479 return CMD_SUCCESS;
3480}
3481
3482static int recv_joinprune(struct vty *vty,
3483 const char *argv[],
3484 int src_is_join)
3485{
3486 char buf[1000];
3487 const char *buf_pastend = buf + sizeof(buf);
3488 char *pim_msg;
3489 char *pim_msg_curr;
3490 int pim_msg_size;
3491 struct ip *ip_hdr;
3492 size_t ip_hlen; /* ip header length in bytes */
3493 int ip_msg_len;
3494 uint16_t neigh_holdtime;
3495 const char *neigh_dst_str;
3496 struct in_addr neigh_dst_addr;
3497 const char *neigh_src_str;
3498 struct in_addr neigh_src_addr;
3499 const char *group_str;
3500 struct in_addr group_addr;
3501 const char *source_str;
3502 struct in_addr source_addr;
3503 const char *ifname;
3504 struct interface *ifp;
3505 int result;
3506 int remain;
3507 uint16_t num_joined;
3508 uint16_t num_pruned;
3509
3510 /* Find interface */
3511 ifname = argv[0];
3512 ifp = if_lookup_by_name(ifname);
3513 if (!ifp) {
3514 vty_out(vty, "No such interface name %s%s",
3515 ifname, VTY_NEWLINE);
3516 return CMD_WARNING;
3517 }
3518
3519 neigh_holdtime = atoi(argv[1]);
3520
3521 /* Neighbor destination address */
3522 neigh_dst_str = argv[2];
3523 result = inet_pton(AF_INET, neigh_dst_str, &neigh_dst_addr);
3524 if (result <= 0) {
3525 vty_out(vty, "Bad neighbor destination address %s: errno=%d: %s%s",
3526 neigh_dst_str, errno, strerror(errno), VTY_NEWLINE);
3527 return CMD_WARNING;
3528 }
3529
3530 /* Neighbor source address */
3531 neigh_src_str = argv[3];
3532 result = inet_pton(AF_INET, neigh_src_str, &neigh_src_addr);
3533 if (result <= 0) {
3534 vty_out(vty, "Bad neighbor source address %s: errno=%d: %s%s",
3535 neigh_src_str, errno, strerror(errno), VTY_NEWLINE);
3536 return CMD_WARNING;
3537 }
3538
3539 /* Multicast group address */
3540 group_str = argv[4];
3541 result = inet_pton(AF_INET, group_str, &group_addr);
3542 if (result <= 0) {
3543 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3544 group_str, errno, strerror(errno), VTY_NEWLINE);
3545 return CMD_WARNING;
3546 }
3547
3548 /* Multicast source address */
3549 source_str = argv[5];
3550 result = inet_pton(AF_INET, source_str, &source_addr);
3551 if (result <= 0) {
3552 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3553 source_str, errno, strerror(errno), VTY_NEWLINE);
3554 return CMD_WARNING;
3555 }
3556
3557 /*
3558 Tweak IP header
3559 */
3560 ip_hdr = (struct ip *) buf;
3561 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
3562 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
3563 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
3564 ip_hdr->ip_src = neigh_src_addr;
3565 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
3566
3567 /*
3568 Build PIM message
3569 */
3570 pim_msg = buf + ip_hlen;
3571
3572 /* skip room for pim header */
3573 pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN;
3574
3575 remain = buf_pastend - pim_msg_curr;
3576 pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr,
3577 remain,
3578 neigh_dst_addr);
3579 if (!pim_msg_curr) {
3580 vty_out(vty, "Failure encoding destination address %s: space left=%d%s",
3581 neigh_dst_str, remain, VTY_NEWLINE);
3582 return CMD_WARNING;
3583 }
3584
3585 remain = buf_pastend - pim_msg_curr;
3586 if (remain < 4) {
3587 vty_out(vty, "Group will not fit: space left=%d%s",
3588 remain, VTY_NEWLINE);
3589 return CMD_WARNING;
3590 }
3591
3592 *pim_msg_curr = 0; /* reserved */
3593 ++pim_msg_curr;
3594 *pim_msg_curr = 1; /* number of groups */
3595 ++pim_msg_curr;
3596 *((uint16_t *) pim_msg_curr) = htons(neigh_holdtime);
3597 ++pim_msg_curr;
3598 ++pim_msg_curr;
3599
3600 remain = buf_pastend - pim_msg_curr;
3601 pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr,
3602 remain,
3603 group_addr);
3604 if (!pim_msg_curr) {
3605 vty_out(vty, "Failure encoding group address %s: space left=%d%s",
3606 group_str, remain, VTY_NEWLINE);
3607 return CMD_WARNING;
3608 }
3609
3610 remain = buf_pastend - pim_msg_curr;
3611 if (remain < 4) {
3612 vty_out(vty, "Sources will not fit: space left=%d%s",
3613 remain, VTY_NEWLINE);
3614 return CMD_WARNING;
3615 }
3616
3617 if (src_is_join) {
3618 num_joined = 1;
3619 num_pruned = 0;
3620 }
3621 else {
3622 num_joined = 0;
3623 num_pruned = 1;
3624 }
3625
3626 /* number of joined sources */
3627 *((uint16_t *) pim_msg_curr) = htons(num_joined);
3628 ++pim_msg_curr;
3629 ++pim_msg_curr;
3630
3631 /* number of pruned sources */
3632 *((uint16_t *) pim_msg_curr) = htons(num_pruned);
3633 ++pim_msg_curr;
3634 ++pim_msg_curr;
3635
3636 remain = buf_pastend - pim_msg_curr;
3637 pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr,
3638 remain,
3639 source_addr);
3640 if (!pim_msg_curr) {
3641 vty_out(vty, "Failure encoding source address %s: space left=%d%s",
3642 source_str, remain, VTY_NEWLINE);
3643 return CMD_WARNING;
3644 }
3645
3646 /* Add PIM header */
3647
3648 pim_msg_size = pim_msg_curr - pim_msg;
3649
3650 pim_msg_build_header(pim_msg, pim_msg_size,
3651 PIM_MSG_TYPE_JOIN_PRUNE);
3652
3653 /*
3654 "Receive" message
3655 */
3656
3657 ip_msg_len = ip_hlen + pim_msg_size;
3658 result = pim_pim_packet(ifp, buf, ip_msg_len);
3659 if (result) {
3660 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
3661 ip_msg_len, result, VTY_NEWLINE);
3662 return CMD_WARNING;
3663 }
3664
3665 return CMD_SUCCESS;
3666}
3667
3668DEFUN (test_pim_receive_join,
3669 test_pim_receive_join_cmd,
3670 "test pim receive join INTERFACE <0-65535> A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
3671 "Test\n"
3672 "Test PIM protocol\n"
3673 "Test PIM message reception\n"
3674 "Test PIM join reception from neighbor\n"
3675 "Interface\n"
3676 "Neighbor holdtime\n"
3677 "Upstream neighbor unicast destination address\n"
3678 "Downstream neighbor unicast source address\n"
3679 "Multicast group address\n"
3680 "Unicast source address\n")
3681{
3682 return recv_joinprune(vty, argv, 1 /* src_is_join=true */);
3683}
3684
3685DEFUN (test_pim_receive_prune,
3686 test_pim_receive_prune_cmd,
3687 "test pim receive prune INTERFACE <0-65535> A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
3688 "Test\n"
3689 "Test PIM protocol\n"
3690 "Test PIM message reception\n"
3691 "Test PIM prune reception from neighbor\n"
3692 "Interface\n"
3693 "Neighbor holdtime\n"
3694 "Upstream neighbor unicast destination address\n"
3695 "Downstream neighbor unicast source address\n"
3696 "Multicast group address\n"
3697 "Unicast source address\n")
3698{
3699 return recv_joinprune(vty, argv, 0 /* src_is_join=false */);
3700}
3701
3702DEFUN (test_pim_receive_upcall,
3703 test_pim_receive_upcall_cmd,
3704 "test pim receive upcall (nocache|wrongvif|wholepkt) <0-65535> A.B.C.D A.B.C.D",
3705 "Test\n"
3706 "Test PIM protocol\n"
3707 "Test PIM message reception\n"
3708 "Test reception of kernel upcall\n"
3709 "NOCACHE kernel upcall\n"
3710 "WRONGVIF kernel upcall\n"
3711 "WHOLEPKT kernel upcall\n"
3712 "Input interface vif index\n"
3713 "Multicast group address\n"
3714 "Multicast source address\n")
3715{
3716 struct igmpmsg msg;
3717 const char *upcall_type;
3718 const char *group_str;
3719 const char *source_str;
3720 int result;
3721
3722 upcall_type = argv[0];
3723
3724 if (upcall_type[0] == 'n')
3725 msg.im_msgtype = IGMPMSG_NOCACHE;
3726 else if (upcall_type[1] == 'r')
3727 msg.im_msgtype = IGMPMSG_WRONGVIF;
3728 else if (upcall_type[1] == 'h')
3729 msg.im_msgtype = IGMPMSG_WHOLEPKT;
3730 else {
3731 vty_out(vty, "Unknown kernel upcall type: %s%s",
3732 upcall_type, VTY_NEWLINE);
3733 return CMD_WARNING;
3734 }
3735
3736 msg.im_vif = atoi(argv[1]);
3737
3738 /* Group address */
3739 group_str = argv[2];
3740 result = inet_pton(AF_INET, group_str, &msg.im_dst);
3741 if (result <= 0) {
3742 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3743 group_str, errno, strerror(errno), VTY_NEWLINE);
3744 return CMD_WARNING;
3745 }
3746
3747 /* Source address */
3748 source_str = argv[3];
3749 result = inet_pton(AF_INET, source_str, &msg.im_src);
3750 if (result <= 0) {
3751 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3752 source_str, errno, strerror(errno), VTY_NEWLINE);
3753 return CMD_WARNING;
3754 }
3755
3756 msg.im_mbz = 0; /* Must be zero */
3757
3758 result = pim_mroute_msg(-1, (char *) &msg, sizeof(msg));
3759 if (result) {
3760 vty_out(vty, "pim_mroute_msg(len=%d) returned failure: %d%s",
3761 sizeof(msg), result, VTY_NEWLINE);
3762 return CMD_WARNING;
3763 }
3764
3765 return CMD_SUCCESS;
3766}
3767
3768void pim_cmd_init()
3769{
3770 install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */
3771 install_node(&pim_interface_node, pim_interface_config_write); /* INTERFACE_NODE */
3772
3773 install_element(CONFIG_NODE, &ip_multicast_routing_cmd);
3774 install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd);
3775#if 0
3776 install_element(CONFIG_NODE, &interface_cmd); /* from if.h */
3777#else
3778 install_element(CONFIG_NODE, &pim_interface_cmd);
3779#endif
3780 install_element(CONFIG_NODE, &no_interface_cmd); /* from if.h */
3781
3782 install_default(INTERFACE_NODE);
3783 install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
3784 install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
3785 install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd);
3786 install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
3787 install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
3788 install_element(INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd);
3789 install_element(INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd);
3790 install_element(INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd);
3791 install_element(INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd);
3792 install_element(INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
3793 install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
3794 install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
3795
3796 install_element(VIEW_NODE, &show_ip_igmp_interface_cmd);
3797 install_element(VIEW_NODE, &show_ip_igmp_parameters_cmd);
3798 install_element(VIEW_NODE, &show_ip_igmp_groups_cmd);
3799 install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
3800 install_element(VIEW_NODE, &show_ip_igmp_sources_cmd);
3801 install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
3802 install_element(VIEW_NODE, &show_ip_igmp_querier_cmd);
3803 install_element(VIEW_NODE, &show_ip_pim_assert_cmd);
3804 install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd);
3805 install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd);
3806 install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
3807 install_element(VIEW_NODE, &show_ip_pim_dr_cmd);
3808 install_element(VIEW_NODE, &show_ip_pim_hello_cmd);
3809 install_element(VIEW_NODE, &show_ip_pim_interface_cmd);
3810 install_element(VIEW_NODE, &show_ip_pim_join_cmd);
3811 install_element(VIEW_NODE, &show_ip_pim_jp_override_interval_cmd);
3812 install_element(VIEW_NODE, &show_ip_pim_lan_prune_delay_cmd);
3813 install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
3814 install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
3815 install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
3816 install_element(VIEW_NODE, &show_ip_pim_secondary_cmd);
3817 install_element(VIEW_NODE, &show_ip_pim_upstream_cmd);
3818 install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
3819 install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
3820 install_element(VIEW_NODE, &show_ip_multicast_cmd);
3821 install_element(VIEW_NODE, &show_ip_mroute_cmd);
3822 install_element(VIEW_NODE, &show_ip_mroute_count_cmd);
3823 install_element(VIEW_NODE, &show_ip_route_cmd);
3824 install_element(VIEW_NODE, &show_debugging_cmd);
3825
3826 install_element(ENABLE_NODE, &clear_ip_interfaces_cmd);
3827 install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
3828 install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
3829
3830 install_element(ENABLE_NODE, &show_ip_igmp_interface_cmd);
3831 install_element(ENABLE_NODE, &show_ip_igmp_parameters_cmd);
3832 install_element(ENABLE_NODE, &show_ip_igmp_groups_cmd);
3833 install_element(ENABLE_NODE, &show_ip_igmp_groups_retransmissions_cmd);
3834 install_element(ENABLE_NODE, &show_ip_igmp_sources_cmd);
3835 install_element(ENABLE_NODE, &show_ip_igmp_sources_retransmissions_cmd);
3836 install_element(ENABLE_NODE, &show_ip_igmp_querier_cmd);
3837 install_element(ENABLE_NODE, &show_ip_pim_address_cmd);
3838 install_element(ENABLE_NODE, &show_ip_pim_assert_cmd);
3839 install_element(ENABLE_NODE, &show_ip_pim_assert_internal_cmd);
3840 install_element(ENABLE_NODE, &show_ip_pim_assert_metric_cmd);
3841 install_element(ENABLE_NODE, &show_ip_pim_assert_winner_metric_cmd);
3842 install_element(ENABLE_NODE, &show_ip_pim_dr_cmd);
3843 install_element(ENABLE_NODE, &show_ip_pim_hello_cmd);
3844 install_element(ENABLE_NODE, &show_ip_pim_interface_cmd);
3845 install_element(ENABLE_NODE, &show_ip_pim_join_cmd);
3846 install_element(ENABLE_NODE, &show_ip_pim_jp_override_interval_cmd);
3847 install_element(ENABLE_NODE, &show_ip_pim_lan_prune_delay_cmd);
3848 install_element(ENABLE_NODE, &show_ip_pim_local_membership_cmd);
3849 install_element(ENABLE_NODE, &show_ip_pim_neighbor_cmd);
3850 install_element(ENABLE_NODE, &show_ip_pim_rpf_cmd);
3851 install_element(ENABLE_NODE, &show_ip_pim_secondary_cmd);
3852 install_element(ENABLE_NODE, &show_ip_pim_upstream_cmd);
3853 install_element(ENABLE_NODE, &show_ip_pim_upstream_join_desired_cmd);
3854 install_element(ENABLE_NODE, &show_ip_pim_upstream_rpf_cmd);
3855 install_element(ENABLE_NODE, &show_ip_multicast_cmd);
3856 install_element(ENABLE_NODE, &show_ip_mroute_cmd);
3857 install_element(ENABLE_NODE, &show_ip_mroute_count_cmd);
3858 install_element(ENABLE_NODE, &show_ip_route_cmd);
3859 install_element(ENABLE_NODE, &show_debugging_cmd);
3860
3861 install_element(ENABLE_NODE, &test_igmp_receive_report_cmd);
3862 install_element(ENABLE_NODE, &test_pim_receive_assert_cmd);
3863 install_element(ENABLE_NODE, &test_pim_receive_hello_cmd);
3864 install_element(ENABLE_NODE, &test_pim_receive_join_cmd);
3865 install_element(ENABLE_NODE, &test_pim_receive_prune_cmd);
3866 install_element(ENABLE_NODE, &test_pim_receive_upcall_cmd);
3867
3868 install_element(ENABLE_NODE, &debug_igmp_cmd);
3869 install_element(ENABLE_NODE, &no_debug_igmp_cmd);
3870 install_element(ENABLE_NODE, &undebug_igmp_cmd);
3871 install_element(ENABLE_NODE, &debug_igmp_events_cmd);
3872 install_element(ENABLE_NODE, &no_debug_igmp_events_cmd);
3873 install_element(ENABLE_NODE, &undebug_igmp_events_cmd);
3874 install_element(ENABLE_NODE, &debug_igmp_packets_cmd);
3875 install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd);
3876 install_element(ENABLE_NODE, &undebug_igmp_packets_cmd);
3877 install_element(ENABLE_NODE, &debug_igmp_trace_cmd);
3878 install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd);
3879 install_element(ENABLE_NODE, &undebug_igmp_trace_cmd);
3880 install_element(ENABLE_NODE, &debug_pim_cmd);
3881 install_element(ENABLE_NODE, &no_debug_pim_cmd);
3882 install_element(ENABLE_NODE, &undebug_pim_cmd);
3883 install_element(ENABLE_NODE, &debug_pim_events_cmd);
3884 install_element(ENABLE_NODE, &no_debug_pim_events_cmd);
3885 install_element(ENABLE_NODE, &undebug_pim_events_cmd);
3886 install_element(ENABLE_NODE, &debug_pim_packets_cmd);
3887 install_element(ENABLE_NODE, &no_debug_pim_packets_cmd);
3888 install_element(ENABLE_NODE, &undebug_pim_packets_cmd);
3889 install_element(ENABLE_NODE, &debug_pim_trace_cmd);
3890 install_element(ENABLE_NODE, &no_debug_pim_trace_cmd);
3891 install_element(ENABLE_NODE, &undebug_pim_trace_cmd);
3892 install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
3893 install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
3894 install_element(ENABLE_NODE, &undebug_pim_zebra_cmd);
3895
3896 install_element(CONFIG_NODE, &debug_igmp_cmd);
3897 install_element(CONFIG_NODE, &no_debug_igmp_cmd);
3898 install_element(CONFIG_NODE, &undebug_igmp_cmd);
3899 install_element(CONFIG_NODE, &debug_igmp_events_cmd);
3900 install_element(CONFIG_NODE, &no_debug_igmp_events_cmd);
3901 install_element(CONFIG_NODE, &undebug_igmp_events_cmd);
3902 install_element(CONFIG_NODE, &debug_igmp_packets_cmd);
3903 install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd);
3904 install_element(CONFIG_NODE, &undebug_igmp_packets_cmd);
3905 install_element(CONFIG_NODE, &debug_igmp_trace_cmd);
3906 install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd);
3907 install_element(CONFIG_NODE, &undebug_igmp_trace_cmd);
3908 install_element(CONFIG_NODE, &debug_pim_cmd);
3909 install_element(CONFIG_NODE, &no_debug_pim_cmd);
3910 install_element(CONFIG_NODE, &undebug_pim_cmd);
3911 install_element(CONFIG_NODE, &debug_pim_events_cmd);
3912 install_element(CONFIG_NODE, &no_debug_pim_events_cmd);
3913 install_element(CONFIG_NODE, &undebug_pim_events_cmd);
3914 install_element(CONFIG_NODE, &debug_pim_packets_cmd);
3915 install_element(CONFIG_NODE, &no_debug_pim_packets_cmd);
3916 install_element(CONFIG_NODE, &undebug_pim_packets_cmd);
3917 install_element(CONFIG_NODE, &debug_pim_trace_cmd);
3918 install_element(CONFIG_NODE, &no_debug_pim_trace_cmd);
3919 install_element(CONFIG_NODE, &undebug_pim_trace_cmd);
3920 install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
3921 install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
3922 install_element(CONFIG_NODE, &undebug_pim_zebra_cmd);
3923}