Skip to content

Commit 2de7957

Browse files
lcolittidavem330
authored andcommitted
ipv6: addrconf: don't remove address state on ifdown if the address is being kept
Currently, addrconf_ifdown does not delete statically configured IPv6 addresses when the interface is brought down. The intent is that when the interface comes back up the address will be usable again. However, this doesn't actually work, because the system stops listening on the corresponding solicited-node multicast address, so the address cannot respond to neighbor solicitations and thus receive traffic. Also, the code notifies the rest of the system that the address is being deleted (e.g, RTM_DELADDR), even though it is not. Fix it so that none of this state is updated if the address is being kept on the interface. Tested: Added a statically configured IPv6 address to an interface, started ping, brought link down, brought link up again. When link came up ping kept on going and "ip -6 maddr" showed that the host was still subscribed to there Signed-off-by: Lorenzo Colitti <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8f49c27 commit 2de7957

File tree

1 file changed

+8
-16
lines changed

1 file changed

+8
-16
lines changed

net/ipv6/addrconf.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,10 +2740,6 @@ static int addrconf_ifdown(struct net_device *dev, int how)
27402740
/* Flag it for later restoration when link comes up */
27412741
ifa->flags |= IFA_F_TENTATIVE;
27422742
ifa->state = INET6_IFADDR_STATE_DAD;
2743-
2744-
write_unlock_bh(&idev->lock);
2745-
2746-
in6_ifa_hold(ifa);
27472743
} else {
27482744
list_del(&ifa->if_list);
27492745

@@ -2758,19 +2754,15 @@ static int addrconf_ifdown(struct net_device *dev, int how)
27582754
ifa->state = INET6_IFADDR_STATE_DEAD;
27592755
spin_unlock_bh(&ifa->state_lock);
27602756

2761-
if (state == INET6_IFADDR_STATE_DEAD)
2762-
goto put_ifa;
2757+
if (state == INET6_IFADDR_STATE_DEAD) {
2758+
in6_ifa_put(ifa);
2759+
} else {
2760+
__ipv6_ifa_notify(RTM_DELADDR, ifa);
2761+
atomic_notifier_call_chain(&inet6addr_chain,
2762+
NETDEV_DOWN, ifa);
2763+
}
2764+
write_lock_bh(&idev->lock);
27632765
}
2764-
2765-
__ipv6_ifa_notify(RTM_DELADDR, ifa);
2766-
if (ifa->state == INET6_IFADDR_STATE_DEAD)
2767-
atomic_notifier_call_chain(&inet6addr_chain,
2768-
NETDEV_DOWN, ifa);
2769-
2770-
put_ifa:
2771-
in6_ifa_put(ifa);
2772-
2773-
write_lock_bh(&idev->lock);
27742766
}
27752767

27762768
list_splice(&keep_list, &idev->addr_list);

0 commit comments

Comments
 (0)