From 6cdea62638c279c5d6e5d23248580aa321dba882 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Wed, 30 Sep 2015 09:55:18 +0200 Subject: [PATCH] Add functions to join/leave v6 multicast 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 mld6 code to convert back to netif. --- src/core/ipv6/mld6.c | 155 +++++++++++++++++++++++++--------------- src/include/lwip/mld6.h | 2 + 2 files changed, 99 insertions(+), 58 deletions(-) diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c index 66eba712..a98afa76 100644 --- a/src/core/ipv6/mld6.c +++ b/src/core/ipv6/mld6.c @@ -326,11 +326,10 @@ mld6_input(struct pbuf *p, struct netif *inp) err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { - err_t err = ERR_VAL; /* no matching interface */ - struct mld_group *group; - struct netif *netif; - u8_t match; - u8_t i; + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + u8_t match; + u8_t i; /* loop through netif's */ netif = netif_list; @@ -350,30 +349,10 @@ mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) } } if (match) { - /* find group or create a new one if not found */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group == NULL) { - /* Joining a new group. Create a new group entry. */ - group = mld6_new_group(netif, groupaddr); - if (group == NULL) { - return ERR_MEM; - } - - /* Activate this address on the MAC layer. */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); - } - - /* Report our membership. */ - MLD6_STATS_INC(mld6.tx_report); - mld6_send(group, ICMP6_TYPE_MLR); - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + err = mld6_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + return err; } - - /* Increment group use */ - group->use++; - err = ERR_OK; } /* proceed to next network interface */ @@ -383,6 +362,44 @@ mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) return err; } +/** + * Join a group on a network interface. + * + * @param netif the network interface which should join a new group. + * @param groupaddr the ipv6 address of the group to join + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t +mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + return ERR_OK; +} + /** * Leave a group on a network interface. * @@ -394,11 +411,10 @@ mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { - err_t err = ERR_VAL; /* no matching interface */ - struct mld_group *group; - struct netif *netif; - u8_t match; - u8_t i; + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + u8_t match; + u8_t i; /* loop through netif's */ netif = netif_list; @@ -418,31 +434,10 @@ mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) } } if (match) { - /* find group */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Leave if there is no other use of the group */ - if (group->use <= 1) { - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - MLD6_STATS_INC(mld6.tx_leave); - mld6_send(group, ICMP6_TYPE_MLD); - } - - /* Disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); - } - - /* Free the group */ - mld6_free_group(group); - } else { - /* Decrement group use */ - group->use--; - } - /* Leave on this interface */ - err = ERR_OK; + err_t res = mld6_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 */ @@ -452,6 +447,50 @@ mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) return err; } +/** + * Leave a group on a network interface. + * + * @param netif the network interface which should leave the group. + * @param groupaddr the ipv6 address of the group to leave + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t +mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) +{ + struct mld_group *group; + + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, MLD6_DEL_MAC_FILTER); + } + + /* Free the group */ + mld6_free_group(group); + } else { + /* Decrement group use */ + group->use--; + } + + /* Left group */ + return ERR_OK; + } + + /* Group not found */ + return ERR_VAL; +} + /** * Periodic timer for mld processing. Must be called every diff --git a/src/include/lwip/mld6.h b/src/include/lwip/mld6.h index f992c992..a54dd49e 100644 --- a/src/include/lwip/mld6.h +++ b/src/include/lwip/mld6.h @@ -105,7 +105,9 @@ void mld6_tmr(void); struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); void mld6_input(struct pbuf *p, struct netif *inp); err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); +err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); #ifdef __cplusplus