Subject: Re: [PATCH net v4] ipv6: addrconf: skip ERRDAD transition when address already DEAD

From: Ido Schimmel <[email-masked]>
Date: Wed, 29 Apr 2026 12:08:22 +0300

On Wed, Apr 29, 2026 at 09:26:51AM +0800, Linmao Li wrote:
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 5476b6536eb7..b58bd9f11606 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -2166,16 +2166,18 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
>  	struct net *net = dev_net(idev->dev);
>  	int max_addresses;
>  
> -	if (addrconf_dad_end(ifp)) {
> +	spin_lock_bh(&ifp->lock);
> +
> +	if (ifp->state != INET6_IFADDR_STATE_DAD) {
> +		spin_unlock_bh(&ifp->lock);
>  		in6_ifa_put(ifp);
>  		return;
>  	}
> +	ifp->state = INET6_IFADDR_STATE_POSTDAD;
>  
>  	net_info_ratelimited("%s: IPv6 duplicate address %pI6c used by %pM detected!\n",
>  			     ifp->idev->dev->name, &ifp->addr, eth_hdr(skb)->h_source);
>  
> -	spin_lock_bh(&ifp->lock);
> -
>  	if (ifp->flags & IFA_F_STABLE_PRIVACY) {
>  		struct in6_addr new_addr;
>  		struct inet6_ifaddr *ifp2;
> @@ -2223,6 +2225,11 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
>  		in6_ifa_put(ifp2);
>  lock_errdad:
>  		spin_lock_bh(&ifp->lock);
> +		if (ifp->state == INET6_IFADDR_STATE_DEAD) {

The code below expects the state to be POSTDAD, so wouldn't it be more
robust to check for anything but POSTDAD rather than specifically
checking for DEAD? Otherwise we risk overwriting a state that was set
while we weren't holding the lock.

Also:

1. Please post new versions in a new thread:

https://docs.kernel.org/process/maintainer-netdev.html#resending-after-review

2. Please include a change log:

https://docs.kernel.org/process/maintainer-netdev.html#changes-requested

> +			spin_unlock_bh(&ifp->lock);
> +			in6_ifa_put(ifp);
> +			return;
> +		}
>  	}
>  
>  errdad:
> -- 
> 2.25.1
>