]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/route.c
[NETNS][DST] dst: pass the dst_ops as parameter to the gc functions
[linux-2.6-omap-h63xx.git] / net / ipv4 / route.c
index fcae074b7ae4f83e87d8e41d6e48b356cea58c27..fc0145385e80e4bddc1e8d7db9031c346657c522 100644 (file)
@@ -154,7 +154,7 @@ static void          ipv4_dst_ifdown(struct dst_entry *dst,
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
 static void             ipv4_link_failure(struct sk_buff *skb);
 static void             ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
-static int rt_garbage_collect(void);
+static int rt_garbage_collect(struct dst_ops *ops);
 
 
 static struct dst_ops ipv4_dst_ops = {
@@ -235,16 +235,25 @@ struct rt_hash_bucket {
 
 static spinlock_t      *rt_hash_locks;
 # define rt_hash_lock_addr(slot) &rt_hash_locks[(slot) & (RT_HASH_LOCK_SZ - 1)]
-# define rt_hash_lock_init()   { \
-               int i; \
-               rt_hash_locks = kmalloc(sizeof(spinlock_t) * RT_HASH_LOCK_SZ, GFP_KERNEL); \
-               if (!rt_hash_locks) panic("IP: failed to allocate rt_hash_locks\n"); \
-               for (i = 0; i < RT_HASH_LOCK_SZ; i++) \
-                       spin_lock_init(&rt_hash_locks[i]); \
-               }
+
+static __init void rt_hash_lock_init(void)
+{
+       int i;
+
+       rt_hash_locks = kmalloc(sizeof(spinlock_t) * RT_HASH_LOCK_SZ,
+                       GFP_KERNEL);
+       if (!rt_hash_locks)
+               panic("IP: failed to allocate rt_hash_locks\n");
+
+       for (i = 0; i < RT_HASH_LOCK_SZ; i++)
+               spin_lock_init(&rt_hash_locks[i]);
+}
 #else
 # define rt_hash_lock_addr(slot) NULL
-# define rt_hash_lock_init()
+
+static inline void rt_hash_lock_init(void)
+{
+}
 #endif
 
 static struct rt_hash_bucket   *rt_hash_table;
@@ -481,6 +490,83 @@ static const struct file_operations rt_cpu_seq_fops = {
        .release = seq_release,
 };
 
+#ifdef CONFIG_NET_CLS_ROUTE
+static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
+                          int length, int *eof, void *data)
+{
+       unsigned int i;
+
+       if ((offset & 3) || (length & 3))
+               return -EIO;
+
+       if (offset >= sizeof(struct ip_rt_acct) * 256) {
+               *eof = 1;
+               return 0;
+       }
+
+       if (offset + length >= sizeof(struct ip_rt_acct) * 256) {
+               length = sizeof(struct ip_rt_acct) * 256 - offset;
+               *eof = 1;
+       }
+
+       offset /= sizeof(u32);
+
+       if (length > 0) {
+               u32 *dst = (u32 *) buffer;
+
+               *start = buffer;
+               memset(dst, 0, length);
+
+               for_each_possible_cpu(i) {
+                       unsigned int j;
+                       u32 *src;
+
+                       src = ((u32 *) per_cpu_ptr(ip_rt_acct, i)) + offset;
+                       for (j = 0; j < length/4; j++)
+                               dst[j] += src[j];
+               }
+       }
+       return length;
+}
+#endif
+
+static __init int ip_rt_proc_init(struct net *net)
+{
+       struct proc_dir_entry *pde;
+
+       pde = proc_net_fops_create(net, "rt_cache", S_IRUGO,
+                       &rt_cache_seq_fops);
+       if (!pde)
+               goto err1;
+
+       pde = create_proc_entry("rt_cache", S_IRUGO, net->proc_net_stat);
+       if (!pde)
+               goto err2;
+
+       pde->proc_fops = &rt_cpu_seq_fops;
+
+#ifdef CONFIG_NET_CLS_ROUTE
+       pde = create_proc_read_entry("rt_acct", 0, net->proc_net,
+                       ip_rt_acct_read, NULL);
+       if (!pde)
+               goto err3;
+#endif
+       return 0;
+
+#ifdef CONFIG_NET_CLS_ROUTE
+err3:
+       remove_proc_entry("rt_cache", net->proc_net_stat);
+#endif
+err2:
+       remove_proc_entry("rt_cache", net->proc_net);
+err1:
+       return -ENOMEM;
+}
+#else
+static inline int ip_rt_proc_init(struct net *net)
+{
+       return 0;
+}
 #endif /* CONFIG_PROC_FS */
 
 static __inline__ void rt_free(struct rtable *rt)
@@ -734,7 +820,7 @@ static void rt_secret_rebuild(unsigned long dummy)
    and when load increases it reduces to limit cache size.
  */
 
-static int rt_garbage_collect(void)
+static int rt_garbage_collect(struct dst_ops *ops)
 {
        static unsigned long expire = RT_GC_TIMEOUT;
        static unsigned long last_gc;
@@ -765,14 +851,14 @@ static int rt_garbage_collect(void)
                        equilibrium = ipv4_dst_ops.gc_thresh;
                goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
                if (goal > 0) {
-                       equilibrium += min_t(unsigned int, goal / 2, rt_hash_mask + 1);
+                       equilibrium += min_t(unsigned int, goal >> 1, rt_hash_mask + 1);
                        goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
                }
        } else {
                /* We are in dangerous area. Try to reduce cache really
                 * aggressively.
                 */
-               goal = max_t(unsigned int, goal / 2, rt_hash_mask + 1);
+               goal = max_t(unsigned int, goal >> 1, rt_hash_mask + 1);
                equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
        }
 
@@ -949,7 +1035,7 @@ restart:
                                int saved_int = ip_rt_gc_min_interval;
                                ip_rt_gc_elasticity     = 1;
                                ip_rt_gc_min_interval   = 0;
-                               rt_garbage_collect();
+                               rt_garbage_collect(&ipv4_dst_ops);
                                ip_rt_gc_min_interval   = saved_int;
                                ip_rt_gc_elasticity     = saved_elasticity;
                                goto restart;
@@ -1068,7 +1154,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                return;
 
        if (new_gw == old_gw || !IN_DEV_RX_REDIRECTS(in_dev)
-           || MULTICAST(new_gw) || BADCLASS(new_gw) || ZERONET(new_gw))
+           || ipv4_is_multicast(new_gw) || ipv4_is_badclass(new_gw)
+           || ipv4_is_zeronet(new_gw))
                goto reject_redirect;
 
        if (!IN_DEV_SHARED_MEDIA(in_dev)) {
@@ -1077,7 +1164,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                if (IN_DEV_SEC_REDIRECTS(in_dev) && ip_fib_check_default(new_gw, dev))
                        goto reject_redirect;
        } else {
-               if (inet_addr_type(new_gw) != RTN_UNICAST)
+               if (inet_addr_type(&init_net, new_gw) != RTN_UNICAST)
                        goto reject_redirect;
        }
 
@@ -1426,8 +1513,9 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 {
        struct rtable *rt = (struct rtable *) dst;
        struct in_device *idev = rt->idev;
-       if (dev != init_net.loopback_dev && idev && idev->dev == dev) {
-               struct in_device *loopback_idev = in_dev_get(init_net.loopback_dev);
+       if (dev != dev->nd_net->loopback_dev && idev && idev->dev == dev) {
+               struct in_device *loopback_idev =
+                       in_dev_get(dev->nd_net->loopback_dev);
                if (loopback_idev) {
                        rt->idev = loopback_idev;
                        in_dev_put(idev);
@@ -1546,12 +1634,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        if (in_dev == NULL)
                return -EINVAL;
 
-       if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr) ||
-           skb->protocol != htons(ETH_P_IP))
+       if (ipv4_is_multicast(saddr) || ipv4_is_badclass(saddr) ||
+           ipv4_is_loopback(saddr) || skb->protocol != htons(ETH_P_IP))
                goto e_inval;
 
-       if (ZERONET(saddr)) {
-               if (!LOCAL_MCAST(daddr))
+       if (ipv4_is_zeronet(saddr)) {
+               if (!ipv4_is_local_multicast(daddr))
                        goto e_inval;
                spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
        } else if (fib_validate_source(saddr, 0, tos, 0,
@@ -1593,7 +1681,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        }
 
 #ifdef CONFIG_IP_MROUTE
-       if (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
+       if (!ipv4_is_local_multicast(daddr) && IN_DEV_MFORWARD(in_dev))
                rth->u.dst.input = ip_mr_input;
 #endif
        RT_CACHE_STAT_INC(in_slow_mc);
@@ -1680,7 +1768,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
        if (err)
                flags |= RTCF_DIRECTSRC;
 
-       if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+       if (out_dev == in_dev && err && !(flags & RTCF_MASQ) &&
            (IN_DEV_SHARED_MEDIA(out_dev) ||
             inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
                flags |= RTCF_DOREDIRECT;
@@ -1689,7 +1777,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
                /* Not IP (i.e. ARP). Do not create route, if it is
                 * invalid for proxy arp. DNAT routes are always valid.
                 */
-               if (out_dev == in_dev && !(flags & RTCF_DNAT)) {
+               if (out_dev == in_dev) {
                        err = -EINVAL;
                        goto cleanup;
                }
@@ -1803,7 +1891,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
           by fib_lookup.
         */
 
-       if (MULTICAST(saddr) || BADCLASS(saddr) || LOOPBACK(saddr))
+       if (ipv4_is_multicast(saddr) || ipv4_is_badclass(saddr) ||
+           ipv4_is_loopback(saddr))
                goto martian_source;
 
        if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0))
@@ -1812,10 +1901,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        /* Accept zero addresses only to limited broadcast;
         * I even do not know to fix it or not. Waiting for complains :-)
         */
-       if (ZERONET(saddr))
+       if (ipv4_is_zeronet(saddr))
                goto martian_source;
 
-       if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
+       if (ipv4_is_badclass(daddr) || ipv4_is_zeronet(daddr) ||
+           ipv4_is_loopback(daddr))
                goto martian_destination;
 
        /*
@@ -1862,7 +1952,7 @@ brd_input:
        if (skb->protocol != htons(ETH_P_IP))
                goto e_inval;
 
-       if (ZERONET(saddr))
+       if (ipv4_is_zeronet(saddr))
                spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
        else {
                err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
@@ -1992,7 +2082,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
           Note, that multicast routers are not affected, because
           route cache entry is created eventually.
         */
-       if (MULTICAST(daddr)) {
+       if (ipv4_is_multicast(daddr)) {
                struct in_device *in_dev;
 
                rcu_read_lock();
@@ -2001,7 +2091,8 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                                ip_hdr(skb)->protocol);
                        if (our
 #ifdef CONFIG_IP_MROUTE
-                           || (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
+                           || (!ipv4_is_local_multicast(daddr) &&
+                               IN_DEV_MFORWARD(in_dev))
 #endif
                            ) {
                                rcu_read_unlock();
@@ -2027,14 +2118,14 @@ static inline int __mkroute_output(struct rtable **result,
        u32 tos = RT_FL_TOS(oldflp);
        int err = 0;
 
-       if (LOOPBACK(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
+       if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
                return -EINVAL;
 
        if (fl->fl4_dst == htonl(0xFFFFFFFF))
                res->type = RTN_BROADCAST;
-       else if (MULTICAST(fl->fl4_dst))
+       else if (ipv4_is_multicast(fl->fl4_dst))
                res->type = RTN_MULTICAST;
-       else if (BADCLASS(fl->fl4_dst) || ZERONET(fl->fl4_dst))
+       else if (ipv4_is_badclass(fl->fl4_dst) || ipv4_is_zeronet(fl->fl4_dst))
                return -EINVAL;
 
        if (dev_out->flags & IFF_LOOPBACK)
@@ -2114,7 +2205,7 @@ static inline int __mkroute_output(struct rtable **result,
 #ifdef CONFIG_IP_MROUTE
                if (res->type == RTN_MULTICAST) {
                        if (IN_DEV_MFORWARD(in_dev) &&
-                           !LOCAL_MCAST(oldflp->fl4_dst)) {
+                           !ipv4_is_local_multicast(oldflp->fl4_dst)) {
                                rth->u.dst.input = ip_mr_input;
                                rth->u.dst.output = ip_mc_output;
                        }
@@ -2184,9 +2275,9 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
 
        if (oldflp->fl4_src) {
                err = -EINVAL;
-               if (MULTICAST(oldflp->fl4_src) ||
-                   BADCLASS(oldflp->fl4_src) ||
-                   ZERONET(oldflp->fl4_src))
+               if (ipv4_is_multicast(oldflp->fl4_src) ||
+                   ipv4_is_badclass(oldflp->fl4_src) ||
+                   ipv4_is_zeronet(oldflp->fl4_src))
                        goto out;
 
                /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
@@ -2203,7 +2294,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
                 */
 
                if (oldflp->oif == 0
-                   && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
+                   && (ipv4_is_multicast(oldflp->fl4_dst) ||
+                       oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
                        /* Special hack: user can direct multicasts
                           and limited broadcast via necessary interface
                           without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -2240,14 +2332,15 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
                        goto out;       /* Wrong error code */
                }
 
-               if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == htonl(0xFFFFFFFF)) {
+               if (ipv4_is_local_multicast(oldflp->fl4_dst) ||
+                   oldflp->fl4_dst == htonl(0xFFFFFFFF)) {
                        if (!fl.fl4_src)
                                fl.fl4_src = inet_select_addr(dev_out, 0,
                                                              RT_SCOPE_LINK);
                        goto make_route;
                }
                if (!fl.fl4_src) {
-                       if (MULTICAST(oldflp->fl4_dst))
+                       if (ipv4_is_multicast(oldflp->fl4_dst))
                                fl.fl4_src = inet_select_addr(dev_out, 0,
                                                              fl.fl4_scope);
                        else if (!oldflp->fl4_dst)
@@ -2449,7 +2542,8 @@ int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk,
                        flp->fl4_src = (*rp)->rt_src;
                if (!flp->fl4_dst)
                        flp->fl4_dst = (*rp)->rt_dst;
-               err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
+               err = __xfrm_lookup((struct dst_entry **)rp, flp, sk,
+                                   flags ? XFRM_LOOKUP_WAIT : 0);
                if (err == -EREMOTE)
                        err = ipv4_dst_blackhole(rp, flp, sk);
 
@@ -2530,8 +2624,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 #ifdef CONFIG_IP_MROUTE
                __be32 dst = rt->rt_dst;
 
-               if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
-                   IPV4_DEVCONF_ALL(MC_FORWARDING)) {
+               if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) &&
+                   IPV4_DEVCONF_ALL(&init_net, MC_FORWARDING)) {
                        int err = ipmr_get_route(skb, r, nowait);
                        if (err <= 0) {
                                if (!nowait) {
@@ -2898,48 +2992,6 @@ ctl_table ipv4_route_table[] = {
 
 #ifdef CONFIG_NET_CLS_ROUTE
 struct ip_rt_acct *ip_rt_acct __read_mostly;
-
-/* IP route accounting ptr for this logical cpu number. */
-#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,
-                          int length, int *eof, void *data)
-{
-       unsigned int i;
-
-       if ((offset & 3) || (length & 3))
-               return -EIO;
-
-       if (offset >= sizeof(struct ip_rt_acct) * 256) {
-               *eof = 1;
-               return 0;
-       }
-
-       if (offset + length >= sizeof(struct ip_rt_acct) * 256) {
-               length = sizeof(struct ip_rt_acct) * 256 - offset;
-               *eof = 1;
-       }
-
-       offset /= sizeof(u32);
-
-       if (length > 0) {
-               u32 *dst = (u32 *) buffer;
-
-               *start = buffer;
-               memset(dst, 0, length);
-
-               for_each_possible_cpu(i) {
-                       unsigned int j;
-                       u32 *src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset;
-
-                       for (j = 0; j < length/4; j++)
-                               dst[j] += src[j];
-               }
-       }
-       return length;
-}
-#endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_CLS_ROUTE */
 
 static __initdata unsigned long rhash_entries;
@@ -3003,20 +3055,8 @@ int __init ip_rt_init(void)
                ip_rt_secret_interval;
        add_timer(&rt_secret_timer);
 
-#ifdef CONFIG_PROC_FS
-       {
-       struct proc_dir_entry *rtstat_pde = NULL; /* keep gcc happy */
-       if (!proc_net_fops_create(&init_net, "rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
-           !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
-                                            init_net.proc_net_stat))) {
-               return -ENOMEM;
-       }
-       rtstat_pde->proc_fops = &rt_cpu_seq_fops;
-       }
-#ifdef CONFIG_NET_CLS_ROUTE
-       create_proc_read_entry("rt_acct", 0, init_net.proc_net, ip_rt_acct_read, NULL);
-#endif
-#endif
+       if (ip_rt_proc_init(&init_net))
+               printk(KERN_ERR "Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
        xfrm_init();
        xfrm4_init();