From a96a2f8d09a2dd90468db33cd46d070ebf09fc14 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 18 Mar 2024 17:05:09 +0200 Subject: [PATCH] net: if: Start IPv6 DAD when interface comes up Start any pending IPv6 DAD timers when interface comes up. If IPv6 addresses have been added to the network interface when it was down, the addresses would never work properly if the DAD is not done. Signed-off-by: Jukka Rissanen --- include/zephyr/net/net_if.h | 2 ++ subsys/net/ip/net_if.c | 36 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 98baae409a..03a936626d 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -71,6 +71,8 @@ struct net_if_addr { #if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6) /** How many times we have done DAD */ uint8_t dad_count; + /* What interface the DAD is running */ + uint8_t ifindex; #endif /** Is the IP address valid forever */ diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 83ca7f6745..644238f8b5 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -1209,28 +1209,22 @@ static void dad_timeout(struct k_work *work) struct net_if_addr *tmp; struct net_if *iface; - NET_DBG("DAD succeeded for %s", - net_sprint_ipv6_addr(&ifaddr->address.in6_addr)); + NET_DBG("DAD succeeded for %s at interface %d", + net_sprint_ipv6_addr(&ifaddr->address.in6_addr), + ifaddr->ifindex); ifaddr->addr_state = NET_ADDR_PREFERRED; + iface = net_if_get_by_index(ifaddr->ifindex); - /* Because we do not know the interface at this point, - * we need to lookup for it. + net_mgmt_event_notify_with_info(NET_EVENT_IPV6_DAD_SUCCEED, + iface, + &ifaddr->address.in6_addr, + sizeof(struct in6_addr)); + + /* The address gets added to neighbor cache which is not + * needed in this case as the address is our own one. */ - iface = NULL; - tmp = net_if_ipv6_addr_lookup(&ifaddr->address.in6_addr, - &iface); - if (tmp == ifaddr) { - net_mgmt_event_notify_with_info( - NET_EVENT_IPV6_DAD_SUCCEED, - iface, &ifaddr->address.in6_addr, - sizeof(struct in6_addr)); - - /* The address gets added to neighbor cache which is not - * needed in this case as the address is our own one. - */ - net_ipv6_nbr_rm(iface, &ifaddr->address.in6_addr); - } + net_ipv6_nbr_rm(iface, &ifaddr->address.in6_addr); } } @@ -1251,8 +1245,11 @@ static void net_if_ipv6_start_dad(struct net_if *iface, if (!net_ipv6_start_dad(iface, ifaddr)) { ifaddr->dad_start = k_uptime_get_32(); + ifaddr->ifindex = net_if_get_by_iface(iface); k_mutex_lock(&lock, K_FOREVER); + sys_slist_find_and_remove(&active_dad_timers, + &ifaddr->dad_node); sys_slist_append(&active_dad_timers, &ifaddr->dad_node); k_mutex_unlock(&lock); @@ -4782,6 +4779,9 @@ done: net_mgmt_event_notify(NET_EVENT_IF_ADMIN_UP, iface); update_operational_state(iface); + /* Make sure that we update the IPv6 addresses */ + net_if_start_dad(iface); + out: net_if_unlock(iface);