@@ -1298,8 +1298,9 @@ void net_if_ipv6_start_dad(struct net_if *iface,
12981298
12991299void net_if_start_dad (struct net_if * iface )
13001300{
1301- struct net_if_addr * ifaddr ;
1301+ struct net_if_addr * ifaddr , * next ;
13021302 struct net_if_ipv6 * ipv6 ;
1303+ sys_slist_t dad_needed ;
13031304 struct in6_addr addr = { };
13041305 int ret ;
13051306
@@ -1331,6 +1332,8 @@ void net_if_start_dad(struct net_if *iface)
13311332 /* Start DAD for all the addresses that were added earlier when
13321333 * the interface was down.
13331334 */
1335+ sys_slist_init (& dad_needed );
1336+
13341337 ARRAY_FOR_EACH (ipv6 -> unicast , i ) {
13351338 if (!ipv6 -> unicast [i ].is_used ||
13361339 ipv6 -> unicast [i ].address .family != AF_INET6 ||
@@ -1340,9 +1343,21 @@ void net_if_start_dad(struct net_if *iface)
13401343 continue ;
13411344 }
13421345
1343- net_if_ipv6_start_dad ( iface , & ipv6 -> unicast [i ]);
1346+ sys_slist_prepend ( & dad_needed , & ipv6 -> unicast [i ]. dad_need_node );
13441347 }
13451348
1349+ net_if_unlock (iface );
1350+
1351+ /* Start DAD for all the addresses without holding the iface lock
1352+ * to avoid any possible mutex deadlock issues.
1353+ */
1354+ SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& dad_needed ,
1355+ ifaddr , next , dad_need_node ) {
1356+ net_if_ipv6_start_dad (iface , ifaddr );
1357+ }
1358+
1359+ return ;
1360+
13461361out :
13471362 net_if_unlock (iface );
13481363}
@@ -1389,7 +1404,10 @@ void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr)
13891404 net_if_ipv6_addr_rm (iface , addr );
13901405
13911406 if (IS_ENABLED (CONFIG_NET_IPV6_PE ) && iface -> pe_enabled ) {
1407+ net_if_unlock (iface );
1408+
13921409 net_ipv6_pe_start (iface , addr , timeout , preferred_lifetime );
1410+ return ;
13931411 }
13941412
13951413out :
@@ -1905,6 +1923,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19051923{
19061924 struct net_if_addr * ifaddr = NULL ;
19071925 struct net_if_ipv6 * ipv6 ;
1926+ bool do_dad = false;
19081927
19091928 net_if_lock (iface );
19101929
@@ -1956,8 +1975,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19561975 */
19571976 join_mcast_nodes (iface ,
19581977 & ipv6 -> unicast [i ].address .in6_addr );
1959-
1960- net_if_ipv6_start_dad (iface , & ipv6 -> unicast [i ]);
1978+ do_dad = true;
19611979 } else {
19621980 /* If DAD is not done for point-to-point links, then
19631981 * the address is usable immediately.
@@ -1971,9 +1989,17 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19711989 sizeof (struct in6_addr ));
19721990
19731991 ifaddr = & ipv6 -> unicast [i ];
1974- goto out ;
1992+ break ;
19751993 }
19761994
1995+ net_if_unlock (iface );
1996+
1997+ if (ifaddr != NULL && do_dad ) {
1998+ net_if_ipv6_start_dad (iface , ifaddr );
1999+ }
2000+
2001+ return ifaddr ;
2002+
19772003out :
19782004 net_if_unlock (iface );
19792005
0 commit comments