@@ -1324,8 +1324,9 @@ void net_if_ipv6_start_dad(struct net_if *iface,
13241324
13251325void net_if_start_dad (struct net_if * iface )
13261326{
1327- struct net_if_addr * ifaddr ;
1327+ struct net_if_addr * ifaddr , * next ;
13281328 struct net_if_ipv6 * ipv6 ;
1329+ sys_slist_t dad_needed ;
13291330 struct in6_addr addr = { };
13301331 int ret ;
13311332
@@ -1357,6 +1358,8 @@ void net_if_start_dad(struct net_if *iface)
13571358 /* Start DAD for all the addresses that were added earlier when
13581359 * the interface was down.
13591360 */
1361+ sys_slist_init (& dad_needed );
1362+
13601363 ARRAY_FOR_EACH (ipv6 -> unicast , i ) {
13611364 if (!ipv6 -> unicast [i ].is_used ||
13621365 ipv6 -> unicast [i ].address .family != AF_INET6 ||
@@ -1366,9 +1369,21 @@ void net_if_start_dad(struct net_if *iface)
13661369 continue ;
13671370 }
13681371
1369- net_if_ipv6_start_dad ( iface , & ipv6 -> unicast [i ]);
1372+ sys_slist_prepend ( & dad_needed , & ipv6 -> unicast [i ]. dad_need_node );
13701373 }
13711374
1375+ net_if_unlock (iface );
1376+
1377+ /* Start DAD for all the addresses without holding the iface lock
1378+ * to avoid any possible mutex deadlock issues.
1379+ */
1380+ SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& dad_needed ,
1381+ ifaddr , next , dad_need_node ) {
1382+ net_if_ipv6_start_dad (iface , ifaddr );
1383+ }
1384+
1385+ return ;
1386+
13721387out :
13731388 net_if_unlock (iface );
13741389}
@@ -1415,7 +1430,10 @@ void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr)
14151430 net_if_ipv6_addr_rm (iface , addr );
14161431
14171432 if (IS_ENABLED (CONFIG_NET_IPV6_PE ) && iface -> pe_enabled ) {
1433+ net_if_unlock (iface );
1434+
14181435 net_ipv6_pe_start (iface , addr , timeout , preferred_lifetime );
1436+ return ;
14191437 }
14201438
14211439out :
@@ -1944,6 +1962,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19441962{
19451963 struct net_if_addr * ifaddr = NULL ;
19461964 struct net_if_ipv6 * ipv6 ;
1965+ bool do_dad = false;
19471966
19481967 net_if_lock (iface );
19491968
@@ -1995,8 +2014,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
19952014 */
19962015 join_mcast_nodes (iface ,
19972016 & ipv6 -> unicast [i ].address .in6_addr );
1998-
1999- net_if_ipv6_start_dad (iface , & ipv6 -> unicast [i ]);
2017+ do_dad = true;
20002018 } else {
20012019 /* If DAD is not done for point-to-point links, then
20022020 * the address is usable immediately.
@@ -2010,9 +2028,17 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
20102028 sizeof (struct in6_addr ));
20112029
20122030 ifaddr = & ipv6 -> unicast [i ];
2013- goto out ;
2031+ break ;
20142032 }
20152033
2034+ net_if_unlock (iface );
2035+
2036+ if (ifaddr != NULL && do_dad ) {
2037+ net_if_ipv6_start_dad (iface , ifaddr );
2038+ }
2039+
2040+ return ifaddr ;
2041+
20162042out :
20172043 net_if_unlock (iface );
20182044
0 commit comments