From 62b4741b192ff8b801ed6458c3df57d7b6141eec Mon Sep 17 00:00:00 2001 From: fbernon Date: Mon, 3 Sep 2007 14:53:18 +0000 Subject: [PATCH] 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). --- CHANGELOG | 8 ++ src/api/api_msg.c | 4 +- src/api/sockets.c | 4 +- src/core/ipv4/igmp.c | 149 ++++++++++++++++++++--------------- src/core/netif.c | 3 + src/include/ipv4/lwip/igmp.h | 4 +- 6 files changed, 102 insertions(+), 70 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bd9ae7ad..0b412854 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 1c4c29a2..9c4439c4 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -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) diff --git a/src/api/sockets.c b/src/api/sockets.c index e3003181..581c1dff 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -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; diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 28f43db1..92c63e6a 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -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; } /** diff --git a/src/core/netif.c b/src/core/netif.c index cce793b0..30f97cc5 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -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; diff --git a/src/include/ipv4/lwip/igmp.h b/src/include/ipv4/lwip/igmp.h index f3412aa3..6eb445d6 100644 --- a/src/include/ipv4/lwip/igmp.h +++ b/src/include/ipv4/lwip/igmp.h @@ -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);