]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/ipv4/route.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[karo-tx-linux.git] / net / ipv4 / route.c
index d9b40248b97feb4a1e3e4dd01c9ec789b4494842..cb562fdd9b9a5342cee41f2cc642a8b4af9e30ce 100644 (file)
@@ -90,6 +90,7 @@
 #include <linux/jhash.h>
 #include <linux/rcupdate.h>
 #include <linux/times.h>
+#include <linux/slab.h>
 #include <net/dst.h>
 #include <net/net_namespace.h>
 #include <net/protocol.h>
@@ -932,10 +933,8 @@ static void rt_secret_rebuild_oneshot(struct net *net)
 {
        del_timer_sync(&net->ipv4.rt_secret_timer);
        rt_cache_invalidate(net);
-       if (ip_rt_secret_interval) {
-               net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval;
-               add_timer(&net->ipv4.rt_secret_timer);
-       }
+       if (ip_rt_secret_interval)
+               mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);
 }
 
 static void rt_emergency_hash_rebuild(struct net *net)
@@ -1099,7 +1098,7 @@ static int slow_chain_length(const struct rtable *head)
 }
 
 static int rt_intern_hash(unsigned hash, struct rtable *rt,
-                         struct rtable **rp, struct sk_buff *skb)
+                         struct rtable **rp, struct sk_buff *skb, int ifindex)
 {
        struct rtable   *rth, **rthp;
        unsigned long   now;
@@ -1214,11 +1213,16 @@ restart:
                    slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {
                        struct net *net = dev_net(rt->u.dst.dev);
                        int num = ++net->ipv4.current_rt_cache_rebuild_count;
-                       if (!rt_caching(dev_net(rt->u.dst.dev))) {
+                       if (!rt_caching(net)) {
                                printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",
                                        rt->u.dst.dev->name, num);
                        }
-                       rt_emergency_hash_rebuild(dev_net(rt->u.dst.dev));
+                       rt_emergency_hash_rebuild(net);
+                       spin_unlock_bh(rt_hash_lock_addr(hash));
+
+                       hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
+                                       ifindex, rt_genid(net));
+                       goto restart;
                }
        }
 
@@ -1443,7 +1447,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                                        dev_hold(rt->u.dst.dev);
                                if (rt->idev)
                                        in_dev_hold(rt->idev);
-                               rt->u.dst.obsolete      = 0;
+                               rt->u.dst.obsolete      = -1;
                                rt->u.dst.lastuse       = jiffies;
                                rt->u.dst.path          = &rt->u.dst;
                                rt->u.dst.neighbour     = NULL;
@@ -1479,7 +1483,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                                                        &netevent);
 
                                rt_del(hash, rth);
-                               if (!rt_intern_hash(hash, rt, &rt, NULL))
+                               if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
                                        ip_rt_put(rt);
                                goto do_next;
                        }
@@ -1508,11 +1512,12 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
        struct dst_entry *ret = dst;
 
        if (rt) {
-               if (dst->obsolete) {
+               if (dst->obsolete > 0) {
                        ip_rt_put(rt);
                        ret = NULL;
                } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
-                          rt->u.dst.expires) {
+                          (rt->u.dst.expires &&
+                           time_after_eq(jiffies, rt->u.dst.expires))) {
                        unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
                                                rt->fl.oif,
                                                rt_genid(dev_net(dst->dev)));
@@ -1728,7 +1733,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
-       return NULL;
+       if (rt_is_expired((struct rtable *)dst))
+               return NULL;
+       return dst;
 }
 
 static void ipv4_dst_destroy(struct dst_entry *dst)
@@ -1890,7 +1897,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        if (!rth)
                goto e_nobufs;
 
-       rth->u.dst.output= ip_rt_bug;
+       rth->u.dst.output = ip_rt_bug;
+       rth->u.dst.obsolete = -1;
 
        atomic_set(&rth->u.dst.__refcnt, 1);
        rth->u.dst.flags= DST_HOST;
@@ -1929,7 +1937,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
        in_dev_put(in_dev);
        hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
-       return rt_intern_hash(hash, rth, NULL, skb);
+       return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
 
 e_nobufs:
        in_dev_put(in_dev);
@@ -2056,6 +2064,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->fl.oif     = 0;
        rth->rt_spec_dst= spec_dst;
 
+       rth->u.dst.obsolete = -1;
        rth->u.dst.input = ip_forward;
        rth->u.dst.output = ip_output;
        rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev));
@@ -2095,7 +2104,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
        /* put it into the cache */
        hash = rt_hash(daddr, saddr, fl->iif,
                       rt_genid(dev_net(rth->u.dst.dev)));
-       return rt_intern_hash(hash, rth, NULL, skb);
+       return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
 }
 
 /*
@@ -2220,6 +2229,7 @@ local_input:
                goto e_nobufs;
 
        rth->u.dst.output= ip_rt_bug;
+       rth->u.dst.obsolete = -1;
        rth->rt_genid = rt_genid(net);
 
        atomic_set(&rth->u.dst.__refcnt, 1);
@@ -2251,7 +2261,7 @@ local_input:
        }
        rth->rt_type    = res.type;
        hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
-       err = rt_intern_hash(hash, rth, NULL, skb);
+       err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
        goto done;
 
 no_route:
@@ -2446,6 +2456,7 @@ static int __mkroute_output(struct rtable **result,
        rth->rt_spec_dst= fl->fl4_src;
 
        rth->u.dst.output=ip_output;
+       rth->u.dst.obsolete = -1;
        rth->rt_genid = rt_genid(dev_net(dev_out));
 
        RT_CACHE_STAT_INC(out_slow_tot);
@@ -2497,7 +2508,7 @@ static int ip_mkroute_output(struct rtable **rp,
        if (err == 0) {
                hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
                               rt_genid(dev_net(dev_out)));
-               err = rt_intern_hash(hash, rth, rp, NULL);
+               err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
        }
 
        return err;
@@ -3103,22 +3114,20 @@ static void rt_secret_reschedule(int old)
        rtnl_lock();
        for_each_net(net) {
                int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
+               long time;
 
                if (!new)
                        continue;
 
                if (deleted) {
-                       long time = net->ipv4.rt_secret_timer.expires - jiffies;
+                       time = net->ipv4.rt_secret_timer.expires - jiffies;
 
                        if (time <= 0 || (time += diff) <= 0)
                                time = 0;
-
-                       net->ipv4.rt_secret_timer.expires = time;
                } else
-                       net->ipv4.rt_secret_timer.expires = new;
+                       time = new;
 
-               net->ipv4.rt_secret_timer.expires += jiffies;
-               add_timer(&net->ipv4.rt_secret_timer);
+               mod_timer(&net->ipv4.rt_secret_timer, jiffies + time);
        }
        rtnl_unlock();
 }