Skip to content

Commit

Permalink
Merge branch 'inet-frags-next'
Browse files Browse the repository at this point in the history
Nikolay Aleksandrov says:

====================
inet: frags: cleanup and kmem_cache use

This patchset does a couple of small cleanups in patches 1-5 and then in
patch 06 it introduces the use of kmem_cache for allocation/freeing of
inet_frag_queue+header objects.

v2: Broke up patch 02 into 3 patches as David suggested

Here are the results of a couple of netperf runs:
netperf options: -l 30 -I95,5 -i 15,10 -m 64k

- 10 gig before the patchset
MIGRATED UDP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.155.1 () port 0 AF_INET : +/-2.500% @ 95% conf.
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec

212992   64000   30.00      442466      0    7551.39
212992           30.00      439130           7494.45

- 10 gig after the patchset
MIGRATED UDP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.155.1 () port 0 AF_INET : +/-2.500% @ 95% conf.
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec

212992   64000   30.00      458846      0    7830.94
212992           30.00      457575           7809.25

- Virtio before the patchset
MIGRATED UDP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.144.1 () port 0 AF_INET : +/-2.500% @ 95% conf.
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec

212992   64000   30.00      735000      0    12543.96
212992           30.00      560322           9562.79

- Virtio after the patchset
MIGRATED UDP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.144.1 () port 0 AF_INET : +/-2.500% @ 95% conf.
Socket  Message  Elapsed      Messages
Size    Size     Time         Okay Errors   Throughput
bytes   bytes    secs            #      #   10^6bits/sec

212992   64000   30.00      731729      0    12488.14
212992           30.00      647241           11046.21
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 2, 2014
2 parents a5536e1 + d4ad4d2 commit 7e32aa4
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 79 deletions.
50 changes: 38 additions & 12 deletions include/net/inet_frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,49 @@ struct netns_frags {
int low_thresh;
};

/**
* fragment queue flags
*
* @INET_FRAG_FIRST_IN: first fragment has arrived
* @INET_FRAG_LAST_IN: final fragment has arrived
* @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
* @INET_FRAG_EVICTED: frag queue is being evicted
*/
enum {
INET_FRAG_FIRST_IN = BIT(0),
INET_FRAG_LAST_IN = BIT(1),
INET_FRAG_COMPLETE = BIT(2),
INET_FRAG_EVICTED = BIT(3)
};

/**
* struct inet_frag_queue - fragment queue
*
* @lock: spinlock protecting the queue
* @timer: queue expiration timer
* @list: hash bucket list
* @refcnt: reference count of the queue
* @fragments: received fragments head
* @fragments_tail: received fragments tail
* @stamp: timestamp of the last received fragment
* @len: total length of the original datagram
* @meat: length of received fragments so far
* @flags: fragment queue flags
* @max_size: (ipv4 only) maximum received fragment size with IP_DF set
* @net: namespace that this frag belongs to
*/
struct inet_frag_queue {
spinlock_t lock;
struct timer_list timer; /* when will this queue expire? */
struct timer_list timer;
struct hlist_node list;
atomic_t refcnt;
struct sk_buff *fragments; /* list of received fragments */
struct sk_buff *fragments;
struct sk_buff *fragments_tail;
ktime_t stamp;
int len; /* total length of orig datagram */
int len;
int meat;
__u8 last_in; /* first/last segment arrived? */

#define INET_FRAG_EVICTED 8
#define INET_FRAG_COMPLETE 4
#define INET_FRAG_FIRST_IN 2
#define INET_FRAG_LAST_IN 1

__u8 flags;
u16 max_size;

struct netns_frags *net;
};

Expand Down Expand Up @@ -77,9 +101,11 @@ struct inet_frags {
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);
Expand Down
21 changes: 13 additions & 8 deletions net/ieee802154/reassembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#include "reassembly.h"

static const char lowpan_frags_cache_name[] = "lowpan-frags";

struct lowpan_frag_info {
__be16 d_tag;
u16 d_size;
Expand Down Expand Up @@ -99,7 +101,7 @@ static void lowpan_frag_expire(unsigned long data)

spin_lock(&fq->q.lock);

if (fq->q.last_in & INET_FRAG_COMPLETE)
if (fq->q.flags & INET_FRAG_COMPLETE)
goto out;

inet_frag_kill(&fq->q, &lowpan_frags);
Expand Down Expand Up @@ -142,7 +144,7 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
struct net_device *dev;
int end, offset;

if (fq->q.last_in & INET_FRAG_COMPLETE)
if (fq->q.flags & INET_FRAG_COMPLETE)
goto err;

offset = lowpan_cb(skb)->d_offset << 3;
Expand All @@ -154,14 +156,14 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
* or have different end, the segment is corrupted.
*/
if (end < fq->q.len ||
((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len))
((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len))
goto err;
fq->q.last_in |= INET_FRAG_LAST_IN;
fq->q.flags |= INET_FRAG_LAST_IN;
fq->q.len = end;
} else {
if (end > fq->q.len) {
/* Some bits beyond end -> corruption. */
if (fq->q.last_in & INET_FRAG_LAST_IN)
if (fq->q.flags & INET_FRAG_LAST_IN)
goto err;
fq->q.len = end;
}
Expand Down Expand Up @@ -201,13 +203,13 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
if (frag_type == LOWPAN_DISPATCH_FRAG1) {
/* Calculate uncomp. 6lowpan header to estimate full size */
fq->q.meat += lowpan_uncompress_size(skb, NULL);
fq->q.last_in |= INET_FRAG_FIRST_IN;
fq->q.flags |= INET_FRAG_FIRST_IN;
} else {
fq->q.meat += skb->len;
}
add_frag_mem_limit(&fq->q, skb->truesize);

if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
fq->q.meat == fq->q.len) {
int res;
unsigned long orefdst = skb->_skb_refdst;
Expand Down Expand Up @@ -571,7 +573,10 @@ int __init lowpan_net_frag_init(void)
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:
Expand Down
41 changes: 25 additions & 16 deletions net/ipv4/inet_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,7 @@ inet_evict_bucket(struct inet_frags *f, struct inet_frag_bucket *hb)
goto evict_again;
}

/* suppress xmit of (icmp) error packet */
fq->last_in &= ~INET_FRAG_FIRST_IN;
fq->last_in |= INET_FRAG_EVICTED;
fq->flags |= INET_FRAG_EVICTED;
hlist_del(&fq->list);
hlist_add_head(&fq->list, &expired);
++evicted;
Expand Down Expand Up @@ -200,7 +198,7 @@ static void inet_frag_schedule_worker(struct inet_frags *f)
schedule_work(&f->frags_work);
}

void inet_frags_init(struct inet_frags *f)
int inet_frags_init(struct inet_frags *f)
{
int i;

Expand All @@ -215,6 +213,12 @@ void inet_frags_init(struct inet_frags *f)

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);

Expand All @@ -227,6 +231,7 @@ EXPORT_SYMBOL(inet_frags_init_net);
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);

Expand Down Expand Up @@ -289,16 +294,16 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f)
if (del_timer(&fq->timer))
atomic_dec(&fq->refcnt);

if (!(fq->last_in & INET_FRAG_COMPLETE)) {
if (!(fq->flags & INET_FRAG_COMPLETE)) {
fq_unlink(fq, f);
atomic_dec(&fq->refcnt);
fq->last_in |= INET_FRAG_COMPLETE;
fq->flags |= INET_FRAG_COMPLETE;
}
}
EXPORT_SYMBOL(inet_frag_kill);

static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f,
struct sk_buff *skb)
struct sk_buff *skb)
{
if (f->skb_free)
f->skb_free(skb);
Expand All @@ -311,7 +316,7 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)
struct netns_frags *nf;
unsigned int sum, sum_truesize = 0;

WARN_ON(!(q->last_in & INET_FRAG_COMPLETE));
WARN_ON(!(q->flags & INET_FRAG_COMPLETE));
WARN_ON(del_timer(&q->timer) != 0);

/* Release all fragment data. */
Expand All @@ -329,13 +334,14 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)

if (f->destructor)
f->destructor(q);
kfree(q);
kmem_cache_free(f->frags_cachep, q);
}
EXPORT_SYMBOL(inet_frag_destroy);

static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
struct inet_frag_queue *qp_in, struct inet_frags *f,
void *arg)
struct inet_frag_queue *qp_in,
struct inet_frags *f,
void *arg)
{
struct inet_frag_bucket *hb = get_frag_bucket_locked(qp_in, f);
struct inet_frag_queue *qp;
Expand All @@ -349,7 +355,7 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
if (qp->net == nf && f->match(qp, arg)) {
atomic_inc(&qp->refcnt);
spin_unlock(&hb->chain_lock);
qp_in->last_in |= INET_FRAG_COMPLETE;
qp_in->flags |= INET_FRAG_COMPLETE;
inet_frag_put(qp_in, f);
return qp;
}
Expand All @@ -368,7 +374,8 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
}

static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
struct inet_frags *f, void *arg)
struct inet_frags *f,
void *arg)
{
struct inet_frag_queue *q;

Expand All @@ -377,7 +384,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
return NULL;
}

q = kzalloc(f->qsize, GFP_ATOMIC);
q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC);
if (q == NULL)
return NULL;

Expand All @@ -393,7 +400,8 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
}

static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
struct inet_frags *f, void *arg)
struct inet_frags *f,
void *arg)
{
struct inet_frag_queue *q;

Expand All @@ -405,7 +413,8 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
}

struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
struct inet_frags *f, void *key, unsigned int hash)
struct inet_frags *f, void *key,
unsigned int hash)
{
struct inet_frag_bucket *hb;
struct inet_frag_queue *q;
Expand Down
Loading

0 comments on commit 7e32aa4

Please sign in to comment.