]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_cmd.c
pimd: Allow keep alive timer configuration
[mirror_frr.git] / pimd / pim_cmd.c
1 /*
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 */
21
22 #include <zebra.h>
23
24 #include "command.h"
25 #include "if.h"
26 #include "prefix.h"
27 #include "zclient.h"
28
29 #include "pimd.h"
30 #include "pim_mroute.h"
31 #include "pim_cmd.h"
32 #include "pim_iface.h"
33 #include "pim_vty.h"
34 #include "pim_mroute.h"
35 #include "pim_str.h"
36 #include "pim_igmp.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 #include "pim_ssmpingd.h"
51 #include "pim_zebra.h"
52 #include "pim_static.h"
53 #include "pim_rp.h"
54 #include "pim_zlookup.h"
55
56 static struct cmd_node pim_global_node = {
57 PIM_NODE,
58 "",
59 1 /* vtysh ? yes */
60 };
61
62 static struct cmd_node interface_node = {
63 INTERFACE_NODE,
64 "%s(config-if)# ",
65 1 /* vtysh ? yes */
66 };
67
68 static void pim_if_membership_clear(struct interface *ifp)
69 {
70 struct pim_interface *pim_ifp;
71
72 pim_ifp = ifp->info;
73 zassert(pim_ifp);
74
75 if (PIM_IF_TEST_PIM(pim_ifp->options) &&
76 PIM_IF_TEST_IGMP(pim_ifp->options)) {
77 return;
78 }
79
80 pim_ifchannel_membership_clear(ifp);
81 }
82
83 /*
84 When PIM is disabled on interface, IGMPv3 local membership
85 information is not injected into PIM interface state.
86
87 The function pim_if_membership_refresh() fetches all IGMPv3 local
88 membership information into PIM. It is intented to be called
89 whenever PIM is enabled on the interface in order to collect missed
90 local membership information.
91 */
92 static void pim_if_membership_refresh(struct interface *ifp)
93 {
94 struct pim_interface *pim_ifp;
95 struct listnode *sock_node;
96 struct igmp_sock *igmp;
97
98 pim_ifp = ifp->info;
99 zassert(pim_ifp);
100
101 if (!PIM_IF_TEST_PIM(pim_ifp->options))
102 return;
103 if (!PIM_IF_TEST_IGMP(pim_ifp->options))
104 return;
105
106 /*
107 First clear off membership from all PIM (S,G) entries on the
108 interface
109 */
110
111 pim_ifchannel_membership_clear(ifp);
112
113 /*
114 Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
115 the interface
116 */
117
118 /* scan igmp sockets */
119 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
120 struct listnode *grpnode;
121 struct igmp_group *grp;
122
123 /* scan igmp groups */
124 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
125 struct listnode *srcnode;
126 struct igmp_source *src;
127
128 /* scan group sources */
129 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
130
131 if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
132 struct prefix_sg sg;
133
134 memset (&sg, 0, sizeof (struct prefix_sg));
135 sg.src = src->source_addr;
136 sg.grp = grp->group_addr;
137 pim_ifchannel_local_membership_add(ifp, &sg);
138 }
139
140 } /* scan group sources */
141 } /* scan igmp groups */
142 } /* scan igmp sockets */
143
144 /*
145 Finally delete every PIM (S,G) entry lacking all state info
146 */
147
148 pim_ifchannel_delete_on_noinfo(ifp);
149
150 }
151
152 static void pim_show_assert(struct vty *vty)
153 {
154 struct listnode *ifnode;
155 struct interface *ifp;
156 time_t now;
157
158 now = pim_time_monotonic_sec();
159
160 vty_out(vty,
161 "Interface Address Source Group State Winner Uptime Timer%s",
162 VTY_NEWLINE);
163
164 for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
165 struct pim_interface *pim_ifp;
166 struct in_addr ifaddr;
167 struct listnode *ch_node;
168 struct pim_ifchannel *ch;
169
170 pim_ifp = ifp->info;
171
172 if (!pim_ifp)
173 continue;
174
175 ifaddr = pim_ifp->primary_address;
176
177 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
178 char ch_src_str[100];
179 char ch_grp_str[100];
180 char winner_str[100];
181 char uptime[10];
182 char timer[10];
183
184 pim_inet4_dump("<ch_src?>", ch->sg.src,
185 ch_src_str, sizeof(ch_src_str));
186 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
187 ch_grp_str, sizeof(ch_grp_str));
188 pim_inet4_dump("<assrt_win?>", ch->ifassert_winner,
189 winner_str, sizeof(winner_str));
190
191 pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
192 pim_time_timer_to_mmss(timer, sizeof(timer),
193 ch->t_ifassert_timer);
194
195 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s",
196 ifp->name,
197 inet_ntoa(ifaddr),
198 ch_src_str,
199 ch_grp_str,
200 pim_ifchannel_ifassert_name(ch->ifassert_state),
201 winner_str,
202 uptime,
203 timer,
204 VTY_NEWLINE);
205 } /* scan interface channels */
206 } /* scan interfaces */
207 }
208
209 static void pim_show_assert_internal(struct vty *vty)
210 {
211 struct listnode *ifnode;
212 struct interface *ifp;
213
214 vty_out(vty,
215 "CA: CouldAssert%s"
216 "ECA: Evaluate CouldAssert%s"
217 "ATD: AssertTrackingDesired%s"
218 "eATD: Evaluate AssertTrackingDesired%s%s",
219 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
220
221 vty_out(vty,
222 "Interface Address Source Group CA eCA ATD eATD%s",
223 VTY_NEWLINE);
224
225 for (ALL_LIST_ELEMENTS_RO(vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
226 struct pim_interface *pim_ifp;
227 struct in_addr ifaddr;
228 struct listnode *ch_node;
229 struct pim_ifchannel *ch;
230
231 pim_ifp = ifp->info;
232
233 if (!pim_ifp)
234 continue;
235
236 ifaddr = pim_ifp->primary_address;
237
238 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
239 char ch_src_str[100];
240 char ch_grp_str[100];
241
242 pim_inet4_dump("<ch_src?>", ch->sg.src,
243 ch_src_str, sizeof(ch_src_str));
244 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
245 ch_grp_str, sizeof(ch_grp_str));
246 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s",
247 ifp->name,
248 inet_ntoa(ifaddr),
249 ch_src_str,
250 ch_grp_str,
251 PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
252 pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
253 PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no",
254 pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no",
255 VTY_NEWLINE);
256 } /* scan interface channels */
257 } /* scan interfaces */
258 }
259
260 static void pim_show_assert_metric(struct vty *vty)
261 {
262 struct listnode *ifnode;
263 struct interface *ifp;
264
265 vty_out(vty,
266 "Interface Address Source Group RPT Pref Metric Address %s",
267 VTY_NEWLINE);
268
269 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
270 struct pim_interface *pim_ifp;
271 struct in_addr ifaddr;
272 struct listnode *ch_node;
273 struct pim_ifchannel *ch;
274
275 pim_ifp = ifp->info;
276
277 if (!pim_ifp)
278 continue;
279
280 ifaddr = pim_ifp->primary_address;
281
282 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
283 char ch_src_str[100];
284 char ch_grp_str[100];
285 char addr_str[100];
286 struct pim_assert_metric am;
287
288 am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address);
289
290 pim_inet4_dump("<ch_src?>", ch->sg.src,
291 ch_src_str, sizeof(ch_src_str));
292 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
293 ch_grp_str, sizeof(ch_grp_str));
294 pim_inet4_dump("<addr?>", am.ip_address,
295 addr_str, sizeof(addr_str));
296
297 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s",
298 ifp->name,
299 inet_ntoa(ifaddr),
300 ch_src_str,
301 ch_grp_str,
302 am.rpt_bit_flag ? "yes" : "no",
303 am.metric_preference,
304 am.route_metric,
305 addr_str,
306 VTY_NEWLINE);
307 } /* scan interface channels */
308 } /* scan interfaces */
309 }
310
311 static void pim_show_assert_winner_metric(struct vty *vty)
312 {
313 struct listnode *ifnode;
314 struct interface *ifp;
315
316 vty_out(vty,
317 "Interface Address Source Group RPT Pref Metric Address %s",
318 VTY_NEWLINE);
319
320 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
321 struct pim_interface *pim_ifp;
322 struct in_addr ifaddr;
323 struct listnode *ch_node;
324 struct pim_ifchannel *ch;
325
326 pim_ifp = ifp->info;
327
328 if (!pim_ifp)
329 continue;
330
331 ifaddr = pim_ifp->primary_address;
332
333 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
334 char ch_src_str[100];
335 char ch_grp_str[100];
336 char addr_str[100];
337 struct pim_assert_metric *am;
338 char pref_str[5];
339 char metr_str[7];
340
341 am = &ch->ifassert_winner_metric;
342
343 pim_inet4_dump("<ch_src?>", ch->sg.src,
344 ch_src_str, sizeof(ch_src_str));
345 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
346 ch_grp_str, sizeof(ch_grp_str));
347 pim_inet4_dump("<addr?>", am->ip_address,
348 addr_str, sizeof(addr_str));
349
350 if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
351 snprintf(pref_str, sizeof(pref_str), "INFI");
352 else
353 snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference);
354
355 if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
356 snprintf(metr_str, sizeof(metr_str), "INFI");
357 else
358 snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
359
360 vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s",
361 ifp->name,
362 inet_ntoa(ifaddr),
363 ch_src_str,
364 ch_grp_str,
365 am->rpt_bit_flag ? "yes" : "no",
366 pref_str,
367 metr_str,
368 addr_str,
369 VTY_NEWLINE);
370 } /* scan interface channels */
371 } /* scan interfaces */
372 }
373
374 static void pim_show_membership(struct vty *vty)
375 {
376 struct listnode *ifnode;
377 struct interface *ifp;
378
379 vty_out(vty,
380 "Interface Address Source Group Membership%s",
381 VTY_NEWLINE);
382
383 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
384 struct pim_interface *pim_ifp;
385 struct in_addr ifaddr;
386 struct listnode *ch_node;
387 struct pim_ifchannel *ch;
388
389 pim_ifp = ifp->info;
390
391 if (!pim_ifp)
392 continue;
393
394 ifaddr = pim_ifp->primary_address;
395
396 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
397 char ch_src_str[100];
398 char ch_grp_str[100];
399
400 pim_inet4_dump("<ch_src?>", ch->sg.src,
401 ch_src_str, sizeof(ch_src_str));
402 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
403 ch_grp_str, sizeof(ch_grp_str));
404
405 vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s",
406 ifp->name,
407 inet_ntoa(ifaddr),
408 ch_src_str,
409 ch_grp_str,
410 ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ?
411 "NOINFO" : "INCLUDE",
412 VTY_NEWLINE);
413 } /* scan interface channels */
414 } /* scan interfaces */
415
416 }
417
418 static void igmp_show_interfaces(struct vty *vty)
419 {
420 struct listnode *node;
421 struct interface *ifp;
422 time_t now;
423
424 now = pim_time_monotonic_sec();
425
426 vty_out(vty,
427 "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s",
428 VTY_NEWLINE);
429
430 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
431 struct pim_interface *pim_ifp;
432 struct listnode *sock_node;
433 struct igmp_sock *igmp;
434
435 pim_ifp = ifp->info;
436
437 if (!pim_ifp)
438 continue;
439
440 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
441 char uptime[10];
442 int mloop;
443
444 pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation);
445
446 mloop = pim_socket_mcastloop_get(igmp->fd);
447
448 vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
449 ifp->name,
450 inet_ntoa(igmp->ifaddr),
451 ifp->ifindex,
452 igmp->fd,
453 uptime,
454 if_is_multicast(ifp) ? "yes" : "no",
455 if_is_broadcast(ifp) ? "yes" : "no",
456 (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
457 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
458 (ifp->flags & IFF_PROMISC) ? "yes" : "no",
459 PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
460 VTY_NEWLINE);
461 }
462 }
463 }
464
465 static void igmp_show_interface_join(struct vty *vty)
466 {
467 struct listnode *node;
468 struct interface *ifp;
469 time_t now;
470
471 now = pim_time_monotonic_sec();
472
473 vty_out(vty,
474 "Interface Address Source Group Socket Uptime %s",
475 VTY_NEWLINE);
476
477 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
478 struct pim_interface *pim_ifp;
479 struct listnode *join_node;
480 struct igmp_join *ij;
481 struct in_addr pri_addr;
482 char pri_addr_str[100];
483
484 pim_ifp = ifp->info;
485
486 if (!pim_ifp)
487 continue;
488
489 if (!pim_ifp->igmp_join_list)
490 continue;
491
492 pri_addr = pim_find_primary_addr(ifp);
493 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
494
495 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) {
496 char group_str[100];
497 char source_str[100];
498 char uptime[10];
499
500 pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation);
501 pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str));
502 pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str));
503
504 vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s%s",
505 ifp->name,
506 pri_addr_str,
507 source_str,
508 group_str,
509 ij->sock_fd,
510 uptime,
511 VTY_NEWLINE);
512 } /* for (pim_ifp->igmp_join_list) */
513
514 } /* for (iflist) */
515
516 }
517
518 static void show_interface_address(struct vty *vty)
519 {
520 struct listnode *ifpnode;
521 struct interface *ifp;
522
523 vty_out(vty,
524 "Interface Primary Secondary %s",
525 VTY_NEWLINE);
526
527 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifpnode, ifp)) {
528 struct listnode *ifcnode;
529 struct connected *ifc;
530 struct in_addr pri_addr;
531 char pri_addr_str[100];
532
533 pri_addr = pim_find_primary_addr(ifp);
534
535 pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
536
537 for (ALL_LIST_ELEMENTS_RO(ifp->connected, ifcnode, ifc)) {
538 char sec_addr_str[100];
539 struct prefix *p = ifc->address;
540
541 if (p->family != AF_INET)
542 continue;
543
544 if (p->u.prefix4.s_addr == pri_addr.s_addr) {
545 sec_addr_str[0] = '\0';
546 }
547 else {
548 pim_inet4_dump("<sec?>", p->u.prefix4, sec_addr_str, sizeof(sec_addr_str));
549 }
550
551 vty_out(vty, "%-9s %-15s %-15s%s",
552 ifp->name,
553 pri_addr_str,
554 sec_addr_str,
555 VTY_NEWLINE);
556 }
557 }
558 }
559
560 static void pim_show_dr(struct vty *vty)
561 {
562 struct listnode *node;
563 struct interface *ifp;
564 time_t now;
565
566 now = pim_time_monotonic_sec();
567
568 vty_out(vty,
569 "NonPri: Number of neighbors missing DR Priority hello option%s"
570 "DrPri: Designated Router Priority sent%s%s",
571 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
572
573 vty_out(vty, "Interface Address DR Uptime Elections Changes NonPri DrPri%s", VTY_NEWLINE);
574
575 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
576 struct pim_interface *pim_ifp;
577 struct in_addr ifaddr;
578 char dr_str[100];
579 char dr_uptime[10];
580
581 pim_ifp = ifp->info;
582
583 if (!pim_ifp)
584 continue;
585
586 if (pim_ifp->pim_sock_fd < 0)
587 continue;
588
589 ifaddr = pim_ifp->primary_address;
590
591 pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime),
592 now, pim_ifp->pim_dr_election_last);
593
594 pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr,
595 dr_str, sizeof(dr_str));
596
597 vty_out(vty, "%-9s %-15s %-15s %8s %9d %7d %6d %10d%s",
598 ifp->name,
599 inet_ntoa(ifaddr),
600 dr_str,
601 dr_uptime,
602 pim_ifp->pim_dr_election_count,
603 pim_ifp->pim_dr_election_changes,
604 pim_ifp->pim_dr_num_nondrpri_neighbors,
605 pim_ifp->pim_dr_priority,
606 VTY_NEWLINE);
607 }
608 }
609
610 static void pim_show_hello(struct vty *vty)
611 {
612 struct listnode *node;
613 struct interface *ifp;
614 time_t now;
615
616 now = pim_time_monotonic_sec();
617
618 vty_out(vty, "Interface Address Period Timer StatStart Recv Rfail Send Sfail LGenid%s", VTY_NEWLINE);
619
620 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
621 struct pim_interface *pim_ifp;
622 struct in_addr ifaddr;
623 char hello_period[10];
624 char hello_timer[10];
625 char stat_uptime[10];
626
627 pim_ifp = ifp->info;
628
629 if (!pim_ifp)
630 continue;
631
632 if (pim_ifp->pim_sock_fd < 0)
633 continue;
634
635 ifaddr = pim_ifp->primary_address;
636
637 pim_time_timer_to_mmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer);
638 pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period);
639 pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start);
640
641 vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u %08x%s",
642 ifp->name,
643 inet_ntoa(ifaddr),
644 hello_period,
645 hello_timer,
646 stat_uptime,
647 pim_ifp->pim_ifstat_hello_recv,
648 pim_ifp->pim_ifstat_hello_recvfail,
649 pim_ifp->pim_ifstat_hello_sent,
650 pim_ifp->pim_ifstat_hello_sendfail,
651 pim_ifp->pim_generation_id,
652 VTY_NEWLINE);
653 }
654 }
655
656 static void pim_show_interfaces(struct vty *vty)
657 {
658 struct listnode *node;
659 struct interface *ifp;
660 time_t now;
661
662 now = pim_time_monotonic_sec();
663
664 vty_out(vty, "Interface Address ifIndex Socket Uptime Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE);
665
666 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
667 struct pim_interface *pim_ifp;
668 struct in_addr ifaddr;
669 char uptime[10];
670 int mloop;
671
672 pim_ifp = ifp->info;
673
674 if (!pim_ifp)
675 continue;
676
677 if (pim_ifp->pim_sock_fd < 0)
678 continue;
679
680 ifaddr = pim_ifp->primary_address;
681
682 pim_time_uptime(uptime, sizeof(uptime), now - pim_ifp->pim_sock_creation);
683
684 mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
685
686 vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
687 ifp->name,
688 inet_ntoa(ifaddr),
689 ifp->ifindex,
690 pim_ifp->pim_sock_fd,
691 uptime,
692 if_is_multicast(ifp) ? "yes" : "no",
693 if_is_broadcast(ifp) ? "yes" : "no",
694 (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
695 (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
696 (ifp->flags & IFF_PROMISC) ? "yes" : "no",
697 PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
698 VTY_NEWLINE);
699 }
700 }
701
702 static void pim_show_join(struct vty *vty)
703 {
704 struct listnode *ifnode;
705 struct interface *ifp;
706 time_t now;
707
708 now = pim_time_monotonic_sec();
709
710 vty_out(vty,
711 "Interface Address Source Group State Uptime Expire Prune%s",
712 VTY_NEWLINE);
713
714 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
715 struct pim_interface *pim_ifp;
716 struct in_addr ifaddr;
717 struct listnode *ch_node;
718 struct pim_ifchannel *ch;
719
720 pim_ifp = ifp->info;
721
722 if (!pim_ifp)
723 continue;
724
725 ifaddr = pim_ifp->primary_address;
726
727 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
728 char ch_src_str[100];
729 char ch_grp_str[100];
730 char uptime[10];
731 char expire[10];
732 char prune[10];
733
734 pim_inet4_dump("<ch_src?>", ch->sg.src,
735 ch_src_str, sizeof(ch_src_str));
736 pim_inet4_dump("<ch_grp?>", ch->sg.grp,
737 ch_grp_str, sizeof(ch_grp_str));
738
739 pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
740 pim_time_timer_to_mmss(expire, sizeof(expire),
741 ch->t_ifjoin_expiry_timer);
742 pim_time_timer_to_mmss(prune, sizeof(prune),
743 ch->t_ifjoin_prune_pending_timer);
744
745 vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s",
746 ifp->name,
747 inet_ntoa(ifaddr),
748 ch_src_str,
749 ch_grp_str,
750 pim_ifchannel_ifjoin_name(ch->ifjoin_state),
751 uptime,
752 expire,
753 prune,
754 VTY_NEWLINE);
755 } /* scan interface channels */
756 } /* scan interfaces */
757
758 }
759
760 static void pim_show_neighbors(struct vty *vty)
761 {
762 struct listnode *node;
763 struct interface *ifp;
764 time_t now;
765
766 now = pim_time_monotonic_sec();
767
768 vty_out(vty,
769 "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s"
770 " T=can_disable_join_suppression%s%s",
771 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
772
773 vty_out(vty, "Interface Address Neighbor Uptime Timer Holdt DrPri GenId Recv %s", VTY_NEWLINE);
774
775 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
776 struct pim_interface *pim_ifp;
777 struct in_addr ifaddr;
778 struct listnode *neighnode;
779 struct pim_neighbor *neigh;
780
781 pim_ifp = ifp->info;
782
783 if (!pim_ifp)
784 continue;
785
786 if (pim_ifp->pim_sock_fd < 0)
787 continue;
788
789 ifaddr = pim_ifp->primary_address;
790
791 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
792 char uptime[10];
793 char holdtime[10];
794 char expire[10];
795 char neigh_src_str[100];
796 char recv[7];
797
798 pim_inet4_dump("<src?>", neigh->source_addr,
799 neigh_src_str, sizeof(neigh_src_str));
800 pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
801 pim_time_mmss(holdtime, sizeof(holdtime), neigh->holdtime);
802 pim_time_timer_to_mmss(expire, sizeof(expire), neigh->t_expire_timer);
803
804 recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME) ? 'H' : ' ';
805 recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? 'L' : ' ';
806 recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) ? 'P' : ' ';
807 recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ? 'G' : ' ';
808 recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST) ? 'A' : ' ';
809 recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' ';
810 recv[6] = '\0';
811
812 vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s",
813 ifp->name,
814 inet_ntoa(ifaddr),
815 neigh_src_str,
816 uptime,
817 expire,
818 holdtime,
819 neigh->dr_priority,
820 neigh->generation_id,
821 recv,
822 VTY_NEWLINE);
823 }
824
825
826 }
827 }
828
829 static void pim_show_lan_prune_delay(struct vty *vty)
830 {
831 struct listnode *node;
832 struct interface *ifp;
833
834 vty_out(vty,
835 "PrDly=propagation_delay (msec) OvInt=override_interval (msec)%s"
836 "HiDly=highest_propagation_delay (msec) HiInt=highest_override_interval (msec)%s"
837 "NoDly=number_of_non_lan_delay_neighbors%s"
838 "T=t_bit LPD=lan_prune_delay_hello_option%s%s",
839 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
840
841 vty_out(vty, "Interface Address PrDly OvInt NoDly HiDly HiInt T | Neighbor LPD PrDly OvInt T%s", VTY_NEWLINE);
842
843 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
844 struct pim_interface *pim_ifp;
845 struct in_addr ifaddr;
846 struct listnode *neighnode;
847 struct pim_neighbor *neigh;
848
849 pim_ifp = ifp->info;
850
851 if (!pim_ifp)
852 continue;
853
854 if (pim_ifp->pim_sock_fd < 0)
855 continue;
856
857 ifaddr = pim_ifp->primary_address;
858
859 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
860 char neigh_src_str[100];
861
862 pim_inet4_dump("<src?>", neigh->source_addr,
863 neigh_src_str, sizeof(neigh_src_str));
864
865 vty_out(vty, "%-9s %-15s %5u %5u %5u %5u %5u %1u | %-15s %-3s %5u %5u %1u%s",
866 ifp->name,
867 inet_ntoa(ifaddr),
868 pim_ifp->pim_propagation_delay_msec,
869 pim_ifp->pim_override_interval_msec,
870 pim_ifp->pim_number_of_nonlandelay_neighbors,
871 pim_ifp->pim_neighbors_highest_propagation_delay_msec,
872 pim_ifp->pim_neighbors_highest_override_interval_msec,
873 PIM_FORCE_BOOLEAN(PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)),
874 neigh_src_str,
875 PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? "yes" : "no",
876 neigh->propagation_delay_msec,
877 neigh->override_interval_msec,
878 PIM_FORCE_BOOLEAN(PIM_OPTION_IS_SET(neigh->hello_options,
879 PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)),
880 VTY_NEWLINE);
881 }
882
883 }
884 }
885
886 static void pim_show_jp_override_interval(struct vty *vty)
887 {
888 struct listnode *node;
889 struct interface *ifp;
890
891 vty_out(vty,
892 "EffPDelay=effective_propagation_delay (msec)%s"
893 "EffOvrInt=override_interval (msec)%s"
894 "JPOvrInt=jp_override_interval (msec)%s%s",
895 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
896
897 vty_out(vty, "Interface Address LAN_Delay EffPDelay EffOvrInt JPOvrInt%s", VTY_NEWLINE);
898
899 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
900 struct pim_interface *pim_ifp;
901 struct in_addr ifaddr;
902
903 pim_ifp = ifp->info;
904
905 if (!pim_ifp)
906 continue;
907
908 if (pim_ifp->pim_sock_fd < 0)
909 continue;
910
911 ifaddr = pim_ifp->primary_address;
912
913 vty_out(vty, "%-9s %-15s %-9s %9u %9u %8u%s",
914 ifp->name,
915 inet_ntoa(ifaddr),
916 pim_if_lan_delay_enabled(ifp) ? "enabled" : "disabled",
917 pim_if_effective_propagation_delay_msec(ifp),
918 pim_if_effective_override_interval_msec(ifp),
919 pim_if_jp_override_interval_msec(ifp),
920 VTY_NEWLINE);
921 }
922 }
923
924 static void pim_show_neighbors_secondary(struct vty *vty)
925 {
926 struct listnode *node;
927 struct interface *ifp;
928
929 vty_out(vty, "Interface Address Neighbor Secondary %s", VTY_NEWLINE);
930
931 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
932 struct pim_interface *pim_ifp;
933 struct in_addr ifaddr;
934 struct listnode *neighnode;
935 struct pim_neighbor *neigh;
936
937 pim_ifp = ifp->info;
938
939 if (!pim_ifp)
940 continue;
941
942 if (pim_ifp->pim_sock_fd < 0)
943 continue;
944
945 ifaddr = pim_ifp->primary_address;
946
947 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
948 char neigh_src_str[100];
949 struct listnode *prefix_node;
950 struct prefix *p;
951
952 if (!neigh->prefix_list)
953 continue;
954
955 pim_inet4_dump("<src?>", neigh->source_addr,
956 neigh_src_str, sizeof(neigh_src_str));
957
958 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
959 char neigh_sec_str[100];
960
961 if (p->family != AF_INET)
962 continue;
963
964 pim_inet4_dump("<src?>", p->u.prefix4,
965 neigh_sec_str, sizeof(neigh_sec_str));
966
967 vty_out(vty, "%-9s %-15s %-15s %-15s%s",
968 ifp->name,
969 inet_ntoa(ifaddr),
970 neigh_src_str,
971 neigh_sec_str,
972 VTY_NEWLINE);
973 }
974 }
975 }
976 }
977
978 static void pim_show_upstream(struct vty *vty)
979 {
980 struct listnode *upnode;
981 struct pim_upstream *up;
982 time_t now;
983
984 now = pim_time_monotonic_sec();
985
986 vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt%s", VTY_NEWLINE);
987
988 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
989 char src_str[100];
990 char grp_str[100];
991 char uptime[10];
992 char join_timer[10];
993 char rs_timer[10];
994 char ka_timer[10];
995
996 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
997 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
998 pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
999 pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer);
1000 pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer);
1001 pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer);
1002
1003 vty_out(vty, "%-10s%-15s %-15s %-5s %-8s %-9s %-9s %-9s %6d%s",
1004 up->rpf.source_nexthop.interface->name,
1005 src_str,
1006 grp_str,
1007 pim_upstream_state2str (up),
1008 uptime,
1009 join_timer,
1010 rs_timer,
1011 ka_timer,
1012 up->ref_count,
1013 VTY_NEWLINE);
1014 }
1015 }
1016
1017 static void pim_show_join_desired(struct vty *vty)
1018 {
1019 struct listnode *ifnode;
1020 struct listnode *chnode;
1021 struct interface *ifp;
1022 struct pim_interface *pim_ifp;
1023 struct pim_ifchannel *ch;
1024 char src_str[100];
1025 char grp_str[100];
1026
1027 vty_out(vty,
1028 "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD%s",
1029 VTY_NEWLINE);
1030
1031 /* scan all interfaces */
1032 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1033 pim_ifp = ifp->info;
1034 if (!pim_ifp)
1035 continue;
1036
1037 /* scan per-interface (S,G) state */
1038 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) {
1039 struct pim_upstream *up = ch->upstream;
1040
1041 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1042 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
1043
1044 vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s",
1045 ifp->name,
1046 src_str,
1047 grp_str,
1048 pim_macro_ch_lost_assert(ch) ? "yes" : "no",
1049 pim_macro_chisin_joins(ch) ? "yes" : "no",
1050 pim_macro_chisin_pim_include(ch) ? "yes" : "no",
1051 PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no",
1052 pim_upstream_evaluate_join_desired(up) ? "yes" : "no",
1053 VTY_NEWLINE);
1054 }
1055 }
1056 }
1057
1058 static void pim_show_upstream_rpf(struct vty *vty)
1059 {
1060 struct listnode *upnode;
1061 struct pim_upstream *up;
1062
1063 vty_out(vty,
1064 "Source Group RpfIface RibNextHop RpfAddress %s",
1065 VTY_NEWLINE);
1066
1067 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
1068 char src_str[100];
1069 char grp_str[100];
1070 char rpf_nexthop_str[100];
1071 char rpf_addr_str[100];
1072 struct pim_rpf *rpf;
1073 const char *rpf_ifname;
1074
1075 rpf = &up->rpf;
1076
1077 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1078 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
1079 pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str));
1080 pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1081
1082 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1083
1084 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s",
1085 src_str,
1086 grp_str,
1087 rpf_ifname,
1088 rpf_nexthop_str,
1089 rpf_addr_str,
1090 VTY_NEWLINE);
1091 }
1092 }
1093
1094 static void show_rpf_refresh_stats(struct vty *vty, time_t now)
1095 {
1096 char refresh_uptime[10];
1097
1098 pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last);
1099
1100 vty_out(vty,
1101 "RPF Cache Refresh Delay: %ld msecs%s"
1102 "RPF Cache Refresh Timer: %ld msecs%s"
1103 "RPF Cache Refresh Requests: %lld%s"
1104 "RPF Cache Refresh Events: %lld%s"
1105 "RPF Cache Refresh Last: %s%s",
1106 qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE,
1107 pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE,
1108 (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE,
1109 (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE,
1110 refresh_uptime, VTY_NEWLINE);
1111 }
1112
1113 static void show_scan_oil_stats(struct vty *vty, time_t now)
1114 {
1115 char uptime_scan_oil[10];
1116 char uptime_mroute_add[10];
1117 char uptime_mroute_del[10];
1118
1119 pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last);
1120 pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last);
1121 pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last);
1122
1123 vty_out(vty,
1124 "Scan OIL - Last: %s Events: %lld%s"
1125 "MFC Add - Last: %s Events: %lld%s"
1126 "MFC Del - Last: %s Events: %lld%s",
1127 uptime_scan_oil, (long long) qpim_scan_oil_events, VTY_NEWLINE,
1128 uptime_mroute_add, (long long) qpim_mroute_add_events, VTY_NEWLINE,
1129 uptime_mroute_del, (long long) qpim_mroute_del_events, VTY_NEWLINE);
1130 }
1131
1132 static void pim_show_rpf(struct vty *vty)
1133 {
1134 struct listnode *up_node;
1135 struct pim_upstream *up;
1136 time_t now = pim_time_monotonic_sec();
1137
1138 show_rpf_refresh_stats(vty, now);
1139
1140 vty_out(vty, "%s", VTY_NEWLINE);
1141
1142 vty_out(vty,
1143 "Source Group RpfIface RpfAddress RibNextHop Metric Pref%s",
1144 VTY_NEWLINE);
1145
1146 for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) {
1147 char src_str[100];
1148 char grp_str[100];
1149 char rpf_addr_str[100];
1150 char rib_nexthop_str[100];
1151 const char *rpf_ifname;
1152 struct pim_rpf *rpf = &up->rpf;
1153
1154 pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
1155 pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
1156 pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1157 pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str));
1158
1159 rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1160
1161 vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s",
1162 src_str,
1163 grp_str,
1164 rpf_ifname,
1165 rpf_addr_str,
1166 rib_nexthop_str,
1167 rpf->source_nexthop.mrib_route_metric,
1168 rpf->source_nexthop.mrib_metric_preference,
1169 VTY_NEWLINE);
1170 }
1171 }
1172
1173 static void igmp_show_querier(struct vty *vty)
1174 {
1175 struct listnode *node;
1176 struct interface *ifp;
1177
1178 vty_out(vty, "Interface Address Querier StartCount Query-Timer Other-Timer%s", VTY_NEWLINE);
1179
1180 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
1181 struct pim_interface *pim_ifp = ifp->info;
1182 struct listnode *sock_node;
1183 struct igmp_sock *igmp;
1184
1185 if (!pim_ifp)
1186 continue;
1187
1188 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1189 char query_hhmmss[10];
1190 char other_hhmmss[10];
1191
1192 pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer);
1193 pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer);
1194
1195 vty_out(vty, "%-9s %-15s %-7s %10d %11s %11s%s",
1196 ifp->name,
1197 inet_ntoa(igmp->ifaddr),
1198 igmp->t_igmp_query_timer ? "THIS" : "OTHER",
1199 igmp->startup_query_count,
1200 query_hhmmss,
1201 other_hhmmss,
1202 VTY_NEWLINE);
1203 }
1204 }
1205 }
1206
1207 static void igmp_show_groups(struct vty *vty)
1208 {
1209 struct listnode *ifnode;
1210 struct interface *ifp;
1211 time_t now;
1212
1213 now = pim_time_monotonic_sec();
1214
1215 vty_out(vty, "Interface Address Group Mode Timer Srcs V Uptime %s", VTY_NEWLINE);
1216
1217 /* scan interfaces */
1218 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1219 struct pim_interface *pim_ifp = ifp->info;
1220 struct listnode *sock_node;
1221 struct igmp_sock *igmp;
1222
1223 if (!pim_ifp)
1224 continue;
1225
1226 /* scan igmp sockets */
1227 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1228 char ifaddr_str[100];
1229 struct listnode *grpnode;
1230 struct igmp_group *grp;
1231
1232 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1233
1234 /* scan igmp groups */
1235 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1236 char group_str[100];
1237 char hhmmss[10];
1238 char uptime[10];
1239
1240 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1241 pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer);
1242 pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation);
1243
1244 vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s",
1245 ifp->name,
1246 ifaddr_str,
1247 group_str,
1248 grp->group_filtermode_isexcl ? "EXCL" : "INCL",
1249 hhmmss,
1250 grp->group_source_list ? listcount(grp->group_source_list) : 0,
1251 igmp_group_compat_mode(igmp, grp),
1252 uptime,
1253 VTY_NEWLINE);
1254
1255 } /* scan igmp groups */
1256 } /* scan igmp sockets */
1257 } /* scan interfaces */
1258 }
1259
1260 static void igmp_show_group_retransmission(struct vty *vty)
1261 {
1262 struct listnode *ifnode;
1263 struct interface *ifp;
1264
1265 vty_out(vty, "Interface Address Group RetTimer Counter RetSrcs%s", VTY_NEWLINE);
1266
1267 /* scan interfaces */
1268 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1269 struct pim_interface *pim_ifp = ifp->info;
1270 struct listnode *sock_node;
1271 struct igmp_sock *igmp;
1272
1273 if (!pim_ifp)
1274 continue;
1275
1276 /* scan igmp sockets */
1277 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1278 char ifaddr_str[100];
1279 struct listnode *grpnode;
1280 struct igmp_group *grp;
1281
1282 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1283
1284 /* scan igmp groups */
1285 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1286 char group_str[100];
1287 char grp_retr_mmss[10];
1288 struct listnode *src_node;
1289 struct igmp_source *src;
1290 int grp_retr_sources = 0;
1291
1292 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1293 pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer);
1294
1295
1296 /* count group sources with retransmission state */
1297 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
1298 if (src->source_query_retransmit_count > 0) {
1299 ++grp_retr_sources;
1300 }
1301 }
1302
1303 vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d%s",
1304 ifp->name,
1305 ifaddr_str,
1306 group_str,
1307 grp_retr_mmss,
1308 grp->group_specific_query_retransmit_count,
1309 grp_retr_sources,
1310 VTY_NEWLINE);
1311
1312 } /* scan igmp groups */
1313 } /* scan igmp sockets */
1314 } /* scan interfaces */
1315 }
1316
1317 static void igmp_show_parameters(struct vty *vty)
1318 {
1319 struct listnode *ifnode;
1320 struct interface *ifp;
1321
1322 vty_out(vty,
1323 "QRV: Robustness Variable SQI: Startup Query Interval%s"
1324 "QQI: Query Interval OQPI: Other Querier Present Interval%s"
1325 "QRI: Query Response Interval LMQT: Last Member Query Time%s"
1326 "GMI: Group Membership Interval OHPI: Older Host Present Interval%s%s",
1327 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1328
1329 vty_out(vty,
1330 "Interface Address QRV QQI QRI GMI SQI OQPI LMQT OHPI %s",
1331 VTY_NEWLINE);
1332
1333 /* scan interfaces */
1334 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1335 struct pim_interface *pim_ifp = ifp->info;
1336 struct listnode *sock_node;
1337 struct igmp_sock *igmp;
1338
1339 if (!pim_ifp)
1340 continue;
1341
1342 /* scan igmp sockets */
1343 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1344 char ifaddr_str[100];
1345 long gmi_dsec; /* Group Membership Interval */
1346 long oqpi_dsec; /* Other Querier Present Interval */
1347 int sqi;
1348 long lmqt_dsec;
1349 long ohpi_dsec;
1350 long qri_dsec;
1351
1352 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1353
1354 gmi_dsec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
1355 igmp->querier_query_interval,
1356 pim_ifp->igmp_query_max_response_time_dsec) / 100;
1357
1358 sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval);
1359
1360 oqpi_dsec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable,
1361 igmp->querier_query_interval,
1362 pim_ifp->igmp_query_max_response_time_dsec) / 100;
1363
1364 lmqt_dsec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec,
1365 igmp->querier_robustness_variable) / 100;
1366
1367 ohpi_dsec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable,
1368 igmp->querier_query_interval,
1369 pim_ifp->igmp_query_max_response_time_dsec);
1370
1371 qri_dsec = pim_ifp->igmp_query_max_response_time_dsec;
1372
1373 vty_out(vty,
1374 "%-9s %-15s %3d %3d %3ld.%ld %3ld.%ld %3d %3ld.%ld %3ld.%ld %3ld.%ld%s",
1375 ifp->name,
1376 ifaddr_str,
1377 igmp->querier_robustness_variable,
1378 igmp->querier_query_interval,
1379 qri_dsec / 10, qri_dsec % 10,
1380 gmi_dsec / 10, gmi_dsec % 10,
1381 sqi,
1382 oqpi_dsec / 10, oqpi_dsec % 10,
1383 lmqt_dsec / 10, lmqt_dsec % 10,
1384 ohpi_dsec / 10, ohpi_dsec % 10,
1385 VTY_NEWLINE);
1386
1387 } /* scan igmp sockets */
1388 } /* scan interfaces */
1389 }
1390
1391 static void igmp_show_sources(struct vty *vty)
1392 {
1393 struct listnode *ifnode;
1394 struct interface *ifp;
1395 time_t now;
1396
1397 now = pim_time_monotonic_sec();
1398
1399 vty_out(vty, "Interface Address Group Source Timer Fwd Uptime %s", VTY_NEWLINE);
1400
1401 /* scan interfaces */
1402 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1403 struct pim_interface *pim_ifp = ifp->info;
1404 struct listnode *sock_node;
1405 struct igmp_sock *igmp;
1406
1407 if (!pim_ifp)
1408 continue;
1409
1410 /* scan igmp sockets */
1411 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1412 char ifaddr_str[100];
1413 struct listnode *grpnode;
1414 struct igmp_group *grp;
1415
1416 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1417
1418 /* scan igmp groups */
1419 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1420 char group_str[100];
1421 struct listnode *srcnode;
1422 struct igmp_source *src;
1423
1424 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1425
1426 /* scan group sources */
1427 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1428 char source_str[100];
1429 char mmss[10];
1430 char uptime[10];
1431
1432 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1433
1434 pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer);
1435
1436 pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation);
1437
1438 vty_out(vty, "%-9s %-15s %-15s %-15s %5s %3s %8s%s",
1439 ifp->name,
1440 ifaddr_str,
1441 group_str,
1442 source_str,
1443 mmss,
1444 IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N",
1445 uptime,
1446 VTY_NEWLINE);
1447
1448 } /* scan group sources */
1449 } /* scan igmp groups */
1450 } /* scan igmp sockets */
1451 } /* scan interfaces */
1452 }
1453
1454 static void igmp_show_source_retransmission(struct vty *vty)
1455 {
1456 struct listnode *ifnode;
1457 struct interface *ifp;
1458
1459 vty_out(vty, "Interface Address Group Source Counter%s", VTY_NEWLINE);
1460
1461 /* scan interfaces */
1462 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
1463 struct pim_interface *pim_ifp = ifp->info;
1464 struct listnode *sock_node;
1465 struct igmp_sock *igmp;
1466
1467 if (!pim_ifp)
1468 continue;
1469
1470 /* scan igmp sockets */
1471 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1472 char ifaddr_str[100];
1473 struct listnode *grpnode;
1474 struct igmp_group *grp;
1475
1476 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1477
1478 /* scan igmp groups */
1479 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1480 char group_str[100];
1481 struct listnode *srcnode;
1482 struct igmp_source *src;
1483
1484 pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1485
1486 /* scan group sources */
1487 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1488 char source_str[100];
1489
1490 pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1491
1492 vty_out(vty, "%-9s %-15s %-15s %-15s %7d%s",
1493 ifp->name,
1494 ifaddr_str,
1495 group_str,
1496 source_str,
1497 src->source_query_retransmit_count,
1498 VTY_NEWLINE);
1499
1500 } /* scan group sources */
1501 } /* scan igmp groups */
1502 } /* scan igmp sockets */
1503 } /* scan interfaces */
1504 }
1505
1506 static void clear_igmp_interfaces()
1507 {
1508 struct listnode *ifnode;
1509 struct listnode *ifnextnode;
1510 struct interface *ifp;
1511
1512 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
1513 pim_if_addr_del_all_igmp(ifp);
1514 }
1515
1516 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
1517 pim_if_addr_add_all(ifp);
1518 }
1519 }
1520
1521 static void clear_pim_interfaces()
1522 {
1523 struct listnode *ifnode;
1524 struct listnode *ifnextnode;
1525 struct interface *ifp;
1526
1527 for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) {
1528 if (ifp->info) {
1529 pim_neighbor_delete_all(ifp, "interface cleared");
1530 }
1531 }
1532 }
1533
1534 static void clear_interfaces()
1535 {
1536 clear_igmp_interfaces();
1537 clear_pim_interfaces();
1538 }
1539
1540 DEFUN (clear_ip_interfaces,
1541 clear_ip_interfaces_cmd,
1542 "clear ip interfaces",
1543 CLEAR_STR
1544 IP_STR
1545 "Reset interfaces\n")
1546 {
1547 clear_interfaces();
1548
1549 return CMD_SUCCESS;
1550 }
1551
1552 DEFUN (clear_ip_igmp_interfaces,
1553 clear_ip_igmp_interfaces_cmd,
1554 "clear ip igmp interfaces",
1555 CLEAR_STR
1556 IP_STR
1557 CLEAR_IP_IGMP_STR
1558 "Reset IGMP interfaces\n")
1559 {
1560 clear_igmp_interfaces();
1561
1562 return CMD_SUCCESS;
1563 }
1564
1565 static void mroute_add_all()
1566 {
1567 struct listnode *node;
1568 struct channel_oil *c_oil;
1569
1570 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
1571 if (pim_mroute_add(c_oil)) {
1572 /* just log warning */
1573 char source_str[100];
1574 char group_str[100];
1575 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
1576 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1577 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
1578 __FILE__, __PRETTY_FUNCTION__,
1579 source_str, group_str);
1580 }
1581 }
1582 }
1583
1584 static void mroute_del_all()
1585 {
1586 struct listnode *node;
1587 struct channel_oil *c_oil;
1588
1589 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
1590 if (pim_mroute_del(c_oil)) {
1591 /* just log warning */
1592 char source_str[100];
1593 char group_str[100];
1594 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
1595 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1596 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
1597 __FILE__, __PRETTY_FUNCTION__,
1598 source_str, group_str);
1599 }
1600 }
1601 }
1602
1603 static void static_mroute_add_all()
1604 {
1605 struct listnode *node;
1606 struct static_route *s_route;
1607
1608 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
1609 if (pim_mroute_add(&s_route->c_oil)) {
1610 /* just log warning */
1611 char source_str[100];
1612 char group_str[100];
1613 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
1614 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1615 zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
1616 __FILE__, __PRETTY_FUNCTION__,
1617 source_str, group_str);
1618 }
1619 }
1620 }
1621
1622 static void static_mroute_del_all()
1623 {
1624 struct listnode *node;
1625 struct static_route *s_route;
1626
1627 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
1628 if (pim_mroute_del(&s_route->c_oil)) {
1629 /* just log warning */
1630 char source_str[100];
1631 char group_str[100];
1632 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
1633 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1634 zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
1635 __FILE__, __PRETTY_FUNCTION__,
1636 source_str, group_str);
1637 }
1638 }
1639 }
1640
1641 DEFUN (clear_ip_mroute,
1642 clear_ip_mroute_cmd,
1643 "clear ip mroute",
1644 CLEAR_STR
1645 IP_STR
1646 "Reset multicast routes\n")
1647 {
1648 mroute_del_all();
1649 mroute_add_all();
1650
1651 return CMD_SUCCESS;
1652 }
1653
1654 DEFUN (clear_ip_pim_interfaces,
1655 clear_ip_pim_interfaces_cmd,
1656 "clear ip pim interfaces",
1657 CLEAR_STR
1658 IP_STR
1659 CLEAR_IP_PIM_STR
1660 "Reset PIM interfaces\n")
1661 {
1662 clear_pim_interfaces();
1663
1664 return CMD_SUCCESS;
1665 }
1666
1667 DEFUN (clear_ip_pim_oil,
1668 clear_ip_pim_oil_cmd,
1669 "clear ip pim oil",
1670 CLEAR_STR
1671 IP_STR
1672 CLEAR_IP_PIM_STR
1673 "Rescan PIM OIL (output interface list)\n")
1674 {
1675 pim_scan_oil();
1676
1677 return CMD_SUCCESS;
1678 }
1679
1680 DEFUN (show_ip_igmp_interface,
1681 show_ip_igmp_interface_cmd,
1682 "show ip igmp interface",
1683 SHOW_STR
1684 IP_STR
1685 IGMP_STR
1686 "IGMP interface information\n")
1687 {
1688 igmp_show_interfaces(vty);
1689
1690 return CMD_SUCCESS;
1691 }
1692
1693 DEFUN (show_ip_igmp_join,
1694 show_ip_igmp_join_cmd,
1695 "show ip igmp join",
1696 SHOW_STR
1697 IP_STR
1698 IGMP_STR
1699 "IGMP static join information\n")
1700 {
1701 igmp_show_interface_join(vty);
1702
1703 return CMD_SUCCESS;
1704 }
1705
1706 DEFUN (show_ip_igmp_groups,
1707 show_ip_igmp_groups_cmd,
1708 "show ip igmp groups",
1709 SHOW_STR
1710 IP_STR
1711 IGMP_STR
1712 IGMP_GROUP_STR)
1713 {
1714 igmp_show_groups(vty);
1715
1716 return CMD_SUCCESS;
1717 }
1718
1719 DEFUN (show_ip_igmp_groups_retransmissions,
1720 show_ip_igmp_groups_retransmissions_cmd,
1721 "show ip igmp groups retransmissions",
1722 SHOW_STR
1723 IP_STR
1724 IGMP_STR
1725 IGMP_GROUP_STR
1726 "IGMP group retransmissions\n")
1727 {
1728 igmp_show_group_retransmission(vty);
1729
1730 return CMD_SUCCESS;
1731 }
1732
1733 DEFUN (show_ip_igmp_parameters,
1734 show_ip_igmp_parameters_cmd,
1735 "show ip igmp parameters",
1736 SHOW_STR
1737 IP_STR
1738 IGMP_STR
1739 "IGMP parameters information\n")
1740 {
1741 igmp_show_parameters(vty);
1742
1743 return CMD_SUCCESS;
1744 }
1745
1746 DEFUN (show_ip_igmp_sources,
1747 show_ip_igmp_sources_cmd,
1748 "show ip igmp sources",
1749 SHOW_STR
1750 IP_STR
1751 IGMP_STR
1752 IGMP_SOURCE_STR)
1753 {
1754 igmp_show_sources(vty);
1755
1756 return CMD_SUCCESS;
1757 }
1758
1759 DEFUN (show_ip_igmp_sources_retransmissions,
1760 show_ip_igmp_sources_retransmissions_cmd,
1761 "show ip igmp sources retransmissions",
1762 SHOW_STR
1763 IP_STR
1764 IGMP_STR
1765 IGMP_SOURCE_STR
1766 "IGMP source retransmissions\n")
1767 {
1768 igmp_show_source_retransmission(vty);
1769
1770 return CMD_SUCCESS;
1771 }
1772
1773 DEFUN (show_ip_igmp_querier,
1774 show_ip_igmp_querier_cmd,
1775 "show ip igmp querier",
1776 SHOW_STR
1777 IP_STR
1778 IGMP_STR
1779 "IGMP querier information\n")
1780 {
1781 igmp_show_querier(vty);
1782
1783 return CMD_SUCCESS;
1784 }
1785
1786 DEFUN (show_ip_pim_address,
1787 show_ip_pim_address_cmd,
1788 "show ip pim address",
1789 SHOW_STR
1790 IP_STR
1791 PIM_STR
1792 "PIM interface address\n")
1793 {
1794 show_interface_address(vty);
1795
1796 return CMD_SUCCESS;
1797 }
1798
1799 DEFUN (show_ip_pim_assert,
1800 show_ip_pim_assert_cmd,
1801 "show ip pim assert",
1802 SHOW_STR
1803 IP_STR
1804 PIM_STR
1805 "PIM interface assert\n")
1806 {
1807 pim_show_assert(vty);
1808
1809 return CMD_SUCCESS;
1810 }
1811
1812 DEFUN (show_ip_pim_assert_internal,
1813 show_ip_pim_assert_internal_cmd,
1814 "show ip pim assert-internal",
1815 SHOW_STR
1816 IP_STR
1817 PIM_STR
1818 "PIM interface internal assert state\n")
1819 {
1820 pim_show_assert_internal(vty);
1821
1822 return CMD_SUCCESS;
1823 }
1824
1825 DEFUN (show_ip_pim_assert_metric,
1826 show_ip_pim_assert_metric_cmd,
1827 "show ip pim assert-metric",
1828 SHOW_STR
1829 IP_STR
1830 PIM_STR
1831 "PIM interface assert metric\n")
1832 {
1833 pim_show_assert_metric(vty);
1834
1835 return CMD_SUCCESS;
1836 }
1837
1838 DEFUN (show_ip_pim_assert_winner_metric,
1839 show_ip_pim_assert_winner_metric_cmd,
1840 "show ip pim assert-winner-metric",
1841 SHOW_STR
1842 IP_STR
1843 PIM_STR
1844 "PIM interface assert winner metric\n")
1845 {
1846 pim_show_assert_winner_metric(vty);
1847
1848 return CMD_SUCCESS;
1849 }
1850
1851 DEFUN (show_ip_pim_dr,
1852 show_ip_pim_dr_cmd,
1853 "show ip pim designated-router",
1854 SHOW_STR
1855 IP_STR
1856 PIM_STR
1857 "PIM interface designated router\n")
1858 {
1859 pim_show_dr(vty);
1860
1861 return CMD_SUCCESS;
1862 }
1863
1864 DEFUN (show_ip_pim_hello,
1865 show_ip_pim_hello_cmd,
1866 "show ip pim hello",
1867 SHOW_STR
1868 IP_STR
1869 PIM_STR
1870 "PIM interface hello information\n")
1871 {
1872 pim_show_hello(vty);
1873
1874 return CMD_SUCCESS;
1875 }
1876
1877 DEFUN (show_ip_pim_interface,
1878 show_ip_pim_interface_cmd,
1879 "show ip pim interface",
1880 SHOW_STR
1881 IP_STR
1882 PIM_STR
1883 "PIM interface information\n")
1884 {
1885 pim_show_interfaces(vty);
1886
1887 return CMD_SUCCESS;
1888 }
1889
1890 DEFUN (show_ip_pim_join,
1891 show_ip_pim_join_cmd,
1892 "show ip pim join",
1893 SHOW_STR
1894 IP_STR
1895 PIM_STR
1896 "PIM interface join information\n")
1897 {
1898 pim_show_join(vty);
1899
1900 return CMD_SUCCESS;
1901 }
1902
1903 DEFUN (show_ip_pim_lan_prune_delay,
1904 show_ip_pim_lan_prune_delay_cmd,
1905 "show ip pim lan-prune-delay",
1906 SHOW_STR
1907 IP_STR
1908 PIM_STR
1909 "PIM neighbors LAN prune delay parameters\n")
1910 {
1911 pim_show_lan_prune_delay(vty);
1912
1913 return CMD_SUCCESS;
1914 }
1915
1916 DEFUN (show_ip_pim_local_membership,
1917 show_ip_pim_local_membership_cmd,
1918 "show ip pim local-membership",
1919 SHOW_STR
1920 IP_STR
1921 PIM_STR
1922 "PIM interface local-membership\n")
1923 {
1924 pim_show_membership(vty);
1925
1926 return CMD_SUCCESS;
1927 }
1928
1929 DEFUN (show_ip_pim_jp_override_interval,
1930 show_ip_pim_jp_override_interval_cmd,
1931 "show ip pim jp-override-interval",
1932 SHOW_STR
1933 IP_STR
1934 PIM_STR
1935 "PIM interface J/P override interval\n")
1936 {
1937 pim_show_jp_override_interval(vty);
1938
1939 return CMD_SUCCESS;
1940 }
1941
1942 DEFUN (show_ip_pim_neighbor,
1943 show_ip_pim_neighbor_cmd,
1944 "show ip pim neighbor",
1945 SHOW_STR
1946 IP_STR
1947 PIM_STR
1948 "PIM neighbor information\n")
1949 {
1950 pim_show_neighbors(vty);
1951
1952 return CMD_SUCCESS;
1953 }
1954
1955 DEFUN (show_ip_pim_secondary,
1956 show_ip_pim_secondary_cmd,
1957 "show ip pim secondary",
1958 SHOW_STR
1959 IP_STR
1960 PIM_STR
1961 "PIM neighbor addresses\n")
1962 {
1963 pim_show_neighbors_secondary(vty);
1964
1965 return CMD_SUCCESS;
1966 }
1967
1968 DEFUN (show_ip_pim_upstream,
1969 show_ip_pim_upstream_cmd,
1970 "show ip pim upstream",
1971 SHOW_STR
1972 IP_STR
1973 PIM_STR
1974 "PIM upstream information\n")
1975 {
1976 pim_show_upstream(vty);
1977
1978 return CMD_SUCCESS;
1979 }
1980
1981 DEFUN (show_ip_pim_upstream_join_desired,
1982 show_ip_pim_upstream_join_desired_cmd,
1983 "show ip pim upstream-join-desired",
1984 SHOW_STR
1985 IP_STR
1986 PIM_STR
1987 "PIM upstream join-desired\n")
1988 {
1989 pim_show_join_desired(vty);
1990
1991 return CMD_SUCCESS;
1992 }
1993
1994 DEFUN (show_ip_pim_upstream_rpf,
1995 show_ip_pim_upstream_rpf_cmd,
1996 "show ip pim upstream-rpf",
1997 SHOW_STR
1998 IP_STR
1999 PIM_STR
2000 "PIM upstream source rpf\n")
2001 {
2002 pim_show_upstream_rpf(vty);
2003
2004 return CMD_SUCCESS;
2005 }
2006
2007 DEFUN (show_ip_pim_rpf,
2008 show_ip_pim_rpf_cmd,
2009 "show ip pim rpf",
2010 SHOW_STR
2011 IP_STR
2012 PIM_STR
2013 "PIM cached source rpf information\n")
2014 {
2015 pim_show_rpf(vty);
2016
2017 return CMD_SUCCESS;
2018 }
2019
2020 static void show_multicast_interfaces(struct vty *vty)
2021 {
2022 struct listnode *node;
2023 struct interface *ifp;
2024
2025 vty_out(vty, "%s", VTY_NEWLINE);
2026
2027 vty_out(vty, "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut%s",
2028 VTY_NEWLINE);
2029
2030 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) {
2031 struct pim_interface *pim_ifp;
2032 struct in_addr ifaddr;
2033 struct sioc_vif_req vreq;
2034
2035 pim_ifp = ifp->info;
2036
2037 if (!pim_ifp)
2038 continue;
2039
2040 memset(&vreq, 0, sizeof(vreq));
2041 vreq.vifi = pim_ifp->mroute_vif_index;
2042
2043 if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) {
2044 zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s%s",
2045 (unsigned long)SIOCGETVIFCNT,
2046 ifp->name,
2047 pim_ifp->mroute_vif_index,
2048 errno,
2049 safe_strerror(errno),
2050 VTY_NEWLINE);
2051 }
2052
2053 ifaddr = pim_ifp->primary_address;
2054
2055 vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu%s",
2056 ifp->name,
2057 inet_ntoa(ifaddr),
2058 ifp->ifindex,
2059 pim_ifp->mroute_vif_index,
2060 (unsigned long) vreq.icount,
2061 (unsigned long) vreq.ocount,
2062 (unsigned long) vreq.ibytes,
2063 (unsigned long) vreq.obytes,
2064 VTY_NEWLINE);
2065 }
2066 }
2067
2068 DEFUN (show_ip_multicast,
2069 show_ip_multicast_cmd,
2070 "show ip multicast",
2071 SHOW_STR
2072 IP_STR
2073 "Multicast global information\n")
2074 {
2075 time_t now = pim_time_monotonic_sec();
2076
2077 if (PIM_MROUTE_IS_ENABLED) {
2078 char uptime[10];
2079
2080 vty_out(vty, "Mroute socket descriptor: %d%s",
2081 qpim_mroute_socket_fd,
2082 VTY_NEWLINE);
2083
2084 pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
2085 vty_out(vty, "Mroute socket uptime: %s%s",
2086 uptime,
2087 VTY_NEWLINE);
2088 }
2089 else {
2090 vty_out(vty, "Multicast disabled%s",
2091 VTY_NEWLINE);
2092 }
2093
2094 vty_out(vty, "%s", VTY_NEWLINE);
2095 vty_out(vty, "Zclient update socket: ");
2096 if (qpim_zclient_update) {
2097 vty_out(vty, "%d failures=%d%s", qpim_zclient_update->sock,
2098 qpim_zclient_update->fail, VTY_NEWLINE);
2099 }
2100 else {
2101 vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
2102 }
2103
2104 pim_zlookup_show_ip_multicast (vty);
2105
2106 vty_out(vty, "%s", VTY_NEWLINE);
2107 vty_out(vty, "Current highest VifIndex: %d%s",
2108 qpim_mroute_oif_highest_vif_index,
2109 VTY_NEWLINE);
2110 vty_out(vty, "Maximum highest VifIndex: %d%s",
2111 PIM_MAX_USABLE_VIFS,
2112 VTY_NEWLINE);
2113
2114 vty_out(vty, "%s", VTY_NEWLINE);
2115 vty_out(vty, "Upstream Join Timer: %d secs%s",
2116 qpim_t_periodic,
2117 VTY_NEWLINE);
2118 vty_out(vty, "Join/Prune Holdtime: %d secs%s",
2119 PIM_JP_HOLDTIME,
2120 VTY_NEWLINE);
2121
2122 vty_out(vty, "%s", VTY_NEWLINE);
2123
2124 show_rpf_refresh_stats(vty, now);
2125
2126 vty_out(vty, "%s", VTY_NEWLINE);
2127
2128 show_scan_oil_stats(vty, now);
2129
2130 show_multicast_interfaces(vty);
2131
2132 return CMD_SUCCESS;
2133 }
2134
2135 static void show_mroute(struct vty *vty)
2136 {
2137 struct listnode *node;
2138 struct channel_oil *c_oil;
2139 struct static_route *s_route;
2140 time_t now;
2141
2142 vty_out(vty, "Proto: I=IGMP P=PIM S=STATIC O=SOURCE%s%s", VTY_NEWLINE, VTY_NEWLINE);
2143
2144 vty_out(vty, "Source Group Proto Input iVifI Output oVifI TTL Uptime %s",
2145 VTY_NEWLINE);
2146
2147 now = pim_time_monotonic_sec();
2148
2149 /* print list of PIM and IGMP routes */
2150 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2151 char group_str[100];
2152 char source_str[100];
2153 int oif_vif_index;
2154
2155 if (!c_oil->installed)
2156 continue;
2157
2158 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2159 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2160
2161 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
2162 struct interface *ifp_in;
2163 struct interface *ifp_out;
2164 char oif_uptime[10];
2165 int ttl;
2166 char proto[5];
2167
2168 ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
2169 if (ttl < 1)
2170 continue;
2171
2172 ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
2173 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
2174
2175 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]);
2176
2177 proto[0] = '\0';
2178 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) {
2179 strcat(proto, "P");
2180 }
2181 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) {
2182 strcat(proto, "I");
2183 }
2184 if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) {
2185 strcat(proto, "O");
2186 }
2187
2188 vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s",
2189 source_str,
2190 group_str,
2191 proto,
2192 ifp_in ? ifp_in->name : "<iif?>",
2193 c_oil->oil.mfcc_parent,
2194 ifp_out ? ifp_out->name : "<oif?>",
2195 oif_vif_index,
2196 ttl,
2197 oif_uptime,
2198 VTY_NEWLINE);
2199 }
2200 }
2201
2202 /* Print list of static routes */
2203 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
2204 char group_str[100];
2205 char source_str[100];
2206 int oif_vif_index;
2207
2208 if (!s_route->c_oil.installed)
2209 continue;
2210
2211 pim_inet4_dump("<group?>", s_route->group, group_str, sizeof(group_str));
2212 pim_inet4_dump("<source?>", s_route->source, source_str, sizeof(source_str));
2213
2214 for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
2215 struct interface *ifp_in;
2216 struct interface *ifp_out;
2217 char oif_uptime[10];
2218 int ttl;
2219 char proto[5];
2220
2221 ttl = s_route->oif_ttls[oif_vif_index];
2222 if (ttl < 1)
2223 continue;
2224
2225 ifp_in = pim_if_find_by_vif_index(s_route->iif);
2226 ifp_out = pim_if_find_by_vif_index(oif_vif_index);
2227
2228 pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]);
2229
2230 proto[0] = '\0';
2231 strcat(proto, "S");
2232
2233 vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s",
2234 source_str,
2235 group_str,
2236 proto,
2237 ifp_in ? ifp_in->name : "<iif?>",
2238 s_route->iif,
2239 ifp_out ? ifp_out->name : "<oif?>",
2240 oif_vif_index,
2241 ttl,
2242 oif_uptime,
2243 VTY_NEWLINE);
2244 }
2245 }
2246 }
2247
2248 DEFUN (show_ip_mroute,
2249 show_ip_mroute_cmd,
2250 "show ip mroute",
2251 SHOW_STR
2252 IP_STR
2253 MROUTE_STR)
2254 {
2255 show_mroute(vty);
2256 return CMD_SUCCESS;
2257 }
2258
2259 static void show_mroute_count(struct vty *vty)
2260 {
2261 struct listnode *node;
2262 struct channel_oil *c_oil;
2263 struct static_route *s_route;
2264
2265 vty_out(vty, "%s", VTY_NEWLINE);
2266
2267 vty_out(vty, "Source Group Packets Bytes WrongIf %s",
2268 VTY_NEWLINE);
2269
2270 /* Print PIM and IGMP route counts */
2271 for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2272 char group_str[100];
2273 char source_str[100];
2274
2275 if (!c_oil->installed)
2276 continue;
2277
2278 pim_mroute_update_counters (c_oil);
2279
2280 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2281 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2282
2283 vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
2284 source_str,
2285 group_str,
2286 c_oil->cc.pktcnt,
2287 c_oil->cc.bytecnt,
2288 c_oil->cc.wrong_if,
2289 VTY_NEWLINE);
2290 }
2291
2292 /* Print static route counts */
2293 for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
2294 char group_str[100];
2295 char source_str[100];
2296
2297 if (!s_route->c_oil.installed)
2298 continue;
2299
2300 pim_mroute_update_counters (&s_route->c_oil);
2301
2302 pim_inet4_dump("<group?>", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2303 pim_inet4_dump("<source?>", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str));
2304
2305 vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
2306 source_str,
2307 group_str,
2308 s_route->c_oil.cc.pktcnt,
2309 s_route->c_oil.cc.bytecnt,
2310 s_route->c_oil.cc.wrong_if,
2311 VTY_NEWLINE);
2312 }
2313 }
2314
2315 DEFUN (show_ip_mroute_count,
2316 show_ip_mroute_count_cmd,
2317 "show ip mroute count",
2318 SHOW_STR
2319 IP_STR
2320 MROUTE_STR
2321 "Route and packet count data\n")
2322 {
2323 show_mroute_count(vty);
2324 return CMD_SUCCESS;
2325 }
2326
2327 DEFUN (show_ip_rib,
2328 show_ip_rib_cmd,
2329 "show ip rib A.B.C.D",
2330 SHOW_STR
2331 IP_STR
2332 RIB_STR
2333 "Unicast address\n")
2334 {
2335 int idx_ipv4 = 3;
2336 struct in_addr addr;
2337 const char *addr_str;
2338 struct pim_nexthop nexthop;
2339 char nexthop_addr_str[100];
2340 int result;
2341
2342 addr_str = argv[idx_ipv4]->arg;
2343 result = inet_pton(AF_INET, addr_str, &addr);
2344 if (result <= 0) {
2345 vty_out(vty, "Bad unicast address %s: errno=%d: %s%s",
2346 addr_str, errno, safe_strerror(errno), VTY_NEWLINE);
2347 return CMD_WARNING;
2348 }
2349
2350 if (pim_nexthop_lookup(&nexthop, addr, NULL)) {
2351 vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s",
2352 addr_str, VTY_NEWLINE);
2353 return CMD_WARNING;
2354 }
2355
2356 vty_out(vty, "Address NextHop Interface Metric Preference%s",
2357 VTY_NEWLINE);
2358
2359 pim_inet4_dump("<nexthop?>", nexthop.mrib_nexthop_addr,
2360 nexthop_addr_str, sizeof(nexthop_addr_str));
2361
2362 vty_out(vty, "%-15s %-15s %-9s %6d %10d%s",
2363 addr_str,
2364 nexthop_addr_str,
2365 nexthop.interface ? nexthop.interface->name : "<ifname?>",
2366 nexthop.mrib_route_metric,
2367 nexthop.mrib_metric_preference,
2368 VTY_NEWLINE);
2369
2370 return CMD_SUCCESS;
2371 }
2372
2373 static void show_ssmpingd(struct vty *vty)
2374 {
2375 struct listnode *node;
2376 struct ssmpingd_sock *ss;
2377 time_t now;
2378
2379 vty_out(vty, "Source Socket Address Port Uptime Requests%s",
2380 VTY_NEWLINE);
2381
2382 if (!qpim_ssmpingd_list)
2383 return;
2384
2385 now = pim_time_monotonic_sec();
2386
2387 for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) {
2388 char source_str[100];
2389 char ss_uptime[10];
2390 struct sockaddr_in bind_addr;
2391 socklen_t len = sizeof(bind_addr);
2392 char bind_addr_str[100];
2393
2394 pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str));
2395
2396 if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) {
2397 vty_out(vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d%s",
2398 source_str, ss->sock_fd, VTY_NEWLINE);
2399 }
2400
2401 pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str));
2402 pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation);
2403
2404 vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld%s",
2405 source_str,
2406 ss->sock_fd,
2407 bind_addr_str,
2408 ntohs(bind_addr.sin_port),
2409 ss_uptime,
2410 (long long)ss->requests,
2411 VTY_NEWLINE);
2412 }
2413 }
2414
2415 DEFUN (show_ip_ssmpingd,
2416 show_ip_ssmpingd_cmd,
2417 "show ip ssmpingd",
2418 SHOW_STR
2419 IP_STR
2420 SHOW_SSMPINGD_STR)
2421 {
2422 show_ssmpingd(vty);
2423 return CMD_SUCCESS;
2424 }
2425
2426 static int
2427 pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
2428 {
2429 int result;
2430 result = pim_rp_new (rp, group);
2431
2432 if (result == -1)
2433 {
2434 vty_out (vty, "%% Bad RP/group address specified: %s", rp);
2435 return CMD_WARNING;
2436 }
2437
2438 if (result == -2)
2439 {
2440 vty_out (vty, "%% No Path to RP address specified: %s", rp);
2441 return CMD_WARNING;
2442 }
2443
2444 if (result == -3)
2445 {
2446 vty_out (vty, "%% Group range specified cannot overlap");
2447 return CMD_ERR_NO_MATCH;
2448 }
2449
2450 return CMD_SUCCESS;
2451 }
2452
2453 DEFUN (ip_pim_keep_alive,
2454 ip_pim_keep_alive_cmd,
2455 "ip pim keep-alive-timer <31-600>",
2456 IP_STR
2457 "pim multicast routing\n"
2458 "Keep alive Timer"
2459 "Seconds")
2460 {
2461 qpim_keep_alive_time = atoi (argv[3]->arg);
2462 return CMD_SUCCESS;
2463 }
2464
2465 DEFUN (no_ip_pim_keep_alive,
2466 no_ip_pim_keep_alive_cmd,
2467 "no ip pim keep-alive-timer <31-600>",
2468 NO_STR
2469 IP_STR
2470 "pim multicast routing\n"
2471 "Keep alive Timer"
2472 "Seconds")
2473 {
2474 qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD;
2475 return CMD_SUCCESS;
2476 }
2477
2478 DEFUN (ip_pim_rp,
2479 ip_pim_rp_cmd,
2480 "ip pim rp A.B.C.D [A.B.C.D/M]",
2481 IP_STR
2482 "pim multicast routing\n"
2483 "Rendevous Point\n"
2484 "ip address of RP\n")
2485 {
2486 int idx_ipv4 = 3;
2487 return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
2488 }
2489
2490 static int
2491 pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
2492 {
2493 int result = pim_rp_del (rp, group);
2494
2495 if (result == -1)
2496 {
2497 vty_out (vty, "%% Unable to Decode specified RP");
2498 return CMD_WARNING;
2499 }
2500
2501 if (result == -2)
2502 {
2503 vty_out (vty, "%% Unable to find specified RP");
2504 return CMD_WARNING;
2505 }
2506
2507 return CMD_SUCCESS;
2508 }
2509
2510 DEFUN (no_ip_pim_rp,
2511 no_ip_pim_rp_cmd,
2512 "no ip pim rp A.B.C.D [A.B.C.D/M]",
2513 NO_STR
2514 IP_STR
2515 "pim multicast routing\n"
2516 "Rendevous Point\n"
2517 "ip address of RP\n")
2518 {
2519 int idx_ipv4 = 4;
2520 return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
2521 }
2522
2523 DEFUN (ip_multicast_routing,
2524 ip_multicast_routing_cmd,
2525 "ip multicast-routing",
2526 IP_STR
2527 "Enable IP multicast forwarding\n")
2528 {
2529 pim_mroute_socket_enable();
2530 pim_if_add_vif_all();
2531 mroute_add_all();
2532 static_mroute_add_all();
2533 return CMD_SUCCESS;
2534 }
2535
2536 DEFUN (no_ip_multicast_routing,
2537 no_ip_multicast_routing_cmd,
2538 "no ip multicast-routing",
2539 NO_STR
2540 IP_STR
2541 "Global IP configuration subcommands\n"
2542 "Enable IP multicast forwarding\n")
2543 {
2544 mroute_del_all();
2545 static_mroute_del_all();
2546 pim_if_del_vif_all();
2547 pim_mroute_socket_disable();
2548 return CMD_SUCCESS;
2549 }
2550
2551 DEFUN (ip_ssmpingd,
2552 ip_ssmpingd_cmd,
2553 "ip ssmpingd [A.B.C.D]",
2554 IP_STR
2555 CONF_SSMPINGD_STR
2556 "Source address\n")
2557 {
2558 int idx_ipv4 = 2;
2559 int result;
2560 struct in_addr source_addr;
2561 const char *source_str = (argc > idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
2562
2563 result = inet_pton(AF_INET, source_str, &source_addr);
2564 if (result <= 0) {
2565 vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
2566 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2567 return CMD_WARNING;
2568 }
2569
2570 result = pim_ssmpingd_start(source_addr);
2571 if (result) {
2572 vty_out(vty, "%% Failure starting ssmpingd for source %s: %d%s",
2573 source_str, result, VTY_NEWLINE);
2574 return CMD_WARNING;
2575 }
2576
2577 return CMD_SUCCESS;
2578 }
2579
2580 DEFUN (no_ip_ssmpingd,
2581 no_ip_ssmpingd_cmd,
2582 "no ip ssmpingd [A.B.C.D]",
2583 NO_STR
2584 IP_STR
2585 CONF_SSMPINGD_STR
2586 "Source address\n")
2587 {
2588 int idx_ipv4 = 3;
2589 int result;
2590 struct in_addr source_addr;
2591 const char *source_str = (argc > idx_ipv4) ? argv[idx_ipv4]->arg : "0.0.0.0";
2592
2593 result = inet_pton(AF_INET, source_str, &source_addr);
2594 if (result <= 0) {
2595 vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
2596 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2597 return CMD_WARNING;
2598 }
2599
2600 result = pim_ssmpingd_stop(source_addr);
2601 if (result) {
2602 vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d%s",
2603 source_str, result, VTY_NEWLINE);
2604 return CMD_WARNING;
2605 }
2606
2607 return CMD_SUCCESS;
2608 }
2609
2610 DEFUN (interface_ip_igmp,
2611 interface_ip_igmp_cmd,
2612 "ip igmp",
2613 IP_STR
2614 IFACE_IGMP_STR)
2615 {
2616 VTY_DECLVAR_CONTEXT(interface, ifp);
2617 struct pim_interface *pim_ifp;
2618
2619 pim_ifp = ifp->info;
2620
2621 if (!pim_ifp) {
2622 pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
2623 if (!pim_ifp) {
2624 vty_out(vty, "Could not enable IGMP on interface %s%s",
2625 ifp->name, VTY_NEWLINE);
2626 return CMD_WARNING;
2627 }
2628 }
2629 else {
2630 PIM_IF_DO_IGMP(pim_ifp->options);
2631 }
2632
2633 pim_if_addr_add_all(ifp);
2634 pim_if_membership_refresh(ifp);
2635
2636 return CMD_SUCCESS;
2637 }
2638
2639 DEFUN (interface_no_ip_igmp,
2640 interface_no_ip_igmp_cmd,
2641 "no ip igmp",
2642 NO_STR
2643 IP_STR
2644 IFACE_IGMP_STR)
2645 {
2646 VTY_DECLVAR_CONTEXT(interface, ifp);
2647 struct pim_interface *pim_ifp;
2648
2649 pim_ifp = ifp->info;
2650 if (!pim_ifp)
2651 return CMD_SUCCESS;
2652
2653 PIM_IF_DONT_IGMP(pim_ifp->options);
2654
2655 pim_if_membership_clear(ifp);
2656
2657 pim_if_addr_del_all_igmp(ifp);
2658
2659 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
2660 pim_if_delete(ifp);
2661 }
2662
2663 return CMD_SUCCESS;
2664 }
2665
2666 DEFUN (interface_ip_igmp_join,
2667 interface_ip_igmp_join_cmd,
2668 "ip igmp join A.B.C.D A.B.C.D",
2669 IP_STR
2670 IFACE_IGMP_STR
2671 "IGMP join multicast group\n"
2672 "Multicast group address\n"
2673 "Source address\n")
2674 {
2675 VTY_DECLVAR_CONTEXT(interface, ifp);
2676 int idx_ipv4 = 3;
2677 int idx_ipv4_2 = 4;
2678 const char *group_str;
2679 const char *source_str;
2680 struct in_addr group_addr;
2681 struct in_addr source_addr;
2682 int result;
2683
2684 /* Group address */
2685 group_str = argv[idx_ipv4]->arg;
2686 result = inet_pton(AF_INET, group_str, &group_addr);
2687 if (result <= 0) {
2688 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2689 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
2690 return CMD_WARNING;
2691 }
2692
2693 /* Source address */
2694 source_str = argv[idx_ipv4_2]->arg;
2695 result = inet_pton(AF_INET, source_str, &source_addr);
2696 if (result <= 0) {
2697 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2698 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2699 return CMD_WARNING;
2700 }
2701
2702 result = pim_if_igmp_join_add(ifp, group_addr, source_addr);
2703 if (result) {
2704 vty_out(vty, "%% Failure joining IGMP group %s source %s on interface %s: %d%s",
2705 group_str, source_str, ifp->name, result, VTY_NEWLINE);
2706 return CMD_WARNING;
2707 }
2708
2709 return CMD_SUCCESS;
2710 }
2711
2712 DEFUN (interface_no_ip_igmp_join,
2713 interface_no_ip_igmp_join_cmd,
2714 "no ip igmp join A.B.C.D A.B.C.D",
2715 NO_STR
2716 IP_STR
2717 IFACE_IGMP_STR
2718 "IGMP join multicast group\n"
2719 "Multicast group address\n"
2720 "Source address\n")
2721 {
2722 VTY_DECLVAR_CONTEXT(interface, ifp);
2723 int idx_ipv4 = 4;
2724 int idx_ipv4_2 = 5;
2725 const char *group_str;
2726 const char *source_str;
2727 struct in_addr group_addr;
2728 struct in_addr source_addr;
2729 int result;
2730
2731 /* Group address */
2732 group_str = argv[idx_ipv4]->arg;
2733 result = inet_pton(AF_INET, group_str, &group_addr);
2734 if (result <= 0) {
2735 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2736 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
2737 return CMD_WARNING;
2738 }
2739
2740 /* Source address */
2741 source_str = argv[idx_ipv4_2]->arg;
2742 result = inet_pton(AF_INET, source_str, &source_addr);
2743 if (result <= 0) {
2744 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2745 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2746 return CMD_WARNING;
2747 }
2748
2749 result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
2750 if (result) {
2751 vty_out(vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d%s",
2752 group_str, source_str, ifp->name, result, VTY_NEWLINE);
2753 return CMD_WARNING;
2754 }
2755
2756 return CMD_SUCCESS;
2757 }
2758
2759 /*
2760 CLI reconfiguration affects the interface level (struct pim_interface).
2761 This function propagates the reconfiguration to every active socket
2762 for that interface.
2763 */
2764 static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
2765 {
2766 struct interface *ifp;
2767 struct pim_interface *pim_ifp;
2768
2769 zassert(igmp);
2770
2771 /* other querier present? */
2772
2773 if (igmp->t_other_querier_timer)
2774 return;
2775
2776 /* this is the querier */
2777
2778 zassert(igmp->interface);
2779 zassert(igmp->interface->info);
2780
2781 ifp = igmp->interface;
2782 pim_ifp = ifp->info;
2783
2784 if (PIM_DEBUG_IGMP_TRACE) {
2785 char ifaddr_str[100];
2786 pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2787 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
2788 __PRETTY_FUNCTION__,
2789 ifaddr_str,
2790 ifp->name,
2791 pim_ifp->igmp_default_query_interval);
2792 }
2793
2794 /*
2795 igmp_startup_mode_on() will reset QQI:
2796
2797 igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
2798 */
2799 igmp_startup_mode_on(igmp);
2800 }
2801
2802 static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
2803 {
2804 if (igmp->t_igmp_query_timer) {
2805 /* other querier present */
2806 zassert(igmp->t_igmp_query_timer);
2807 zassert(!igmp->t_other_querier_timer);
2808
2809 pim_igmp_general_query_off(igmp);
2810 pim_igmp_general_query_on(igmp);
2811
2812 zassert(igmp->t_igmp_query_timer);
2813 zassert(!igmp->t_other_querier_timer);
2814 }
2815 else {
2816 /* this is the querier */
2817
2818 zassert(!igmp->t_igmp_query_timer);
2819 zassert(igmp->t_other_querier_timer);
2820
2821 pim_igmp_other_querier_timer_off(igmp);
2822 pim_igmp_other_querier_timer_on(igmp);
2823
2824 zassert(!igmp->t_igmp_query_timer);
2825 zassert(igmp->t_other_querier_timer);
2826 }
2827 }
2828
2829 static void change_query_interval(struct pim_interface *pim_ifp,
2830 int query_interval)
2831 {
2832 struct listnode *sock_node;
2833 struct igmp_sock *igmp;
2834
2835 pim_ifp->igmp_default_query_interval = query_interval;
2836
2837 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2838 igmp_sock_query_interval_reconfig(igmp);
2839 igmp_sock_query_reschedule(igmp);
2840 }
2841 }
2842
2843 static void change_query_max_response_time(struct pim_interface *pim_ifp,
2844 int query_max_response_time_dsec)
2845 {
2846 struct listnode *sock_node;
2847 struct igmp_sock *igmp;
2848
2849 pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec;
2850
2851 /*
2852 Below we modify socket/group/source timers in order to quickly
2853 reflect the change. Otherwise, those timers would eventually catch
2854 up.
2855 */
2856
2857 /* scan all sockets */
2858 for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2859 struct listnode *grp_node;
2860 struct igmp_group *grp;
2861
2862 /* reschedule socket general query */
2863 igmp_sock_query_reschedule(igmp);
2864
2865 /* scan socket groups */
2866 for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) {
2867 struct listnode *src_node;
2868 struct igmp_source *src;
2869
2870 /* reset group timers for groups in EXCLUDE mode */
2871 if (grp->group_filtermode_isexcl) {
2872 igmp_group_reset_gmi(grp);
2873 }
2874
2875 /* scan group sources */
2876 for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
2877
2878 /* reset source timers for sources with running timers */
2879 if (src->t_source_timer) {
2880 igmp_source_reset_gmi(igmp, grp, src);
2881 }
2882 }
2883 }
2884 }
2885 }
2886
2887 #define IGMP_QUERY_INTERVAL_MIN (1)
2888 #define IGMP_QUERY_INTERVAL_MAX (1800)
2889
2890 DEFUN (interface_ip_igmp_query_interval,
2891 interface_ip_igmp_query_interval_cmd,
2892 "ip igmp query-interval (1-1800)",
2893 IP_STR
2894 IFACE_IGMP_STR
2895 IFACE_IGMP_QUERY_INTERVAL_STR
2896 "Query interval in seconds\n")
2897 {
2898 VTY_DECLVAR_CONTEXT(interface, ifp);
2899 struct pim_interface *pim_ifp;
2900 int query_interval;
2901 int query_interval_dsec;
2902
2903 pim_ifp = ifp->info;
2904
2905 if (!pim_ifp) {
2906 vty_out(vty,
2907 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2908 ifp->name,
2909 VTY_NEWLINE);
2910 return CMD_WARNING;
2911 }
2912
2913 query_interval = atoi(argv[4]->arg);
2914 query_interval_dsec = 10 * query_interval;
2915
2916 /*
2917 It seems we don't need to check bounds since command.c does it
2918 already, but we verify them anyway for extra safety.
2919 */
2920 if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
2921 vty_out(vty, "General query interval %d lower than minimum %d%s",
2922 query_interval,
2923 IGMP_QUERY_INTERVAL_MIN,
2924 VTY_NEWLINE);
2925 return CMD_WARNING;
2926 }
2927 if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
2928 vty_out(vty, "General query interval %d higher than maximum %d%s",
2929 query_interval,
2930 IGMP_QUERY_INTERVAL_MAX,
2931 VTY_NEWLINE);
2932 return CMD_WARNING;
2933 }
2934
2935 if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2936 vty_out(vty,
2937 "Can't set general query interval %d dsec <= query max response time %d dsec.%s",
2938 query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2939 VTY_NEWLINE);
2940 return CMD_WARNING;
2941 }
2942
2943 change_query_interval(pim_ifp, query_interval);
2944
2945 return CMD_SUCCESS;
2946 }
2947
2948 DEFUN (interface_no_ip_igmp_query_interval,
2949 interface_no_ip_igmp_query_interval_cmd,
2950 "no ip igmp query-interval",
2951 NO_STR
2952 IP_STR
2953 IFACE_IGMP_STR
2954 IFACE_IGMP_QUERY_INTERVAL_STR)
2955 {
2956 VTY_DECLVAR_CONTEXT(interface, ifp);
2957 struct pim_interface *pim_ifp;
2958 int default_query_interval_dsec;
2959
2960 pim_ifp = ifp->info;
2961
2962 if (!pim_ifp)
2963 return CMD_SUCCESS;
2964
2965 default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
2966
2967 if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2968 vty_out(vty,
2969 "Can't set default general query interval %d dsec <= query max response time %d dsec.%s",
2970 default_query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2971 VTY_NEWLINE);
2972 return CMD_WARNING;
2973 }
2974
2975 change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
2976
2977 return CMD_SUCCESS;
2978 }
2979
2980 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1)
2981 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25)
2982
2983 DEFUN (interface_ip_igmp_query_max_response_time,
2984 interface_ip_igmp_query_max_response_time_cmd,
2985 "ip igmp query-max-response-time (1-25)",
2986 IP_STR
2987 IFACE_IGMP_STR
2988 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
2989 "Query response value in seconds\n")
2990 {
2991 VTY_DECLVAR_CONTEXT(interface, ifp);
2992 struct pim_interface *pim_ifp;
2993 int query_max_response_time;
2994
2995 pim_ifp = ifp->info;
2996
2997 if (!pim_ifp) {
2998 vty_out(vty,
2999 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3000 ifp->name,
3001 VTY_NEWLINE);
3002 return CMD_WARNING;
3003 }
3004
3005 query_max_response_time = atoi(argv[4]->arg);
3006
3007 /*
3008 It seems we don't need to check bounds since command.c does it
3009 already, but we verify them anyway for extra safety.
3010 */
3011 if (query_max_response_time < IGMP_QUERY_MAX_RESPONSE_TIME_MIN) {
3012 vty_out(vty, "Query max response time %d sec lower than minimum %d sec%s",
3013 query_max_response_time,
3014 IGMP_QUERY_MAX_RESPONSE_TIME_MIN,
3015 VTY_NEWLINE);
3016 return CMD_WARNING;
3017 }
3018 if (query_max_response_time > IGMP_QUERY_MAX_RESPONSE_TIME_MAX) {
3019 vty_out(vty, "Query max response time %d sec higher than maximum %d sec%s",
3020 query_max_response_time,
3021 IGMP_QUERY_MAX_RESPONSE_TIME_MAX,
3022 VTY_NEWLINE);
3023 return CMD_WARNING;
3024 }
3025
3026 if (query_max_response_time >= pim_ifp->igmp_default_query_interval) {
3027 vty_out(vty,
3028 "Can't set query max response time %d sec >= general query interval %d sec%s",
3029 query_max_response_time, pim_ifp->igmp_default_query_interval,
3030 VTY_NEWLINE);
3031 return CMD_WARNING;
3032 }
3033
3034 change_query_max_response_time(pim_ifp, 10 * query_max_response_time);
3035
3036 return CMD_SUCCESS;
3037 }
3038
3039 DEFUN (interface_no_ip_igmp_query_max_response_time,
3040 interface_no_ip_igmp_query_max_response_time_cmd,
3041 "no ip igmp query-max-response-time",
3042 NO_STR
3043 IP_STR
3044 IFACE_IGMP_STR
3045 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR)
3046 {
3047 VTY_DECLVAR_CONTEXT(interface, ifp);
3048 struct pim_interface *pim_ifp;
3049 int default_query_interval_dsec;
3050
3051 pim_ifp = ifp->info;
3052
3053 if (!pim_ifp)
3054 return CMD_SUCCESS;
3055
3056 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3057
3058 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
3059 vty_out(vty,
3060 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
3061 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
3062 VTY_NEWLINE);
3063 return CMD_WARNING;
3064 }
3065
3066 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
3067
3068 return CMD_SUCCESS;
3069 }
3070
3071 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
3072 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
3073
3074 DEFUN (interface_ip_igmp_query_max_response_time_dsec,
3075 interface_ip_igmp_query_max_response_time_dsec_cmd,
3076 "ip igmp query-max-response-time-dsec (10-250)",
3077 IP_STR
3078 IFACE_IGMP_STR
3079 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
3080 "Query response value in deciseconds\n")
3081 {
3082 VTY_DECLVAR_CONTEXT(interface, ifp);
3083 struct pim_interface *pim_ifp;
3084 int query_max_response_time_dsec;
3085 int default_query_interval_dsec;
3086
3087 pim_ifp = ifp->info;
3088
3089 if (!pim_ifp) {
3090 vty_out(vty,
3091 "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3092 ifp->name,
3093 VTY_NEWLINE);
3094 return CMD_WARNING;
3095 }
3096
3097 query_max_response_time_dsec = atoi(argv[4]->arg);
3098
3099 /*
3100 It seems we don't need to check bounds since command.c does it
3101 already, but we verify them anyway for extra safety.
3102 */
3103 if (query_max_response_time_dsec < IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC) {
3104 vty_out(vty, "Query max response time %d dsec lower than minimum %d dsec%s",
3105 query_max_response_time_dsec,
3106 IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC,
3107 VTY_NEWLINE);
3108 return CMD_WARNING;
3109 }
3110 if (query_max_response_time_dsec > IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC) {
3111 vty_out(vty, "Query max response time %d dsec higher than maximum %d dsec%s",
3112 query_max_response_time_dsec,
3113 IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC,
3114 VTY_NEWLINE);
3115 return CMD_WARNING;
3116 }
3117
3118 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3119
3120 if (query_max_response_time_dsec >= default_query_interval_dsec) {
3121 vty_out(vty,
3122 "Can't set query max response time %d dsec >= general query interval %d dsec%s",
3123 query_max_response_time_dsec, default_query_interval_dsec,
3124 VTY_NEWLINE);
3125 return CMD_WARNING;
3126 }
3127
3128 change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
3129
3130 return CMD_SUCCESS;
3131 }
3132
3133 DEFUN (interface_no_ip_igmp_query_max_response_time_dsec,
3134 interface_no_ip_igmp_query_max_response_time_dsec_cmd,
3135 "no ip igmp query-max-response-time-dsec",
3136 NO_STR
3137 IP_STR
3138 IFACE_IGMP_STR
3139 IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
3140 {
3141 VTY_DECLVAR_CONTEXT(interface, ifp);
3142 struct pim_interface *pim_ifp;
3143 int default_query_interval_dsec;
3144
3145 pim_ifp = ifp->info;
3146
3147 if (!pim_ifp)
3148 return CMD_SUCCESS;
3149
3150 default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3151
3152 if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
3153 vty_out(vty,
3154 "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
3155 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
3156 VTY_NEWLINE);
3157 return CMD_WARNING;
3158 }
3159
3160 change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
3161
3162 return CMD_SUCCESS;
3163 }
3164
3165 DEFUN (interface_ip_pim_drprio,
3166 interface_ip_pim_drprio_cmd,
3167 "ip pim drpriority (1-4294967295)",
3168 IP_STR
3169 PIM_STR
3170 "Set the Designated Router Election Priority\n"
3171 "Value of the new DR Priority\n")
3172 {
3173 VTY_DECLVAR_CONTEXT(interface, ifp);
3174 int idx_number = 3;
3175 struct pim_interface *pim_ifp;
3176 uint32_t old_dr_prio;
3177
3178 pim_ifp = ifp->info;
3179
3180 if (!pim_ifp) {
3181 vty_out(vty, "Please enable PIM on interface, first%s", VTY_NEWLINE);
3182 return CMD_WARNING;
3183 }
3184
3185 old_dr_prio = pim_ifp->pim_dr_priority;
3186
3187 pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
3188
3189 if (old_dr_prio != pim_ifp->pim_dr_priority) {
3190 if (pim_if_dr_election(ifp))
3191 pim_hello_restart_now(ifp);
3192 }
3193
3194 return CMD_SUCCESS;
3195 }
3196
3197 DEFUN (interface_no_ip_pim_drprio,
3198 interface_no_ip_pim_drprio_cmd,
3199 "no ip pim drpriority [(1-4294967295)]",
3200 NO_STR
3201 IP_STR
3202 PIM_STR
3203 "Revert the Designated Router Priority to default\n"
3204 "Old Value of the Priority\n")
3205 {
3206 VTY_DECLVAR_CONTEXT(interface, ifp);
3207 struct pim_interface *pim_ifp;
3208
3209 pim_ifp = ifp->info;
3210
3211 if (!pim_ifp) {
3212 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3213 return CMD_WARNING;
3214 }
3215
3216 if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
3217 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
3218 if (pim_if_dr_election(ifp))
3219 pim_hello_restart_now(ifp);
3220 }
3221
3222 return CMD_SUCCESS;
3223 }
3224
3225 static int
3226 pim_cmd_interface_add (struct interface *ifp, enum pim_interface_type itype)
3227 {
3228 struct pim_interface *pim_ifp = ifp->info;
3229 struct in_addr null = { .s_addr = 0 };
3230
3231 if (!pim_ifp) {
3232 pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
3233 if (!pim_ifp) {
3234 return 0;
3235 }
3236 }
3237 else {
3238 PIM_IF_DO_PIM(pim_ifp->options);
3239 }
3240
3241 pim_ifp->itype = itype;
3242 pim_if_addr_add_all(ifp);
3243 pim_if_membership_refresh(ifp);
3244
3245 pim_rp_check_rp (null, pim_ifp->primary_address);
3246 return 1;
3247 }
3248
3249
3250 DEFUN (interface_ip_pim_ssm,
3251 interface_ip_pim_ssm_cmd,
3252 "ip pim ssm",
3253 IP_STR
3254 PIM_STR
3255 IFACE_PIM_STR)
3256 {
3257 VTY_DECLVAR_CONTEXT(interface, ifp);
3258
3259 if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SSM)) {
3260 vty_out(vty, "Could not enable PIM SSM on interface%s", VTY_NEWLINE);
3261 return CMD_WARNING;
3262 }
3263
3264 return CMD_SUCCESS;
3265 }
3266
3267 DEFUN (interface_ip_pim_sm,
3268 interface_ip_pim_sm_cmd,
3269 "ip pim sm",
3270 IP_STR
3271 PIM_STR
3272 IFACE_PIM_SM_STR)
3273 {
3274 VTY_DECLVAR_CONTEXT(interface, ifp);
3275 if (!pim_cmd_interface_add(ifp, PIM_INTERFACE_SM)) {
3276 vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE);
3277 return CMD_WARNING;
3278 }
3279
3280 pim_if_create_pimreg();
3281
3282 return CMD_SUCCESS;
3283 }
3284
3285 static int
3286 pim_cmd_interface_delete (struct interface *ifp)
3287 {
3288 struct pim_interface *pim_ifp = ifp->info;
3289
3290 if (!pim_ifp)
3291 return 1;
3292
3293 PIM_IF_DONT_PIM(pim_ifp->options);
3294
3295 pim_if_membership_clear(ifp);
3296
3297 /*
3298 pim_if_addr_del_all() removes all sockets from
3299 pim_ifp->igmp_socket_list.
3300 */
3301 pim_if_addr_del_all(ifp);
3302
3303 /*
3304 pim_sock_delete() removes all neighbors from
3305 pim_ifp->pim_neighbor_list.
3306 */
3307 pim_sock_delete(ifp, "pim unconfigured on interface");
3308
3309 if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
3310 pim_if_delete(ifp);
3311 }
3312
3313 return 1;
3314 }
3315
3316 DEFUN (interface_no_ip_pim_ssm,
3317 interface_no_ip_pim_ssm_cmd,
3318 "no ip pim ssm",
3319 NO_STR
3320 IP_STR
3321 PIM_STR
3322 IFACE_PIM_STR)
3323 {
3324 VTY_DECLVAR_CONTEXT(interface, ifp);
3325 if (!pim_cmd_interface_delete(ifp)) {
3326 vty_out(vty, "Unable to delete interface information%s", VTY_NEWLINE);
3327 return CMD_WARNING;
3328 }
3329
3330 return CMD_SUCCESS;
3331 }
3332
3333 DEFUN (interface_no_ip_pim_sm,
3334 interface_no_ip_pim_sm_cmd,
3335 "no ip pim sm",
3336 NO_STR
3337 IP_STR
3338 PIM_STR
3339 IFACE_PIM_SM_STR)
3340 {
3341 VTY_DECLVAR_CONTEXT(interface, ifp);
3342 if (!pim_cmd_interface_delete(ifp)) {
3343 vty_out(vty, "Unable to delete interface information%s", VTY_NEWLINE);
3344 return CMD_WARNING;
3345 }
3346
3347 return CMD_SUCCESS;
3348 }
3349
3350 DEFUN (interface_ip_mroute,
3351 interface_ip_mroute_cmd,
3352 "ip mroute INTERFACE A.B.C.D",
3353 IP_STR
3354 "Add multicast route\n"
3355 "Outgoing interface name\n"
3356 "Group address\n")
3357 {
3358 VTY_DECLVAR_CONTEXT(interface, iif);
3359 int idx_interface = 2;
3360 int idx_ipv4 = 3;
3361 struct interface *oif;
3362 const char *oifname;
3363 const char *grp_str;
3364 struct in_addr grp_addr;
3365 struct in_addr src_addr;
3366 int result;
3367
3368 oifname = argv[idx_interface]->arg;
3369 oif = if_lookup_by_name(oifname);
3370 if (!oif) {
3371 vty_out(vty, "No such interface name %s%s",
3372 oifname, VTY_NEWLINE);
3373 return CMD_WARNING;
3374 }
3375
3376 grp_str = argv[idx_ipv4]->arg;
3377 result = inet_pton(AF_INET, grp_str, &grp_addr);
3378 if (result <= 0) {
3379 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3380 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3381 return CMD_WARNING;
3382 }
3383
3384 src_addr.s_addr = INADDR_ANY;
3385
3386 if (pim_static_add(iif, oif, grp_addr, src_addr)) {
3387 vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
3388 return CMD_WARNING;
3389 }
3390
3391 return CMD_SUCCESS;
3392 }
3393
3394 DEFUN (interface_ip_mroute_source,
3395 interface_ip_mroute_source_cmd,
3396 "ip mroute INTERFACE A.B.C.D A.B.C.D",
3397 IP_STR
3398 "Add multicast route\n"
3399 "Outgoing interface name\n"
3400 "Group address\n"
3401 "Source address\n")
3402 {
3403 VTY_DECLVAR_CONTEXT(interface, iif);
3404 int idx_interface = 2;
3405 int idx_ipv4 = 3;
3406 int idx_ipv4_2 = 4;
3407 struct interface *oif;
3408 const char *oifname;
3409 const char *grp_str;
3410 struct in_addr grp_addr;
3411 const char *src_str;
3412 struct in_addr src_addr;
3413 int result;
3414
3415 oifname = argv[idx_interface]->arg;
3416 oif = if_lookup_by_name(oifname);
3417 if (!oif) {
3418 vty_out(vty, "No such interface name %s%s",
3419 oifname, VTY_NEWLINE);
3420 return CMD_WARNING;
3421 }
3422
3423 grp_str = argv[idx_ipv4]->arg;
3424 result = inet_pton(AF_INET, grp_str, &grp_addr);
3425 if (result <= 0) {
3426 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3427 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3428 return CMD_WARNING;
3429 }
3430
3431 src_str = argv[idx_ipv4_2]->arg;
3432 result = inet_pton(AF_INET, src_str, &src_addr);
3433 if (result <= 0) {
3434 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3435 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
3436 return CMD_WARNING;
3437 }
3438
3439 if (pim_static_add(iif, oif, grp_addr, src_addr)) {
3440 vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
3441 return CMD_WARNING;
3442 }
3443
3444 return CMD_SUCCESS;
3445 }
3446
3447 DEFUN (interface_no_ip_mroute,
3448 interface_no_ip_mroute_cmd,
3449 "no ip mroute INTERFACE A.B.C.D",
3450 NO_STR
3451 IP_STR
3452 "Add multicast route\n"
3453 "Outgoing interface name\n"
3454 "Group Address\n")
3455 {
3456 VTY_DECLVAR_CONTEXT(interface, iif);
3457 int idx_interface = 3;
3458 int idx_ipv4 = 4;
3459 struct interface *oif;
3460 const char *oifname;
3461 const char *grp_str;
3462 struct in_addr grp_addr;
3463 struct in_addr src_addr;
3464 int result;
3465
3466 oifname = argv[idx_interface]->arg;
3467 oif = if_lookup_by_name(oifname);
3468 if (!oif) {
3469 vty_out(vty, "No such interface name %s%s",
3470 oifname, VTY_NEWLINE);
3471 return CMD_WARNING;
3472 }
3473
3474 grp_str = argv[idx_ipv4]->arg;
3475 result = inet_pton(AF_INET, grp_str, &grp_addr);
3476 if (result <= 0) {
3477 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3478 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3479 return CMD_WARNING;
3480 }
3481
3482 src_addr.s_addr = INADDR_ANY;
3483
3484 if (pim_static_del(iif, oif, grp_addr, src_addr)) {
3485 vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
3486 return CMD_WARNING;
3487 }
3488
3489 return CMD_SUCCESS;
3490 }
3491
3492 DEFUN (interface_no_ip_mroute_source,
3493 interface_no_ip_mroute_source_cmd,
3494 "no ip mroute INTERFACE A.B.C.D A.B.C.D",
3495 NO_STR
3496 IP_STR
3497 "Add multicast route\n"
3498 "Outgoing interface name\n"
3499 "Group Address\n"
3500 "Source Address\n")
3501 {
3502 VTY_DECLVAR_CONTEXT(interface, iif);
3503 int idx_interface = 3;
3504 int idx_ipv4 = 4;
3505 int idx_ipv4_2 = 5;
3506 struct interface *oif;
3507 const char *oifname;
3508 const char *grp_str;
3509 struct in_addr grp_addr;
3510 const char *src_str;
3511 struct in_addr src_addr;
3512 int result;
3513
3514 oifname = argv[idx_interface]->arg;
3515 oif = if_lookup_by_name(oifname);
3516 if (!oif) {
3517 vty_out(vty, "No such interface name %s%s",
3518 oifname, VTY_NEWLINE);
3519 return CMD_WARNING;
3520 }
3521
3522 grp_str = argv[idx_ipv4]->arg;
3523 result = inet_pton(AF_INET, grp_str, &grp_addr);
3524 if (result <= 0) {
3525 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3526 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3527 return CMD_WARNING;
3528 }
3529
3530 src_str = argv[idx_ipv4_2]->arg;
3531 result = inet_pton(AF_INET, src_str, &src_addr);
3532 if (result <= 0) {
3533 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3534 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
3535 return CMD_WARNING;
3536 }
3537
3538 if (pim_static_del(iif, oif, grp_addr, src_addr)) {
3539 vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
3540 return CMD_WARNING;
3541 }
3542
3543 return CMD_SUCCESS;
3544 }
3545
3546 DEFUN (interface_ip_pim_hello,
3547 interface_ip_pim_hello_cmd,
3548 "ip pim hello (1-180) [(1-180)]",
3549 IP_STR
3550 PIM_STR
3551 IFACE_PIM_HELLO_STR
3552 IFACE_PIM_HELLO_TIME_STR
3553 IFACE_PIM_HELLO_HOLD_STR)
3554 {
3555 VTY_DECLVAR_CONTEXT(interface, ifp);
3556 int idx_time = 3;
3557 int idx_hold = 4;
3558 struct pim_interface *pim_ifp;
3559
3560 pim_ifp = ifp->info;
3561
3562 if (!pim_ifp) {
3563 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3564 return CMD_WARNING;
3565 }
3566
3567 pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
3568
3569 if (argc > idx_hold)
3570 pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10);
3571
3572 return CMD_SUCCESS;
3573 }
3574
3575
3576
3577 DEFUN (interface_no_ip_pim_hello,
3578 interface_no_ip_pim_hello_cmd,
3579 "no ip pim hello [(1-180) (1-180)]",
3580 NO_STR
3581 IP_STR
3582 PIM_STR
3583 IFACE_PIM_HELLO_STR
3584 IFACE_PIM_HELLO_TIME_STR
3585 IFACE_PIM_HELLO_HOLD_STR)
3586 {
3587 VTY_DECLVAR_CONTEXT(interface, ifp);
3588 struct pim_interface *pim_ifp;
3589
3590 pim_ifp = ifp->info;
3591
3592 if (!pim_ifp) {
3593 vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3594 return CMD_WARNING;
3595 }
3596
3597 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
3598 pim_ifp->pim_default_holdtime = -1;
3599
3600 return CMD_SUCCESS;
3601 }
3602
3603 DEFUN (debug_igmp,
3604 debug_igmp_cmd,
3605 "debug igmp",
3606 DEBUG_STR
3607 DEBUG_IGMP_STR)
3608 {
3609 PIM_DO_DEBUG_IGMP_EVENTS;
3610 PIM_DO_DEBUG_IGMP_PACKETS;
3611 PIM_DO_DEBUG_IGMP_TRACE;
3612 return CMD_SUCCESS;
3613 }
3614
3615 DEFUN (no_debug_igmp,
3616 no_debug_igmp_cmd,
3617 "no debug igmp",
3618 NO_STR
3619 DEBUG_STR
3620 DEBUG_IGMP_STR)
3621 {
3622 PIM_DONT_DEBUG_IGMP_EVENTS;
3623 PIM_DONT_DEBUG_IGMP_PACKETS;
3624 PIM_DONT_DEBUG_IGMP_TRACE;
3625 return CMD_SUCCESS;
3626 }
3627
3628
3629 DEFUN (debug_igmp_events,
3630 debug_igmp_events_cmd,
3631 "debug igmp events",
3632 DEBUG_STR
3633 DEBUG_IGMP_STR
3634 DEBUG_IGMP_EVENTS_STR)
3635 {
3636 PIM_DO_DEBUG_IGMP_EVENTS;
3637 return CMD_SUCCESS;
3638 }
3639
3640 DEFUN (no_debug_igmp_events,
3641 no_debug_igmp_events_cmd,
3642 "no debug igmp events",
3643 NO_STR
3644 DEBUG_STR
3645 DEBUG_IGMP_STR
3646 DEBUG_IGMP_EVENTS_STR)
3647 {
3648 PIM_DONT_DEBUG_IGMP_EVENTS;
3649 return CMD_SUCCESS;
3650 }
3651
3652
3653 DEFUN (debug_igmp_packets,
3654 debug_igmp_packets_cmd,
3655 "debug igmp packets",
3656 DEBUG_STR
3657 DEBUG_IGMP_STR
3658 DEBUG_IGMP_PACKETS_STR)
3659 {
3660 PIM_DO_DEBUG_IGMP_PACKETS;
3661 return CMD_SUCCESS;
3662 }
3663
3664 DEFUN (no_debug_igmp_packets,
3665 no_debug_igmp_packets_cmd,
3666 "no debug igmp packets",
3667 NO_STR
3668 DEBUG_STR
3669 DEBUG_IGMP_STR
3670 DEBUG_IGMP_PACKETS_STR)
3671 {
3672 PIM_DONT_DEBUG_IGMP_PACKETS;
3673 return CMD_SUCCESS;
3674 }
3675
3676
3677 DEFUN (debug_igmp_trace,
3678 debug_igmp_trace_cmd,
3679 "debug igmp trace",
3680 DEBUG_STR
3681 DEBUG_IGMP_STR
3682 DEBUG_IGMP_TRACE_STR)
3683 {
3684 PIM_DO_DEBUG_IGMP_TRACE;
3685 return CMD_SUCCESS;
3686 }
3687
3688 DEFUN (no_debug_igmp_trace,
3689 no_debug_igmp_trace_cmd,
3690 "no debug igmp trace",
3691 NO_STR
3692 DEBUG_STR
3693 DEBUG_IGMP_STR
3694 DEBUG_IGMP_TRACE_STR)
3695 {
3696 PIM_DONT_DEBUG_IGMP_TRACE;
3697 return CMD_SUCCESS;
3698 }
3699
3700
3701 DEFUN (debug_mroute,
3702 debug_mroute_cmd,
3703 "debug mroute",
3704 DEBUG_STR
3705 DEBUG_MROUTE_STR)
3706 {
3707 PIM_DO_DEBUG_MROUTE;
3708 return CMD_SUCCESS;
3709 }
3710
3711 DEFUN (debug_mroute_detail,
3712 debug_mroute_detail_cmd,
3713 "debug mroute detail",
3714 DEBUG_STR
3715 DEBUG_MROUTE_STR
3716 "detailed\n")
3717 {
3718 PIM_DO_DEBUG_MROUTE_DETAIL;
3719 return CMD_SUCCESS;
3720 }
3721
3722 DEFUN (no_debug_mroute,
3723 no_debug_mroute_cmd,
3724 "no debug mroute",
3725 NO_STR
3726 DEBUG_STR
3727 DEBUG_MROUTE_STR)
3728 {
3729 PIM_DONT_DEBUG_MROUTE;
3730 return CMD_SUCCESS;
3731 }
3732
3733 DEFUN (no_debug_mroute_detail,
3734 no_debug_mroute_detail_cmd,
3735 "no debug mroute detail",
3736 NO_STR
3737 DEBUG_STR
3738 DEBUG_MROUTE_STR
3739 "detailed\n")
3740 {
3741 PIM_DONT_DEBUG_MROUTE_DETAIL;
3742 return CMD_SUCCESS;
3743 }
3744
3745 DEFUN (debug_static,
3746 debug_static_cmd,
3747 "debug static",
3748 DEBUG_STR
3749 DEBUG_STATIC_STR)
3750 {
3751 PIM_DO_DEBUG_STATIC;
3752 return CMD_SUCCESS;
3753 }
3754
3755 DEFUN (no_debug_static,
3756 no_debug_static_cmd,
3757 "no debug static",
3758 NO_STR
3759 DEBUG_STR
3760 DEBUG_STATIC_STR)
3761 {
3762 PIM_DONT_DEBUG_STATIC;
3763 return CMD_SUCCESS;
3764 }
3765
3766
3767 DEFUN (debug_pim,
3768 debug_pim_cmd,
3769 "debug pim",
3770 DEBUG_STR
3771 DEBUG_PIM_STR)
3772 {
3773 PIM_DO_DEBUG_PIM_EVENTS;
3774 PIM_DO_DEBUG_PIM_PACKETS;
3775 PIM_DO_DEBUG_PIM_TRACE;
3776 return CMD_SUCCESS;
3777 }
3778
3779 DEFUN (no_debug_pim,
3780 no_debug_pim_cmd,
3781 "no debug pim",
3782 NO_STR
3783 DEBUG_STR
3784 DEBUG_PIM_STR)
3785 {
3786 PIM_DONT_DEBUG_PIM_EVENTS;
3787 PIM_DONT_DEBUG_PIM_PACKETS;
3788 PIM_DONT_DEBUG_PIM_TRACE;
3789
3790 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
3791 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
3792
3793 return CMD_SUCCESS;
3794 }
3795
3796
3797 DEFUN (debug_pim_events,
3798 debug_pim_events_cmd,
3799 "debug pim events",
3800 DEBUG_STR
3801 DEBUG_PIM_STR
3802 DEBUG_PIM_EVENTS_STR)
3803 {
3804 PIM_DO_DEBUG_PIM_EVENTS;
3805 return CMD_SUCCESS;
3806 }
3807
3808 DEFUN (no_debug_pim_events,
3809 no_debug_pim_events_cmd,
3810 "no debug pim events",
3811 NO_STR
3812 DEBUG_STR
3813 DEBUG_PIM_STR
3814 DEBUG_PIM_EVENTS_STR)
3815 {
3816 PIM_DONT_DEBUG_PIM_EVENTS;
3817 return CMD_SUCCESS;
3818 }
3819
3820
3821 DEFUN (debug_pim_packets,
3822 debug_pim_packets_cmd,
3823 "debug pim packets",
3824 DEBUG_STR
3825 DEBUG_PIM_STR
3826 DEBUG_PIM_PACKETS_STR)
3827 {
3828 PIM_DO_DEBUG_PIM_PACKETS;
3829 vty_out (vty, "PIM Packet debugging is on %s", VTY_NEWLINE);
3830 return CMD_SUCCESS;
3831 }
3832
3833 DEFUN (debug_pim_packets_filter,
3834 debug_pim_packets_filter_cmd,
3835 "debug pim packets <hello|joins|register>",
3836 DEBUG_STR
3837 DEBUG_PIM_STR
3838 DEBUG_PIM_PACKETS_STR
3839 DEBUG_PIM_HELLO_PACKETS_STR
3840 DEBUG_PIM_J_P_PACKETS_STR
3841 DEBUG_PIM_PIM_REG_PACKETS_STR)
3842 {
3843 int idx_hello_join = 3;
3844 if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0)
3845 {
3846 PIM_DO_DEBUG_PIM_HELLO;
3847 vty_out (vty, "PIM Hello debugging is on%s", VTY_NEWLINE);
3848 }
3849 else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0)
3850 {
3851 PIM_DO_DEBUG_PIM_J_P;
3852 vty_out (vty, "PIM Join/Prune debugging is on%s", VTY_NEWLINE);
3853 }
3854 else if (strncmp(argv[idx_hello_join]->arg,"r",1) == 0)
3855 {
3856 PIM_DO_DEBUG_PIM_REG;
3857 vty_out (vty, "PIM Register debugging is on%s", VTY_NEWLINE);
3858 }
3859 return CMD_SUCCESS;
3860 }
3861
3862 DEFUN (no_debug_pim_packets,
3863 no_debug_pim_packets_cmd,
3864 "no debug pim packets",
3865 NO_STR
3866 DEBUG_STR
3867 DEBUG_PIM_STR
3868 DEBUG_PIM_PACKETS_STR
3869 DEBUG_PIM_HELLO_PACKETS_STR
3870 DEBUG_PIM_J_P_PACKETS_STR)
3871 {
3872 PIM_DONT_DEBUG_PIM_PACKETS;
3873 vty_out (vty, "PIM Packet debugging is off %s", VTY_NEWLINE);
3874 return CMD_SUCCESS;
3875 }
3876
3877 DEFUN (no_debug_pim_packets_filter,
3878 no_debug_pim_packets_filter_cmd,
3879 "no debug pim packets <hello|joins|register>",
3880 NO_STR
3881 DEBUG_STR
3882 DEBUG_PIM_STR
3883 DEBUG_PIM_PACKETS_STR
3884 DEBUG_PIM_HELLO_PACKETS_STR
3885 DEBUG_PIM_J_P_PACKETS_STR)
3886 {
3887 int idx_hello_join = 4;
3888 if (strncmp(argv[idx_hello_join]->arg,"h",1) == 0)
3889 {
3890 PIM_DONT_DEBUG_PIM_HELLO;
3891 vty_out (vty, "PIM Hello debugging is off %s", VTY_NEWLINE);
3892 }
3893 else if (strncmp(argv[idx_hello_join]->arg,"j",1) == 0)
3894 {
3895 PIM_DONT_DEBUG_PIM_J_P;
3896 vty_out (vty, "PIM Join/Prune debugging is off %s", VTY_NEWLINE);
3897 }
3898 else if (strncmp (argv[idx_hello_join]->arg, "r", 1) == 0)
3899 {
3900 PIM_DONT_DEBUG_PIM_REG;
3901 vty_out (vty, "PIM Register debugging is off%s", VTY_NEWLINE);
3902 }
3903 return CMD_SUCCESS;
3904 }
3905
3906
3907 DEFUN (debug_pim_packetdump_send,
3908 debug_pim_packetdump_send_cmd,
3909 "debug pim packet-dump send",
3910 DEBUG_STR
3911 DEBUG_PIM_STR
3912 DEBUG_PIM_PACKETDUMP_STR
3913 DEBUG_PIM_PACKETDUMP_SEND_STR)
3914 {
3915 PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
3916 return CMD_SUCCESS;
3917 }
3918
3919 DEFUN (no_debug_pim_packetdump_send,
3920 no_debug_pim_packetdump_send_cmd,
3921 "no debug pim packet-dump send",
3922 NO_STR
3923 DEBUG_STR
3924 DEBUG_PIM_STR
3925 DEBUG_PIM_PACKETDUMP_STR
3926 DEBUG_PIM_PACKETDUMP_SEND_STR)
3927 {
3928 PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
3929 return CMD_SUCCESS;
3930 }
3931
3932
3933 DEFUN (debug_pim_packetdump_recv,
3934 debug_pim_packetdump_recv_cmd,
3935 "debug pim packet-dump receive",
3936 DEBUG_STR
3937 DEBUG_PIM_STR
3938 DEBUG_PIM_PACKETDUMP_STR
3939 DEBUG_PIM_PACKETDUMP_RECV_STR)
3940 {
3941 PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
3942 return CMD_SUCCESS;
3943 }
3944
3945 DEFUN (no_debug_pim_packetdump_recv,
3946 no_debug_pim_packetdump_recv_cmd,
3947 "no debug pim packet-dump receive",
3948 NO_STR
3949 DEBUG_STR
3950 DEBUG_PIM_STR
3951 DEBUG_PIM_PACKETDUMP_STR
3952 DEBUG_PIM_PACKETDUMP_RECV_STR)
3953 {
3954 PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
3955 return CMD_SUCCESS;
3956 }
3957
3958
3959 DEFUN (debug_pim_trace,
3960 debug_pim_trace_cmd,
3961 "debug pim trace",
3962 DEBUG_STR
3963 DEBUG_PIM_STR
3964 DEBUG_PIM_TRACE_STR)
3965 {
3966 PIM_DO_DEBUG_PIM_TRACE;
3967 return CMD_SUCCESS;
3968 }
3969
3970 DEFUN (no_debug_pim_trace,
3971 no_debug_pim_trace_cmd,
3972 "no debug pim trace",
3973 NO_STR
3974 DEBUG_STR
3975 DEBUG_PIM_STR
3976 DEBUG_PIM_TRACE_STR)
3977 {
3978 PIM_DONT_DEBUG_PIM_TRACE;
3979 return CMD_SUCCESS;
3980 }
3981
3982
3983 DEFUN (debug_ssmpingd,
3984 debug_ssmpingd_cmd,
3985 "debug ssmpingd",
3986 DEBUG_STR
3987 DEBUG_PIM_STR
3988 DEBUG_SSMPINGD_STR)
3989 {
3990 PIM_DO_DEBUG_SSMPINGD;
3991 return CMD_SUCCESS;
3992 }
3993
3994 DEFUN (no_debug_ssmpingd,
3995 no_debug_ssmpingd_cmd,
3996 "no debug ssmpingd",
3997 NO_STR
3998 DEBUG_STR
3999 DEBUG_PIM_STR
4000 DEBUG_SSMPINGD_STR)
4001 {
4002 PIM_DONT_DEBUG_SSMPINGD;
4003 return CMD_SUCCESS;
4004 }
4005
4006
4007 DEFUN (debug_pim_zebra,
4008 debug_pim_zebra_cmd,
4009 "debug pim zebra",
4010 DEBUG_STR
4011 DEBUG_PIM_STR
4012 DEBUG_PIM_ZEBRA_STR)
4013 {
4014 PIM_DO_DEBUG_ZEBRA;
4015 return CMD_SUCCESS;
4016 }
4017
4018 DEFUN (no_debug_pim_zebra,
4019 no_debug_pim_zebra_cmd,
4020 "no debug pim zebra",
4021 NO_STR
4022 DEBUG_STR
4023 DEBUG_PIM_STR
4024 DEBUG_PIM_ZEBRA_STR)
4025 {
4026 PIM_DONT_DEBUG_ZEBRA;
4027 return CMD_SUCCESS;
4028 }
4029
4030
4031 DEFUN (show_debugging_pim,
4032 show_debugging_pim_cmd,
4033 "show debugging pim",
4034 SHOW_STR
4035 DEBUG_STR
4036 PIM_STR)
4037 {
4038 pim_debug_config_write(vty);
4039 return CMD_SUCCESS;
4040 }
4041
4042 static struct igmp_sock *find_igmp_sock_by_fd(int fd)
4043 {
4044 struct listnode *ifnode;
4045 struct interface *ifp;
4046
4047 /* scan all interfaces */
4048 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) {
4049 struct pim_interface *pim_ifp;
4050 struct igmp_sock *igmp;
4051
4052 if (!ifp->info)
4053 continue;
4054
4055 pim_ifp = ifp->info;
4056
4057 /* lookup igmp socket under current interface */
4058 igmp = igmp_sock_lookup_by_fd(pim_ifp->igmp_socket_list, fd);
4059 if (igmp)
4060 return igmp;
4061 }
4062
4063 return 0;
4064 }
4065
4066 DEFUN (test_igmp_receive_report,
4067 test_igmp_receive_report_cmd,
4068 "test igmp receive report (0-65535) A.B.C.D (1-6) LINE...",
4069 "Test\n"
4070 "Test IGMP protocol\n"
4071 "Test IGMP message\n"
4072 "Test IGMP report\n"
4073 "Socket\n"
4074 "IGMP group address\n"
4075 "Record type\n"
4076 "Sources\n")
4077 {
4078 int idx_number = 4;
4079 int idx_ipv4 = 5;
4080 int idx_number_2 = 6;
4081 int idx_line = 7;
4082 char buf[1000];
4083 char *igmp_msg;
4084 struct ip *ip_hdr;
4085 size_t ip_hlen; /* ip header length in bytes */
4086 int ip_msg_len;
4087 int igmp_msg_len;
4088 const char *socket;
4089 int socket_fd;
4090 const char *grp_str;
4091 struct in_addr grp_addr;
4092 const char *record_type_str;
4093 int record_type;
4094 const char *src_str;
4095 int result;
4096 struct igmp_sock *igmp;
4097 char *group_record;
4098 int num_sources;
4099 struct in_addr *sources;
4100 struct in_addr *src_addr;
4101 int argi;
4102
4103 socket = argv[idx_number]->arg;
4104 socket_fd = atoi(socket);
4105 igmp = find_igmp_sock_by_fd(socket_fd);
4106 if (!igmp) {
4107 vty_out(vty, "Could not find IGMP socket %s: fd=%d%s",
4108 socket, socket_fd, VTY_NEWLINE);
4109 return CMD_WARNING;
4110 }
4111
4112 grp_str = argv[idx_ipv4]->arg;
4113 result = inet_pton(AF_INET, grp_str, &grp_addr);
4114 if (result <= 0) {
4115 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4116 grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4117 return CMD_WARNING;
4118 }
4119
4120 record_type_str = argv[idx_number_2]->arg;
4121 record_type = atoi(record_type_str);
4122
4123 /*
4124 Tweak IP header
4125 */
4126 ip_hdr = (struct ip *) buf;
4127 ip_hdr->ip_p = PIM_IP_PROTO_IGMP;
4128 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4129 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
4130 ip_hdr->ip_src = igmp->ifaddr;
4131 ip_hdr->ip_dst = igmp->ifaddr;
4132
4133 /*
4134 Build IGMP v3 report message
4135 */
4136 igmp_msg = buf + ip_hlen;
4137 group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
4138 *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */
4139 *(uint16_t *) (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; /* for computing checksum */
4140 *(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */
4141 *(uint8_t *) (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type;
4142 memcpy(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, &grp_addr, sizeof(struct in_addr));
4143
4144 /* Scan LINE sources */
4145 sources = (struct in_addr *) (group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET);
4146 src_addr = sources;
4147 for (argi = idx_line; argi < argc; ++argi,++src_addr) {
4148 src_str = argv[argi]->arg;
4149 result = inet_pton(AF_INET, src_str, src_addr);
4150 if (result <= 0) {
4151 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4152 src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4153 return CMD_WARNING;
4154 }
4155 }
4156 num_sources = src_addr - sources;
4157
4158 *(uint16_t *)(group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET) = htons(num_sources);
4159
4160 igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4); /* v3 report for one single group record */
4161
4162 /* compute checksum */
4163 *(uint16_t *)(igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len);
4164
4165 /* "receive" message */
4166
4167 ip_msg_len = ip_hlen + igmp_msg_len;
4168 result = pim_igmp_packet(igmp, buf, ip_msg_len);
4169 if (result) {
4170 vty_out(vty, "pim_igmp_packet(len=%d) returned: %d%s",
4171 ip_msg_len, result, VTY_NEWLINE);
4172 return CMD_WARNING;
4173 }
4174
4175 return CMD_SUCCESS;
4176 }
4177
4178 static int hexval(uint8_t ch)
4179 {
4180 return isdigit(ch) ? (ch - '0') : (10 + tolower(ch) - 'a');
4181 }
4182
4183 DEFUN (test_pim_receive_dump,
4184 test_pim_receive_dump_cmd,
4185 "test pim receive dump INTERFACE A.B.C.D LINE...",
4186 "Test\n"
4187 "Test PIM protocol\n"
4188 "Test PIM message reception\n"
4189 "Test PIM packet dump reception from neighbor\n"
4190 "Interface\n"
4191 "Neighbor address\n"
4192 "Packet dump\n")
4193 {
4194 int idx_interface = 4;
4195 int idx_ipv4 = 5;
4196 int idx_line = 6;
4197 uint8_t buf[1000];
4198 uint8_t *pim_msg;
4199 struct ip *ip_hdr;
4200 size_t ip_hlen; /* ip header length in bytes */
4201 int ip_msg_len;
4202 int pim_msg_size;
4203 const char *neigh_str;
4204 struct in_addr neigh_addr;
4205 const char *ifname;
4206 struct interface *ifp;
4207 int argi;
4208 int result;
4209
4210 /* Find interface */
4211 ifname = argv[idx_interface]->arg;
4212 ifp = if_lookup_by_name(ifname);
4213 if (!ifp) {
4214 vty_out(vty, "No such interface name %s%s",
4215 ifname, VTY_NEWLINE);
4216 return CMD_WARNING;
4217 }
4218
4219 /* Neighbor address */
4220 neigh_str = argv[idx_ipv4]->arg;
4221 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4222 if (result <= 0) {
4223 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4224 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4225 return CMD_WARNING;
4226 }
4227
4228 /*
4229 Tweak IP header
4230 */
4231 ip_hdr = (struct ip *) buf;
4232 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4233 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4234 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
4235 ip_hdr->ip_src = neigh_addr;
4236 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4237
4238 /*
4239 Build PIM hello message
4240 */
4241 pim_msg = buf + ip_hlen;
4242 pim_msg_size = 0;
4243
4244 /* Scan LINE dump into buffer */
4245 for (argi = idx_line; argi < argc; ++argi) {
4246 const char *str = argv[argi]->arg;
4247 int str_len = strlen(str);
4248 int str_last = str_len - 1;
4249 int i;
4250
4251 if (str_len % 2) {
4252 vty_out(vty, "%% Uneven hex array arg %d=%s%s",
4253 argi, str, VTY_NEWLINE);
4254 return CMD_WARNING;
4255 }
4256
4257 for (i = 0; i < str_last; i += 2) {
4258 uint8_t octet;
4259 int left;
4260 uint8_t h1 = str[i];
4261 uint8_t h2 = str[i + 1];
4262
4263 if (!isxdigit(h1) || !isxdigit(h2)) {
4264 vty_out(vty, "%% Non-hex octet %c%c at hex array arg %d=%s%s",
4265 h1, h2, argi, str, VTY_NEWLINE);
4266 return CMD_WARNING;
4267 }
4268 octet = (hexval(h1) << 4) + hexval(h2);
4269
4270 left = sizeof(buf) - ip_hlen - pim_msg_size;
4271 if (left < 1) {
4272 vty_out(vty, "%% Overflow buf_size=%zu buf_left=%d at hex array arg %d=%s octet %02x%s",
4273 sizeof(buf), left, argi, str, octet, VTY_NEWLINE);
4274 return CMD_WARNING;
4275 }
4276
4277 pim_msg[pim_msg_size++] = octet;
4278 }
4279 }
4280
4281 ip_msg_len = ip_hlen + pim_msg_size;
4282
4283 vty_out(vty, "Receiving: buf_size=%zu ip_msg_size=%d pim_msg_size=%d%s",
4284 sizeof(buf), ip_msg_len, pim_msg_size, VTY_NEWLINE);
4285
4286 /* "receive" message */
4287
4288 result = pim_pim_packet(ifp, buf, ip_msg_len);
4289 if (result) {
4290 vty_out(vty, "%% pim_pim_packet(len=%d) returned failure: %d%s",
4291 ip_msg_len, result, VTY_NEWLINE);
4292 return CMD_WARNING;
4293 }
4294
4295 return CMD_SUCCESS;
4296 }
4297
4298 DEFUN (test_pim_receive_hello,
4299 test_pim_receive_hello_cmd,
4300 "test pim receive hello INTERFACE A.B.C.D (0-65535) (0-65535) (0-65535) (0-32767) (0-65535) (0-1) [LINE]",
4301 "Test\n"
4302 "Test PIM protocol\n"
4303 "Test PIM message reception\n"
4304 "Test PIM hello reception from neighbor\n"
4305 "Interface\n"
4306 "Neighbor address\n"
4307 "Neighbor holdtime\n"
4308 "Neighbor DR priority\n"
4309 "Neighbor generation ID\n"
4310 "Neighbor propagation delay (msec)\n"
4311 "Neighbor override interval (msec)\n"
4312 "Neighbor LAN prune delay T-bit\n"
4313 "Neighbor secondary addresses\n")
4314 {
4315 int idx_interface = 4;
4316 int idx_ipv4 = 5;
4317 int idx_number = 6;
4318 int idx_number_2 = 7;
4319 int idx_number_3 = 8;
4320 int idx_number_4 = 9;
4321 int idx_number_5 = 10;
4322 int idx_number_6 = 11;
4323 int idx_line = 12;
4324 uint8_t buf[1000];
4325 uint8_t *pim_msg;
4326 struct ip *ip_hdr;
4327 size_t ip_hlen; /* ip header length in bytes */
4328 int ip_msg_len;
4329 int pim_tlv_size;
4330 int pim_msg_size;
4331 const char *neigh_str;
4332 struct in_addr neigh_addr;
4333 const char *ifname;
4334 struct interface *ifp;
4335 uint16_t neigh_holdtime;
4336 uint16_t neigh_propagation_delay;
4337 uint16_t neigh_override_interval;
4338 int neigh_can_disable_join_suppression;
4339 uint32_t neigh_dr_priority;
4340 uint32_t neigh_generation_id;
4341 int argi;
4342 int result;
4343
4344 /* Find interface */
4345 ifname = argv[idx_interface]->arg;
4346 ifp = if_lookup_by_name(ifname);
4347 if (!ifp) {
4348 vty_out(vty, "No such interface name %s%s",
4349 ifname, VTY_NEWLINE);
4350 return CMD_WARNING;
4351 }
4352
4353 /* Neighbor address */
4354 neigh_str = argv[idx_ipv4]->arg;
4355 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4356 if (result <= 0) {
4357 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4358 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4359 return CMD_WARNING;
4360 }
4361
4362 neigh_holdtime = atoi(argv[idx_number]->arg);
4363 neigh_dr_priority = atoi(argv[idx_number_2]->arg);
4364 neigh_generation_id = atoi(argv[idx_number_3]->arg);
4365 neigh_propagation_delay = atoi(argv[idx_number_4]->arg);
4366 neigh_override_interval = atoi(argv[idx_number_5]->arg);
4367 neigh_can_disable_join_suppression = atoi(argv[idx_number_6]->arg);
4368
4369 /*
4370 Tweak IP header
4371 */
4372 ip_hdr = (struct ip *) buf;
4373 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4374 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4375 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
4376 ip_hdr->ip_src = neigh_addr;
4377 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4378
4379 /*
4380 Build PIM hello message
4381 */
4382 pim_msg = buf + ip_hlen;
4383
4384 /* Scan LINE addresses */
4385 for (argi = idx_line; argi < argc; ++argi) {
4386 const char *sec_str = argv[argi]->arg;
4387 struct in_addr sec_addr;
4388 result = inet_pton(AF_INET, sec_str, &sec_addr);
4389 if (result <= 0) {
4390 vty_out(vty, "Bad neighbor secondary address %s: errno=%d: %s%s",
4391 sec_str, errno, safe_strerror(errno), VTY_NEWLINE);
4392 return CMD_WARNING;
4393 }
4394
4395 vty_out(vty,
4396 "FIXME WRITEME consider neighbor secondary address %s%s",
4397 sec_str, VTY_NEWLINE);
4398 }
4399
4400 pim_tlv_size = pim_hello_build_tlv(ifp->name,
4401 pim_msg + PIM_PIM_MIN_LEN,
4402 sizeof(buf) - ip_hlen - PIM_PIM_MIN_LEN,
4403 neigh_holdtime,
4404 neigh_dr_priority,
4405 neigh_generation_id,
4406 neigh_propagation_delay,
4407 neigh_override_interval,
4408 neigh_can_disable_join_suppression,
4409 0 /* FIXME secondary address list */);
4410 if (pim_tlv_size < 0) {
4411 vty_out(vty, "pim_hello_build_tlv() returned failure: %d%s",
4412 pim_tlv_size, VTY_NEWLINE);
4413 return CMD_WARNING;
4414 }
4415
4416 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
4417
4418 pim_msg_build_header(pim_msg, pim_msg_size,
4419 PIM_MSG_TYPE_HELLO);
4420
4421 /* "receive" message */
4422
4423 ip_msg_len = ip_hlen + pim_msg_size;
4424 result = pim_pim_packet(ifp, buf, ip_msg_len);
4425 if (result) {
4426 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4427 ip_msg_len, result, VTY_NEWLINE);
4428 return CMD_WARNING;
4429 }
4430
4431 return CMD_SUCCESS;
4432 }
4433
4434 DEFUN (test_pim_receive_assert,
4435 test_pim_receive_assert_cmd,
4436 "test pim receive assert INTERFACE A.B.C.D A.B.C.D A.B.C.D (0-65535) (0-65535) (0-1)",
4437 "Test\n"
4438 "Test PIM protocol\n"
4439 "Test PIM message reception\n"
4440 "Test reception of PIM assert\n"
4441 "Interface\n"
4442 "Neighbor address\n"
4443 "Assert multicast group address\n"
4444 "Assert unicast source address\n"
4445 "Assert metric preference\n"
4446 "Assert route metric\n"
4447 "Assert RPT bit flag\n")
4448 {
4449 int idx_interface = 4;
4450 int idx_ipv4 = 5;
4451 int idx_ipv4_2 = 6;
4452 int idx_ipv4_3 = 7;
4453 int idx_number = 8;
4454 int idx_number_2 = 9;
4455 int idx_number_3 = 10;
4456 uint8_t buf[1000];
4457 uint8_t *buf_pastend = buf + sizeof(buf);
4458 uint8_t *pim_msg;
4459 struct ip *ip_hdr;
4460 size_t ip_hlen; /* ip header length in bytes */
4461 int ip_msg_len;
4462 int pim_msg_size;
4463 const char *neigh_str;
4464 struct in_addr neigh_addr;
4465 const char *group_str;
4466 struct in_addr group_addr;
4467 const char *source_str;
4468 struct in_addr source_addr;
4469 const char *ifname;
4470 struct interface *ifp;
4471 uint32_t assert_metric_preference;
4472 uint32_t assert_route_metric;
4473 uint32_t assert_rpt_bit_flag;
4474 int remain;
4475 int result;
4476
4477 /* Find interface */
4478 ifname = argv[idx_interface]->arg;
4479 ifp = if_lookup_by_name(ifname);
4480 if (!ifp) {
4481 vty_out(vty, "No such interface name %s%s",
4482 ifname, VTY_NEWLINE);
4483 return CMD_WARNING;
4484 }
4485
4486 /* Neighbor address */
4487 neigh_str = argv[idx_ipv4]->arg;
4488 result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4489 if (result <= 0) {
4490 vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4491 neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4492 return CMD_WARNING;
4493 }
4494
4495 /* Group address */
4496 group_str = argv[idx_ipv4_2]->arg;
4497 result = inet_pton(AF_INET, group_str, &group_addr);
4498 if (result <= 0) {
4499 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4500 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4501 return CMD_WARNING;
4502 }
4503
4504 /* Source address */
4505 source_str = argv[idx_ipv4_3]->arg;
4506 result = inet_pton(AF_INET, source_str, &source_addr);
4507 if (result <= 0) {
4508 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4509 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4510 return CMD_WARNING;
4511 }
4512
4513 assert_metric_preference = atoi(argv[idx_number]->arg);
4514 assert_route_metric = atoi(argv[idx_number_2]->arg);
4515 assert_rpt_bit_flag = atoi(argv[idx_number_3]->arg);
4516
4517 remain = buf_pastend - buf;
4518 if (remain < (int) sizeof(struct ip)) {
4519 vty_out(vty, "No room for ip header: buf_size=%d < ip_header_size=%zu%s",
4520 remain, sizeof(struct ip), VTY_NEWLINE);
4521 return CMD_WARNING;
4522 }
4523
4524 /*
4525 Tweak IP header
4526 */
4527 ip_hdr = (struct ip *) buf;
4528 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4529 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4530 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
4531 ip_hdr->ip_src = neigh_addr;
4532 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4533
4534 /*
4535 Build PIM assert message
4536 */
4537 pim_msg = buf + ip_hlen; /* skip ip header */
4538
4539 pim_msg_size = pim_assert_build_msg(pim_msg, buf_pastend - pim_msg, ifp,
4540 group_addr, source_addr,
4541 assert_metric_preference,
4542 assert_route_metric,
4543 assert_rpt_bit_flag);
4544 if (pim_msg_size < 0) {
4545 vty_out(vty, "Failure building PIM assert message: size=%d%s",
4546 pim_msg_size, VTY_NEWLINE);
4547 return CMD_WARNING;
4548 }
4549
4550 /* "receive" message */
4551
4552 ip_msg_len = ip_hlen + pim_msg_size;
4553 result = pim_pim_packet(ifp, buf, ip_msg_len);
4554 if (result) {
4555 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4556 ip_msg_len, result, VTY_NEWLINE);
4557 return CMD_WARNING;
4558 }
4559
4560 return CMD_SUCCESS;
4561 }
4562
4563 static int recv_joinprune(struct vty *vty,
4564 struct cmd_token **argv,
4565 int src_is_join)
4566 {
4567 uint8_t buf[1000];
4568 const uint8_t *buf_pastend = buf + sizeof(buf);
4569 uint8_t *pim_msg;
4570 int pim_msg_size;
4571 struct ip *ip_hdr;
4572 size_t ip_hlen; /* ip header length in bytes */
4573 int ip_msg_len;
4574 uint16_t neigh_holdtime;
4575 const char *neigh_dst_str;
4576 struct in_addr neigh_dst_addr;
4577 const char *neigh_src_str;
4578 struct in_addr neigh_src_addr;
4579 const char *group_str;
4580 struct in_addr group_addr;
4581 const char *source_str;
4582 struct in_addr source_addr;
4583 const char *ifname;
4584 struct interface *ifp;
4585 int result;
4586
4587 /* Find interface */
4588 ifname = argv[0]->arg;
4589 ifp = if_lookup_by_name(ifname);
4590 if (!ifp) {
4591 vty_out(vty, "No such interface name %s%s",
4592 ifname, VTY_NEWLINE);
4593 return CMD_WARNING;
4594 }
4595
4596 neigh_holdtime = atoi(argv[1]->arg);
4597
4598 /* Neighbor destination address */
4599 neigh_dst_str = argv[2]->arg;
4600 result = inet_pton(AF_INET, neigh_dst_str, &neigh_dst_addr);
4601 if (result <= 0) {
4602 vty_out(vty, "Bad neighbor destination address %s: errno=%d: %s%s",
4603 neigh_dst_str, errno, safe_strerror(errno), VTY_NEWLINE);
4604 return CMD_WARNING;
4605 }
4606
4607 /* Neighbor source address */
4608 neigh_src_str = argv[3]->arg;
4609 result = inet_pton(AF_INET, neigh_src_str, &neigh_src_addr);
4610 if (result <= 0) {
4611 vty_out(vty, "Bad neighbor source address %s: errno=%d: %s%s",
4612 neigh_src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4613 return CMD_WARNING;
4614 }
4615
4616 /* Multicast group address */
4617 group_str = argv[4]->arg;
4618 result = inet_pton(AF_INET, group_str, &group_addr);
4619 if (result <= 0) {
4620 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4621 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4622 return CMD_WARNING;
4623 }
4624
4625 /* Multicast source address */
4626 source_str = argv[5]->arg;
4627 result = inet_pton(AF_INET, source_str, &source_addr);
4628 if (result <= 0) {
4629 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4630 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4631 return CMD_WARNING;
4632 }
4633
4634 /*
4635 Tweak IP header
4636 */
4637 ip_hdr = (struct ip *) buf;
4638 ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4639 ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4640 ip_hdr->ip_hl = ip_hlen >> 2; /* ip header length in 4-byte words */
4641 ip_hdr->ip_src = neigh_src_addr;
4642 ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4643
4644 /*
4645 Build PIM message
4646 */
4647 pim_msg = buf + ip_hlen;
4648
4649 pim_msg_size = pim_msg_join_prune_encode (pim_msg, buf_pastend - pim_msg, src_is_join,
4650 source_addr, group_addr, neigh_dst_addr,
4651 neigh_holdtime);
4652
4653 /*
4654 "Receive" message
4655 */
4656
4657 ip_msg_len = ip_hlen + pim_msg_size;
4658 result = pim_pim_packet(ifp, buf, ip_msg_len);
4659 if (result) {
4660 vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4661 ip_msg_len, result, VTY_NEWLINE);
4662 return CMD_WARNING;
4663 }
4664
4665 return CMD_SUCCESS;
4666 }
4667
4668 DEFUN (test_pim_receive_join,
4669 test_pim_receive_join_cmd,
4670 "test pim receive join INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
4671 "Test\n"
4672 "Test PIM protocol\n"
4673 "Test PIM message reception\n"
4674 "Test PIM join reception from neighbor\n"
4675 "Interface\n"
4676 "Neighbor holdtime\n"
4677 "Upstream neighbor unicast destination address\n"
4678 "Downstream neighbor unicast source address\n"
4679 "Multicast group address\n"
4680 "Unicast source address\n")
4681 {
4682 return recv_joinprune(vty, argv, 1 /* src_is_join=true */);
4683 }
4684
4685 DEFUN (test_pim_receive_prune,
4686 test_pim_receive_prune_cmd,
4687 "test pim receive prune INTERFACE (0-65535) A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
4688 "Test\n"
4689 "Test PIM protocol\n"
4690 "Test PIM message reception\n"
4691 "Test PIM prune reception from neighbor\n"
4692 "Interface\n"
4693 "Neighbor holdtime\n"
4694 "Upstream neighbor unicast destination address\n"
4695 "Downstream neighbor unicast source address\n"
4696 "Multicast group address\n"
4697 "Unicast source address\n")
4698 {
4699 return recv_joinprune(vty, argv, 0 /* src_is_join=false */);
4700 }
4701
4702 DEFUN (test_pim_receive_upcall,
4703 test_pim_receive_upcall_cmd,
4704 "test pim receive upcall <nocache|wrongvif|wholepkt> (0-65535) A.B.C.D A.B.C.D",
4705 "Test\n"
4706 "Test PIM protocol\n"
4707 "Test PIM message reception\n"
4708 "Test reception of kernel upcall\n"
4709 "NOCACHE kernel upcall\n"
4710 "WRONGVIF kernel upcall\n"
4711 "WHOLEPKT kernel upcall\n"
4712 "Input interface vif index\n"
4713 "Multicast group address\n"
4714 "Multicast source address\n")
4715 {
4716 int idx_type = 4;
4717 int idx_number = 5;
4718 int idx_ipv4 = 6;
4719 int idx_ipv4_2 = 7;
4720 struct igmpmsg msg;
4721 const char *upcall_type;
4722 const char *group_str;
4723 const char *source_str;
4724 int result;
4725
4726 upcall_type = argv[idx_type]->arg;
4727
4728 if (upcall_type[0] == 'n')
4729 msg.im_msgtype = IGMPMSG_NOCACHE;
4730 else if (upcall_type[1] == 'r')
4731 msg.im_msgtype = IGMPMSG_WRONGVIF;
4732 else if (upcall_type[1] == 'h')
4733 msg.im_msgtype = IGMPMSG_WHOLEPKT;
4734 else {
4735 vty_out(vty, "Unknown kernel upcall type: %s%s",
4736 upcall_type, VTY_NEWLINE);
4737 return CMD_WARNING;
4738 }
4739
4740 msg.im_vif = atoi(argv[idx_number]->arg);
4741
4742 /* Group address */
4743 group_str = argv[idx_ipv4]->arg;
4744 result = inet_pton(AF_INET, group_str, &msg.im_dst);
4745 if (result <= 0) {
4746 vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4747 group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4748 return CMD_WARNING;
4749 }
4750
4751 /* Source address */
4752 source_str = argv[idx_ipv4_2]->arg;
4753 result = inet_pton(AF_INET, source_str, &msg.im_src);
4754 if (result <= 0) {
4755 vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4756 source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4757 return CMD_WARNING;
4758 }
4759
4760 msg.im_mbz = 0; /* Must be zero */
4761
4762 result = pim_mroute_msg(-1, (char *) &msg, sizeof(msg));
4763 if (result) {
4764 vty_out(vty, "pim_mroute_msg(len=%zu) returned failure: %d%s",
4765 sizeof(msg), result, VTY_NEWLINE);
4766 return CMD_WARNING;
4767 }
4768
4769 return CMD_SUCCESS;
4770 }
4771
4772 void pim_cmd_init()
4773 {
4774 install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */
4775 install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */
4776 if_cmd_init ();
4777
4778 install_element (CONFIG_NODE, &ip_multicast_routing_cmd);
4779 install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
4780 install_element (CONFIG_NODE, &ip_pim_rp_cmd);
4781 install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
4782 install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
4783 install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
4784 install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
4785 install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd);
4786
4787 install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
4788 install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd);
4789 install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd);
4790 install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd);
4791 install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
4792 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd);
4793 install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd);
4794 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd);
4795 install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd);
4796 install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd);
4797 install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
4798 install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
4799 install_element (INTERFACE_NODE, &interface_ip_pim_sm_cmd);
4800 install_element (INTERFACE_NODE, &interface_no_ip_pim_sm_cmd);
4801 install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
4802 install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
4803 install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd);
4804 install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
4805
4806 // Static mroutes NEB
4807 install_element (INTERFACE_NODE, &interface_ip_mroute_cmd);
4808 install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd);
4809 install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd);
4810 install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
4811
4812 install_element (VIEW_NODE, &show_ip_igmp_interface_cmd);
4813 install_element (VIEW_NODE, &show_ip_igmp_join_cmd);
4814 install_element (VIEW_NODE, &show_ip_igmp_parameters_cmd);
4815 install_element (VIEW_NODE, &show_ip_igmp_groups_cmd);
4816 install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
4817 install_element (VIEW_NODE, &show_ip_igmp_sources_cmd);
4818 install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
4819 install_element (VIEW_NODE, &show_ip_igmp_querier_cmd);
4820 install_element (VIEW_NODE, &show_ip_pim_assert_cmd);
4821 install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd);
4822 install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd);
4823 install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
4824 install_element (VIEW_NODE, &show_ip_pim_dr_cmd);
4825 install_element (VIEW_NODE, &show_ip_pim_hello_cmd);
4826 install_element (VIEW_NODE, &show_ip_pim_interface_cmd);
4827 install_element (VIEW_NODE, &show_ip_pim_join_cmd);
4828 install_element (VIEW_NODE, &show_ip_pim_jp_override_interval_cmd);
4829 install_element (VIEW_NODE, &show_ip_pim_lan_prune_delay_cmd);
4830 install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd);
4831 install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd);
4832 install_element (VIEW_NODE, &show_ip_pim_rpf_cmd);
4833 install_element (VIEW_NODE, &show_ip_pim_secondary_cmd);
4834 install_element (VIEW_NODE, &show_ip_pim_upstream_cmd);
4835 install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
4836 install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
4837 install_element (VIEW_NODE, &show_ip_multicast_cmd);
4838 install_element (VIEW_NODE, &show_ip_mroute_cmd);
4839 install_element (VIEW_NODE, &show_ip_mroute_count_cmd);
4840 install_element (VIEW_NODE, &show_ip_rib_cmd);
4841 install_element (VIEW_NODE, &show_ip_ssmpingd_cmd);
4842 install_element (VIEW_NODE, &show_debugging_pim_cmd);
4843
4844 install_element (ENABLE_NODE, &show_ip_pim_address_cmd);
4845
4846 install_element (ENABLE_NODE, &clear_ip_interfaces_cmd);
4847 install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
4848 install_element (ENABLE_NODE, &clear_ip_mroute_cmd);
4849 install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
4850 install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd);
4851
4852 install_element (ENABLE_NODE, &test_igmp_receive_report_cmd);
4853 install_element (ENABLE_NODE, &test_pim_receive_assert_cmd);
4854 install_element (ENABLE_NODE, &test_pim_receive_dump_cmd);
4855 install_element (ENABLE_NODE, &test_pim_receive_hello_cmd);
4856 install_element (ENABLE_NODE, &test_pim_receive_join_cmd);
4857 install_element (ENABLE_NODE, &test_pim_receive_prune_cmd);
4858 install_element (ENABLE_NODE, &test_pim_receive_upcall_cmd);
4859
4860 install_element (ENABLE_NODE, &debug_igmp_cmd);
4861 install_element (ENABLE_NODE, &no_debug_igmp_cmd);
4862 install_element (ENABLE_NODE, &debug_igmp_events_cmd);
4863 install_element (ENABLE_NODE, &no_debug_igmp_events_cmd);
4864 install_element (ENABLE_NODE, &debug_igmp_packets_cmd);
4865 install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd);
4866 install_element (ENABLE_NODE, &debug_igmp_trace_cmd);
4867 install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd);
4868 install_element (ENABLE_NODE, &debug_mroute_cmd);
4869 install_element (ENABLE_NODE, &debug_mroute_detail_cmd);
4870 install_element (ENABLE_NODE, &no_debug_mroute_cmd);
4871 install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd);
4872 install_element (ENABLE_NODE, &debug_static_cmd);
4873 install_element (ENABLE_NODE, &no_debug_static_cmd);
4874 install_element (ENABLE_NODE, &debug_pim_cmd);
4875 install_element (ENABLE_NODE, &no_debug_pim_cmd);
4876 install_element (ENABLE_NODE, &debug_pim_events_cmd);
4877 install_element (ENABLE_NODE, &no_debug_pim_events_cmd);
4878 install_element (ENABLE_NODE, &debug_pim_packets_cmd);
4879 install_element (ENABLE_NODE, &debug_pim_packets_filter_cmd);
4880 install_element (ENABLE_NODE, &no_debug_pim_packets_cmd);
4881 install_element (ENABLE_NODE, &no_debug_pim_packets_filter_cmd);
4882 install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd);
4883 install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
4884 install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
4885 install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
4886 install_element (ENABLE_NODE, &debug_pim_trace_cmd);
4887 install_element (ENABLE_NODE, &no_debug_pim_trace_cmd);
4888 install_element (ENABLE_NODE, &debug_ssmpingd_cmd);
4889 install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd);
4890 install_element (ENABLE_NODE, &debug_pim_zebra_cmd);
4891 install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd);
4892
4893 install_element (CONFIG_NODE, &debug_igmp_cmd);
4894 install_element (CONFIG_NODE, &no_debug_igmp_cmd);
4895 install_element (CONFIG_NODE, &debug_igmp_events_cmd);
4896 install_element (CONFIG_NODE, &no_debug_igmp_events_cmd);
4897 install_element (CONFIG_NODE, &debug_igmp_packets_cmd);
4898 install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd);
4899 install_element (CONFIG_NODE, &debug_igmp_trace_cmd);
4900 install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd);
4901 install_element (CONFIG_NODE, &debug_mroute_cmd);
4902 install_element (CONFIG_NODE, &debug_mroute_detail_cmd);
4903 install_element (CONFIG_NODE, &no_debug_mroute_cmd);
4904 install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd);
4905 install_element (CONFIG_NODE, &debug_static_cmd);
4906 install_element (CONFIG_NODE, &no_debug_static_cmd);
4907 install_element (CONFIG_NODE, &debug_pim_cmd);
4908 install_element (CONFIG_NODE, &no_debug_pim_cmd);
4909 install_element (CONFIG_NODE, &debug_pim_events_cmd);
4910 install_element (CONFIG_NODE, &no_debug_pim_events_cmd);
4911 install_element (CONFIG_NODE, &debug_pim_packets_cmd);
4912 install_element (CONFIG_NODE, &debug_pim_packets_filter_cmd);
4913 install_element (CONFIG_NODE, &no_debug_pim_packets_cmd);
4914 install_element (CONFIG_NODE, &no_debug_pim_packets_filter_cmd);
4915 install_element (CONFIG_NODE, &debug_pim_trace_cmd);
4916 install_element (CONFIG_NODE, &no_debug_pim_trace_cmd);
4917 install_element (CONFIG_NODE, &debug_ssmpingd_cmd);
4918 install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd);
4919 install_element (CONFIG_NODE, &debug_pim_zebra_cmd);
4920 install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd);
4921 }