diff options
author | David S. Miller <davem@davemloft.net> | 2011-01-26 16:49:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-26 16:49:30 -0500 |
commit | b4e69ac670d71b5748dc81e536b2cb103489badd (patch) | |
tree | 26a04ba5d950657132fd6acb4e0ef17d0bcabe93 /net/ipv6 | |
parent | 144ce879b057c760194d808c90826cd96308f423 (diff) | |
parent | 7cc2edb83447775a34ed3bf9d29d8295a434b523 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 81 | ||||
-rw-r--r-- | net/ipv6/route.c | 9 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 6 |
3 files changed, 40 insertions, 56 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 24a1cf110d80..fd6782e3a038 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2661,14 +2661,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2661 | struct net *net = dev_net(dev); | 2661 | struct net *net = dev_net(dev); |
2662 | struct inet6_dev *idev; | 2662 | struct inet6_dev *idev; |
2663 | struct inet6_ifaddr *ifa; | 2663 | struct inet6_ifaddr *ifa; |
2664 | LIST_HEAD(keep_list); | 2664 | int state, i; |
2665 | int state; | ||
2666 | 2665 | ||
2667 | ASSERT_RTNL(); | 2666 | ASSERT_RTNL(); |
2668 | 2667 | ||
2669 | /* Flush routes if device is being removed or it is not loopback */ | 2668 | rt6_ifdown(net, dev); |
2670 | if (how || !(dev->flags & IFF_LOOPBACK)) | 2669 | neigh_ifdown(&nd_tbl, dev); |
2671 | rt6_ifdown(net, dev); | ||
2672 | 2670 | ||
2673 | idev = __in6_dev_get(dev); | 2671 | idev = __in6_dev_get(dev); |
2674 | if (idev == NULL) | 2672 | if (idev == NULL) |
@@ -2689,6 +2687,23 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2689 | 2687 | ||
2690 | } | 2688 | } |
2691 | 2689 | ||
2690 | /* Step 2: clear hash table */ | ||
2691 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | ||
2692 | struct hlist_head *h = &inet6_addr_lst[i]; | ||
2693 | struct hlist_node *n; | ||
2694 | |||
2695 | spin_lock_bh(&addrconf_hash_lock); | ||
2696 | restart: | ||
2697 | hlist_for_each_entry_rcu(ifa, n, h, addr_lst) { | ||
2698 | if (ifa->idev == idev) { | ||
2699 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2700 | addrconf_del_timer(ifa); | ||
2701 | goto restart; | ||
2702 | } | ||
2703 | } | ||
2704 | spin_unlock_bh(&addrconf_hash_lock); | ||
2705 | } | ||
2706 | |||
2692 | write_lock_bh(&idev->lock); | 2707 | write_lock_bh(&idev->lock); |
2693 | 2708 | ||
2694 | /* Step 2: clear flags for stateless addrconf */ | 2709 | /* Step 2: clear flags for stateless addrconf */ |
@@ -2722,52 +2737,23 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2722 | struct inet6_ifaddr, if_list); | 2737 | struct inet6_ifaddr, if_list); |
2723 | addrconf_del_timer(ifa); | 2738 | addrconf_del_timer(ifa); |
2724 | 2739 | ||
2725 | /* If just doing link down, and address is permanent | 2740 | list_del(&ifa->if_list); |
2726 | and not link-local, then retain it. */ | ||
2727 | if (!how && | ||
2728 | (ifa->flags&IFA_F_PERMANENT) && | ||
2729 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2730 | list_move_tail(&ifa->if_list, &keep_list); | ||
2731 | |||
2732 | /* If not doing DAD on this address, just keep it. */ | ||
2733 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
2734 | idev->cnf.accept_dad <= 0 || | ||
2735 | (ifa->flags & IFA_F_NODAD)) | ||
2736 | continue; | ||
2737 | 2741 | ||
2738 | /* If it was tentative already, no need to notify */ | 2742 | write_unlock_bh(&idev->lock); |
2739 | if (ifa->flags & IFA_F_TENTATIVE) | ||
2740 | continue; | ||
2741 | 2743 | ||
2742 | /* Flag it for later restoration when link comes up */ | 2744 | spin_lock_bh(&ifa->state_lock); |
2743 | ifa->flags |= IFA_F_TENTATIVE; | 2745 | state = ifa->state; |
2744 | ifa->state = INET6_IFADDR_STATE_DAD; | 2746 | ifa->state = INET6_IFADDR_STATE_DEAD; |
2745 | } else { | 2747 | spin_unlock_bh(&ifa->state_lock); |
2746 | list_del(&ifa->if_list); | ||
2747 | |||
2748 | /* clear hash table */ | ||
2749 | spin_lock_bh(&addrconf_hash_lock); | ||
2750 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2751 | spin_unlock_bh(&addrconf_hash_lock); | ||
2752 | |||
2753 | write_unlock_bh(&idev->lock); | ||
2754 | spin_lock_bh(&ifa->state_lock); | ||
2755 | state = ifa->state; | ||
2756 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
2757 | spin_unlock_bh(&ifa->state_lock); | ||
2758 | |||
2759 | if (state != INET6_IFADDR_STATE_DEAD) { | ||
2760 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | ||
2761 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2762 | NETDEV_DOWN, ifa); | ||
2763 | } | ||
2764 | 2748 | ||
2765 | in6_ifa_put(ifa); | 2749 | if (state != INET6_IFADDR_STATE_DEAD) { |
2766 | write_lock_bh(&idev->lock); | 2750 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2751 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
2767 | } | 2752 | } |
2768 | } | 2753 | in6_ifa_put(ifa); |
2769 | 2754 | ||
2770 | list_splice(&keep_list, &idev->addr_list); | 2755 | write_lock_bh(&idev->lock); |
2756 | } | ||
2771 | 2757 | ||
2772 | write_unlock_bh(&idev->lock); | 2758 | write_unlock_bh(&idev->lock); |
2773 | 2759 | ||
@@ -4156,8 +4142,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4156 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4142 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4157 | dst_hold(&ifp->rt->dst); | 4143 | dst_hold(&ifp->rt->dst); |
4158 | 4144 | ||
4159 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | 4145 | if (ip6_del_rt(ifp->rt)) |
4160 | ip6_del_rt(ifp->rt)) | ||
4161 | dst_free(&ifp->rt->dst); | 4146 | dst_free(&ifp->rt->dst); |
4162 | break; | 4147 | break; |
4163 | } | 4148 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 373bd0416f69..1534508f6c68 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -72,8 +72,6 @@ | |||
72 | #define RT6_TRACE(x...) do { ; } while (0) | 72 | #define RT6_TRACE(x...) do { ; } while (0) |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | #define CLONE_OFFLINK_ROUTE 0 | ||
76 | |||
77 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); | 75 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); |
78 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); | 76 | static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); |
79 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); | 77 | static unsigned int ip6_default_advmss(const struct dst_entry *dst); |
@@ -738,13 +736,8 @@ restart: | |||
738 | 736 | ||
739 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 737 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
740 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | 738 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); |
741 | else { | 739 | else |
742 | #if CLONE_OFFLINK_ROUTE | ||
743 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | 740 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); |
744 | #else | ||
745 | goto out2; | ||
746 | #endif | ||
747 | } | ||
748 | 741 | ||
749 | dst_release(&rt->dst); | 742 | dst_release(&rt->dst); |
750 | rt = nrt ? : net->ipv6.ip6_null_entry; | 743 | rt = nrt ? : net->ipv6.ip6_null_entry; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 7e74023ea6e4..da87428681cc 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -98,6 +98,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
98 | if (!xdst->u.rt6.rt6i_idev) | 98 | if (!xdst->u.rt6.rt6i_idev) |
99 | return -ENODEV; | 99 | return -ENODEV; |
100 | 100 | ||
101 | xdst->u.rt6.rt6i_peer = rt->rt6i_peer; | ||
102 | if (rt->rt6i_peer) | ||
103 | atomic_inc(&rt->rt6i_peer->refcnt); | ||
104 | |||
101 | /* Sheit... I remember I did this right. Apparently, | 105 | /* Sheit... I remember I did this right. Apparently, |
102 | * it was magically lost, so this code needs audit */ | 106 | * it was magically lost, so this code needs audit */ |
103 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | | 107 | xdst->u.rt6.rt6i_flags = rt->rt6i_flags & (RTF_ANYCAST | |
@@ -216,6 +220,8 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) | |||
216 | 220 | ||
217 | if (likely(xdst->u.rt6.rt6i_idev)) | 221 | if (likely(xdst->u.rt6.rt6i_idev)) |
218 | in6_dev_put(xdst->u.rt6.rt6i_idev); | 222 | in6_dev_put(xdst->u.rt6.rt6i_idev); |
223 | if (likely(xdst->u.rt6.rt6i_peer)) | ||
224 | inet_putpeer(xdst->u.rt6.rt6i_peer); | ||
219 | xfrm_dst_destroy(xdst); | 225 | xfrm_dst_destroy(xdst); |
220 | } | 226 | } |
221 | 227 | ||