Skip to content

Commit

Permalink
ipv6: Replace inet6_ifaddr->dead with state
Browse files Browse the repository at this point in the history
This patch replaces the boolean dead flag on inet6_ifaddr with
a state enum.  This allows us to roll back changes when deleting
an address according to whether DAD has completed or not.

This patch only adds the state field and does not change the logic.

Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
herbertx authored and davem330 committed May 18, 2010
1 parent e29f5db commit e9d3e08
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
12 changes: 10 additions & 2 deletions include/net/if_inet6.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@

#ifdef __KERNEL__

enum {
INET6_IFADDR_STATE_DAD,
INET6_IFADDR_STATE_POSTDAD,
INET6_IFADDR_STATE_UP,
INET6_IFADDR_STATE_DEAD,
};

struct inet6_ifaddr {
struct in6_addr addr;
__u32 prefix_len;
Expand All @@ -40,6 +47,9 @@ struct inet6_ifaddr {
__u32 prefered_lft;
atomic_t refcnt;
spinlock_t lock;
spinlock_t state_lock;

int state;

__u8 probes;
__u8 flags;
Expand All @@ -62,8 +72,6 @@ struct inet6_ifaddr {
struct inet6_ifaddr *ifpub;
int regen_count;
#endif

int dead;
struct rcu_head rcu;
};

Expand Down
16 changes: 9 additions & 7 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
if (del_timer(&ifp->timer))
pr_notice("Timer is still running, when freeing ifa=%p\n", ifp);

if (!ifp->dead) {
if (ifp->state != INET6_IFADDR_STATE_DEAD) {
pr_warning("Freeing alive inet6 address %p\n", ifp);
return;
}
Expand Down Expand Up @@ -648,6 +648,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
ipv6_addr_copy(&ifa->addr, addr);

spin_lock_init(&ifa->lock);
spin_lock_init(&ifa->state_lock);
init_timer(&ifa->timer);
INIT_HLIST_NODE(&ifa->addr_lst);
ifa->timer.data = (unsigned long) ifa;
Expand Down Expand Up @@ -720,7 +721,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)

hash = ipv6_addr_hash(&ifp->addr);

ifp->dead = 1;
ifp->state = INET6_IFADDR_STATE_DEAD;

spin_lock_bh(&addrconf_hash_lock);
hlist_del_init_rcu(&ifp->addr_lst);
Expand Down Expand Up @@ -2665,7 +2666,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
ifa = list_first_entry(&idev->tempaddr_list,
struct inet6_ifaddr, tmp_list);
list_del(&ifa->tmp_list);
ifa->dead = 1;
ifa->state = INET6_IFADDR_STATE_DEAD;
write_unlock_bh(&idev->lock);
spin_lock_bh(&ifa->lock);

Expand Down Expand Up @@ -2707,7 +2708,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
write_unlock_bh(&idev->lock);
} else {
list_del(&ifa->if_list);
ifa->dead = 1;
ifa->state = INET6_IFADDR_STATE_DEAD;
write_unlock_bh(&idev->lock);

/* clear hash table */
Expand All @@ -2717,7 +2718,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
}

__ipv6_ifa_notify(RTM_DELADDR, ifa);
if (ifa->dead)
if (ifa->state == INET6_IFADDR_STATE_DEAD)
atomic_notifier_call_chain(&inet6addr_chain,
NETDEV_DOWN, ifa);
in6_ifa_put(ifa);
Expand Down Expand Up @@ -2815,7 +2816,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
net_srandom(ifp->addr.s6_addr32[3]);

read_lock_bh(&idev->lock);
if (ifp->dead)
if (ifp->state == INET6_IFADDR_STATE_DEAD)
goto out;

spin_lock(&ifp->lock);
Expand Down Expand Up @@ -4050,7 +4051,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
addrconf_leave_solict(ifp->idev, &ifp->addr);
dst_hold(&ifp->rt->u.dst);

if (ifp->dead && ip6_del_rt(ifp->rt))
if (ifp->state == INET6_IFADDR_STATE_DEAD &&
ip6_del_rt(ifp->rt))
dst_free(&ifp->rt->u.dst);
break;
}
Expand Down

0 comments on commit e9d3e08

Please sign in to comment.