X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=net%2Fipv6%2Freassembly.c;h=76c88a93b9b5a7714678a0ccb28aa140aa4e4998;hb=c5b875e354a54e2b5ba24eecae69bf94e025edd5;hp=21913c78f053a98a5ab8125e54a456c0da5a8544;hpb=e521db9d790aaa60ae8920e21cb7faedc280fc36;p=linux-2.6-omap-h63xx.git diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 21913c78f05..76c88a93b9b 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -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); }