]> Pileus Git - ~andy/linux/blobdiff - net/ipv6/route.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / net / ipv6 / route.c
index a0a48ac3403f3a9284786aa5b8f00dc03696e2e0..11dac21e658690cdf01d7eb41c7e653d142ad9d4 100644 (file)
@@ -66,8 +66,9 @@
 #endif
 
 enum rt6_nud_state {
-       RT6_NUD_FAIL_HARD = -2,
-       RT6_NUD_FAIL_SOFT = -1,
+       RT6_NUD_FAIL_HARD = -3,
+       RT6_NUD_FAIL_PROBE = -2,
+       RT6_NUD_FAIL_DO_RR = -1,
        RT6_NUD_SUCCEED = 1
 };
 
@@ -103,6 +104,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
                                           const struct in6_addr *gwaddr, int ifindex);
 #endif
 
+static void rt6_bind_peer(struct rt6_info *rt, int create)
+{
+       struct inet_peer_base *base;
+       struct inet_peer *peer;
+
+       base = inetpeer_base_ptr(rt->_rt6i_peer);
+       if (!base)
+               return;
+
+       peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
+       if (peer) {
+               if (!rt6_set_peer(rt, peer))
+                       inet_putpeer(peer);
+       }
+}
+
+static struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
+{
+       if (rt6_has_peer(rt))
+               return rt6_peer_ptr(rt);
+
+       rt6_bind_peer(rt, create);
+       return (rt6_has_peer(rt) ? rt6_peer_ptr(rt) : NULL);
+}
+
+static struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
+{
+       return __rt6_get_peer(rt, 1);
+}
+
 static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
 {
        struct rt6_info *rt = (struct rt6_info *) dst;
@@ -311,22 +342,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
        }
 }
 
-void rt6_bind_peer(struct rt6_info *rt, int create)
-{
-       struct inet_peer_base *base;
-       struct inet_peer *peer;
-
-       base = inetpeer_base_ptr(rt->_rt6i_peer);
-       if (!base)
-               return;
-
-       peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
-       if (peer) {
-               if (!rt6_set_peer(rt, peer))
-                       inet_putpeer(peer);
-       }
-}
-
 static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
                           int how)
 {
@@ -521,7 +536,7 @@ static void rt6_probe(struct rt6_info *rt)
                work = kmalloc(sizeof(*work), GFP_ATOMIC);
 
                if (neigh && work)
-                       neigh->updated = jiffies;
+                       __neigh_set_probe_once(neigh);
 
                if (neigh)
                        write_unlock(&neigh->lock);
@@ -577,11 +592,13 @@ static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
 #ifdef CONFIG_IPV6_ROUTER_PREF
                else if (!(neigh->nud_state & NUD_FAILED))
                        ret = RT6_NUD_SUCCEED;
+               else
+                       ret = RT6_NUD_FAIL_PROBE;
 #endif
                read_unlock(&neigh->lock);
        } else {
                ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
-                     RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT;
+                     RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR;
        }
        rcu_read_unlock_bh();
 
@@ -618,16 +635,17 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
                goto out;
 
        m = rt6_score_route(rt, oif, strict);
-       if (m == RT6_NUD_FAIL_SOFT) {
+       if (m == RT6_NUD_FAIL_DO_RR) {
                match_do_rr = true;
                m = 0; /* lowest valid score */
-       } else if (m < 0) {
+       } else if (m == RT6_NUD_FAIL_HARD) {
                goto out;
        }
 
        if (strict & RT6_LOOKUP_F_REACHABLE)
                rt6_probe(rt);
 
+       /* note that m can be RT6_NUD_FAIL_PROBE at this point */
        if (m > *mpri) {
                *do_rr = match_do_rr;
                *mpri = m;
@@ -1905,9 +1923,7 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
                else
                        rt->rt6i_gateway = *dest;
                rt->rt6i_flags = ort->rt6i_flags;
-               if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
-                   (RTF_DEFAULT | RTF_ADDRCONF))
-                       rt6_set_from(rt, ort);
+               rt6_set_from(rt, ort);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -2240,7 +2256,7 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
                .net = net,
                .addr = &ifp->addr,
        };
-       fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+       fib6_clean_all(net, fib6_remove_prefsrc, &adni);
 }
 
 struct arg_dev_net {
@@ -2267,7 +2283,7 @@ void rt6_ifdown(struct net *net, struct net_device *dev)
                .net = net,
        };
 
-       fib6_clean_all(net, fib6_ifdown, 0, &adn);
+       fib6_clean_all(net, fib6_ifdown, &adn);
        icmp6_clean_all(fib6_ifdown, &adn);
 }
 
@@ -2322,7 +2338,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
                .mtu = mtu,
        };
 
-       fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg);
+       fib6_clean_all(dev_net(dev), rt6_mtu_change_route, &arg);
 }
 
 static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {