Skip to content

Commit

Permalink
compat: Detect and use inet_frags->frags_work.
Browse files Browse the repository at this point in the history
Kernels 3.17 and newer have a work queue to evict old fragments, while
older kernel versions use an LRU in the fast path; see upstream commit
b13d3cbfb8e8 ("inet: frag: move eviction of queues to work queue").
This commit fixes the version checking so that rather than enabling the
code for either of these approaches using version checks, it is
triggered based on the presence of the work queue in "struct inet_frags".

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
  • Loading branch information
joestringer committed Feb 2, 2016
1 parent 30ed3d0 commit 1efdc8a
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 40 deletions.
2 changes: 2 additions & 0 deletions acinclude.m4
Expand Up @@ -355,6 +355,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
[OVS_DEFINE([HAVE_INET_FRAGS_CONST])])
OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [last_in],
[OVS_DEFINE([HAVE_INET_FRAGS_LAST_IN])])
OVS_FIND_FIELD_IFELSE([$KSRC/include/net/inet_frag.h], [inet_frags],
[frags_work])
OVS_GREP_IFELSE([$KSRC/include/net/dst_metadata.h], [metadata_dst])
Expand Down
6 changes: 3 additions & 3 deletions datapath/linux/compat/include/net/inet_frag.h
Expand Up @@ -36,11 +36,11 @@ struct ovs_inet_frag_queue {

static inline bool rpl_inet_frag_evicting(struct inet_frag_queue *q)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != NULL;
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
struct ovs_inet_frag_queue *ofq = (struct ovs_inet_frag_queue *)q;
return !hlist_unhashed(&ofq->list_evictor);
#else
return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != NULL;
#endif
}
#define inet_frag_evicting rpl_inet_frag_evicting
Expand Down
70 changes: 35 additions & 35 deletions datapath/linux/compat/inet_fragment.c
Expand Up @@ -61,7 +61,7 @@ inet_frag_hashfn(const struct inet_frags *f, struct inet_frag_queue *q)
return f->hashfn(q) & (INETFRAGS_HASHSZ - 1);
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
static bool inet_frag_may_rebuild(struct inet_frags *f)
{
return time_after(jiffies,
Expand Down Expand Up @@ -207,7 +207,7 @@ int inet_frags_init(struct inet_frags *f)
{
int i;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
INIT_WORK(&f->frags_work, inet_frag_worker);
#endif

Expand All @@ -218,39 +218,32 @@ int inet_frags_init(struct inet_frags *f)
INIT_HLIST_HEAD(&hb->chain);
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
rwlock_init(&f->lock);
f->secret_timer.expires = jiffies + f->secret_interval;
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
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;
#else
rwlock_init(&f->lock);
f->secret_timer.expires = jiffies + f->secret_interval;
#endif

return 0;
}

void inet_frags_fini(struct inet_frags *f)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
cancel_work_sync(&f->frags_work);
kmem_cache_destroy(f->frags_cachep);
#endif
}

int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force);

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
{
read_lock_bh(&f->lock);
inet_frag_evictor(nf, f, true);
read_unlock_bh(&f->lock);
}
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
{
unsigned int seq;
Expand All @@ -268,6 +261,13 @@ void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
percpu_counter_sum(&nf->mem))
goto evict_again;
}
#else
void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f)
{
read_lock_bh(&f->lock);
inet_frag_evictor(nf, f, true);
read_unlock_bh(&f->lock);
}
#endif

static struct inet_frag_bucket *
Expand Down Expand Up @@ -363,18 +363,25 @@ void rpl_inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)

if (f->destructor)
f->destructor(q);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
kfree(q);
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
kmem_cache_free(f->frags_cachep, q);
#else
kfree(q);
#endif

sub_frag_mem_limit(nf, sum);
}

int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
int i;

for (i = 0; i < INETFRAGS_HASHSZ ; i++)
inet_evict_bucket(f, &f->hash[i]);

return 0;
#else
struct inet_frag_queue *q;
int work, evicted = 0;

Expand Down Expand Up @@ -406,13 +413,6 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force)
}

return evicted;
#else
int i;

for (i = 0; i < INETFRAGS_HASHSZ ; i++)
inet_evict_bucket(f, &f->hash[i]);

return 0;
#endif
}

Expand Down Expand Up @@ -464,16 +464,16 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
struct inet_frag_queue *q;

if (frag_mem_limit(nf) > nf->high_thresh) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
inet_frag_schedule_worker(f);
#endif
return NULL;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
q = kzalloc(f->qsize, GFP_ATOMIC);
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC);
#else
q = kzalloc(f->qsize, GFP_ATOMIC);
#endif
if (!q)
return NULL;
Expand Down Expand Up @@ -510,12 +510,12 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
struct inet_frag_queue *q;
int depth = 0;

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
if (frag_mem_limit(nf) > nf->high_thresh)
inet_frag_evictor(nf, f, false);
#else
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
if (frag_mem_limit(nf) > nf->low_thresh)
inet_frag_schedule_worker(f);
#else
if (frag_mem_limit(nf) > nf->high_thresh)
inet_frag_evictor(nf, f, false);
#endif

hash &= (INETFRAGS_HASHSZ - 1);
Expand All @@ -535,7 +535,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
if (depth <= INETFRAGS_MAXDEPTH)
return inet_frag_create(nf, f, key);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
if (inet_frag_may_rebuild(f)) {
if (!f->rebuild)
f->rebuild = true;
Expand Down
2 changes: 1 addition & 1 deletion datapath/linux/compat/ip_fragment.c
Expand Up @@ -731,7 +731,7 @@ int __init rpl_ipfrag_init(void)
ip4_frags.qsize = sizeof(struct ipq);
ip4_frags.match = ip4_frag_match;
ip4_frags.frag_expire = ip_expire;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
ip4_frags.frags_cache_name = ip_frag_cache_name;
#endif
if (inet_frags_init(&ip4_frags)) {
Expand Down
2 changes: 1 addition & 1 deletion datapath/linux/compat/nf_conntrack_reasm.c
Expand Up @@ -631,7 +631,7 @@ int rpl_nf_ct_frag6_init(void)
nf_frags.qsize = sizeof(struct frag_queue);
nf_frags.match = rpl_ip6_frag_match;
nf_frags.frag_expire = nf_ct_frag6_expire;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
#ifdef HAVE_INET_FRAGS_WITH_FRAGS_WORK
nf_frags.frags_cache_name = nf_frags_cache_name;
#endif
ret = inet_frags_init(&nf_frags);
Expand Down

0 comments on commit 1efdc8a

Please sign in to comment.