3 Copyright (C) 2008 Everton da Silva Marques
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.
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.
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,
23 #include "zebra/rib.h"
36 #include "pim_zebra.h"
37 #include "pim_iface.h"
43 #include "pim_zlookup.h"
44 #include "pim_ifchannel.h"
46 #include "pim_igmpv3.h"
47 #include "pim_jp_agg.h"
51 #undef PIM_DEBUG_IFADDR_DUMP
52 #define PIM_DEBUG_IFADDR_DUMP
54 static struct zclient
*zclient
= NULL
;
56 static int fib_lookup_if_vif_index(struct in_addr addr
);
58 /* Router-id update message from zebra. */
59 static int pim_router_id_update_zebra(int command
, struct zclient
*zclient
,
60 zebra_size_t length
, vrf_id_t vrf_id
)
62 struct prefix router_id
;
64 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
69 static int pim_zebra_if_add(int command
, struct zclient
*zclient
,
70 zebra_size_t length
, vrf_id_t vrf_id
)
72 struct interface
*ifp
;
75 zebra api adds/dels interfaces using the same call
76 interface_add_read below, see comments in lib/zclient.c
78 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
82 if (PIM_DEBUG_ZEBRA
) {
83 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
85 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
86 ifp
->mtu
, if_is_operative(ifp
));
89 if (if_is_operative(ifp
))
90 pim_if_addr_add_all(ifp
);
95 static int pim_zebra_if_del(int command
, struct zclient
*zclient
,
96 zebra_size_t length
, vrf_id_t vrf_id
)
98 struct interface
*ifp
;
101 zebra api adds/dels interfaces using the same call
102 interface_add_read below, see comments in lib/zclient.c
104 comments in lib/zclient.c seem to indicate that calling
105 zebra_interface_add_read is the correct call, but that
106 results in an attemted out of bounds read which causes
107 pimd to assert. Other clients use zebra_interface_state_read
108 and it appears to work just fine.
110 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
114 if (PIM_DEBUG_ZEBRA
) {
115 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
117 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
118 ifp
->mtu
, if_is_operative(ifp
));
121 if (!if_is_operative(ifp
))
122 pim_if_addr_del_all(ifp
);
127 static int pim_zebra_if_state_up(int command
, struct zclient
*zclient
,
128 zebra_size_t length
, vrf_id_t vrf_id
)
130 struct interface
*ifp
;
133 zebra api notifies interface up/down events by using the same call
134 zebra_interface_state_read below, see comments in lib/zclient.c
136 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
140 if (PIM_DEBUG_ZEBRA
) {
141 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
143 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
144 ifp
->mtu
, if_is_operative(ifp
));
147 if (if_is_operative(ifp
)) {
149 pim_if_addr_add_all() suffices for bringing up both IGMP and PIM
151 pim_if_addr_add_all(ifp
);
157 static int pim_zebra_if_state_down(int command
, struct zclient
*zclient
,
158 zebra_size_t length
, vrf_id_t vrf_id
)
160 struct interface
*ifp
;
163 zebra api notifies interface up/down events by using the same call
164 zebra_interface_state_read below, see comments in lib/zclient.c
166 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
170 if (PIM_DEBUG_ZEBRA
) {
171 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
173 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
174 ifp
->mtu
, if_is_operative(ifp
));
177 if (!if_is_operative(ifp
)) {
178 pim_ifchannel_delete_all(ifp
);
180 pim_if_addr_del_all() suffices for shutting down IGMP,
181 but not for shutting down PIM
183 pim_if_addr_del_all(ifp
);
186 pim_sock_delete() closes the socket, stops read and timer threads,
187 and kills all neighbors.
190 pim_sock_delete(ifp
, "link down");
200 #ifdef PIM_DEBUG_IFADDR_DUMP
201 static void dump_if_address(struct interface
*ifp
)
203 struct connected
*ifc
;
204 struct listnode
*node
;
206 zlog_debug("%s %s: interface %s addresses:",
207 __FILE__
, __PRETTY_FUNCTION__
,
210 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
211 struct prefix
*p
= ifc
->address
;
213 if (p
->family
!= AF_INET
)
216 zlog_debug("%s %s: interface %s address %s %s",
217 __FILE__
, __PRETTY_FUNCTION__
,
219 inet_ntoa(p
->u
.prefix4
),
220 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
) ?
221 "secondary" : "primary");
226 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
227 zebra_size_t length
, vrf_id_t vrf_id
)
231 struct pim_interface
*pim_ifp
;
234 zebra api notifies address adds/dels events by using the same call
235 interface_add_read below, see comments in lib/zclient.c
237 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
238 will add address to interface list by calling
239 connected_add_by_prefix()
241 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
245 pim_ifp
= c
->ifp
->info
;
248 if (PIM_DEBUG_ZEBRA
) {
250 prefix2str(p
, buf
, BUFSIZ
);
251 zlog_debug("%s: %s connected IP address %s flags %u %s",
253 c
->ifp
->name
, buf
, c
->flags
,
254 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
) ? "secondary" : "primary");
256 #ifdef PIM_DEBUG_IFADDR_DUMP
257 dump_if_address(c
->ifp
);
261 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
262 /* trying to add primary address */
264 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
265 if (p
->family
!= AF_INET
|| primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
266 if (PIM_DEBUG_ZEBRA
) {
267 /* but we had a primary address already */
271 prefix2str(p
, buf
, BUFSIZ
);
273 zlog_warn("%s: %s : forcing secondary flag on %s",
277 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
283 pim_rp_check_on_if_add(pim_ifp
);
285 if (if_is_loopback (c
->ifp
))
287 struct listnode
*ifnode
;
288 struct interface
*ifp
;
290 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
292 if (!if_is_loopback (ifp
) && if_is_operative (ifp
))
293 pim_if_addr_add_all (ifp
);
300 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
301 zebra_size_t length
, vrf_id_t vrf_id
)
307 zebra api notifies address adds/dels events by using the same call
308 interface_add_read below, see comments in lib/zclient.c
310 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
311 will remove address from interface list by calling
312 connected_delete_by_prefix()
314 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
319 if (p
->family
== AF_INET
)
321 if (PIM_DEBUG_ZEBRA
) {
323 prefix2str(p
, buf
, BUFSIZ
);
324 zlog_debug("%s: %s disconnected IP address %s flags %u %s",
326 c
->ifp
->name
, buf
, c
->flags
,
327 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
) ? "secondary" : "primary");
329 #ifdef PIM_DEBUG_IFADDR_DUMP
330 dump_if_address(c
->ifp
);
334 pim_if_addr_del(c
, 0);
336 pim_i_am_rp_re_evaluate();
343 static void scan_upstream_rpf_cache()
345 struct listnode
*up_node
;
346 struct listnode
*ifnode
;
347 struct listnode
*up_nextnode
;
348 struct listnode
*node
;
349 struct pim_upstream
*up
;
350 struct interface
*ifp
;
352 for (ALL_LIST_ELEMENTS(pim_upstream_list
, up_node
, up_nextnode
, up
)) {
353 enum pim_rpf_result rpf_result
;
356 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
357 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
358 rpf_result
= pim_rpf_update(up
, &old
, 0);
360 if (rpf_result
== PIM_RPF_FAILURE
)
363 if (rpf_result
== PIM_RPF_CHANGED
) {
364 struct pim_neighbor
*nbr
;
366 nbr
= pim_neighbor_find (old
.source_nexthop
.interface
,
367 old
.rpf_addr
.u
.prefix4
);
369 pim_jp_agg_remove_group (nbr
->upstream_jp_agg
, up
);
372 * We have detected a case where we might need to rescan
373 * the inherited o_list so do it.
375 if (up
->channel_oil
->oil_inherited_rescan
)
377 pim_upstream_inherited_olist_decide (up
);
378 up
->channel_oil
->oil_inherited_rescan
= 0;
381 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
383 * If we come up real fast we can be here
384 * where the mroute has not been installed
387 if (!up
->channel_oil
->installed
)
388 pim_mroute_add (up
->channel_oil
, __PRETTY_FUNCTION__
);
391 * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
393 * Transitions from Joined State
395 * RPF'(S,G) changes not due to an Assert
397 * The upstream (S,G) state machine remains in Joined
398 * state. Send Join(S,G) to the new upstream neighbor, which is
399 * the new value of RPF'(S,G). Send Prune(S,G) to the old
400 * upstream neighbor, which is the old value of RPF'(S,G). Set
401 * the Join Timer (JT) to expire after t_periodic seconds.
403 pim_jp_agg_switch_interface (&old
, &up
->rpf
, up
);
405 pim_upstream_join_timer_restart(up
, &old
);
406 } /* up->join_state == PIM_UPSTREAM_JOINED */
408 /* FIXME can join_desired actually be changed by pim_rpf_update()
409 returning PIM_RPF_CHANGED ? */
410 pim_upstream_update_join_desired(up
);
412 } /* PIM_RPF_CHANGED */
414 } /* for (qpim_upstream_list) */
416 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
419 struct pim_interface
*pim_ifp
= ifp
->info
;
420 struct pim_iface_upstream_switch
*us
;
422 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
, us
))
425 rpf
.source_nexthop
.interface
= ifp
;
426 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
427 pim_joinprune_send(&rpf
, us
->us
);
428 pim_jp_agg_clear_group(us
->us
);
434 pim_scan_individual_oil (struct channel_oil
*c_oil
, int in_vif_index
)
436 struct in_addr vif_source
;
437 int input_iface_vif_index
;
440 if (!pim_rp_set_upstream_addr (&vif_source
, c_oil
->oil
.mfcc_origin
, c_oil
->oil
.mfcc_mcastgrp
))
444 input_iface_vif_index
= in_vif_index
;
446 input_iface_vif_index
= fib_lookup_if_vif_index (vif_source
);
447 if (input_iface_vif_index
< 1)
451 char source_str
[INET_ADDRSTRLEN
];
452 char group_str
[INET_ADDRSTRLEN
];
453 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
454 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
455 zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
456 __FILE__
, __PRETTY_FUNCTION__
, c_oil
->oil
.mfcc_parent
,
457 source_str
, group_str
);
459 pim_mroute_del (c_oil
, __PRETTY_FUNCTION__
);
463 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
)
465 if (!c_oil
->installed
)
466 pim_mroute_add (c_oil
, __PRETTY_FUNCTION__
);
474 struct interface
*old_iif
= pim_if_find_by_vif_index(c_oil
->oil
.mfcc_parent
);
475 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
476 char source_str
[INET_ADDRSTRLEN
];
477 char group_str
[INET_ADDRSTRLEN
];
478 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
479 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
480 zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
481 __FILE__
, __PRETTY_FUNCTION__
,
482 source_str
, group_str
,
483 old_iif
->name
, c_oil
->oil
.mfcc_parent
,
484 new_iif
->name
, input_iface_vif_index
);
487 /* new iif loops to existing oif ? */
488 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
])
490 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
492 if (PIM_DEBUG_ZEBRA
) {
493 char source_str
[INET_ADDRSTRLEN
];
494 char group_str
[INET_ADDRSTRLEN
];
495 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
496 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
497 zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
498 __FILE__
, __PRETTY_FUNCTION__
,
499 source_str
, group_str
,
500 new_iif
->name
, input_iface_vif_index
);
504 /* update iif vif_index */
505 old_vif_index
= c_oil
->oil
.mfcc_parent
;
506 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
508 /* update kernel multicast forwarding cache (MFC) */
509 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
))
511 if (PIM_DEBUG_MROUTE
)
513 /* just log warning */
514 struct interface
*old_iif
= pim_if_find_by_vif_index(old_vif_index
);
515 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
516 char source_str
[INET_ADDRSTRLEN
];
517 char group_str
[INET_ADDRSTRLEN
];
518 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
519 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
520 zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
521 __FILE__
, __PRETTY_FUNCTION__
,
522 source_str
, group_str
,
523 old_iif
? old_iif
->name
: "<old_iif?>", c_oil
->oil
.mfcc_parent
,
524 new_iif
? new_iif
->name
: "<new_iif?>", input_iface_vif_index
);
531 struct listnode
*node
;
532 struct listnode
*nextnode
;
533 struct channel_oil
*c_oil
;
535 qpim_scan_oil_last
= pim_time_monotonic_sec();
536 ++qpim_scan_oil_events
;
538 for (ALL_LIST_ELEMENTS(pim_channel_oil_list
, node
, nextnode
, c_oil
))
539 pim_scan_individual_oil (c_oil
, 0);
542 static int on_rpf_cache_refresh(struct thread
*t
)
544 zassert(qpim_rpf_cache_refresher
);
546 qpim_rpf_cache_refresher
= 0;
548 /* update PIM protocol state */
549 scan_upstream_rpf_cache();
551 /* update kernel multicast forwarding cache (MFC) */
554 qpim_rpf_cache_refresh_last
= pim_time_monotonic_sec();
555 ++qpim_rpf_cache_refresh_events
;
561 void sched_rpf_cache_refresh(void)
563 ++qpim_rpf_cache_refresh_requests
;
565 pim_rpf_set_refresh_time ();
567 if (qpim_rpf_cache_refresher
) {
568 /* Refresh timer is already running */
572 /* Start refresh timer */
574 if (PIM_DEBUG_ZEBRA
) {
575 zlog_debug("%s: triggering %ld msec timer",
577 qpim_rpf_cache_refresh_delay_msec
);
580 THREAD_TIMER_MSEC_ON(master
, qpim_rpf_cache_refresher
,
581 on_rpf_cache_refresh
,
582 0, qpim_rpf_cache_refresh_delay_msec
);
586 pim_zebra_nexthop_update (int command
, struct zclient
*zclient
,
587 zebra_size_t length
, vrf_id_t vrf_id
)
589 pim_parse_nexthop_update (zclient
, command
, vrf_id
);
594 pim_zebra_connected (struct zclient
*zclient
)
596 zclient_send_reg_requests (zclient
, VRF_DEFAULT
);
599 void pim_zebra_init(void)
603 #ifdef HAVE_TCP_ZEBRA
604 zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT
);
606 zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get());
609 /* Socket for receiving updates from Zebra daemon */
610 zclient
= zclient_new (master
);
612 zclient
->zebra_connected
= pim_zebra_connected
;
613 zclient
->router_id_update
= pim_router_id_update_zebra
;
614 zclient
->interface_add
= pim_zebra_if_add
;
615 zclient
->interface_delete
= pim_zebra_if_del
;
616 zclient
->interface_up
= pim_zebra_if_state_up
;
617 zclient
->interface_down
= pim_zebra_if_state_down
;
618 zclient
->interface_address_add
= pim_zebra_if_address_add
;
619 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
620 zclient
->nexthop_update
= pim_zebra_nexthop_update
;
622 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0);
623 if (PIM_DEBUG_PIM_TRACE
) {
624 zlog_info("zclient_init cleared redistribution request");
627 zassert(zclient
->redist_default
== ZEBRA_ROUTE_PIM
);
629 /* Request all redistribution */
630 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
631 if (i
== zclient
->redist_default
)
633 vrf_bitmap_set (zclient
->redist
[AFI_IP
][i
], VRF_DEFAULT
);;
634 if (PIM_DEBUG_PIM_TRACE
) {
635 zlog_debug("%s: requesting redistribution for %s (%i)",
636 __PRETTY_FUNCTION__
, zebra_route_string(i
), i
);
640 /* Request default information */
641 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
642 zclient
, VRF_DEFAULT
);
644 if (PIM_DEBUG_PIM_TRACE
) {
645 zlog_info("%s: requesting default information redistribution",
646 __PRETTY_FUNCTION__
);
648 zlog_notice("%s: zclient update socket initialized",
649 __PRETTY_FUNCTION__
);
652 zclient_lookup_new();
655 void igmp_anysource_forward_start(struct igmp_group
*group
)
657 struct igmp_source
*source
;
658 struct in_addr src_addr
= { .s_addr
= 0 };
659 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
660 zassert(group
->group_filtermode_isexcl
);
661 zassert(listcount(group
->group_source_list
) < 1);
663 source
= source_new (group
, src_addr
);
666 zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__
);
670 igmp_source_forward_start (source
);
673 void igmp_anysource_forward_stop(struct igmp_group
*group
)
675 struct igmp_source
*source
;
676 struct in_addr star
= { .s_addr
= 0 };
678 source
= igmp_find_source_by_addr (group
, star
);
680 igmp_source_forward_stop (source
);
683 static int fib_lookup_if_vif_index(struct in_addr addr
)
685 struct pim_zlookup_nexthop nexthop_tab
[MULTIPATH_NUM
];
688 ifindex_t first_ifindex
;
690 num_ifindex
= zclient_lookup_nexthop(nexthop_tab
,
692 PIM_NEXTHOP_LOOKUP_MAX
);
693 if (num_ifindex
< 1) {
696 char addr_str
[INET_ADDRSTRLEN
];
697 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
698 zlog_debug("%s %s: could not find nexthop ifindex for address %s",
699 __FILE__
, __PRETTY_FUNCTION__
,
705 first_ifindex
= nexthop_tab
[0].ifindex
;
707 if (num_ifindex
> 1) {
710 char addr_str
[INET_ADDRSTRLEN
];
711 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
712 zlog_debug("%s %s: FIXME ignoring multiple nexthop ifindex'es num_ifindex=%d for address %s (using only ifindex=%d)",
713 __FILE__
, __PRETTY_FUNCTION__
,
714 num_ifindex
, addr_str
, first_ifindex
);
716 /* debug warning only, do not return */
719 if (PIM_DEBUG_ZEBRA
) {
720 char addr_str
[INET_ADDRSTRLEN
];
721 pim_inet4_dump("<ifaddr?>", addr
, addr_str
, sizeof(addr_str
));
722 zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s",
723 __FILE__
, __PRETTY_FUNCTION__
,
724 first_ifindex
, ifindex2ifname(first_ifindex
, VRF_DEFAULT
), addr_str
);
727 vif_index
= pim_if_find_vifindex_by_ifindex(first_ifindex
);
732 char addr_str
[INET_ADDRSTRLEN
];
733 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
734 zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s",
735 __FILE__
, __PRETTY_FUNCTION__
,
736 vif_index
, addr_str
);
745 igmp_source_forward_reevaluate_one(struct igmp_source
*source
)
748 struct igmp_group
*group
= source
->source_group
;
749 struct pim_ifchannel
*ch
;
751 if ((source
->source_addr
.s_addr
!= INADDR_ANY
) ||
752 !IGMP_SOURCE_TEST_FORWARDING (source
->source_flags
))
755 memset (&sg
, 0, sizeof (struct prefix_sg
));
756 sg
.src
= source
->source_addr
;
757 sg
.grp
= group
->group_addr
;
759 ch
= pim_ifchannel_find (group
->group_igmp_sock
->interface
, &sg
);
760 if (pim_is_grp_ssm (group
->group_addr
))
762 /* If SSM group withdraw local membership */
763 if (ch
&& (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
))
765 if (PIM_DEBUG_PIM_EVENTS
)
766 zlog_debug ("local membership del for %s as G is now SSM",
767 pim_str_sg_dump (&sg
));
768 pim_ifchannel_local_membership_del (group
->group_igmp_sock
->interface
, &sg
);
773 /* If ASM group add local membership */
774 if (!ch
|| (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
))
776 if (PIM_DEBUG_PIM_EVENTS
)
777 zlog_debug ("local membership add for %s as G is now ASM",
778 pim_str_sg_dump (&sg
));
779 pim_ifchannel_local_membership_add (group
->group_igmp_sock
->interface
, &sg
);
785 igmp_source_forward_reevaluate_all(void)
787 struct listnode
*ifnode
;
788 struct interface
*ifp
;
790 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
792 struct pim_interface
*pim_ifp
= ifp
->info
;
793 struct listnode
*sock_node
;
794 struct igmp_sock
*igmp
;
799 /* scan igmp sockets */
800 for (ALL_LIST_ELEMENTS_RO (pim_ifp
->igmp_socket_list
, sock_node
, igmp
))
802 struct listnode
*grpnode
;
803 struct igmp_group
*grp
;
805 /* scan igmp groups */
806 for (ALL_LIST_ELEMENTS_RO (igmp
->igmp_group_list
, grpnode
, grp
))
808 struct listnode
*srcnode
;
809 struct igmp_source
*src
;
811 /* scan group sources */
812 for (ALL_LIST_ELEMENTS_RO (grp
->group_source_list
,
815 igmp_source_forward_reevaluate_one (src
);
816 } /* scan group sources */
817 } /* scan igmp groups */
818 } /* scan igmp sockets */
819 } /* scan interfaces */
822 void igmp_source_forward_start(struct igmp_source
*source
)
824 struct igmp_group
*group
;
828 memset (&sg
, 0, sizeof (struct prefix_sg
));
829 sg
.src
= source
->source_addr
;
830 sg
.grp
= source
->source_group
->group_addr
;
832 if (PIM_DEBUG_IGMP_TRACE
) {
833 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
835 pim_str_sg_dump (&sg
),
836 source
->source_group
->group_igmp_sock
->fd
,
837 source
->source_group
->group_igmp_sock
->interface
->name
,
838 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
841 /* Prevent IGMP interface from installing multicast route multiple
843 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
847 group
= source
->source_group
;
849 if (!source
->source_channel_oil
) {
850 struct in_addr vif_source
;
851 struct pim_interface
*pim_oif
;
853 if (!pim_rp_set_upstream_addr (&vif_source
, source
->source_addr
, sg
.grp
))
856 int input_iface_vif_index
= fib_lookup_if_vif_index(vif_source
);
857 if (input_iface_vif_index
< 1) {
858 if (PIM_DEBUG_IGMP_TRACE
)
860 char source_str
[INET_ADDRSTRLEN
];
861 pim_inet4_dump("<source?>", source
->source_addr
, source_str
, sizeof(source_str
));
862 zlog_debug("%s %s: could not find input interface for source %s",
863 __FILE__
, __PRETTY_FUNCTION__
,
870 Protect IGMP against adding looped MFC entries created by both
871 source and receiver attached to the same interface. See TODO
874 pim_oif
= source
->source_group
->group_igmp_sock
->interface
->info
;
876 if (PIM_DEBUG_IGMP_TRACE
)
878 zlog_debug("%s: multicast not enabled on oif=%s ?",
880 source
->source_group
->group_igmp_sock
->interface
->name
);
885 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
886 /* ignore request for looped MFC entry */
887 if (PIM_DEBUG_IGMP_TRACE
) {
888 zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
890 pim_str_sg_dump (&sg
),
891 source
->source_group
->group_igmp_sock
->fd
,
892 source
->source_group
->group_igmp_sock
->interface
->name
,
893 input_iface_vif_index
);
898 source
->source_channel_oil
= pim_channel_oil_add(&sg
,
899 input_iface_vif_index
);
900 if (!source
->source_channel_oil
) {
901 if (PIM_DEBUG_IGMP_TRACE
)
903 zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
904 __FILE__
, __PRETTY_FUNCTION__
,
905 pim_str_sg_dump (&sg
));
911 result
= pim_channel_add_oif(source
->source_channel_oil
,
912 group
->group_igmp_sock
->interface
,
913 PIM_OIF_FLAG_PROTO_IGMP
);
915 if (PIM_DEBUG_MROUTE
)
917 zlog_warn("%s: add_oif() failed with return=%d",
924 Feed IGMPv3-gathered local membership information into PIM
925 per-interface (S,G) state.
927 if (!pim_ifchannel_local_membership_add(group
->group_igmp_sock
->interface
, &sg
))
929 if (PIM_DEBUG_MROUTE
)
930 zlog_warn ("%s: Failure to add local membership for %s",
931 __PRETTY_FUNCTION__
, pim_str_sg_dump (&sg
));
935 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
939 igmp_source_forward_stop: stop fowarding, but keep the source
940 igmp_source_delete: stop fowarding, and delete the source
942 void igmp_source_forward_stop(struct igmp_source
*source
)
944 struct igmp_group
*group
;
948 memset (&sg
, 0, sizeof (struct prefix_sg
));
949 sg
.src
= source
->source_addr
;
950 sg
.grp
= source
->source_group
->group_addr
;
952 if (PIM_DEBUG_IGMP_TRACE
) {
953 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
955 pim_str_sg_dump (&sg
),
956 source
->source_group
->group_igmp_sock
->fd
,
957 source
->source_group
->group_igmp_sock
->interface
->name
,
958 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
961 /* Prevent IGMP interface from removing multicast route multiple
963 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
967 group
= source
->source_group
;
970 It appears that in certain circumstances that
971 igmp_source_forward_stop is called when IGMP forwarding
972 was not enabled in oif_flags for this outgoing interface.
973 Possibly because of multiple calls. When that happens, we
974 enter the below if statement and this function returns early
975 which in turn triggers the calling function to assert.
976 Making the call to pim_channel_del_oif and ignoring the return code
977 fixes the issue without ill effect, similar to
978 pim_forward_stop below.
980 result
= pim_channel_del_oif(source
->source_channel_oil
,
981 group
->group_igmp_sock
->interface
,
982 PIM_OIF_FLAG_PROTO_IGMP
);
984 if (PIM_DEBUG_IGMP_TRACE
)
985 zlog_debug("%s: pim_channel_del_oif() failed with return=%d",
991 Feed IGMPv3-gathered local membership information into PIM
992 per-interface (S,G) state.
994 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
997 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1000 void pim_forward_start(struct pim_ifchannel
*ch
)
1002 struct pim_upstream
*up
= ch
->upstream
;
1003 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1005 if (PIM_DEBUG_PIM_TRACE
) {
1006 char source_str
[INET_ADDRSTRLEN
];
1007 char group_str
[INET_ADDRSTRLEN
];
1008 char upstream_str
[INET_ADDRSTRLEN
];
1010 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
, sizeof(source_str
));
1011 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
, sizeof(group_str
));
1012 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
, sizeof(upstream_str
));
1013 zlog_debug("%s: (S,G)=(%s,%s) oif=%s(%s)",
1014 __PRETTY_FUNCTION__
,
1015 source_str
, group_str
, ch
->interface
->name
, upstream_str
);
1018 if (!up
->channel_oil
) {
1019 int input_iface_vif_index
= fib_lookup_if_vif_index(up
->upstream_addr
);
1020 if (input_iface_vif_index
< 1) {
1021 if (PIM_DEBUG_PIM_TRACE
)
1023 char source_str
[INET_ADDRSTRLEN
];
1024 pim_inet4_dump("<source?>", up
->sg
.src
, source_str
, sizeof(source_str
));
1025 zlog_debug("%s %s: could not find input interface for source %s",
1026 __FILE__
, __PRETTY_FUNCTION__
,
1032 up
->channel_oil
= pim_channel_oil_add(&up
->sg
,
1033 input_iface_vif_index
);
1034 if (!up
->channel_oil
) {
1035 if (PIM_DEBUG_PIM_TRACE
)
1036 zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
1037 __FILE__
, __PRETTY_FUNCTION__
,
1043 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1044 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1046 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1049 void pim_forward_stop(struct pim_ifchannel
*ch
)
1051 struct pim_upstream
*up
= ch
->upstream
;
1053 if (PIM_DEBUG_PIM_TRACE
) {
1054 zlog_debug("%s: (S,G)=%s oif=%s",
1055 __PRETTY_FUNCTION__
,
1056 ch
->sg_str
, ch
->interface
->name
);
1059 pim_channel_del_oif(up
->channel_oil
,
1061 PIM_OIF_FLAG_PROTO_PIM
);
1065 pim_zebra_zclient_update (struct vty
*vty
)
1067 vty_out(vty
, "Zclient update socket: ");
1070 vty_out(vty
, "%d failures=%d%s", zclient
->sock
,
1071 zclient
->fail
, VTY_NEWLINE
);
1074 vty_out(vty
, "<null zclient>%s", VTY_NEWLINE
);
1078 struct zclient
*pim_zebra_zclient_get (void)