return vif_index;
}
- static int del_oif(struct channel_oil *channel_oil,
- struct interface *oif,
- uint32_t proto_mask)
- {
- struct pim_interface *pim_ifp;
- int old_ttl;
-
- pim_ifp = oif->info;
-
- if (PIM_DEBUG_MROUTE) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str,
- proto_mask, oif->name, pim_ifp->mroute_vif_index);
- }
-
- /* Prevent single protocol from unsubscribing same interface from
- channel (S,G) multiple times */
- if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) {
- if (PIM_DEBUG_MROUTE)
- {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- proto_mask, oif->name, pim_ifp->mroute_vif_index,
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
- source_str, group_str);
- }
- return -2;
- }
-
- /* Mark that protocol is no longer interested in this OIF */
- channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask;
-
- /* Allow multiple protocols to unsubscribe same interface from
- channel (S,G) multiple times, by silently ignoring requests while
- there is at least one protocol interested in the channel */
- if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) {
-
- /* Check the OIF keeps existing before returning, and only log
- warning otherwise */
- if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) {
- if (PIM_DEBUG_MROUTE)
- {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- proto_mask, oif->name, pim_ifp->mroute_vif_index,
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index],
- source_str, group_str);
- }
- }
-
- return 0;
- }
-
- old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index];
-
- if (old_ttl < 1) {
- if (PIM_DEBUG_MROUTE)
- {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- oif->name, pim_ifp->mroute_vif_index,
- source_str, group_str);
- }
- return -3;
- }
-
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0;
-
- if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_warn("%s %s: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- oif->name, pim_ifp->mroute_vif_index,
- source_str, group_str);
-
- channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl;
- return -4;
- }
-
- --channel_oil->oil_size;
-
- if (channel_oil->oil_size < 1) {
- if (pim_mroute_del(channel_oil, __PRETTY_FUNCTION__)) {
- if (PIM_DEBUG_MROUTE)
- {
- /* just log a warning in case of failure */
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: failure removing OIL for channel (S,G)=(%s,%s)",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str);
- }
- }
- }
-
- if (PIM_DEBUG_MROUTE) {
- char group_str[INET_ADDRSTRLEN];
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
- pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str));
- zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE",
- __FILE__, __PRETTY_FUNCTION__,
- source_str, group_str,
- proto_mask, oif->name, pim_ifp->mroute_vif_index);
- }
-
- return 0;
- }
-
+static void
+igmp_source_forward_reevaluate_one(struct igmp_source *source)
+{
+ struct prefix_sg sg;
+ struct igmp_group *group = source->source_group;
+ struct pim_ifchannel *ch;
+
+ if ((source->source_addr.s_addr != INADDR_ANY) ||
+ !IGMP_SOURCE_TEST_FORWARDING (source->source_flags))
+ return;
+
+ memset (&sg, 0, sizeof (struct prefix_sg));
+ sg.src = source->source_addr;
+ sg.grp = group->group_addr;
+
+ ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg);
+ if (pim_is_grp_ssm (group->group_addr))
+ {
+ /* If SSM group withdraw local membership */
+ if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE))
+ {
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug ("local membership del for %s as G is now SSM",
+ pim_str_sg_dump (&sg));
+ pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg);
+ }
+ }
+ else
+ {
+ /* If ASM group add local membership */
+ if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO))
+ {
+ if (PIM_DEBUG_PIM_EVENTS)
+ zlog_debug ("local membership add for %s as G is now ASM",
+ pim_str_sg_dump (&sg));
+ pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg);
+ }
+ }
+}
+
+void
+igmp_source_forward_reevaluate_all(void)
+{
+ struct listnode *ifnode;
+ struct interface *ifp;
+
+ for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp))
+ {
+ struct pim_interface *pim_ifp = ifp->info;
+ struct listnode *sock_node;
+ struct igmp_sock *igmp;
+
+ if (!pim_ifp)
+ continue;
+
+ /* scan igmp sockets */
+ for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp))
+ {
+ struct listnode *grpnode;
+ struct igmp_group *grp;
+
+ /* scan igmp groups */
+ for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp))
+ {
+ struct listnode *srcnode;
+ struct igmp_source *src;
+
+ /* scan group sources */
+ for (ALL_LIST_ELEMENTS_RO (grp->group_source_list,
+ srcnode, src))
+ {
+ igmp_source_forward_reevaluate_one (src);
+ } /* scan group sources */
+ } /* scan igmp groups */
+ } /* scan igmp sockets */
+ } /* scan interfaces */
+}
+
void igmp_source_forward_start(struct igmp_source *source)
{
struct igmp_group *group;