diff mbox

[ovs-dev,3/3] datapath: Add support for 4.3 kernel.

Message ID 1442615016-2399-1-git-send-email-pshelar@nicira.com
State Deferred
Headers show

Commit Message

Pravin B Shelar Sept. 18, 2015, 10:23 p.m. UTC
Kernel 4.3 is not released yet, but we need this to support
netdev based vport in out of tree ovs module.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
 FAQ.md                                          |    2 +-
 acinclude.m4                                    |   11 ++++++-
 datapath/linux/compat/geneve.c                  |    3 +-
 datapath/linux/compat/gre.c                     |    2 +-
 datapath/linux/compat/gso.c                     |    5 ++-
 datapath/linux/compat/gso.h                     |   32 +++++++++++++++--------
 datapath/linux/compat/include/linux/netdevice.h |   18 +++++-------
 datapath/linux/compat/include/net/geneve.h      |    3 +-
 datapath/linux/compat/include/net/gre.h         |   10 +++++--
 datapath/linux/compat/include/net/ip_tunnels.h  |    3 +-
 datapath/linux/compat/include/net/udp_tunnel.h  |    4 ++-
 datapath/linux/compat/include/net/vxlan.h       |    4 ++-
 datapath/linux/compat/ip_tunnels_core.c         |    8 ++++-
 datapath/linux/compat/udp_tunnel.c              |    3 +-
 14 files changed, 70 insertions(+), 38 deletions(-)

Comments

Jesse Gross Sept. 24, 2015, 12:57 a.m. UTC | #1
On Fri, Sep 18, 2015 at 3:23 PM, Pravin B Shelar <pshelar@nicira.com> wrote:
> Kernel 4.3 is not released yet, but we need this to support
> netdev based vport in out of tree ovs module.
>
> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>

Just so that we're clear, this patch is an intermediate step so that
it's easier to do incremental development of the rest of the
backports, right? In particular, I assume that we'd want to stop using
the compat code for tunnels on 4.3 and use net devices?

And of course there are plenty of things that were added to OVS in 4.3
upstream in addition to this.

I understand that why we need to re-enable the various protocol
modules now but is it possible to avoid all of the supporting code? It
seems like we should be able to continue using the upstream
implementations of GSO, socket registration, etc.
Pravin B Shelar Sept. 24, 2015, 3:13 a.m. UTC | #2
On Wed, Sep 23, 2015 at 5:57 PM, Jesse Gross <jesse@nicira.com> wrote:
> On Fri, Sep 18, 2015 at 3:23 PM, Pravin B Shelar <pshelar@nicira.com> wrote:
>> Kernel 4.3 is not released yet, but we need this to support
>> netdev based vport in out of tree ovs module.
>>
>> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
>
> Just so that we're clear, this patch is an intermediate step so that
> it's easier to do incremental development of the rest of the
> backports, right? In particular, I assume that we'd want to stop using
> the compat code for tunnels on 4.3 and use net devices?
>

This is first step towards full 4.3 backport.

> And of course there are plenty of things that were added to OVS in 4.3
> upstream in addition to this.
>
> I understand that why we need to re-enable the various protocol
> modules now but is it possible to avoid all of the supporting code? It
> seems like we should be able to continue using the upstream
> implementations of GSO, socket registration, etc.

I was thinking using compat version on 4.3 for this case. since this
code will be only used when using vswitchd which creates tunnel vport
using ovs-vports rather than tunnel netdev. I am planing on changing
vswitchd so that it creates netdevs for tunnel vport. So soon this
code will be compat code. So to keep things simple I decided to go
this way. But if you want I can change the patch to use kernel tunnel
netdevice for ovs-tunnel-vport implementation.
Jesse Gross Sept. 24, 2015, 8:18 p.m. UTC | #3
On Wed, Sep 23, 2015 at 8:13 PM, Pravin Shelar <pshelar@nicira.com> wrote:
> On Wed, Sep 23, 2015 at 5:57 PM, Jesse Gross <jesse@nicira.com> wrote:
>> I understand that why we need to re-enable the various protocol
>> modules now but is it possible to avoid all of the supporting code? It
>> seems like we should be able to continue using the upstream
>> implementations of GSO, socket registration, etc.
>
> I was thinking using compat version on 4.3 for this case. since this
> code will be only used when using vswitchd which creates tunnel vport
> using ovs-vports rather than tunnel netdev. I am planing on changing
> vswitchd so that it creates netdevs for tunnel vport. So soon this
> code will be compat code. So to keep things simple I decided to go
> this way. But if you want I can change the patch to use kernel tunnel
> netdevice for ovs-tunnel-vport implementation.

I agree it makes sense to not spend a lot time worrying about
optimizing the backport on 4.3 if we won't use it. (In particular, if
we don't use netdevices we will lose GRO.) One thing that I do worry
about by not using netdevices at all in 4.3 is that it will cause the
non-compat code to diverge from upstream. (I know this is still really
compat code but it is different in the sense that it is upstream.)

Another related question is how we will maintain the protocol modules
over time? Will we convert STT and LISP to modules? And what about
backports to the modules that are upstream? (IPv6 support is something
that comes to mind as a feature in the relatively near future.) If so,
the performance will become important again.

Either way, I think my comment about trying to use the existing
supporting functions such as GSO and socket registration is still
valid and would make the code easier to understand.
Pravin B Shelar Sept. 24, 2015, 10:18 p.m. UTC | #4
On Thu, Sep 24, 2015 at 1:18 PM, Jesse Gross <jesse@nicira.com> wrote:
> On Wed, Sep 23, 2015 at 8:13 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>> On Wed, Sep 23, 2015 at 5:57 PM, Jesse Gross <jesse@nicira.com> wrote:
>>> I understand that why we need to re-enable the various protocol
>>> modules now but is it possible to avoid all of the supporting code? It
>>> seems like we should be able to continue using the upstream
>>> implementations of GSO, socket registration, etc.
>>
>> I was thinking using compat version on 4.3 for this case. since this
>> code will be only used when using vswitchd which creates tunnel vport
>> using ovs-vports rather than tunnel netdev. I am planing on changing
>> vswitchd so that it creates netdevs for tunnel vport. So soon this
>> code will be compat code. So to keep things simple I decided to go
>> this way. But if you want I can change the patch to use kernel tunnel
>> netdevice for ovs-tunnel-vport implementation.
>
> I agree it makes sense to not spend a lot time worrying about
> optimizing the backport on 4.3 if we won't use it. (In particular, if
> we don't use netdevices we will lose GRO.) One thing that I do worry
> about by not using netdevices at all in 4.3 is that it will cause the
> non-compat code to diverge from upstream. (I know this is still really
> compat code but it is different in the sense that it is upstream.)
>
> Another related question is how we will maintain the protocol modules
> over time? Will we convert STT and LISP to modules? And what about
> backports to the modules that are upstream? (IPv6 support is something
> that comes to mind as a feature in the relatively near future.) If so,
> the performance will become important again.
>
I am not targeting STT and LISP in this 4.3 patch set, Once this
backport are done, I will work on these tunnel implementation.

> Either way, I think my comment about trying to use the existing
> supporting functions such as GSO and socket registration is still
> valid and would make the code easier to understand.

OK. I agree GSO is preferred. Let me check how to make GSO work with
or without using tunnel netdev.
Jesse Gross Sept. 25, 2015, 2:11 a.m. UTC | #5
On Thu, Sep 24, 2015 at 3:18 PM, Pravin Shelar <pshelar@nicira.com> wrote:
> On Thu, Sep 24, 2015 at 1:18 PM, Jesse Gross <jesse@nicira.com> wrote:
>> On Wed, Sep 23, 2015 at 8:13 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>> On Wed, Sep 23, 2015 at 5:57 PM, Jesse Gross <jesse@nicira.com> wrote:
>>>> I understand that why we need to re-enable the various protocol
>>>> modules now but is it possible to avoid all of the supporting code? It
>>>> seems like we should be able to continue using the upstream
>>>> implementations of GSO, socket registration, etc.
>>>
>>> I was thinking using compat version on 4.3 for this case. since this
>>> code will be only used when using vswitchd which creates tunnel vport
>>> using ovs-vports rather than tunnel netdev. I am planing on changing
>>> vswitchd so that it creates netdevs for tunnel vport. So soon this
>>> code will be compat code. So to keep things simple I decided to go
>>> this way. But if you want I can change the patch to use kernel tunnel
>>> netdevice for ovs-tunnel-vport implementation.
>>
>> I agree it makes sense to not spend a lot time worrying about
>> optimizing the backport on 4.3 if we won't use it. (In particular, if
>> we don't use netdevices we will lose GRO.) One thing that I do worry
>> about by not using netdevices at all in 4.3 is that it will cause the
>> non-compat code to diverge from upstream. (I know this is still really
>> compat code but it is different in the sense that it is upstream.)
>>
>> Another related question is how we will maintain the protocol modules
>> over time? Will we convert STT and LISP to modules? And what about
>> backports to the modules that are upstream? (IPv6 support is something
>> that comes to mind as a feature in the relatively near future.) If so,
>> the performance will become important again.
>>
> I am not targeting STT and LISP in this 4.3 patch set, Once this
> backport are done, I will work on these tunnel implementation.

Even if it isn't done immediately, do you have an idea of what it
would look like long term? Not just for STT and LISP but also any
future feature backports to the tunnels that are upstream (like IPv6)?
It seems like this could be a real pain to maintain for both pre-4.3
and post-4.3 kernels.
Pravin B Shelar Sept. 25, 2015, 3:06 a.m. UTC | #6
On Thu, Sep 24, 2015 at 7:11 PM, Jesse Gross <jesse@nicira.com> wrote:
> On Thu, Sep 24, 2015 at 3:18 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>> On Thu, Sep 24, 2015 at 1:18 PM, Jesse Gross <jesse@nicira.com> wrote:
>>> On Wed, Sep 23, 2015 at 8:13 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>>> On Wed, Sep 23, 2015 at 5:57 PM, Jesse Gross <jesse@nicira.com> wrote:
>>>>> I understand that why we need to re-enable the various protocol
>>>>> modules now but is it possible to avoid all of the supporting code? It
>>>>> seems like we should be able to continue using the upstream
>>>>> implementations of GSO, socket registration, etc.
>>>>
>>>> I was thinking using compat version on 4.3 for this case. since this
>>>> code will be only used when using vswitchd which creates tunnel vport
>>>> using ovs-vports rather than tunnel netdev. I am planing on changing
>>>> vswitchd so that it creates netdevs for tunnel vport. So soon this
>>>> code will be compat code. So to keep things simple I decided to go
>>>> this way. But if you want I can change the patch to use kernel tunnel
>>>> netdevice for ovs-tunnel-vport implementation.
>>>
>>> I agree it makes sense to not spend a lot time worrying about
>>> optimizing the backport on 4.3 if we won't use it. (In particular, if
>>> we don't use netdevices we will lose GRO.) One thing that I do worry
>>> about by not using netdevices at all in 4.3 is that it will cause the
>>> non-compat code to diverge from upstream. (I know this is still really
>>> compat code but it is different in the sense that it is upstream.)
>>>
>>> Another related question is how we will maintain the protocol modules
>>> over time? Will we convert STT and LISP to modules? And what about
>>> backports to the modules that are upstream? (IPv6 support is something
>>> that comes to mind as a feature in the relatively near future.) If so,
>>> the performance will become important again.
>>>
>> I am not targeting STT and LISP in this 4.3 patch set, Once this
>> backport are done, I will work on these tunnel implementation.
>
> Even if it isn't done immediately, do you have an idea of what it
> would look like long term? Not just for STT and LISP but also any
> future feature backports to the tunnels that are upstream (like IPv6)?
> It seems like this could be a real pain to maintain for both pre-4.3
> and post-4.3 kernels.

I do not think we have option for STT and LISP but to maintain two
different code bases.
For IPv6 tunnels, I think it would be available on kernel which
support it. So only kernel from distributions which has backported
IPv6 tunnels and kernel 4.4 or newer will support such tunnels.
Jesse Gross Sept. 25, 2015, 3:37 a.m. UTC | #7
On Thu, Sep 24, 2015 at 8:06 PM, Pravin Shelar <pshelar@nicira.com> wrote:
> On Thu, Sep 24, 2015 at 7:11 PM, Jesse Gross <jesse@nicira.com> wrote:
>> On Thu, Sep 24, 2015 at 3:18 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>> I am not targeting STT and LISP in this 4.3 patch set, Once this
>>> backport are done, I will work on these tunnel implementation.
>>
>> Even if it isn't done immediately, do you have an idea of what it
>> would look like long term? Not just for STT and LISP but also any
>> future feature backports to the tunnels that are upstream (like IPv6)?
>> It seems like this could be a real pain to maintain for both pre-4.3
>> and post-4.3 kernels.
>
> I do not think we have option for STT and LISP but to maintain two
> different code bases.
> For IPv6 tunnels, I think it would be available on kernel which
> support it. So only kernel from distributions which has backported
> IPv6 tunnels and kernel 4.4 or newer will support such tunnels.

I think this would be the first feature that isn't available with the
out of tree module running on older kernels. I believe any other
limitations that we might have are strictly performance related, at
worst. If that's correct, that would make this a significant departure
and something that we shouldn't do lightly.

I wonder if it might be possible to create a shim layer (perhaps using
per-CPU data as a safe place to store things) to emulate the skb dst
changes to carry metadata around purely internal to OVS. We could then
have backports of the netdevices (or new netdevices in the case of STT
and LISP) in the OVS tree, which should be possible on all kernels.
That would seem to eliminate both problems if we can pull it off.
Pravin B Shelar Sept. 25, 2015, 4:01 a.m. UTC | #8
On Thu, Sep 24, 2015 at 8:37 PM, Jesse Gross <jesse@nicira.com> wrote:
> On Thu, Sep 24, 2015 at 8:06 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>> On Thu, Sep 24, 2015 at 7:11 PM, Jesse Gross <jesse@nicira.com> wrote:
>>> On Thu, Sep 24, 2015 at 3:18 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>>> I am not targeting STT and LISP in this 4.3 patch set, Once this
>>>> backport are done, I will work on these tunnel implementation.
>>>
>>> Even if it isn't done immediately, do you have an idea of what it
>>> would look like long term? Not just for STT and LISP but also any
>>> future feature backports to the tunnels that are upstream (like IPv6)?
>>> It seems like this could be a real pain to maintain for both pre-4.3
>>> and post-4.3 kernels.
>>
>> I do not think we have option for STT and LISP but to maintain two
>> different code bases.
>> For IPv6 tunnels, I think it would be available on kernel which
>> support it. So only kernel from distributions which has backported
>> IPv6 tunnels and kernel 4.4 or newer will support such tunnels.
>
> I think this would be the first feature that isn't available with the
> out of tree module running on older kernels. I believe any other
> limitations that we might have are strictly performance related, at
> worst. If that's correct, that would make this a significant departure
> and something that we shouldn't do lightly.
>
ok, Lets revisit it once IPv6 support is merged upstream.

> I wonder if it might be possible to create a shim layer (perhaps using
> per-CPU data as a safe place to store things) to emulate the skb dst
> changes to carry metadata around purely internal to OVS. We could then
> have backports of the netdevices (or new netdevices in the case of STT
> and LISP) in the OVS tree, which should be possible on all kernels.
> That would seem to eliminate both problems if we can pull it off.

This is good idea!
I need to check if skb processing can be migrated to different CPU by
flow steering in our case.
Pravin B Shelar Sept. 25, 2015, 7:47 a.m. UTC | #9
On Thu, Sep 24, 2015 at 9:01 PM, Pravin Shelar <pshelar@nicira.com> wrote:
> On Thu, Sep 24, 2015 at 8:37 PM, Jesse Gross <jesse@nicira.com> wrote:
>> On Thu, Sep 24, 2015 at 8:06 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>> On Thu, Sep 24, 2015 at 7:11 PM, Jesse Gross <jesse@nicira.com> wrote:
>>>> On Thu, Sep 24, 2015 at 3:18 PM, Pravin Shelar <pshelar@nicira.com> wrote:
>>>>> I am not targeting STT and LISP in this 4.3 patch set, Once this
>>>>> backport are done, I will work on these tunnel implementation.
>>>>
>>>> Even if it isn't done immediately, do you have an idea of what it
>>>> would look like long term? Not just for STT and LISP but also any
>>>> future feature backports to the tunnels that are upstream (like IPv6)?
>>>> It seems like this could be a real pain to maintain for both pre-4.3
>>>> and post-4.3 kernels.
>>>
>>> I do not think we have option for STT and LISP but to maintain two
>>> different code bases.
>>> For IPv6 tunnels, I think it would be available on kernel which
>>> support it. So only kernel from distributions which has backported
>>> IPv6 tunnels and kernel 4.4 or newer will support such tunnels.
>>
>> I think this would be the first feature that isn't available with the
>> out of tree module running on older kernels. I believe any other
>> limitations that we might have are strictly performance related, at
>> worst. If that's correct, that would make this a significant departure
>> and something that we shouldn't do lightly.
>>
> ok, Lets revisit it once IPv6 support is merged upstream.
>
>> I wonder if it might be possible to create a shim layer (perhaps using
>> per-CPU data as a safe place to store things) to emulate the skb dst
>> changes to carry metadata around purely internal to OVS. We could then
>> have backports of the netdevices (or new netdevices in the case of STT
>> and LISP) in the OVS tree, which should be possible on all kernels.
>> That would seem to eliminate both problems if we can pull it off.
>
> This is good idea!
> I need to check if skb processing can be migrated to different CPU by
> flow steering in our case.

I gave it some more thought and I see following issues with using
per-cpu data to pass skb-dst.
1. Pre-emptive kernel.
2. Flow steering - RPS
3. skb async processing --- netdev backlog queue. There can be
multiple skb in queue  between tunnel device and OVS.

3rd issue is show stopper for per-cpu data structure. So now I am
exploring other data structure around this idea.
diff mbox

Patch

diff --git a/FAQ.md b/FAQ.md
index 512bd2c..d51a0f5 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -156,7 +156,7 @@  A: The following table lists the Linux kernel versions against which the
 |    2.1.x     | 2.6.32 to 3.11
 |    2.3.x     | 2.6.32 to 3.14
 |    2.4.x     | 2.6.32 to 4.0
-|    2.5.x     | 2.6.32 to 4.2
+|    2.5.x     | 2.6.32 to 4.3
 
    Open vSwitch userspace should also work with the Linux kernel module
    built into Linux 3.3 and later.
diff --git a/acinclude.m4 b/acinclude.m4
index 42d1f45..ef61c7d 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -134,10 +134,10 @@  AC_DEFUN([OVS_CHECK_LINUX], [
     AC_MSG_RESULT([$kversion])
 
     if test "$version" -ge 4; then
-       if test "$version" = 4 && test "$patchlevel" -le 2; then
+       if test "$version" = 4 && test "$patchlevel" -le 3; then
           : # Linux 4.x
        else
-          AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.2.x is not supported (please refer to the FAQ for advice)])
+          AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.3.x is not supported (please refer to the FAQ for advice)])
        fi
     elif test "$version" = 3; then
        : # Linux 3.x
@@ -329,6 +329,9 @@  AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/linux/in.h], [proto_ports_offset])
   OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [__ip_select_ident.*dst_entry],
                   [OVS_DEFINE([HAVE_IP_SELECT_IDENT_USING_DST_ENTRY])])
+  OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [__ip_select_ident.*net],
+                  [OVS_DEFINE([HAVE_IP_SELECT_IDENT_USING_NET])])
+
   OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [inet_get_local_port_range.*net],
                   [OVS_DEFINE([HAVE_INET_GET_LOCAL_PORT_RANGE_USING_NET])])
   OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [ip_is_fragment])
@@ -346,6 +349,9 @@  AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [net_device_extended])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [rx_handler_func_t.*pskb],
                   [OVS_DEFINE([HAVE_RX_HANDLER_PSKB])])
+  OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [netif_needs_gso.*net_device],
+                  [OVS_DEFINE([HAVE_NETIF_NEEDS_GSO_NETDEV])])
+
   OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hookfn.*nf_hook_ops],
                   [OVS_DEFINE([HAVE_NF_HOOKFN_ARG_OPS])])
 
@@ -422,6 +428,7 @@  AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/net/geneve.h], [geneve_hdr])
 
   OVS_GREP_IFELSE([$KSRC/include/net/gre.h], [gre_cisco_register])
+  OVS_GREP_IFELSE([$KSRC/include/net/gre.h], [gre_handle_offloads])
   OVS_GREP_IFELSE([$KSRC/include/net/ipv6.h], [IP6_FH_F_SKIP_RH])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be16])
diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 85cf95f..2723b0d 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -12,7 +12,8 @@ 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 
 #include <linux/kernel.h>
 #include <linux/types.h>
diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
index fe81380..de1dbaf 100644
--- a/datapath/linux/compat/gre.c
+++ b/datapath/linux/compat/gre.c
@@ -40,7 +40,7 @@ 
 
 #if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
 
 #ifndef HAVE_GRE_CISCO_REGISTER
 
diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c
index 2c19b58..d11c62e 100644
--- a/datapath/linux/compat/gso.c
+++ b/datapath/linux/compat/gso.c
@@ -130,7 +130,7 @@  int rpl_dev_queue_xmit(struct sk_buff *skb)
 		if (mpls)
 			features &= NETIF_F_SG;
 
-		if (netif_needs_gso(skb->dev, skb, features)) {
+		if (netif_needs_gso(skb, features)) {
 			struct sk_buff *nskb;
 
 			nskb = skb_gso_segment(skb, features);
@@ -170,7 +170,8 @@  drop:
 EXPORT_SYMBOL_GPL(rpl_dev_queue_xmit);
 #endif /* OVS_USE_COMPAT_GSO_SEGMENTATION */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 static __be16 __skb_network_protocol(struct sk_buff *skb)
 {
 	__be16 type = skb->protocol;
diff --git a/datapath/linux/compat/gso.h b/datapath/linux/compat/gso.h
index 6fcaff8..bf409cf 100644
--- a/datapath/linux/compat/gso.h
+++ b/datapath/linux/compat/gso.h
@@ -2,7 +2,8 @@ 
 #define __LINUX_GSO_WRAPPER_H
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
@@ -14,13 +15,10 @@  typedef void (*gso_fix_segment_t)(struct sk_buff *);
 struct ovs_gso_cb {
 	struct ovs_skb_cb dp_cb;
 	gso_fix_segment_t fix_segment;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 	__be16		inner_protocol;
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
 	unsigned int	inner_mac_header;
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
 	unsigned int	inner_network_header;
 #endif
 };
@@ -37,12 +35,15 @@  static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
+#define skb_inner_mac_header rpl_skb_inner_mac_header
 static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
 {
 	return skb->head + OVS_GSO_CB(skb)->inner_mac_header;
 }
 
+#define skb_set_inner_mac_header rpl_skb_set_inner_mac_header
 static inline void skb_set_inner_mac_header(const struct sk_buff *skb,
 					    int offset)
 {
@@ -50,12 +51,15 @@  static inline void skb_set_inner_mac_header(const struct sk_buff *skb,
 }
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
+#define skb_inner_network_header rpl_skb_inner_network_header
 static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
 {
 	return skb->head + OVS_GSO_CB(skb)->inner_network_header;
 }
 
+#define skb_inner_network_offset rpl_skb_inner_network_offset
 static inline int skb_inner_network_offset(const struct sk_buff *skb)
 {
 	return skb_inner_network_header(skb) - skb->data;
@@ -70,6 +74,7 @@  static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
 	return 0;
 }
 
+#define skb_set_inner_network_header rpl_skb_set_inner_network_header
 static inline void skb_set_inner_network_header(const struct sk_buff *skb,
 						int offset)
 {
@@ -77,6 +82,7 @@  static inline void skb_set_inner_network_header(const struct sk_buff *skb,
 						+ offset;
 }
 
+#define skb_set_inner_transport_header rpl_skb_set_inner_transport_header
 static inline void skb_set_inner_transport_header(const struct sk_buff *skb,
 						  int offset)
 { }
@@ -90,7 +96,8 @@  static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
 
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
 	OVS_GSO_CB(skb)->inner_protocol = htons(0);
 }
@@ -114,7 +121,8 @@  static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
 	 */
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
 					      __be16 ethertype)
 {
@@ -134,10 +142,12 @@  static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
 }
 #endif /* 3.11 */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) ||\
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 #define ip_local_out rpl_ip_local_out
 int rpl_ip_local_out(struct sk_buff *skb);
 
+#define skb_inner_mac_offset rpl_skb_inner_mac_offset
 static inline int skb_inner_mac_offset(const struct sk_buff *skb)
 {
 	return skb_inner_mac_header(skb) - skb->data;
diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h
index 0fb2144..a2f7eb9 100644
--- a/datapath/linux/compat/include/linux/netdevice.h
+++ b/datapath/linux/compat/include/linux/netdevice.h
@@ -88,7 +88,8 @@  static inline struct net_device *dev_get_by_index_rcu(struct net *net, int ifind
 typedef u32 netdev_features_t;
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 #define OVS_USE_COMPAT_GSO_SEGMENTATION
 #endif
 
@@ -112,18 +113,15 @@  struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, netdev_features_t featu
 netdev_features_t rpl_netif_skb_features(struct sk_buff *skb);
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
-static inline int rpl_netif_needs_gso(struct net_device *dev,
-				      struct sk_buff *skb, int features)
+#ifdef HAVE_NETIF_NEEDS_GSO_NETDEV
+#define netif_needs_gso rpl_netif_needs_gso
+static inline bool netif_needs_gso(struct sk_buff *skb,
+				   netdev_features_t features)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
 	return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
-		unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
-#else
-	return netif_needs_gso(skb, features);
-#endif
+		unlikely((skb->ip_summed != CHECKSUM_PARTIAL) &&
+			 (skb->ip_summed != CHECKSUM_UNNECESSARY)));
 }
-#define netif_needs_gso rpl_netif_needs_gso
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
diff --git a/datapath/linux/compat/include/net/geneve.h b/datapath/linux/compat/include/net/geneve.h
index 4f250c2..116ebc7 100644
--- a/datapath/linux/compat/include/net/geneve.h
+++ b/datapath/linux/compat/include/net/geneve.h
@@ -3,7 +3,8 @@ 
 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) && \
+    defined(HAVE_GRE_HANDLE_OFFLOADS)
 #include_next <net/geneve.h>
 #else
 
diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h
index 6e0df0f..040fd11 100644
--- a/datapath/linux/compat/include/net/gre.h
+++ b/datapath/linux/compat/include/net/gre.h
@@ -28,13 +28,17 @@  int rpl_gre_cisco_register(struct gre_cisco_protocol *proto);
 #define gre_cisco_unregister rpl_gre_cisco_unregister
 int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
+#ifndef GRE_HEADER_SECTION
 struct gre_base_hdr {
 	__be16 flags;
 	__be16 protocol;
 };
 #define GRE_HEADER_SECTION 4
 
+#endif
+
+#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags
 static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
 {
 	__be16 tflags = 0;
@@ -57,6 +61,7 @@  static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
 	return tflags;
 }
 
+#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags
 static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
 {
 	__be16 flags = 0;
@@ -84,8 +89,7 @@  static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
 #define gre_handle_offloads rpl_gre_handle_offloads
 struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
-
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
 #define gre_build_header rpl_gre_build_header
 void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
 		          int hdr_len);
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 3ed6f91..0ca086f 100644
--- a/datapath/linux/compat/include/net/ip_tunnels.h
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
@@ -7,7 +7,8 @@ 
 #include_next <net/ip_tunnels.h>
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 
 #include <linux/if_tunnel.h>
 #include <linux/netdevice.h>
diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h
index d334746..21d05ff 100644
--- a/datapath/linux/compat/include/net/udp_tunnel.h
+++ b/datapath/linux/compat/include/net/udp_tunnel.h
@@ -4,7 +4,9 @@ 
 #include <linux/version.h>
 #include <linux/kconfig.h>
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) && \
+    defined(HAVE_GRE_HANDLE_OFFLOADS)
+
 #include_next <net/udp_tunnel.h>
 
 static inline struct sk_buff *
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index cafff79..1a85a17 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -8,7 +8,9 @@ 
 
 #include <linux/version.h>
 
-#ifdef HAVE_VXLAN_METADATA
+/* gre_handle_offload is not defined on kernel with netdev-vport support
+ * Use this as way to switch between compatibility implementations. */
+#if defined(HAVE_VXLAN_METADATA) && defined(HAVE_GRE_HANDLE_OFFLOADS)
 #define USE_UPSTREAM_VXLAN
 
 #include_next <net/vxlan.h>
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index 8ff7cd7..05c8564 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -35,7 +35,8 @@ 
 #include "compat.h"
 #include "gso.h"
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
                       __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl,
                       __be16 df, bool xnet)
@@ -71,6 +72,9 @@  int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 
 #ifdef HAVE_IP_SELECT_IDENT_USING_DST_ENTRY
 	__ip_select_ident(iph, &rt_dst(rt), (skb_shinfo(skb)->gso_segs ?: 1) - 1);
+#elif defined(HAVE_IP_SELECT_IDENT_USING_NET)
+	__ip_select_ident(dev_net(rt->dst.dev), iph,
+			  skb_shinfo(skb)->gso_segs ?: 1);
 #else
 	__ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1);
 #endif
@@ -84,7 +88,7 @@  EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit);
 
 struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
 					     bool csum_help, int gso_type_mask,
-				             void (*fix_segment)(struct sk_buff *))
+					     void (*fix_segment)(struct sk_buff *))
 {
 	int err;
 
diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c
index a3223fd..ff27ee0 100644
--- a/datapath/linux/compat/udp_tunnel.c
+++ b/datapath/linux/compat/udp_tunnel.c
@@ -1,6 +1,7 @@ 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) || \
+    !defined(HAVE_GRE_HANDLE_OFFLOADS)
 
 #include <linux/module.h>
 #include <linux/errno.h>