]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/reassembly.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / net / ipv6 / reassembly.c
index 21913c78f053a98a5ab8125e54a456c0da5a8544..76c88a93b9b5a7714678a0ccb28aa140aa4e4998 100644 (file)
@@ -143,17 +143,17 @@ static unsigned int ip6_hashfn(struct inet_frag_queue *q)
        return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr);
 }
 
-int ip6_frag_equal(struct inet_frag_queue *q1, struct inet_frag_queue *q2)
+int ip6_frag_match(struct inet_frag_queue *q, void *a)
 {
-       struct frag_queue *fq1, *fq2;
+       struct frag_queue *fq;
+       struct ip6_create_arg *arg = a;
 
-       fq1 = container_of(q1, struct frag_queue, q);
-       fq2 = container_of(q2, struct frag_queue, q);
-       return (fq1->id == fq2->id &&
-                       ipv6_addr_equal(&fq2->saddr, &fq1->saddr) &&
-                       ipv6_addr_equal(&fq2->daddr, &fq1->daddr));
+       fq = container_of(q, struct frag_queue, q);
+       return (fq->id == arg->id &&
+                       ipv6_addr_equal(&fq->saddr, arg->src) &&
+                       ipv6_addr_equal(&fq->daddr, arg->dst));
 }
-EXPORT_SYMBOL(ip6_frag_equal);
+EXPORT_SYMBOL(ip6_frag_match);
 
 /* Memory Tracking Functions. */
 static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
@@ -164,18 +164,16 @@ static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
        kfree_skb(skb);
 }
 
-static void ip6_frag_free(struct inet_frag_queue *fq)
+void ip6_frag_init(struct inet_frag_queue *q, void *a)
 {
-       kfree(container_of(fq, struct frag_queue, q));
-}
+       struct frag_queue *fq = container_of(q, struct frag_queue, q);
+       struct ip6_create_arg *arg = a;
 
-static inline struct frag_queue *frag_alloc_queue(void)
-{
-       struct inet_frag_queue *q;
-
-       q = inet_frag_alloc(&ip6_frags);
-       return q ? container_of(q, struct frag_queue, q) : NULL;
+       fq->id = arg->id;
+       ipv6_addr_copy(&fq->saddr, arg->src);
+       ipv6_addr_copy(&fq->daddr, arg->dst);
 }
+EXPORT_SYMBOL(ip6_frag_init);
 
 /* Destruction primitives. */
 
@@ -242,64 +240,30 @@ out:
        fq_put(fq);
 }
 
-/* Creation primitives. */
-
-
-static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in,
-               unsigned int hash)
+static __inline__ struct frag_queue *
+fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
+       struct inet6_dev *idev)
 {
        struct inet_frag_queue *q;
+       struct ip6_create_arg arg;
+       unsigned int hash;
 
-       q = inet_frag_intern(&fq_in->q, &ip6_frags, hash);
-       return container_of(q, struct frag_queue, q);
-}
-
-
-static struct frag_queue *
-ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst,
-               struct inet6_dev *idev, unsigned int hash)
-{
-       struct frag_queue *fq;
+       arg.id = id;
+       arg.src = src;
+       arg.dst = dst;
+       hash = ip6qhashfn(id, src, dst);
 
-       if ((fq = frag_alloc_queue()) == NULL)
+       q = inet_frag_find(&ip6_frags, &arg, hash);
+       if (q == NULL)
                goto oom;
 
-       fq->id = id;
-       ipv6_addr_copy(&fq->saddr, src);
-       ipv6_addr_copy(&fq->daddr, dst);
-
-       return ip6_frag_intern(fq, hash);
+       return container_of(q, struct frag_queue, q);
 
 oom:
        IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
        return NULL;
 }
 
-static __inline__ struct frag_queue *
-fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
-       struct inet6_dev *idev)
-{
-       struct frag_queue *fq;
-       struct hlist_node *n;
-       unsigned int hash;
-
-       read_lock(&ip6_frags.lock);
-       hash = ip6qhashfn(id, src, dst);
-       hlist_for_each_entry(fq, n, &ip6_frags.hash[hash], q.list) {
-               if (fq->id == id &&
-                   ipv6_addr_equal(src, &fq->saddr) &&
-                   ipv6_addr_equal(dst, &fq->daddr)) {
-                       atomic_inc(&fq->q.refcnt);
-                       read_unlock(&ip6_frags.lock);
-                       return fq;
-               }
-       }
-       read_unlock(&ip6_frags.lock);
-
-       return ip6_frag_create(id, src, dst, idev, hash);
-}
-
-
 static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
                           struct frag_hdr *fhdr, int nhoff)
 {
@@ -675,10 +639,11 @@ void __init ipv6_frag_init(void)
 
        ip6_frags.ctl = &ip6_frags_ctl;
        ip6_frags.hashfn = ip6_hashfn;
-       ip6_frags.destructor = ip6_frag_free;
+       ip6_frags.constructor = ip6_frag_init;
+       ip6_frags.destructor = NULL;
        ip6_frags.skb_free = NULL;
        ip6_frags.qsize = sizeof(struct frag_queue);
-       ip6_frags.equal = ip6_frag_equal;
+       ip6_frags.match = ip6_frag_match;
        ip6_frags.frag_expire = ip6_frag_expire;
        inet_frags_init(&ip6_frags);
 }