void                    (*destructor)(struct inet_frag_queue *);
        void                    (*skb_free)(struct sk_buff *);
        void                    (*frag_expire)(unsigned long data);
+       struct kmem_cache       *frags_cachep;
+       const char              *frags_cache_name;
 };
 
-void inet_frags_init(struct inet_frags *);
+int inet_frags_init(struct inet_frags *);
 void inet_frags_fini(struct inet_frags *);
 
 void inet_frags_init_net(struct netns_frags *nf);
 
 
 #include "reassembly.h"
 
+static const char lowpan_frags_cache_name[] = "lowpan-frags";
+
 struct lowpan_frag_info {
        __be16 d_tag;
        u16 d_size;
        lowpan_frags.qsize = sizeof(struct frag_queue);
        lowpan_frags.match = lowpan_frag_match;
        lowpan_frags.frag_expire = lowpan_frag_expire;
-       inet_frags_init(&lowpan_frags);
+       lowpan_frags.frags_cache_name = lowpan_frags_cache_name;
+       ret = inet_frags_init(&lowpan_frags);
+       if (ret)
+               goto err_pernet;
 
        return ret;
 err_pernet:
 
                schedule_work(&f->frags_work);
 }
 
-void inet_frags_init(struct inet_frags *f)
+int inet_frags_init(struct inet_frags *f)
 {
        int i;
 
 
        seqlock_init(&f->rnd_seqlock);
        f->last_rebuild_jiffies = 0;
+       f->frags_cachep = kmem_cache_create(f->frags_cache_name, f->qsize, 0, 0,
+                                           NULL);
+       if (!f->frags_cachep)
+               return -ENOMEM;
+
+       return 0;
 }
 EXPORT_SYMBOL(inet_frags_init);
 
 void inet_frags_fini(struct inet_frags *f)
 {
        cancel_work_sync(&f->frags_work);
+       kmem_cache_destroy(f->frags_cachep);
 }
 EXPORT_SYMBOL(inet_frags_fini);
 
 
        if (f->destructor)
                f->destructor(q);
-       kfree(q);
+       kmem_cache_free(f->frags_cachep, q);
 }
 EXPORT_SYMBOL(inet_frag_destroy);
 
                return NULL;
        }
 
-       q = kzalloc(f->qsize, GFP_ATOMIC);
+       q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC);
        if (q == NULL)
                return NULL;
 
 
  */
 
 static int sysctl_ipfrag_max_dist __read_mostly = 64;
+static const char ip_frag_cache_name[] = "ip4-frags";
 
 struct ipfrag_skb_cb
 {
        ip4_frags.qsize = sizeof(struct ipq);
        ip4_frags.match = ip4_frag_match;
        ip4_frags.frag_expire = ip_expire;
-       inet_frags_init(&ip4_frags);
+       ip4_frags.frags_cache_name = ip_frag_cache_name;
+       if (inet_frags_init(&ip4_frags))
+               panic("IP: failed to allocate ip4_frags cache\n");
 }
 
 #include <linux/module.h>
 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 
+static const char nf_frags_cache_name[] = "nf-frags";
 
 struct nf_ct_frag6_skb_cb
 {
        nf_frags.qsize = sizeof(struct frag_queue);
        nf_frags.match = ip6_frag_match;
        nf_frags.frag_expire = nf_ct_frag6_expire;
-       inet_frags_init(&nf_frags);
-
+       nf_frags.frags_cache_name = nf_frags_cache_name;
+       ret = inet_frags_init(&nf_frags);
+       if (ret)
+               goto out;
        ret = register_pernet_subsys(&nf_ct_net_ops);
        if (ret)
                inet_frags_fini(&nf_frags);
 
+out:
        return ret;
 }
 
 
 #include <net/inet_frag.h>
 #include <net/inet_ecn.h>
 
+static const char ip6_frag_cache_name[] = "ip6-frags";
+
 struct ip6frag_skb_cb
 {
        struct inet6_skb_parm   h;
        ip6_frags.qsize = sizeof(struct frag_queue);
        ip6_frags.match = ip6_frag_match;
        ip6_frags.frag_expire = ip6_frag_expire;
-       inet_frags_init(&ip6_frags);
+       ip6_frags.frags_cache_name = ip6_frag_cache_name;
+       ret = inet_frags_init(&ip6_frags);
+       if (ret)
+               goto err_pernet;
 out:
        return ret;