Linux 3.2.82
[pandora-kernel.git] / net / ipv6 / route.c
index 1768238..3a8776d 100644 (file)
@@ -106,7 +106,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
        u32 *p = NULL;
 
        if (!(rt->dst.flags & DST_HOST))
-               return NULL;
+               return dst_cow_metrics_generic(dst, old);
 
        if (!rt->rt6i_peer)
                rt6_bind_peer(rt, 1);
@@ -1018,12 +1018,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 
        if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) {
                rt6->rt6i_flags |= RTF_MODIFIED;
-               if (mtu < IPV6_MIN_MTU) {
-                       u32 features = dst_metric(dst, RTAX_FEATURES);
+               if (mtu < IPV6_MIN_MTU)
                        mtu = IPV6_MIN_MTU;
-                       features |= RTAX_FEATURE_ALLFRAG;
-                       dst_metric_set(dst, RTAX_FEATURES, features);
-               }
+
                dst_metric_set(dst, RTAX_MTU, mtu);
        }
 }
@@ -1056,7 +1053,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
        unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
 
        if (mtu)
-               return mtu;
+               goto out;
 
        mtu = IPV6_MIN_MTU;
 
@@ -1066,7 +1063,8 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
                mtu = idev->cnf.mtu6;
        rcu_read_unlock();
 
-       return mtu;
+out:
+       return min_t(unsigned int, mtu, IP6_MAX_MTU);
 }
 
 static struct dst_entry *icmp6_dst_gc_list;
@@ -1161,7 +1159,6 @@ static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
 
 static int ip6_dst_gc(struct dst_ops *ops)
 {
-       unsigned long now = jiffies;
        struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
        int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
        int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
@@ -1171,13 +1168,12 @@ static int ip6_dst_gc(struct dst_ops *ops)
        int entries;
 
        entries = dst_entries_get_fast(ops);
-       if (time_after(rt_last_gc + rt_min_interval, now) &&
+       if (time_after(rt_last_gc + rt_min_interval, jiffies) &&
            entries <= rt_max_size)
                goto out;
 
        net->ipv6.ip6_rt_gc_expire++;
-       fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net);
-       net->ipv6.ip6_rt_last_gc = now;
+       fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, entries > rt_max_size);
        entries = dst_entries_get_slow(ops);
        if (entries < ops->gc_thresh)
                net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
@@ -1250,7 +1246,7 @@ int ip6_route_add(struct fib6_config *cfg)
                goto out;
        }
 
-       rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT);
+       rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
 
        if (rt == NULL) {
                err = -ENOMEM;
@@ -2058,15 +2054,11 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 {
        struct net *net = dev_net(idev->dev);
        struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
-                                           net->loopback_dev, 0);
+                                           net->loopback_dev, DST_NOCOUNT);
        struct neighbour *neigh;
 
-       if (rt == NULL) {
-               if (net_ratelimit())
-                       pr_warning("IPv6:  Maximum number of routes reached,"
-                                  " consider increasing route/max_size.\n");
+       if (rt == NULL)
                return ERR_PTR(-ENOMEM);
-       }
 
        in6_dev_hold(idev);
 
@@ -2732,7 +2724,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
        net = (struct net *)ctl->extra1;
        delay = net->ipv6.sysctl.flush_delay;
        proc_dointvec(ctl, write, buffer, lenp, ppos);
-       fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
+       fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
        return 0;
 }