summaryrefslogtreecommitdiff
path: root/pimd/pim_igmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_igmp.c')
-rw-r--r--pimd/pim_igmp.c104
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);