compat: Detect and use inet_frags->frags_work.
authorJoe Stringer <joe@ovn.org>
Thu, 24 Dec 2015 18:54:37 +0000 (10:54 -0800)
committerJoe Stringer <joe@ovn.org>
Tue, 2 Feb 2016 22:26:45 +0000 (14:26 -0800)
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>
acinclude.m4
datapath/linux/compat/include/net/inet_frag.h
datapath/linux/compat/inet_fragment.c
datapath/linux/compat/ip_fragment.c
datapath/linux/compat/nf_conntrack_reasm.c

index e99ab01..3e44abb 100644 (file)
@@ -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])
 
index 0c0c076..2708cdd 100644 (file)
@@ -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
index 3232268..15321de 100644 (file)
@@ -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,
@@ -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
 
@@ -218,16 +218,16 @@ 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;
@@ -235,7 +235,7 @@ int inet_frags_init(struct inet_frags *f)
 
 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
@@ -243,14 +243,7 @@ void inet_frags_fini(struct inet_frags *f)
 
 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;
@@ -268,6 +261,13 @@ evict_again:
            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 *
@@ -363,10 +363,10 @@ 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);
@@ -374,7 +374,14 @@ void rpl_inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f)
 
 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;
 
@@ -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
 }
 
@@ -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;
@@ -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);
@@ -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;
index 42514e4..3815067 100644 (file)
@@ -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)) {
index 1e207b1..89a3978 100644 (file)
@@ -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);