diff options
Diffstat (limited to 'pimd/pim_igmp.c')
| -rw-r--r-- | pimd/pim_igmp.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 57c4cdc470..8f81dbc23a 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -72,42 +72,42 @@ void igmp_anysource_forward_stop(struct gm_group *group) } static void igmp_source_forward_reevaluate_one(struct pim_instance *pim, - struct gm_source *source) + struct gm_source *source, + int is_grp_ssm) { pim_sgaddr sg; struct gm_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(sg)); sg.src = source->source_addr; sg.grp = group->group_addr; - ch = pim_ifchannel_find(group->interface, &sg); - if (pim_is_grp_ssm(pim, 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 %pSG as G is now SSM", - &sg); - pim_ifchannel_local_membership_del(group->interface, - &sg); + /** if there is no PIM state **/ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + if (pim_addr_is_any(source->source_addr)) { + if (is_grp_ssm) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership del for %pSG as G is now SSM", + &sg); + igmp_source_forward_stop(source); + } + } else { + if (!is_grp_ssm) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership del for %pSG as G is now ASM", + &sg); + igmp_source_forward_stop(source); + } } } else { - /* If ASM group add local membership */ - if (!ch || - (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { + if (!pim_addr_is_any(source->source_addr) && (is_grp_ssm)) { if (PIM_DEBUG_PIM_EVENTS) zlog_debug( - "local membership add for %pSG as G is now ASM", + "local membership add for %pSG as G is now SSM", &sg); - pim_ifchannel_local_membership_add( - group->interface, &sg, false /*is_vxlan*/); + igmp_source_forward_start(pim, source); } } } @@ -118,7 +118,7 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) FOR_ALL_INTERFACES (pim->vrf, ifp) { struct pim_interface *pim_ifp = ifp->info; - struct listnode *grpnode; + struct listnode *grpnode, *grp_nextnode; struct gm_group *grp; struct pim_ifchannel *ch, *ch_temp; @@ -126,10 +126,11 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) continue; /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, - grp)) { + for (ALL_LIST_ELEMENTS(pim_ifp->gm_group_list, grpnode, + grp_nextnode, grp)) { struct listnode *srcnode; struct gm_source *src; + int is_grp_ssm; /* * RFC 4604 @@ -139,16 +140,16 @@ void igmp_source_forward_reevaluate_all(struct pim_instance *pim) * MODE_IS_EXCLUDE and CHANGE_TO_EXCLUDE_MODE * requests in the SSM range. */ - if (pim_is_grp_ssm(pim, grp->group_addr) && - grp->group_filtermode_isexcl) { + is_grp_ssm = pim_is_grp_ssm(pim, grp->group_addr); + if (is_grp_ssm && grp->group_filtermode_isexcl) { igmp_group_delete(grp); } else { /* scan group sources */ for (ALL_LIST_ELEMENTS_RO( grp->group_source_list, srcnode, src)) { - igmp_source_forward_reevaluate_one(pim, - src); + igmp_source_forward_reevaluate_one( + pim, src, is_grp_ssm); } /* scan group sources */ } } /* scan igmp groups */ @@ -179,6 +180,18 @@ void igmp_source_forward_start(struct pim_instance *pim, IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); } + /* + * PIM state should not be allowed for ASM group with valid source + * address. + */ + if ((!pim_is_grp_ssm(pim, source->source_group->group_addr)) && + !pim_addr_is_any(source->source_addr)) { + zlog_warn( + "%s: (S,G)=%pSG ASM range having source address, not allowed to create PIM state", + __func__, &sg); + return; + } + /* Prevent IGMP interface from installing multicast route multiple times */ if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { @@ -193,8 +206,8 @@ void igmp_source_forward_start(struct pim_instance *pim, } /* - igmp_source_forward_stop: stop fowarding, but keep the source - igmp_source_delete: stop fowarding, and delete the source + igmp_source_forward_stop: stop forwarding, but keep the source + igmp_source_delete: stop forwarding, and delete the source */ void igmp_source_forward_stop(struct gm_source *source) { @@ -229,8 +242,7 @@ void igmp_source_forward_stop(struct gm_source *source) /* This socket is used for TXing IGMP packets only, IGMP RX happens * in pim_mroute_msg() */ -static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, - uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp) { int fd; int join = 0; @@ -242,17 +254,14 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, if (fd < 0) return -1; - if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { - if (inet_aton(PIM_ALL_ROUTERS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex, - pim_ifp)) - ++join; - } else { - zlog_warn( - "%s %s: IGMP socket fd=%d interface %pI4: could not solve %s to group address: errno=%d: %s", - __FILE__, __func__, fd, &ifaddr, - PIM_ALL_ROUTERS, errno, safe_strerror(errno)); - } + if (inet_aton(PIM_ALL_ROUTERS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex, pim_ifp)) + ++join; + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %pI4: could not solve %s to group address: errno=%d: %s", + __FILE__, __func__, fd, &ifaddr, PIM_ALL_ROUTERS, errno, + safe_strerror(errno)); } /* @@ -1244,14 +1253,11 @@ struct gm_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp, bool mtrace_only) { - struct pim_interface *pim_ifp; struct gm_sock *igmp; struct sockaddr_in sin; int fd; - pim_ifp = ifp->info; - - fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); + fd = igmp_sock_open(ifaddr, ifp); if (fd < 0) { zlog_warn("Could not open IGMP socket for %pI4 on %s", &ifaddr, ifp->name); |
