fqdir
struct fqdir *fqdir;
int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net);
void fqdir_pre_exit(struct fqdir *fqdir);
void fqdir_exit(struct fqdir *fqdir);
struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key);
static inline long frag_mem_limit(const struct fqdir *fqdir)
return atomic_long_read(&fqdir->mem);
static inline void sub_frag_mem_limit(struct fqdir *fqdir, long val)
atomic_long_sub(val, &fqdir->mem);
static inline void add_frag_mem_limit(struct fqdir *fqdir, long val)
atomic_long_add(val, &fqdir->mem);
if (READ_ONCE(fq->q.fqdir->dead)) {
struct fqdir *fqdir;
struct fqdir *fqdir;
struct fqdir *fqdir;
struct fqdir *fqdir;
struct fqdir *fqdir;
add_frag_mem_limit(fq->q.fqdir, skb->truesize);
table[0].data = &ieee802154_lowpan->fqdir->high_thresh;
table[0].extra1 = &ieee802154_lowpan->fqdir->low_thresh;
table[1].data = &ieee802154_lowpan->fqdir->low_thresh;
table[1].extra2 = &ieee802154_lowpan->fqdir->high_thresh;
table[2].data = &ieee802154_lowpan->fqdir->timeout;
res = fqdir_init(&ieee802154_lowpan->fqdir, &lowpan_frags, net);
ieee802154_lowpan->fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
ieee802154_lowpan->fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
ieee802154_lowpan->fqdir->timeout = IPV6_FRAG_TIMEOUT;
fqdir_exit(ieee802154_lowpan->fqdir);
fqdir_pre_exit(ieee802154_lowpan->fqdir);
fqdir_exit(ieee802154_lowpan->fqdir);
q = inet_frag_find(ieee802154_lowpan->fqdir, &key);
struct fqdir *fqdir, *tmp;
llist_for_each_entry_safe(fqdir, tmp, kill_list, free_list) {
f = fqdir->f;
kfree(fqdir);
struct fqdir *fqdir = container_of(work, struct fqdir, destroy_work);
rhashtable_free_and_destroy(&fqdir->rhashtable, inet_frags_free_cb, NULL);
if (llist_add(&fqdir->free_list, &fqdir_free_list))
int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net)
struct fqdir *fqdir = kzalloc_obj(*fqdir);
if (!fqdir)
fqdir->f = f;
fqdir->net = net;
res = rhashtable_init(&fqdir->rhashtable, &fqdir->f->rhash_params);
kfree(fqdir);
*fqdirp = fqdir;
void fqdir_pre_exit(struct fqdir *fqdir)
WRITE_ONCE(fqdir->high_thresh, 0);
WRITE_ONCE(fqdir->dead, true);
rhashtable_walk_enter(&fqdir->rhashtable, &hti);
void fqdir_exit(struct fqdir *fqdir)
INIT_WORK(&fqdir->destroy_work, fqdir_work_fn);
queue_work(inet_frag_wq, &fqdir->destroy_work);
struct fqdir *fqdir = fq->fqdir;
if (!READ_ONCE(fqdir->dead)) {
rhashtable_remove_fast(&fqdir->rhashtable, &fq->node,
fqdir->f->rhash_params);
struct inet_frags *f = q->fqdir->f;
sub_frag_mem_limit(q->fqdir, sum);
struct fqdir *fqdir;
fqdir = q->fqdir;
f = fqdir->f;
sub_frag_mem_limit(fqdir, sum);
static struct inet_frag_queue *inet_frag_alloc(struct fqdir *fqdir,
q->fqdir = fqdir;
add_frag_mem_limit(fqdir, f->qsize);
static struct inet_frag_queue *inet_frag_create(struct fqdir *fqdir,
struct inet_frags *f = fqdir->f;
q = inet_frag_alloc(fqdir, f, arg);
mod_timer(&q->timer, jiffies + fqdir->timeout);
*prev = rhashtable_lookup_get_insert_key(&fqdir->rhashtable, &q->key,
struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key)
long high_thresh = READ_ONCE(fqdir->high_thresh);
if (!high_thresh || frag_mem_limit(fqdir) > high_thresh)
prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params);
fq = inet_frag_create(fqdir, key, &prev);
add_frag_mem_limit(q->fqdir, delta);
add_frag_mem_limit(q->fqdir, clone->truesize);
sub_frag_mem_limit(q->fqdir, sum_truesize);
sub_frag_mem_limit(q->fqdir, head->truesize);
net = qp->q.fqdir->net;
if (READ_ONCE(qp->q.fqdir->dead)) {
q = inet_frag_find(net->ipv4.fqdir, &key);
unsigned int max = qp->q.fqdir->max_dist;
__IP_INC_STATS(qp->q.fqdir->net, IPSTATS_MIB_REASMFAILS);
if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout))
struct net *net = qp->q.fqdir->net;
add_frag_mem_limit(qp->q.fqdir, skb->truesize);
struct net *net = qp->q.fqdir->net;
table[0].data = &net->ipv4.fqdir->high_thresh;
table[0].extra1 = &net->ipv4.fqdir->low_thresh;
table[1].data = &net->ipv4.fqdir->low_thresh;
table[1].extra2 = &net->ipv4.fqdir->high_thresh;
table[2].data = &net->ipv4.fqdir->timeout;
table[3].data = &net->ipv4.fqdir->max_dist;
res = fqdir_init(&net->ipv4.fqdir, &ip4_frags, net);
net->ipv4.fqdir->high_thresh = 4 * 1024 * 1024;
net->ipv4.fqdir->low_thresh = 3 * 1024 * 1024;
net->ipv4.fqdir->timeout = IP_FRAG_TIME;
net->ipv4.fqdir->max_dist = 64;
fqdir_exit(net->ipv4.fqdir);
fqdir_pre_exit(net->ipv4.fqdir);
fqdir_exit(net->ipv4.fqdir);
struct net *net = q->fqdir->net;
if (q->fqdir->max_dist) {
atomic_read(&net->ipv4.fqdir->rhashtable.nelems),
frag_mem_limit(net->ipv4.fqdir));
ip6frag_expire_frag_queue(fq->q.fqdir->net, fq);
q = inet_frag_find(nf_frag->fqdir, &key);
add_frag_mem_limit(fq->q.fqdir, skb->truesize);
res = fqdir_init(&nf_frag->fqdir, &nf_frags, net);
nf_frag->fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
nf_frag->fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
nf_frag->fqdir->timeout = IPV6_FRAG_TIMEOUT;
fqdir_exit(nf_frag->fqdir);
fqdir_pre_exit(nf_frag->fqdir);
fqdir_exit(nf_frag->fqdir);
table[0].data = &nf_frag->fqdir->timeout;
table[1].data = &nf_frag->fqdir->low_thresh;
table[1].extra2 = &nf_frag->fqdir->high_thresh;
table[2].data = &nf_frag->fqdir->high_thresh;
table[2].extra1 = &nf_frag->fqdir->low_thresh;
atomic_read(&net->ipv6.fqdir->rhashtable.nelems),
frag_mem_limit(net->ipv6.fqdir));
q = inet_frag_find(net->ipv6.fqdir, &key);
add_frag_mem_limit(fq->q.fqdir, skb->truesize);
struct net *net = fq->q.fqdir->net;
table[0].data = &net->ipv6.fqdir->high_thresh;
table[0].extra1 = &net->ipv6.fqdir->low_thresh;
table[1].data = &net->ipv6.fqdir->low_thresh;
table[1].extra2 = &net->ipv6.fqdir->high_thresh;
table[2].data = &net->ipv6.fqdir->timeout;
res = fqdir_init(&net->ipv6.fqdir, &ip6_frags, net);
net->ipv6.fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
net->ipv6.fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
net->ipv6.fqdir->timeout = IPV6_FRAG_TIMEOUT;
fqdir_exit(net->ipv6.fqdir);
fqdir_pre_exit(net->ipv6.fqdir);
fqdir_exit(net->ipv6.fqdir);
ip6frag_expire_frag_queue(fq->q.fqdir->net, fq);