Changes for "#20503 IGMP Improvement". Initialize igmp_mac_filter to NULL in netif_add (this field should be set in the netif's "init" function). Use the "imr_interface" field (for socket layer) and/or the "interface" field (for netconn layer), for join/leave operations. The igmp_join/leavegroup first parameter change from a netif to an ipaddr. This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany).

This commit is contained in:
fbernon 2007-09-03 14:53:18 +00:00
parent 327f06bbaf
commit 62b4741b19
6 changed files with 102 additions and 70 deletions

View File

@ -19,6 +19,14 @@ HISTORY
++ New features:
2007-09-03 Frédéric Bernon
* igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement".
Initialize igmp_mac_filter to NULL in netif_add (this field should be set in
the netif's "init" function). Use the "imr_interface" field (for socket layer)
and/or the "interface" field (for netconn layer), for join/leave operations.
The igmp_join/leavegroup first parameter change from a netif to an ipaddr.
This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany).
2007-08-30 Frédéric Bernon
* Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions
from api/api_lib". Now netbuf API is independant of netconn, and can be used

View File

@ -915,9 +915,9 @@ do_join_leave_group(struct api_msg_msg *msg)
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
#if LWIP_UDP
if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
msg->conn->err = igmp_joingroup ( netif_default, msg->msg.jl.multiaddr);
msg->conn->err = igmp_joingroup ( msg->msg.jl.interface, msg->msg.jl.multiaddr);
} else {
msg->conn->err = igmp_leavegroup( netif_default, msg->msg.jl.multiaddr);
msg->conn->err = igmp_leavegroup( msg->msg.jl.interface, msg->msg.jl.multiaddr);
}
#endif /* LWIP_UDP */
#if (LWIP_TCP || LWIP_RAW)

View File

@ -1626,9 +1626,9 @@ static void lwip_setsockopt_internal(void *arg)
/* If this is a TCP or a RAW socket, ignore these options. */
struct ip_mreq *imr = (struct ip_mreq *)optval;
if(optname == IP_ADD_MEMBERSHIP){
data->err = igmp_joingroup(netif_default, (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
data->err = igmp_joingroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
} else {
data->err = igmp_leavegroup(netif_default, (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
data->err = igmp_leavegroup((struct ip_addr*)&(imr->imr_interface.s_addr), (struct ip_addr*)&(imr->imr_multiaddr.s_addr));
}
if(data->err != ERR_OK) {
data->err = EADDRNOTAVAIL;

View File

@ -330,102 +330,123 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
/**
* Join a group on one network interface.
*
* @param ifp the network interface which should join a new group
* @param ifaddr ip address of 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, an err_t otherwise
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
*/
err_t
igmp_joingroup(struct netif *ifp, struct ip_addr *groupaddr)
igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
/* make sure netif is valid */
LWIP_ERROR("igmp_joingroup: attempt to join on NULL netif", (ifp!=NULL), return ERR_VAL;);
struct netif *netif;
/* make sure it is multicast address */
LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
/* find group or create a new one if not found */
group = igmp_lookup_group(ifp, groupaddr);
/* loop through netif's */
netif = netif_list;
while (netif != NULL) {
/* Should we join this interface ? */
if ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr))) {
/* find group or create a new one if not found */
group = igmp_lookup_group(netif, groupaddr);
if (group != NULL) {
/* This should create a new group, check the state to make sure */
if (group->group_state != NON_MEMBER) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state NON_MEMBER\n"));
return ERR_OK;
if (group != NULL) {
/* This should create a new group, check the state to make sure */
if (group->group_state != NON_MEMBER) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state NON_MEMBER\n"));
} else {
/* OK - it was new group */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
if (netif->igmp_mac_filter != NULL) {
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
}
IGMP_STATS_INC(igmp.join_sent);
igmp_send(group, IGMP_V2_MEMB_REPORT);
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
/* Need to work out where this timer comes from */
group->group_state = DELAYING_MEMBER;
}
/* Join on this interface */
err = ERR_OK;
} else {
/* Return an error even if some network interfaces are joined */
/** @todo undo any other netif already joined */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n"));
return ERR_MEM;
}
}
/* OK - it was new group */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
if (ifp->igmp_mac_filter != NULL) {
ifp->igmp_mac_filter(ifp, groupaddr, IGMP_ADD_MAC_FILTER);
}
IGMP_STATS_INC(igmp.join_sent);
igmp_send(group, IGMP_V2_MEMB_REPORT);
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
/* Need to work out where this timer comes from */
group->group_state = DELAYING_MEMBER;
return ERR_OK;
/* proceed to next network interface */
netif = netif->next;
}
return ERR_MEM;
return err;
}
/**
* Leave a group on one network interface.
*
* @param ifp the network interface which should leave a group
* @param ifaddr ip address of 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, an err_t otherwise
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
*/
err_t
igmp_leavegroup(struct netif *ifp, struct ip_addr *groupaddr)
igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
{
err_t err = ERR_VAL; /* no matching interface */
struct igmp_group *group;
/* make sure netif is valid */
LWIP_ERROR("igmp_leavegroup: attempt to leave on NULL netif", (ifp!=NULL), return ERR_VAL;);
struct netif *netif;
/* make sure it is multicast address */
LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
/* find group */
group = igmp_lookfor_group(ifp, groupaddr);
/* loop through netif's */
netif = netif_list;
while (netif != NULL) {
/* Should we leave this interface ? */
if ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr))) {
/* find group */
group = igmp_lookfor_group(netif, groupaddr);
if (group != NULL) {
/* Only send a leave if the flag is set according to the state diagram */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
if (group != NULL) {
/* Only send a leave if the flag is set according to the state diagram */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));
ip_addr_debug_print(IGMP_DEBUG, groupaddr);
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
IGMP_STATS_INC(igmp.leave_sent);
igmp_send(group, IGMP_LEAVE_GROUP);
if (group->last_reporter_flag) {
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
IGMP_STATS_INC(igmp.leave_sent);
igmp_send(group, IGMP_LEAVE_GROUP);
}
/* The block is not deleted since the group still exists and we may rejoin */
group->last_reporter_flag = 0;
group->group_state = NON_MEMBER;
group->timer = 0;
if (netif->igmp_mac_filter != NULL) {
netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
}
/* Leave on this interface */
err = ERR_OK;
} else {
/* It's not a fatal error on "leavegroup" */
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));
}
}
/* The block is not deleted since the group still exists and we may rejoin */
group->last_reporter_flag = 0;
group->group_state = NON_MEMBER;
group->timer = 0;
if (ifp->igmp_mac_filter != NULL) {
ifp->igmp_mac_filter(ifp, groupaddr, IGMP_DEL_MAC_FILTER);
}
return ERR_OK;
/* proceed to next network interface */
netif = netif->next;
}
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));
return ERR_VAL;
return err;
}
/**

View File

@ -115,6 +115,9 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
#if LWIP_NETIF_LINK_CALLBACK
netif->link_callback = NULL;
#endif /* LWIP_NETIF_LINK_CALLBACK */
#if LWIP_IGMP
netif->igmp_mac_filter = NULL;
#endif /* LWIP_IGMP */
/* remember netif specific state information data */
netif->state = state;

View File

@ -117,9 +117,9 @@ struct igmp_group *igmp_lookup_group(struct netif *ifp, struct ip_addr *addr);
void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest);
err_t igmp_joingroup( struct netif* ifp, struct ip_addr *groupaddr);
err_t igmp_joingroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
err_t igmp_leavegroup( struct netif* ifp, struct ip_addr *groupaddr);
err_t igmp_leavegroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
void igmp_tmr(void);