]> Pileus Git - ~andy/linux/blobdiff - net/ipv6/route.c
Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[~andy/linux] / net / ipv6 / route.c
index ad0aa6b0b86ae02f80b6b2184588605a3d5d7a6c..bd5fd7054031d677f9ac111ef7d78c74b3d68b24 100644 (file)
@@ -83,6 +83,7 @@ static void           ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
                                           struct sk_buff *skb, u32 mtu);
 static void            rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
                                        struct sk_buff *skb);
+static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
 static struct rt6_info *rt6_add_route_info(struct net *net,
@@ -394,7 +395,8 @@ static int rt6_info_hash_nhsfn(unsigned int candidate_count,
 }
 
 static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
-                                            struct flowi6 *fl6)
+                                            struct flowi6 *fl6, int oif,
+                                            int strict)
 {
        struct rt6_info *sibling, *next_sibling;
        int route_choosen;
@@ -408,6 +410,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
                                &match->rt6i_siblings, rt6i_siblings) {
                        route_choosen--;
                        if (route_choosen == 0) {
+                               if (rt6_score_route(sibling, oif, strict) < 0)
+                                       break;
                                match = sibling;
                                break;
                        }
@@ -547,6 +551,8 @@ static inline bool rt6_check_neigh(struct rt6_info *rt)
                        ret = true;
 #endif
                read_unlock(&neigh->lock);
+       } else if (IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) {
+               ret = true;
        }
        rcu_read_unlock_bh();
 
@@ -743,7 +749,7 @@ restart:
        rt = fn->leaf;
        rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
        if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
-               rt = rt6_multipath_select(rt, fl6);
+               rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags);
        BACKTRACK(net, &fl6->saddr);
 out:
        dst_use(&rt->dst, jiffies);
@@ -875,8 +881,8 @@ restart_2:
 
 restart:
        rt = rt6_select(fn, oif, strict | reachable);
-       if (rt->rt6i_nsiblings && oif == 0)
-               rt = rt6_multipath_select(rt, fl6);
+       if (rt->rt6i_nsiblings)
+               rt = rt6_multipath_select(rt, fl6, oif, strict | reachable);
        BACKTRACK(net, &fl6->saddr);
        if (rt == net->ipv6.ip6_null_entry ||
            rt->rt6i_flags & RTF_CACHE)
@@ -1649,7 +1655,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
        int optlen, on_link;
        u8 *lladdr;
 
-       optlen = skb->tail - skb->transport_header;
+       optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        optlen -= sizeof(*msg);
 
        if (optlen < 0) {
@@ -2681,9 +2687,9 @@ errout:
 }
 
 static int ip6_route_dev_notify(struct notifier_block *this,
-                               unsigned long event, void *data)
+                               unsigned long event, void *ptr)
 {
-       struct net_device *dev = (struct net_device *)data;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
@@ -2790,7 +2796,7 @@ static const struct file_operations rt6_stats_seq_fops = {
 #ifdef CONFIG_SYSCTL
 
 static
-int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
+int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,
                              void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        struct net *net;
@@ -2805,7 +2811,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
        return 0;
 }
 
-ctl_table ipv6_route_table_template[] = {
+struct ctl_table ipv6_route_table_template[] = {
        {
                .procname       =       "flush",
                .data           =       &init_net.ipv6.sysctl.flush_delay,