]> err.no Git - linux-2.6/blobdiff - net/ipv4/route.c
[NET]: NET_CLS_ROUTE : convert ip_rt_acct to per_cpu variables
[linux-2.6] / net / ipv4 / route.c
index c426dec6d57903467fd5cd7a233a872efa0524ce..a21021bf1409179e59d0be454df4f51e3e347c4e 100644 (file)
@@ -92,6 +92,7 @@
 #include <linux/jhash.h>
 #include <linux/rcupdate.h>
 #include <linux/times.h>
+#include <net/dst.h>
 #include <net/net_namespace.h>
 #include <net/protocol.h>
 #include <net/ip.h>
@@ -165,6 +166,7 @@ static struct dst_ops ipv4_dst_ops = {
        .negative_advice =      ipv4_negative_advice,
        .link_failure =         ipv4_link_failure,
        .update_pmtu =          ip_rt_update_pmtu,
+       .local_out =            ip_local_out,
        .entry_size =           sizeof(struct rtable),
 };
 
@@ -283,12 +285,12 @@ static struct rtable *rt_cache_get_first(struct seq_file *seq)
                        break;
                rcu_read_unlock_bh();
        }
-       return r;
+       return rcu_dereference(r);
 }
 
 static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
 {
-       struct rt_cache_iter_state *st = rcu_dereference(seq->private);
+       struct rt_cache_iter_state *st = seq->private;
 
        r = r->u.dst.rt_next;
        while (!r) {
@@ -298,7 +300,7 @@ static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
                rcu_read_lock_bh();
                r = rt_hash_table[st->bucket].chain;
        }
-       return r;
+       return rcu_dereference(r);
 }
 
 static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos)
@@ -1161,7 +1163,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
                        unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
                                                rt->fl.oif);
 #if RT_CACHE_DEBUG >= 1
-                       printk(KERN_DEBUG "ip_rt_advice: redirect to "
+                       printk(KERN_DEBUG "ipv4_negative_advice: redirect to "
                                          "%u.%u.%u.%u/%02x dropped\n",
                                NIPQUAD(rt->rt_dst), rt->fl.fl4_tos);
 #endif
@@ -1252,6 +1254,7 @@ static int ip_error(struct sk_buff *skb)
                        break;
                case ENETUNREACH:
                        code = ICMP_NET_UNREACH;
+                       IP_INC_STATS_BH(IPSTATS_MIB_INNOROUTES);
                        break;
                case EACCES:
                        code = ICMP_PKT_FILTERED;
@@ -1881,6 +1884,8 @@ no_route:
        RT_CACHE_STAT_INC(in_no_route);
        spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
        res.type = RTN_UNREACHABLE;
+       if (err == -ESRCH)
+               err = -ENETUNREACH;
        goto local_input;
 
        /*
@@ -2354,12 +2359,6 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
 };
 
 
-static int ipv4_blackhole_output(struct sk_buff *skb)
-{
-       kfree_skb(skb);
-       return 0;
-}
-
 static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock *sk)
 {
        struct rtable *ort = *rp;
@@ -2371,8 +2370,8 @@ static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp, struct sock
 
                atomic_set(&new->__refcnt, 1);
                new->__use = 1;
-               new->input = ipv4_blackhole_output;
-               new->output = ipv4_blackhole_output;
+               new->input = dst_discard;
+               new->output = dst_discard;
                memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
 
                new->dev = ort->u.dst.dev;
@@ -2623,11 +2622,10 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
        int idx, s_idx;
 
        s_h = cb->args[0];
+       if (s_h < 0)
+               s_h = 0;
        s_idx = idx = cb->args[1];
-       for (h = 0; h <= rt_hash_mask; h++) {
-               if (h < s_h) continue;
-               if (h > s_h)
-                       s_idx = 0;
+       for (h = s_h; h <= rt_hash_mask; h++) {
                rcu_read_lock_bh();
                for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
                     rt = rcu_dereference(rt->u.dst.rt_next), idx++) {
@@ -2644,6 +2642,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
                        dst_release(xchg(&skb->dst, NULL));
                }
                rcu_read_unlock_bh();
+               s_idx = 0;
        }
 
 done:
@@ -2859,12 +2858,10 @@ ctl_table ipv4_route_table[] = {
 #endif
 
 #ifdef CONFIG_NET_CLS_ROUTE
-struct ip_rt_acct *ip_rt_acct;
-
-/* This code sucks.  But you should have seen it before! --RR */
+struct ip_rt_acct *ip_rt_acct __read_mostly;
 
 /* IP route accounting ptr for this logical cpu number. */
-#define IP_RT_ACCT_CPU(i) (ip_rt_acct + i * 256)
+#define IP_RT_ACCT_CPU(cpu) (per_cpu_ptr(ip_rt_acct, cpu))
 
 #ifdef CONFIG_PROC_FS
 static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
@@ -2924,16 +2921,9 @@ int __init ip_rt_init(void)
                             (jiffies ^ (jiffies >> 7)));
 
 #ifdef CONFIG_NET_CLS_ROUTE
-       {
-       int order;
-       for (order = 0;
-            (PAGE_SIZE << order) < 256 * sizeof(struct ip_rt_acct) * NR_CPUS; order++)
-               /* NOTHING */;
-       ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);
+       ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct));
        if (!ip_rt_acct)
                panic("IP: failed to allocate ip_rt_acct\n");
-       memset(ip_rt_acct, 0, PAGE_SIZE << order);
-       }
 #endif
 
        ipv4_dst_ops.kmem_cachep =
@@ -2961,10 +2951,8 @@ int __init ip_rt_init(void)
        devinet_init();
        ip_fib_init();
 
-       init_timer(&rt_flush_timer);
-       rt_flush_timer.function = rt_run_flush;
-       init_timer(&rt_secret_timer);
-       rt_secret_timer.function = rt_secret_rebuild;
+       setup_timer(&rt_flush_timer, rt_run_flush, 0);
+       setup_timer(&rt_secret_timer, rt_secret_rebuild, 0);
 
        /* All the timers, started at system startup tend
           to synchronize. Perturb it a bit.