From 939180c1a1b69a64ece55bfc7a644be564e09dcb Mon Sep 17 00:00:00 2001 From: fbernon Date: Sun, 9 Sep 2007 20:46:33 +0000 Subject: [PATCH] igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). igmp_report_groups() is now called inside netif_set_link_up() (need to have LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait the next query message to receive the matching multicast streams). --- CHANGELOG | 8 +++ src/core/ipv4/igmp.c | 99 +++++++++++++++++++++++++++++++++--- src/core/ipv4/ip.c | 2 +- src/core/netif.c | 18 ++++++- src/include/ipv4/lwip/igmp.h | 10 ++-- src/include/lwip/netif.h | 2 + 6 files changed, 127 insertions(+), 12 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e0914f76..c8d025c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,14 @@ HISTORY ++ New features: + 2007-09-09 Frédéric Bernon, Bill Florac + * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, + and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags + if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). + igmp_report_groups() is now called inside netif_set_link_up() (need to have + LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait + the next query message to receive the matching multicast streams). + 2007-09-08 Frédéric Bernon * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 1045d598..c8370b7b 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -117,6 +117,27 @@ igmp_init(void) igmp_group_list = NULL; } +#ifdef LWIP_DEBUG +/** + * Dump global IGMP groups list + */ +void +igmp_dump_group_list() +{ + struct igmp_group *group = igmp_group_list; + + while (group != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state))); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface)); + group = group->next; + } + LWIP_DEBUGF(IGMP_DEBUG, ("\n")); +} +#else +#define igmp_dump_group_list() +#endif /* LWIP_DEBUG */ + /** * Start IGMP processing on interface * @@ -149,6 +170,70 @@ igmp_start(struct netif *netif) return ERR_MEM; } +/** + * Stop IGMP processing on interface + * + * @param netif network interface on which stop IGMP processing + */ +err_t +igmp_stop(struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + struct igmp_group *prev = NULL; + struct igmp_group *next; + + /* look for groups joined on this interface further down the list */ + while (group != NULL) { + next = group->next; + /* is it a group joined on this interface? */ + if (group->interface == netif) { + /* is it the first group of the list? */ + if (group == igmp_group_list) { + igmp_group_list = next; + } + /* is there a "previous" group defined? */ + if (prev != NULL) { + prev->next = next; + } + /* disable the group at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); + ip_addr_debug_print(IGMP_DEBUG, &group->group_address); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif)); + netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER); + } + /* free group */ + memp_free(MEMP_IGMP_GROUP, group); + } else { + /* change the "previous" */ + prev = group; + } + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report IGMP memberships for this interface + * + * @param netif network interface on which report IGMP memberships + */ +void +igmp_report_groups( struct netif *netif) +{ + struct igmp_group *group = igmp_group_list; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %x\n", (int) netif)); + + while (group != NULL) { + if (group->interface == netif) { + igmp_delaying_member( group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } + group = group->next; + } +} + /** * Search for a group in the global igmp_group_list * @@ -162,7 +247,7 @@ igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr) { struct igmp_group *group = igmp_group_list; - while (group) { + while (group != NULL) { if ((group->interface == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { return group; } @@ -224,14 +309,14 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr) */ err_t igmp_remove_group(struct igmp_group *group) -{ +{ err_t err = ERR_OK; /* Is it the first group? */ if (igmp_group_list == group) { igmp_group_list = group->next; } else { - /* look for group further down the list */ + /* look for group further down the list */ struct igmp_group *tmpGroup; for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) { if (tmpGroup->next == group) { @@ -245,7 +330,7 @@ igmp_remove_group(struct igmp_group *group) } /* free group */ memp_free(MEMP_IGMP_GROUP, group); - + return err; } @@ -386,7 +471,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr) netif = netif_list; while (netif != NULL) { /* Should we join this interface ? */ - if ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr))) { + if ((netif->flags & NETIF_FLAG_IGMP) && ((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); @@ -456,7 +541,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr) netif = netif_list; while (netif != NULL) { /* Should we leave this interface ? */ - if ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr))) { + if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) { /* find group */ group = igmp_lookfor_group(netif, groupaddr); @@ -479,7 +564,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr) if (netif->igmp_mac_filter != NULL) { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL ")); ip_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif)); + LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif)); netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER); } diff --git a/src/core/ipv4/ip.c b/src/core/ipv4/ip.c index de58019f..9980cbc8 100644 --- a/src/core/ipv4/ip.c +++ b/src/core/ipv4/ip.c @@ -237,7 +237,7 @@ ip_input(struct pbuf *p, struct netif *inp) { /* match packet against an interface, i.e. is this packet for us? */ #if LWIP_IGMP if (ip_addr_ismulticast(&(iphdr->dest))) - { if (igmp_lookfor_group( inp, &(iphdr->dest))) + { if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group( inp, &(iphdr->dest)))) { netif = inp; } else diff --git a/src/core/netif.c b/src/core/netif.c index e00a2d60..9c9da2b1 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -138,7 +138,9 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, #if LWIP_IGMP /* start IGMP processing */ - igmp_start( netif); + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_start( netif); + } #endif /* LWIP_IGMP */ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", @@ -179,6 +181,13 @@ void netif_remove(struct netif * netif) { if ( netif == NULL ) return; +#if LWIP_IGMP + /* stop IGMP processing */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_stop( netif); + } +#endif /* LWIP_IGMP */ + snmp_delete_ipaddridx_tree(netif); /* is it the first netif? */ @@ -461,6 +470,13 @@ void netif_set_link_up(struct netif *netif ) } #endif /* LWIP_ARP */ +#if LWIP_IGMP + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } +#endif /* LWIP_IGMP */ + NETIF_LINK_CALLBACK(netif); } diff --git a/src/include/ipv4/lwip/igmp.h b/src/include/ipv4/lwip/igmp.h index 05c4cbd6..f0703e40 100644 --- a/src/include/ipv4/lwip/igmp.h +++ b/src/include/ipv4/lwip/igmp.h @@ -112,11 +112,15 @@ void igmp_init(void); err_t igmp_start( struct netif *netif); -struct igmp_group *igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr); +err_t igmp_stop( struct netif *netif); -struct igmp_group *igmp_lookup_group(struct netif *ifp, struct ip_addr *addr); +void igmp_report_groups( struct netif *netif); -err_t igmp_remove_group(struct igmp_group *group); +struct igmp_group *igmp_lookfor_group( struct netif *ifp, struct ip_addr *addr); + +struct igmp_group *igmp_lookup_group( struct netif *ifp, struct ip_addr *addr); + +err_t igmp_remove_group( struct igmp_group *group); void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest); diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index d320e7c5..bde006a7 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -76,6 +76,8 @@ extern "C" { #define NETIF_FLAG_LINK_UP 0x10U /** if set, the netif is an device using ARP */ #define NETIF_FLAG_ETHARP 0x20U +/** if set, the netif has IGMP capability */ +#define NETIF_FLAG_IGMP 0x40U /** Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization