Merge branch 'stable/cleanups-3.2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / net / ipv4 / route.c
index 075212e..155138d 100644 (file)
 
 static int ip_rt_max_size;
 static int ip_rt_gc_timeout __read_mostly      = RT_GC_TIMEOUT;
-static int ip_rt_gc_interval __read_mostly     = 60 * HZ;
 static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
 static int ip_rt_redirect_number __read_mostly = 9;
 static int ip_rt_redirect_load __read_mostly   = HZ / 50;
@@ -324,7 +323,7 @@ static struct rtable *rt_cache_get_first(struct seq_file *seq)
        struct rtable *r = NULL;
 
        for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
-               if (!rcu_dereference_raw(rt_hash_table[st->bucket].chain))
+               if (!rcu_access_pointer(rt_hash_table[st->bucket].chain))
                        continue;
                rcu_read_lock_bh();
                r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
@@ -350,7 +349,7 @@ static struct rtable *__rt_cache_get_next(struct seq_file *seq,
                do {
                        if (--st->bucket < 0)
                                return NULL;
-               } while (!rcu_dereference_raw(rt_hash_table[st->bucket].chain));
+               } while (!rcu_access_pointer(rt_hash_table[st->bucket].chain));
                rcu_read_lock_bh();
                r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
        }
@@ -761,7 +760,7 @@ static void rt_do_flush(struct net *net, int process_context)
 
                if (process_context && need_resched())
                        cond_resched();
-               rth = rcu_dereference_raw(rt_hash_table[i].chain);
+               rth = rcu_access_pointer(rt_hash_table[i].chain);
                if (!rth)
                        continue;
 
@@ -1309,7 +1308,12 @@ static void rt_del(unsigned hash, struct rtable *rt)
 void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                    __be32 saddr, struct net_device *dev)
 {
+       int s, i;
        struct in_device *in_dev = __in_dev_get_rcu(dev);
+       struct rtable *rt;
+       __be32 skeys[2] = { saddr, 0 };
+       int    ikeys[2] = { dev->ifindex, 0 };
+       struct flowi4 fl4;
        struct inet_peer *peer;
        struct net *net;
 
@@ -1332,13 +1336,34 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                        goto reject_redirect;
        }
 
-       peer = inet_getpeer_v4(daddr, 1);
-       if (peer) {
-               peer->redirect_learned.a4 = new_gw;
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.daddr = daddr;
+       for (s = 0; s < 2; s++) {
+               for (i = 0; i < 2; i++) {
+                       fl4.flowi4_oif = ikeys[i];
+                       fl4.saddr = skeys[s];
+                       rt = __ip_route_output_key(net, &fl4);
+                       if (IS_ERR(rt))
+                               continue;
 
-               inet_putpeer(peer);
+                       if (rt->dst.error || rt->dst.dev != dev ||
+                           rt->rt_gateway != old_gw) {
+                               ip_rt_put(rt);
+                               continue;
+                       }
+
+                       if (!rt->peer)
+                               rt_bind_peer(rt, rt->rt_dst, 1);
+
+                       peer = rt->peer;
+                       if (peer) {
+                               peer->redirect_learned.a4 = new_gw;
+                               atomic_inc(&__rt_peer_genid);
+                       }
 
-               atomic_inc(&__rt_peer_genid);
+                       ip_rt_put(rt);
+                       return;
+               }
        }
        return;
 
@@ -1568,11 +1593,10 @@ unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph,
                        est_mtu = mtu;
                        peer->pmtu_learned = mtu;
                        peer->pmtu_expires = pmtu_expires;
+                       atomic_inc(&__rt_peer_genid);
                }
 
                inet_putpeer(peer);
-
-               atomic_inc(&__rt_peer_genid);
        }
        return est_mtu ? : new_mtu;
 }
@@ -3120,13 +3144,6 @@ static ctl_table ipv4_route_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       {
-               .procname       = "gc_interval",
-               .data           = &ip_rt_gc_interval,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
        {
                .procname       = "redirect_load",
                .data           = &ip_rt_redirect_load,