net: ipv4: Re-join multicast groups if needed
If network interface goes operative down, then re-join user defined IPv4 multicast groups that where joined earlier when the interface comes up again. If user takes the network interface down manually (admin down), then the user specific groups are not re-joined. This works now the same way as IPv6 re-joining. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
parent
64492b656f
commit
24bf9c2334
1 changed files with 79 additions and 1 deletions
|
|
@ -4840,6 +4840,78 @@ static void iface_ipv4_start(struct net_if *iface)
|
|||
net_if_start_acd(iface);
|
||||
}
|
||||
}
|
||||
|
||||
/* To be called when interface comes up so that all the non-joined multicast
|
||||
* groups are joined.
|
||||
*/
|
||||
static void rejoin_ipv4_mcast_groups(struct net_if *iface)
|
||||
{
|
||||
struct net_if_ipv4 *ipv4;
|
||||
|
||||
net_if_lock(iface);
|
||||
|
||||
if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (net_if_config_ipv4_get(iface, &ipv4) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Rejoin any mcast address present on the interface, but marked as not joined. */
|
||||
ARRAY_FOR_EACH(ipv4->mcast, i) {
|
||||
int ret;
|
||||
|
||||
if (!ipv4->mcast[i].is_used ||
|
||||
net_if_ipv4_maddr_is_joined(&ipv4->mcast[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = net_ipv4_igmp_join(iface, &ipv4->mcast[i].address.in_addr, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot join mcast address %s for %d (%d)",
|
||||
net_sprint_ipv4_addr(&ipv4->mcast[i].address.in_addr),
|
||||
net_if_get_by_iface(iface), ret);
|
||||
} else {
|
||||
NET_DBG("Rejoined mcast address %s for %d",
|
||||
net_sprint_ipv4_addr(&ipv4->mcast[i].address.in_addr),
|
||||
net_if_get_by_iface(iface));
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
net_if_unlock(iface);
|
||||
}
|
||||
|
||||
/* To be called when interface comes operational down so that multicast
|
||||
* groups are rejoined when back up.
|
||||
*/
|
||||
static void clear_joined_ipv4_mcast_groups(struct net_if *iface)
|
||||
{
|
||||
struct net_if_ipv4 *ipv4;
|
||||
|
||||
net_if_lock(iface);
|
||||
|
||||
if (!net_if_flag_is_set(iface, NET_IF_IPV4)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (net_if_config_ipv4_get(iface, &ipv4) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ARRAY_FOR_EACH(ipv4->mcast, i) {
|
||||
if (!ipv4->mcast[i].is_used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
net_if_ipv4_maddr_leave(iface, &ipv4->mcast[i]);
|
||||
}
|
||||
|
||||
out:
|
||||
net_if_unlock(iface);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_NATIVE_IPV4 */
|
||||
#else /* CONFIG_NET_IPV4 */
|
||||
struct net_if_mcast_addr *net_if_ipv4_maddr_lookup(const struct in_addr *addr,
|
||||
|
|
@ -4872,6 +4944,7 @@ struct in_addr *net_if_ipv4_get_global_addr(struct net_if *iface,
|
|||
|
||||
#if !defined(CONFIG_NET_NATIVE_IPV4)
|
||||
#define leave_ipv4_mcast_all(...)
|
||||
#define clear_joined_ipv4_mcast_groups(...)
|
||||
#define iface_ipv4_init(...)
|
||||
#define iface_ipv4_start(...)
|
||||
#endif /* !CONFIG_NET_NATIVE_IPV4 */
|
||||
|
|
@ -5351,7 +5424,11 @@ static void rejoin_multicast_groups(struct net_if *iface)
|
|||
if (l2_flags_get(iface) & NET_L2_MULTICAST) {
|
||||
join_mcast_allnodes(iface);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
#if defined(CONFIG_NET_NATIVE_IPV4)
|
||||
rejoin_ipv4_mcast_groups(iface);
|
||||
#endif
|
||||
#if !defined(CONFIG_NET_NATIVE_IPV6) && !defined(CONFIG_NET_NATIVE_IPV4)
|
||||
ARG_UNUSED(iface);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -5400,6 +5477,7 @@ static void notify_iface_down(struct net_if *iface)
|
|||
!(l2_flags_get(iface) & NET_L2_POINT_TO_POINT)) {
|
||||
iface_ipv6_stop(iface);
|
||||
clear_joined_ipv6_mcast_groups(iface);
|
||||
clear_joined_ipv4_mcast_groups(iface);
|
||||
net_ipv4_autoconf_reset(iface);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue