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