Skip to content

Commit dc2b99f

Browse files
stephen hemmingerdavem330
authored andcommitted
IPv6: keep permanent addresses on admin down
Permanent IPV6 addresses should not be removed when the link is set to admin down, only when device is removed. When link is lost permanent addresses should be marked as tentative so that when link comes back they are subject to duplicate address detection (if DAD was enabled for that address). Other routing systems keep manually configured IPv6 addresses when link is set down. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c0ad984 commit dc2b99f

File tree

1 file changed

+24
-11
lines changed

1 file changed

+24
-11
lines changed

net/ipv6/addrconf.c

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2646,7 +2646,8 @@ static int addrconf_ifdown(struct net_device *dev, int how)
26462646

26472647
write_lock_bh(&addrconf_hash_lock);
26482648
while ((ifa = *bifa) != NULL) {
2649-
if (ifa->idev == idev) {
2649+
if (ifa->idev == idev &&
2650+
(how || !(ifa->flags&IFA_F_PERMANENT))) {
26502651
*bifa = ifa->lst_next;
26512652
ifa->lst_next = NULL;
26522653
addrconf_del_timer(ifa);
@@ -2686,18 +2687,30 @@ static int addrconf_ifdown(struct net_device *dev, int how)
26862687
write_lock_bh(&idev->lock);
26872688
}
26882689
#endif
2689-
while ((ifa = idev->addr_list) != NULL) {
2690-
idev->addr_list = ifa->if_next;
2691-
ifa->if_next = NULL;
2692-
ifa->dead = 1;
2693-
addrconf_del_timer(ifa);
2694-
write_unlock_bh(&idev->lock);
2690+
bifa = &idev->addr_list;
2691+
while ((ifa = *bifa) != NULL) {
2692+
if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) {
2693+
/* Retain permanent address on admin down */
2694+
bifa = &ifa->if_next;
2695+
2696+
/* Restart DAD if needed when link comes back up */
2697+
if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
2698+
idev->cnf.accept_dad <= 0 ||
2699+
(ifa->flags & IFA_F_NODAD)))
2700+
ifa->flags |= IFA_F_TENTATIVE;
2701+
} else {
2702+
*bifa = ifa->if_next;
2703+
ifa->if_next = NULL;
26952704

2696-
__ipv6_ifa_notify(RTM_DELADDR, ifa);
2697-
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
2698-
in6_ifa_put(ifa);
2705+
ifa->dead = 1;
2706+
write_unlock_bh(&idev->lock);
26992707

2700-
write_lock_bh(&idev->lock);
2708+
__ipv6_ifa_notify(RTM_DELADDR, ifa);
2709+
atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
2710+
in6_ifa_put(ifa);
2711+
2712+
write_lock_bh(&idev->lock);
2713+
}
27012714
}
27022715
write_unlock_bh(&idev->lock);
27032716

0 commit comments

Comments
 (0)