Add functions to join/leave IGMP group by netif

Existing functions are based on IP address, but the address is used
only to look up which netif to act on. The netif-based core code is
extracted to new exported functions.

If you have a netif handle, this makes it easier to join/leave
groups, without the need to convert to IP address first only for the
IGMP code to convert back to netif.
This commit is contained in:
Erik Ekman 2015-09-28 16:38:31 +02:00 committed by goldsimon
parent 373714c02f
commit ba71ac78d9
2 changed files with 131 additions and 83 deletions

View File

@ -489,7 +489,6 @@ err_t
igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
{ {
err_t err = ERR_VAL; /* no matching interface */ err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
struct netif *netif; struct netif *netif;
/* make sure it is multicast address */ /* make sure it is multicast address */
@ -501,22 +500,54 @@ igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
while (netif != NULL) { while (netif != NULL) {
/* Should we join this interface ? */ /* Should we join this interface ? */
if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
err = igmp_joingroup_netif(netif, groupaddr);
if (err != ERR_OK) {
/* Return an error even if some network interfaces are joined */
/** @todo undo any other netif already joined */
return err;
}
}
/* proceed to next network interface */
netif = netif->next;
}
return err;
}
/**
* Join a group on one network interface.
*
* @param netif the network interface which should join a new group
* @param groupaddr the ip address of the group which to join
* @return ERR_OK if group was joined on the netif, an err_t otherwise
*/
err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
struct igmp_group *group;
/* make sure it is multicast address */
LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* make sure it is an igmp-enabled netif */
LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
/* find group or create a new one if not found */ /* find group or create a new one if not found */
group = igmp_lookup_group(netif, groupaddr); group = igmp_lookup_group(netif, groupaddr);
if (group != NULL) { if (group != NULL) {
/* This should create a new group, check the state to make sure */ /* This should create a new group, check the state to make sure */
if (group->group_state != IGMP_GROUP_NON_MEMBER) { if (group->group_state != IGMP_GROUP_NON_MEMBER) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
} else { } else {
/* OK - it was new group */ /* OK - it was new group */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: ")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr); ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n")); LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
/* If first use of the group, allow the group at the MAC level */ /* If first use of the group, allow the group at the MAC level */
if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD ")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr); ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER); netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
@ -533,19 +564,11 @@ igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
/* Increment group use */ /* Increment group use */
group->use++; group->use++;
/* Join on this interface */ /* Join on this interface */
err = ERR_OK; return ERR_OK;
} else { } else {
/* Return an error even if some network interfaces are joined */ LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n"));
/** @todo undo any other netif already joined */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enough memory to join to group\n"));
return ERR_MEM; return ERR_MEM;
} }
}
/* proceed to next network interface */
netif = netif->next;
}
return err;
} }
/** /**
@ -559,7 +582,6 @@ err_t
igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
{ {
err_t err = ERR_VAL; /* no matching interface */ err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
struct netif *netif; struct netif *netif;
/* make sure it is multicast address */ /* make sure it is multicast address */
@ -571,12 +593,43 @@ igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
while (netif != NULL) { while (netif != NULL) {
/* Should we leave this interface ? */ /* Should we leave this interface ? */
if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) {
err_t res = igmp_leavegroup_netif(netif, groupaddr);
if (err != ERR_OK) {
/* Store this result if we have not yet gotten a success */
err = res;
}
}
/* proceed to next network interface */
netif = netif->next;
}
return err;
}
/**
* Leave a group on one network interface.
*
* @param netif the network interface which should leave a group
* @param groupaddr the ip address of the group which to leave
* @return ERR_OK if group was left on the netif, an err_t otherwise
*/
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr)
{
struct igmp_group *group;
/* make sure it is multicast address */
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;);
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
/* make sure it is an igmp-enabled netif */
LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;);
/* find group */ /* find group */
group = igmp_lookfor_group(netif, groupaddr); group = igmp_lookfor_group(netif, groupaddr);
if (group != NULL) { if (group != NULL) {
/* Only send a leave if the flag is set according to the state diagram */ /* Only send a leave if the flag is set according to the state diagram */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: ")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr); ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n")); LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
@ -584,20 +637,20 @@ igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
if (group->use <= 1) { if (group->use <= 1) {
/* If we are the last reporter for this group */ /* If we are the last reporter for this group */
if (group->last_reporter_flag) { if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n"));
IGMP_STATS_INC(igmp.tx_leave); IGMP_STATS_INC(igmp.tx_leave);
igmp_send(group, IGMP_LEAVE_GROUP); igmp_send(group, IGMP_LEAVE_GROUP);
} }
/* Disable the group at the MAC level */ /* Disable the group at the MAC level */
if (netif->igmp_mac_filter != NULL) { if (netif->igmp_mac_filter != NULL) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr); ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif));
netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
} }
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: ")); LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: remove group: "));
ip4_addr_debug_print(IGMP_DEBUG, groupaddr); ip4_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n")); LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
@ -607,18 +660,11 @@ igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr)
/* Decrement group use */ /* Decrement group use */
group->use--; group->use--;
} }
/* Leave on this interface */ return ERR_OK;
err = ERR_OK;
} else { } else {
/* It's not a fatal error on "leavegroup" */ LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n"));
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n")); return ERR_VAL;
} }
}
/* proceed to next network interface */
netif = netif->next;
}
return err;
} }
/** /**

View File

@ -94,7 +94,9 @@ void igmp_report_groups(struct netif *netif);
struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr);
void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest);
err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr);
err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr);
err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr);
err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr);
void igmp_tmr(void); void igmp_tmr(void);
#ifdef __cplusplus #ifdef __cplusplus