Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-2.6-block.git] / net / ipv4 / ip_tunnel.c
index 89e8861e05fcb1d371c371c1784b89499b69d9df..dff8a05739a289d20844cd91ae21350fa689c47d 100644 (file)
@@ -68,61 +68,6 @@ static unsigned int ip_tunnel_hash(__be32 key, __be32 remote)
                         IP_TNL_HASH_BITS);
 }
 
-static void __tunnel_dst_set(struct ip_tunnel_dst *idst,
-                            struct dst_entry *dst, __be32 saddr)
-{
-       struct dst_entry *old_dst;
-
-       dst_clone(dst);
-       old_dst = xchg((__force struct dst_entry **)&idst->dst, dst);
-       dst_release(old_dst);
-       idst->saddr = saddr;
-}
-
-static noinline void tunnel_dst_set(struct ip_tunnel *t,
-                          struct dst_entry *dst, __be32 saddr)
-{
-       __tunnel_dst_set(raw_cpu_ptr(t->dst_cache), dst, saddr);
-}
-
-static void tunnel_dst_reset(struct ip_tunnel *t)
-{
-       tunnel_dst_set(t, NULL, 0);
-}
-
-void ip_tunnel_dst_reset_all(struct ip_tunnel *t)
-{
-       int i;
-
-       for_each_possible_cpu(i)
-               __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0);
-}
-EXPORT_SYMBOL(ip_tunnel_dst_reset_all);
-
-static struct rtable *tunnel_rtable_get(struct ip_tunnel *t,
-                                       u32 cookie, __be32 *saddr)
-{
-       struct ip_tunnel_dst *idst;
-       struct dst_entry *dst;
-
-       rcu_read_lock();
-       idst = raw_cpu_ptr(t->dst_cache);
-       dst = rcu_dereference(idst->dst);
-       if (dst && !atomic_inc_not_zero(&dst->__refcnt))
-               dst = NULL;
-       if (dst) {
-               if (!dst->obsolete || dst->ops->check(dst, cookie)) {
-                       *saddr = idst->saddr;
-               } else {
-                       tunnel_dst_reset(t);
-                       dst_release(dst);
-                       dst = NULL;
-               }
-       }
-       rcu_read_unlock();
-       return (struct rtable *)dst;
-}
-
 static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
                                __be16 flags, __be32 key)
 {
@@ -381,7 +326,8 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
 
                if (!IS_ERR(rt)) {
                        tdev = rt->dst.dev;
-                       tunnel_dst_set(tunnel, &rt->dst, fl4.saddr);
+                       dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
+                                         fl4.saddr);
                        ip_rt_put(rt);
                }
                if (dev->type != ARPHRD_ETHER)
@@ -729,7 +675,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
                goto tx_error;
 
-       rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL;
+       rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) :
+                        NULL;
 
        if (!rt) {
                rt = ip_route_output_key(tunnel->net, &fl4);
@@ -739,7 +686,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                        goto tx_error;
                }
                if (connected)
-                       tunnel_dst_set(tunnel, &rt->dst, fl4.saddr);
+                       dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
+                                         fl4.saddr);
        }
 
        if (rt->dst.dev == dev) {
@@ -836,7 +784,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
                if (set_mtu)
                        dev->mtu = mtu;
        }
-       ip_tunnel_dst_reset_all(t);
+       dst_cache_reset(&t->dst_cache);
        netdev_state_change(dev);
 }
 
@@ -975,7 +923,7 @@ static void ip_tunnel_dev_free(struct net_device *dev)
        struct ip_tunnel *tunnel = netdev_priv(dev);
 
        gro_cells_destroy(&tunnel->gro_cells);
-       free_percpu(tunnel->dst_cache);
+       dst_cache_destroy(&tunnel->dst_cache);
        free_percpu(dev->tstats);
        free_netdev(dev);
 }
@@ -1169,15 +1117,15 @@ int ip_tunnel_init(struct net_device *dev)
        if (!dev->tstats)
                return -ENOMEM;
 
-       tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst);
-       if (!tunnel->dst_cache) {
+       err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
+       if (err) {
                free_percpu(dev->tstats);
-               return -ENOMEM;
+               return err;
        }
 
        err = gro_cells_init(&tunnel->gro_cells, dev);
        if (err) {
-               free_percpu(tunnel->dst_cache);
+               dst_cache_destroy(&tunnel->dst_cache);
                free_percpu(dev->tstats);
                return err;
        }
@@ -1207,7 +1155,7 @@ void ip_tunnel_uninit(struct net_device *dev)
        if (itn->fb_tunnel_dev != dev)
                ip_tunnel_del(itn, netdev_priv(dev));
 
-       ip_tunnel_dst_reset_all(tunnel);
+       dst_cache_reset(&tunnel->dst_cache);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_uninit);