net: if: Leave all joined IPv6 multicast groups at net_if_down

When network interface is taken down, leave only those
IPv6 multicast groups that were joined.

Change-Id: I414556c093ba67be7c13e6c86e0451465c2203f3
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-02-10 09:36:09 +02:00
commit f8467437e6
3 changed files with 41 additions and 23 deletions

View file

@ -75,7 +75,12 @@ struct net_if_addr {
*/
struct net_if_mcast_addr {
/** Is this multicast IP address used or not */
bool is_used;
uint8_t is_used : 1;
/** Did we join to this group */
uint8_t is_joined : 1;
uint8_t _unused : 6;
/** IP address */
struct net_addr address;
@ -631,6 +636,30 @@ bool net_if_ipv6_maddr_rm(struct net_if *iface, const struct in6_addr *addr);
struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr,
struct net_if **iface);
/**
* @brief Mark a given multicast address to be joined.
*
* @param addr IPv6 multicast address
*/
static inline void net_if_ipv6_maddr_join(struct net_if_mcast_addr *addr)
{
NET_ASSERT(addr);
addr->is_joined = true;
}
/**
* @brief Mark a given multicast address to be left.
*
* @param addr IPv6 multicast address
*/
static inline void net_if_ipv6_maddr_leave(struct net_if_mcast_addr *addr)
{
NET_ASSERT(addr);
addr->is_joined = false;
}
/**
* @brief Check if this IPv6 prefix belongs to this interface
*

View file

@ -2284,7 +2284,7 @@ static int send_mldv2(struct net_if *iface, const struct in6_addr *addr,
int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr)
{
const struct net_if_mcast_addr *maddr;
struct net_if_mcast_addr *maddr;
int ret;
maddr = net_if_ipv6_maddr_lookup(addr, &iface);
@ -2302,6 +2302,8 @@ int net_ipv6_mld_join(struct net_if *iface, const struct in6_addr *addr)
return ret;
}
net_if_ipv6_maddr_join(maddr);
net_mgmt_event_notify(NET_EVENT_IPV6_MCAST_JOIN, iface);
return ret;

View file

@ -265,35 +265,24 @@ static void join_mcast_solicit_node(struct net_if *iface,
net_ipv6_mld_join(iface, &addr);
}
static void leave_mcast_allnodes(struct net_if *iface)
static void leave_mcast_all(struct net_if *iface)
{
struct in6_addr addr;
net_ipv6_addr_create_ll_allnodes_mcast(&addr);
net_ipv6_mld_leave(iface, &addr);
}
static void leave_mcast_solicit_node_all(struct net_if *iface)
{
struct in6_addr addr;
int i;
for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
if (!iface->ipv6.mcast[i].is_used) {
if (!iface->ipv6.mcast[i].is_used ||
!iface->ipv6.mcast[i].is_joined) {
continue;
}
net_ipv6_addr_create_solicited_node(
&iface->ipv6.mcast[i].address.in6_addr, &addr);
net_ipv6_mld_leave(iface, &addr);
net_ipv6_mld_leave(iface,
&iface->ipv6.mcast[i].address.in6_addr);
}
}
#else
#define join_mcast_allnodes(...)
#define join_mcast_solicit_node(...)
#define leave_mcast_allnodes(...)
#define leave_mcast_solicit_node_all(...)
#define leave_mcast_all(...)
#endif /* CONFIG_NET_IPV6_MLD */
#if defined(CONFIG_NET_IPV6_DAD)
@ -1186,8 +1175,7 @@ uint32_t net_if_ipv6_calc_reachable_time(struct net_if *iface)
#else /* CONFIG_NET_IPV6 */
#define join_mcast_allnodes(...)
#define join_mcast_solicit_node(...)
#define leave_mcast_allnodes(...)
#define leave_mcast_solicit_node_all(...)
#define leave_mcast_all(...)
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
@ -1499,8 +1487,7 @@ int net_if_down(struct net_if *iface)
/* FIXME: Make sure that the IPV6 mcast leave message
* gets actually sent.
*/
leave_mcast_allnodes(iface);
leave_mcast_solicit_node_all(iface);
leave_mcast_all(iface);
/* If the L2 does not support enable just clear the flag */
if (!iface->l2->enable) {