On 5/31/2018 9:06 AM, Darrell Ball wrote:


On Thu, May 31, 2018 at 8:32 AM, Greg Rose <gvrose8...@gmail.com <mailto:gvrose8...@gmail.com>> wrote:

    A recent patch series added support for ERSPAN but left some problems
    remaining for kernel releases from 4.10 to 4.14.  This patch
    addresses those problems.

    Of note is that the old cisco gre compat layer code is gone for good.

    Also, several compat defines in acinclude.m4 were looking for keys
    in .c source files - this does not work on distros without source
    code.  A more reliable key was already defined so we use that instead.

    We have pared support for the Linux kernel releases in .travis.yml
    to reflect that 4.15 is no longer in the LTS list.  With this patch
    the Out of Tree OVS datapath kernel modules can build on kernels
    up to 4.14.47.  Support for kernels up to 4.16.x will be added
    later.

    There are still clang warnings from Travis:
    lib/netdev-native-tnl.c:666:17: error: cast from 'struct
    erspan_base_hdr *' to 'ovs_be32 *' (aka 'unsigned int *')
    increases required alignment from 1 to 4 [-Werror,-Wcast-align]
            index = (ovs_be32 *)(ersh + 1);



Hi Greg

The above code no longer exists in the repo.
I suspect whatever branch you used to push to your git repo is not up to date.

Darrell

I rebased to master and see that now.  Good!

Thanks,

- Greg




    I will post a follow on patch to fix that so we can have clean Travis
    builds again.

    Signed-off-by: Greg Rose <gvrose8...@gmail.com
    <mailto:gvrose8...@gmail.com>>
    ---
     .travis.yml                                        |  11 +-
     acinclude.m4                                       |  15 +--
     datapath/linux/compat/geneve.c                     |  15 +++
     datapath/linux/compat/gre.c                        | 149
    ---------------------
     datapath/linux/compat/include/linux/compiler-gcc.h |   5 +
     datapath/linux/compat/include/net/dst_metadata.h  |   4 +-
     datapath/linux/compat/include/net/erspan.h  |   2 +-
     datapath/linux/compat/include/net/gre.h |   2 +
     datapath/linux/compat/include/net/ip_tunnels.h  |  20 ++-
     datapath/linux/compat/ip6_gre.c |  46 ++++---
     datapath/linux/compat/ip6_tunnel.c  |  19 +--
     datapath/linux/compat/ip_gre.c                     | 118
    +++++++---------
     datapath/linux/compat/ip_tunnel.c |   2 +
     datapath/linux/compat/ip_tunnels_core.c |  25 +++-
     datapath/linux/compat/vxlan.c                      |  18 ++-
     15 files changed, 176 insertions(+), 275 deletions(-)

    diff --git a/.travis.yml b/.travis.yml
    index cf37e8c..ff2fa2e 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -33,12 +33,11 @@ env:
       - BUILD_ENV="-m32" OPTS="--disable-ssl"
       - KERNEL=3.16.54 DPDK=1
       - KERNEL=3.16.54 DPDK=1 OPTS="--enable-shared"
    -  - KERNEL=4.15.3
    -  - KERNEL=4.14.19
    -  - KERNEL=4.9.81
    -  - KERNEL=4.4.115
    -  - KERNEL=4.1.49
    -  - KERNEL=3.10.108
    +  - KERNEL=4.14.47
    +  - KERNEL=4.9.105
    +  - KERNEL=4.4.135
    +  - KERNEL=4.1.52
    +  - KERNEL=3.16.56
       - TESTSUITE=1 LIBS=-ljemalloc

     matrix:
    diff --git a/acinclude.m4 b/acinclude.m4
    index 2351792..7a653cb 100644
    --- a/acinclude.m4
    +++ b/acinclude.m4
    @@ -151,10 +151,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
         AC_MSG_RESULT([$kversion])

         if test "$version" -ge 4; then
    -       if test "$version" = 4 && test "$patchlevel" -le 15; then
    +       if test "$version" = 4 && test "$patchlevel" -le 14; then
               : # Linux 4.x
            else
    -          AC_ERROR([Linux kernel in $KBUILD is version $kversion,
    but version newer than 4.15.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.14.x is not supported (please refer to
    the FAQ for advice)])
            fi
         elif test "$version" = 3 && test "$patchlevel" -ge 10; then
            : # Linux 3.x
    @@ -828,12 +828,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
       OVS_FIND_FIELD_IFELSE([$KSRC/include/linux/netdevice.h],
    [net_device],
                             [max_mtu],
                             [OVS_DEFINE([HAVE_NET_DEVICE_MAX_MTU])])
    -  OVS_GREP_IFELSE([$KSRC/include/net/erspan.h],
    -                  [__LINUX_ERSPAN_H],
    -                  [OVS_DEFINE([HAVE_LINUX_ERSPAN_H])])
    -  OVS_FIND_PARAM_IFELSE([$KSRC/net/ipv6/ip6_gre.c],
    -                        [ip6gre_tunnel_validate], [extack],
    -                        [OVS_DEFINE([HAVE_IP6GRE_EXTACK])])
       OVS_FIND_FIELD_IFELSE([$KSRC/include/net/ip6_tunnel.h],
    [__ip6_tnl_parm],
                             [erspan_ver],
                             [OVS_DEFINE([HAVE_IP6_TNL_PARM_ERSPAN_VER])])
    @@ -864,9 +858,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
       OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
                       [IFLA_IPTUN_COLLECT_METADATA],
                       [OVS_DEFINE([HAVE_IFLA_IPTUN_COLLECT_METADATA])])
    -  OVS_GREP_IFELSE([$KSRC/net/ipv4/gre_demux.c],
    -                  [parse_gre_header],
    -                  [OVS_DEFINE([HAVE_DEMUX_PARSE_GRE_HEADER])])
       OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
                       [IFLA_GRE_ENCAP_DPORT])
       OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
    @@ -879,6 +870,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
                       [IFLA_GRE_ERSPAN_INDEX])
       OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
                       [IFLA_GRE_ERSPAN_HWID])
    +  OVS_GREP_IFELSE([$KSRC/include/uapi/linux/if_tunnel.h],
    +                  [IFLA_IPTUN_FWMARK])

       if cmp -s datapath/linux/kcompat.h.new \
                 datapath/linux/kcompat.h >/dev/null 2>&1; then
    diff --git a/datapath/linux/compat/geneve.c
    b/datapath/linux/compat/geneve.c
    index 0fcc6e5..435a23f 100644
    --- a/datapath/linux/compat/geneve.c
    +++ b/datapath/linux/compat/geneve.c
    @@ -1336,7 +1336,11 @@ static void geneve_setup(struct net_device
    *dev)

            dev->netdev_ops = &geneve_netdev_ops;
            dev->ethtool_ops = &geneve_ethtool_ops;
    +#ifndef HAVE_NEEDS_FREE_NETDEV
            dev->destructor = free_netdev;
    +#else
    +       dev->needs_free_netdev = true;
    +#endif

            SET_NETDEV_DEVTYPE(dev, &geneve_type);

    @@ -1370,7 +1374,12 @@ static const struct nla_policy
    geneve_policy[IFLA_GENEVE_MAX + 1] = {
            [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
     };

    +#ifdef  HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int geneve_validate(struct nlattr *tb[], struct nlattr
    *data[],
    +                          struct netlink_ext_ack *extack)
    +#else
     static int geneve_validate(struct nlattr *tb[], struct nlattr
    *data[])
    +#endif
     {
            if (tb[IFLA_ADDRESS]) {
                    if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
    @@ -1489,8 +1498,14 @@ static int geneve_configure(struct net
    *net, struct net_device *dev,
            return 0;
     }

    +#ifdef  HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int geneve_newlink(struct net *net, struct net_device *dev,
    +                         struct nlattr *tb[], struct nlattr *data[],
    +                         struct netlink_ext_ack *extack)
    +#else
     static int geneve_newlink(struct net *net, struct net_device *dev,
                              struct nlattr *tb[], struct nlattr *data[])
    +#endif
     {
            __be16 dst_port = htons(GENEVE_UDP_PORT);
            __u8 ttl = 0, tos = 0;
    diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
    index b45f8b4..7f2b545 100644
    --- a/datapath/linux/compat/gre.c
    +++ b/datapath/linux/compat/gre.c
    @@ -154,155 +154,6 @@ static int rpl_ip_gre_calc_hlen(__be16 o_flags)
            return addend;
     }

    -#ifndef HAVE_GRE_HANDLE_OFFLOADS
    -#ifndef HAVE_GRE_CISCO_REGISTER
    -
    -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
    -static __sum16 check_checksum(struct sk_buff *skb)
    -{
    -       __sum16 csum = 0;
    -
    -       switch (skb->ip_summed) {
    -       case CHECKSUM_COMPLETE:
    -               csum = csum_fold(skb->csum);
    -
    -               if (!csum)
    -                       break;
    -               /* Fall through. */
    -
    -       case CHECKSUM_NONE:
    -               skb->csum = 0;
    -               csum = __skb_checksum_complete(skb);
    -               skb->ip_summed = CHECKSUM_COMPLETE;
    -               break;
    -       }
    -
    -       return csum;
    -}
    -
    -static int parse_gre_header(struct sk_buff *skb, struct
    tnl_ptk_info *tpi,
    -                           bool *csum_err)
    -{
    -       unsigned int ip_hlen = ip_hdrlen(skb);
    -       struct gre_base_hdr *greh;
    -       __be32 *options;
    -       int hdr_len;
    -
    -       if (unlikely(!pskb_may_pull(skb, sizeof(struct
    gre_base_hdr))))
    -               return -EINVAL;
    -
    -       greh = (struct gre_base_hdr *)(skb_network_header(skb) +
    ip_hlen);
    -       if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING)))
    -               return -EINVAL;
    -
    -       tpi->flags = gre_flags_to_tnl_flags(greh->flags);
    -       hdr_len = ip_gre_calc_hlen(tpi->flags);
    -       tpi->hdr_len = hdr_len;
    -       tpi->proto = greh->protocol;
    -
    -       if (!pskb_may_pull(skb, hdr_len))
    -               return -EINVAL;
    -
    -       options = (__be32 *)(greh + 1);
    -       if (greh->flags & GRE_CSUM) {
    -               if (check_checksum(skb)) {
    -                       *csum_err = true;
    -                       return -EINVAL;
    -               }
    -               options++;
    -       }
    -
    -       if (greh->flags & GRE_KEY) {
    -               tpi->key = *options;
    -               options++;
    -       } else
    -               tpi->key = 0;
    -
    -       if (unlikely(greh->flags & GRE_SEQ)) {
    -               tpi->seq = *options;
    -               options++;
    -       } else
    -               tpi->seq = 0;
    -
    -       /* WCCP version 1 and 2 protocol decoding.
    -        * - Change protocol to IP
    -        * - When dealing with WCCPv2, Skip extra 4 bytes in GRE
    header
    -        */
    -       if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
    -               tpi->proto = htons(ETH_P_IP);
    -               if ((*(u8 *)options & 0xF0) != 0x40) {
    -                       hdr_len += 4;
    -                       if (!pskb_may_pull(skb, hdr_len))
    -                               return -EINVAL;
    -               }
    -       }
    -
    -       return iptunnel_pull_header(skb, hdr_len, tpi->proto, false);
    -}
    -
    -static struct gre_cisco_protocol __rcu *gre_cisco_proto;
    -static int gre_cisco_rcv(struct sk_buff *skb)
    -{
    -       struct gre_cisco_protocol *proto;
    -       struct tnl_ptk_info tpi;
    -       bool csum_err = false;
    -
    -       rcu_read_lock();
    -       proto = rcu_dereference(gre_cisco_proto);
    -       if (!proto)
    -               goto drop;
    -
    -       if (parse_gre_header(skb, &tpi, &csum_err) < 0)
    -                       goto drop;
    -       proto->handler(skb, &tpi);
    -       rcu_read_unlock();
    -       return 0;
    -
    -drop:
    -       rcu_read_unlock();
    -       kfree_skb(skb);
    -       return 0;
    -}
    -
    -static const struct gre_protocol ipgre_protocol = {
    -       .handler        =       gre_cisco_rcv,
    -};
    -
    -int rpl_gre_cisco_register(struct gre_cisco_protocol *newp)
    -{
    -       int err;
    -
    -       err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
    -       if (err) {
    -               pr_warn("%s: cannot register gre_cisco protocol
    handler\n", __func__);
    -               return err;
    -       }
    -
    -
    -       return (cmpxchg((struct gre_cisco_protocol
    **)&gre_cisco_proto, NULL, newp) == NULL) ?
    -               0 : -EBUSY;
    -}
    -EXPORT_SYMBOL_GPL(rpl_gre_cisco_register);
    -
    -int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto)
    -{
    -       int ret;
    -       ret = (cmpxchg((struct gre_cisco_protocol
    **)&gre_cisco_proto, proto, NULL) == proto) ?
    -               0 : -EINVAL;
    -
    -       if (ret)
    -               return ret;
    -
    -       synchronize_net();
    -       ret = gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
    -       return ret;
    -}
    -EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister);
    -
    -#endif /* HAVE_DEMUX_PARSE_GRE_HEADER */
    -#endif /* !HAVE_GRE_CISCO_REGISTER */
    -#endif
    -
     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/linux/compiler-gcc.h
    b/datapath/linux/compat/include/linux/compiler-gcc.h
    index bfcd531..39d2e01 100644
    --- a/datapath/linux/compat/include/linux/compiler-gcc.h
    +++ b/datapath/linux/compat/include/linux/compiler-gcc.h
    @@ -1,8 +1,13 @@
     #ifndef __LINUX_COMPILER_H
    +#if 0
    +/* Disable this check - it no longer makes sense with so many
    backports
    + * due to spectre mitigation
    + */
     #ifndef HAVE_LINUX_COMPILER_TYPES_H
     #error "Please don't include <linux/compiler-gcc.h> directly,
    include <linux/compiler.h> instead."
     #endif
     #endif
    +#endif

     #include_next <linux/compiler-gcc.h>

    diff --git a/datapath/linux/compat/include/net/dst_metadata.h
    b/datapath/linux/compat/include/net/dst_metadata.h
    index 93ea954..02e717b 100644
    --- a/datapath/linux/compat/include/net/dst_metadata.h
    +++ b/datapath/linux/compat/include/net/dst_metadata.h
    @@ -116,13 +116,13 @@ static inline void
    ovs_ipv6_tun_rx_dst(struct metadata_dst *md_dst,
     void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
                          struct metadata_dst *tun_dst);

    -#ifndef HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE
    +// #ifndef HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE
     static inline struct metadata_dst *
     rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t
    flags)
     {
            return metadata_dst_alloc(optslen, flags);
     }
     #define metadata_dst_alloc rpl_metadata_dst_alloc
    -#endif
    +// #endif

     #endif /* __NET_DST_METADATA_WRAPPER_H */
    diff --git a/datapath/linux/compat/include/net/erspan.h
    b/datapath/linux/compat/include/net/erspan.h
    index 8adc89f..9fdae97 100644
    --- a/datapath/linux/compat/include/net/erspan.h
    +++ b/datapath/linux/compat/include/net/erspan.h
    @@ -1,4 +1,4 @@
    -#ifndef HAVE_LINUX_ERSPAN_H
    +#ifndef USE_UPSTREAM_TUNNEL
     #ifndef __LINUX_ERSPAN_H
     #define __LINUX_ERSPAN_H

    diff --git a/datapath/linux/compat/include/net/gre.h
    b/datapath/linux/compat/include/net/gre.h
    index 141ed2d..a3121b1 100644
    --- a/datapath/linux/compat/include/net/gre.h
    +++ b/datapath/linux/compat/include/net/gre.h
    @@ -124,6 +124,7 @@ static inline __be16
    rpl_gre_tnl_flags_to_gre_flags(__be16 tflags)
            return flags;
     }

    +#if 0
     #ifndef HAVE_GRE_CISCO_REGISTER

     /* GRE demux not available, implement our own demux. */
    @@ -151,6 +152,7 @@ struct gre_base_hdr {
     #endif

     #endif /* HAVE_GRE_CISCO_REGISTER */
    +#endif

     #define gre_build_header rpl_gre_build_header
     void rpl_gre_build_header(struct sk_buff *skb, const struct
    tnl_ptk_info *tpi,
    diff --git a/datapath/linux/compat/include/net/ip_tunnels.h
    b/datapath/linux/compat/include/net/ip_tunnels.h
    index 9b2621e..f9ae265 100644
    --- a/datapath/linux/compat/include/net/ip_tunnels.h
    +++ b/datapath/linux/compat/include/net/ip_tunnels.h
    @@ -60,9 +60,15 @@ int ovs_iptunnel_handle_offloads(struct sk_buff
    *skb,
      * rpl prefix is to make OVS build happy.
      */
     #define iptunnel_handle_offloads rpl_iptunnel_handle_offloads
    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
     struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
                                                 bool csum_help,
                                                 int gso_type_mask);
    +#else
    +int rpl_iptunnel_handle_offloads(struct sk_buff *skb,
    +                                bool csum_help,
    +                                int gso_type_mask);
    +#endif

     #define iptunnel_xmit rpl_iptunnel_xmit
     void rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct
    sk_buff *skb,
    @@ -231,7 +237,7 @@ static inline void ip_tunnel_key_init(struct
    ip_tunnel_key *key,

     #define ip_tunnel_collect_metadata() true

    -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0)
    +// #if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0)
     #undef TUNNEL_NOCACHE
     #define TUNNEL_NOCACHE 0

    @@ -248,7 +254,7 @@ ip_tunnel_dst_cache_usable(const struct
    sk_buff *skb,

            return true;
     }
    -#endif
    +// #endif

     #define ip_tunnel_dst rpl_ip_tunnel_dst
     struct rpl_ip_tunnel_dst {
    @@ -359,14 +365,14 @@ static inline int ovs_ip_tunnel_encap(struct
    sk_buff *skb, struct ip_tunnel *t,
            return ret;
     }

    -#ifndef HAVE_PCPU_SW_NETSTATS
     #define ip_tunnel_get_stats64 rpl_ip_tunnel_get_stats64
    -#else
    -#define rpl_ip_tunnel_get_stats64 ip_tunnel_get_stats64
    -#endif
    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
     struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct
    net_device *dev,
                                                        struct
    rtnl_link_stats64 *tot);
    -
    +#else
    +void rpl_ip_tunnel_get_stats64(struct net_device *dev,
    +                                                   struct
    rtnl_link_stats64 *tot);
    +#endif
     #define ip_tunnel_get_dsfield rpl_ip_tunnel_get_dsfield
     static inline u8 rpl_ip_tunnel_get_dsfield(const struct iphdr *iph,
                                               const struct sk_buff *skb)
    diff --git a/datapath/linux/compat/ip6_gre.c
    b/datapath/linux/compat/ip6_gre.c
    index 94a031c..dd22240 100644
    --- a/datapath/linux/compat/ip6_gre.c
    +++ b/datapath/linux/compat/ip6_gre.c
    @@ -785,9 +785,9 @@ static int rpl_gre_handle_offloads(struct
    sk_buff *skb, bool gre_csum)
     #else
     static int gre_handle_offloads(struct sk_buff *skb, bool csum)
     {
    -       return iptunnel_handle_offloads(skb,
    +       return iptunnel_handle_offloads(skb, csum,
                                            csum ? SKB_GSO_GRE_CSUM :
    SKB_GSO_GRE);
    -
    +}
     #endif

     static void prepare_ip6gre_xmit_ipv4(struct sk_buff *skb,
    @@ -1526,7 +1526,7 @@ static const struct net_device_ops
    ip6gre_netdev_ops = {
            .ndo_start_xmit         = ip6gre_tunnel_xmit,
            .ndo_do_ioctl           = ip6gre_tunnel_ioctl,
            .ndo_change_mtu         = ip6_tnl_change_mtu,
    -       .ndo_get_stats64        = rpl_ip_tunnel_get_stats64,
    +       .ndo_get_stats64        = ip_tunnel_get_stats64,
     #ifdef HAVE_NDO_GET_IFLINK
            .ndo_get_iflink         = ip6_tnl_get_iflink,
     #endif
    @@ -1787,7 +1787,7 @@ static struct pernet_operations
    ip6gre_net_ops = {
            .id   = &ip6gre_net_id,
            .size = sizeof(struct ip6gre_net),
     };
    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6gre_tunnel_validate(struct nlattr *tb[],
                                          struct nlattr *data[],
                                          struct netlink_ext_ack *extack)
    @@ -1813,7 +1813,7 @@ static int rpl_ip6gre_tunnel_validate(struct
    nlattr *tb[],
     }
     #define ip6gre_tunnel_validate rpl_ip6gre_tunnel_validate

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6gre_tap_validate(struct nlattr *tb[], struct
    nlattr *data[],
                                       struct netlink_ext_ack *extack)
     #else
    @@ -1839,7 +1839,7 @@ static int rpl_ip6gre_tap_validate(struct
    nlattr *tb[], struct nlattr *data[])
            }

     out:
    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            return ip6gre_tunnel_validate(tb, data, extack);
     #else
            return ip6gre_tunnel_validate(tb, data);
    @@ -1847,7 +1847,7 @@ out:
     }
     #define ip6gre_tap_validate rpl_ip6gre_tap_validate

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6erspan_tap_validate(struct nlattr *tb[],
                                          struct nlattr *data[],
                                          struct netlink_ext_ack *extack)
    @@ -1862,7 +1862,7 @@ static int rpl_ip6erspan_tap_validate(struct
    nlattr *tb[],
            if (!data)
                    return 0;

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            ret = ip6gre_tap_validate(tb, data, extack);
     #else
            ret = ip6gre_tap_validate(tb, data);
    @@ -2011,7 +2011,7 @@ static const struct net_device_ops
    ip6gre_tap_netdev_ops = {
            .ndo_set_mac_address = eth_mac_addr,
            .ndo_validate_addr = eth_validate_addr,
            .ndo_change_mtu = ip6_tnl_change_mtu,
    -       .ndo_get_stats64 = rpl_ip_tunnel_get_stats64,
    +       .ndo_get_stats64 = ip_tunnel_get_stats64,
     #ifdef HAVE_NDO_GET_IFLINK
            .ndo_get_iflink = ip6_tnl_get_iflink,
     #endif
    @@ -2134,7 +2134,7 @@ static bool
    ip6gre_netlink_encap_parms(struct nlattr *data[],
            return ret;
     }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6gre_newlink_common(struct net *src_net, struct
    net_device *dev,
                                  struct nlattr *tb[], struct nlattr
    *data[],
                                  struct netlink_ext_ack *extack)
    @@ -2176,7 +2176,7 @@ out:
     }
     #define ip6gre_newlink_common rpl_ip6gre_newlink_common

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6gre_newlink(struct net *src_net, struct
    net_device *dev,
                              struct nlattr *tb[], struct nlattr *data[],
                              struct netlink_ext_ack *extack)
    @@ -2201,7 +2201,7 @@ static int rpl_ip6gre_newlink(struct net
    *src_net, struct net_device *dev,
                            return -EEXIST;
            }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            err = ip6gre_newlink_common(src_net, dev, tb, data, extack);
     #else
            err = ip6gre_newlink_common(src_net, dev, tb, data);
    @@ -2216,7 +2216,7 @@ static int rpl_ip6gre_newlink(struct net
    *src_net, struct net_device *dev,

     #define ip6gre_newlink rpl_ip6gre_newlink

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static struct ip6_tnl *
     rpl_ip6gre_changelink_common(struct net_device *dev, struct
    nlattr *tb[],
                             struct nlattr *data[], struct
    __ip6_tnl_parm *p_p,
    @@ -2257,7 +2257,7 @@ rpl_ip6gre_changelink_common(struct
    net_device *dev, struct nlattr *tb[],
     }
     #define ip6gre_changelink_common rpl_ip6gre_changelink_common

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6gre_changelink(struct net_device *dev, struct
    nlattr *tb[],
                                 struct nlattr *data[],
                                 struct netlink_ext_ack *extack)
    @@ -2270,7 +2270,7 @@ static int rpl_ip6gre_changelink(struct
    net_device *dev, struct nlattr *tb[],
            struct __ip6_tnl_parm p;
            struct ip6_tnl *t;

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            t = ip6gre_changelink_common(dev, tb, data, &p, extack);
     #else
            t = ip6gre_changelink_common(dev, tb, data, &p);
    @@ -2436,7 +2436,7 @@ static void ip6erspan_tap_setup(struct
    net_device *dev)
            netif_keep_dst(dev);
     }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6erspan_newlink(struct net *src_net, struct
    net_device *dev,
                                     struct nlattr *tb[], struct
    nlattr *data[],
                                     struct netlink_ext_ack *extack)
    @@ -2461,7 +2461,7 @@ static int rpl_ip6erspan_newlink(struct net
    *src_net, struct net_device *dev,
                            return -EEXIST;
            }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            err = ip6gre_newlink_common(src_net, dev, tb, data, extack);
     #else
            err = ip6gre_newlink_common(src_net, dev, tb, data);
    @@ -2489,7 +2489,7 @@ static int ip6erspan_tnl_change(struct
    ip6_tnl *t,
            return 0;
     }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6erspan_changelink(struct net_device *dev,
    struct nlattr *tb[],
                                        struct nlattr *data[],
                                        struct netlink_ext_ack *extack)
    @@ -2501,7 +2501,7 @@ static int rpl_ip6erspan_changelink(struct
    net_device *dev, struct nlattr *tb[],
            struct ip6gre_net *ign = net_generic(dev_net(dev),
    ip6gre_net_id);
            struct __ip6_tnl_parm p;
            struct ip6_tnl *t;
    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
            t = ip6gre_changelink_common(dev, tb, data, &p, extack);
     #else
            t = ip6gre_changelink_common(dev, tb, data, &p);
    @@ -2588,7 +2588,11 @@ struct net_device
    *ip6erspan_fb_dev_create(struct net *net, const char *name,
            t = netdev_priv(dev);
            t->parms.collect_md = true;

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       err = ip6erspan_newlink(net, dev, tb, NULL, NULL);
    +#else
            err = ip6erspan_newlink(net, dev, tb, NULL);
    +#endif
            if (err < 0) {
                    free_netdev(dev);
                    return ERR_PTR(err);
    @@ -2685,7 +2689,11 @@ struct net_device
    *ip6gre_fb_dev_create(struct net *net, const char *name,
            t = netdev_priv(dev);
            t->parms.collect_md = true;

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       err = ip6gre_newlink(net, dev, tb, NULL, NULL);
    +#else
            err = ip6gre_newlink(net, dev, tb, NULL);
    +#endif
            if (err < 0) {
                    free_netdev(dev);
                    return ERR_PTR(err);
    diff --git a/datapath/linux/compat/ip6_tunnel.c
    b/datapath/linux/compat/ip6_tunnel.c
    index f9720a3..f6ac069 100644
    --- a/datapath/linux/compat/ip6_tunnel.c
    +++ b/datapath/linux/compat/ip6_tunnel.c
    @@ -73,9 +73,11 @@ enum {
            IFLA_IPTUN_ENCAP_SPORT,
            IFLA_IPTUN_ENCAP_DPORT,
     #endif
    -#ifndef HAVE_IFLA_IPTUN_COLLECT_METADTA
    +#ifndef HAVE_IFLA_IPTUN_COLLECT_METADATA
            IFLA_IPTUN_COLLECT_METADATA = IFLA_IPTUN_ENCAP_DPORT + 1,
    -       IFLA_IPTUN_FWMARK,
    +#endif
    +#ifndef HAVE_IFLA_IPTUN_FWMARK
    +       IFLA_IPTUN_FWMARK = IFLA_IPTUN_COLLECT_METADATA + 1,
     #endif
            RPL__IFLA_IPTUN_MAX = IFLA_IPTUN_FWMARK + 1,
     };
    @@ -104,7 +106,8 @@ static void gre_csum_fix(struct sk_buff *skb)
     }

     #define iptunnel_handle_offloads rpl__iptunnel_handle_offloads
    -static int rpl__iptunnel_handle_offloads(struct sk_buff *skb,
    bool gre_csum)
    +static int rpl__iptunnel_handle_offloads(struct sk_buff *skb,
    bool gre_csum,
    +                                        int __always_unused ignored)
     {
            int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE;
            gso_fix_segment_t fix_segment;
    @@ -1116,7 +1119,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct
    net_device *dev)
     // FIX ME
     //     fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);

    -       if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
    +       if (iptunnel_handle_offloads(skb, true, SKB_GSO_IPXIP6))
                    return -1;

            dsfield = INET_ECN_encapsulate(dsfield,
    ipv4_get_dsfield(iph));
    @@ -1208,7 +1211,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct
    net_device *dev)
     //     FIX ME
     //     fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);

    -       if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
    +       if (iptunnel_handle_offloads(skb, true, SKB_GSO_IPXIP6))
                    return -1;

            dsfield = INET_ECN_encapsulate(dsfield,
    ipv6_get_dsfield(ipv6h));
    @@ -1746,7 +1749,7 @@ static int __net_init
    ip6_fb_tnl_dev_init(struct net_device *dev)
            return 0;
     }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6_tnl_validate(struct nlattr *tb[], struct
    nlattr *data[],
                                    struct netlink_ext_ack *extack)
     #else
    @@ -1840,7 +1843,7 @@ static bool
    ip6_tnl_netlink_encap_parms(struct nlattr *data[],
            return ret;
     }

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6_tnl_newlink(struct net *src_net, struct
    net_device *dev,
                                   struct nlattr *tb[], struct nlattr
    *data[],
                                   struct netlink_ext_ack *extack)
    @@ -1882,7 +1885,7 @@ static int rpl_ip6_tnl_newlink(struct net
    *src_net, struct net_device *dev,
     }
     #define ip6_tnl_newlink rpl_ip6_tnl_newlink

    -#ifdef HAVE_IP6GRE_EXTACK
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
     static int rpl_ip6_tnl_changelink(struct net_device *dev, struct
    nlattr *tb[],
                                      struct nlattr *data[],
                                      struct netlink_ext_ack *extack)
    diff --git a/datapath/linux/compat/ip_gre.c
    b/datapath/linux/compat/ip_gre.c
    index 5911c6c..d35614e 100644
    --- a/datapath/linux/compat/ip_gre.c
    +++ b/datapath/linux/compat/ip_gre.c
    @@ -19,7 +19,7 @@
     #include <linux/kernel.h>
     #include <linux/kconfig.h>
     #include <linux/slab.h>
    -#include <asm/uaccess.h>
    +#include <linux/uaccess.h>
     #include <linux/skbuff.h>
     #include <linux/netdevice.h>
     #include <linux/netdev_features.h>
    @@ -96,14 +96,6 @@ static __be32 tunnel_id_to_key(__be64 x)
     #endif
     }

    -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
    -/* Called with rcu_read_lock and BH disabled. */
    -static int gre_err(struct sk_buff *skb, u32 info,
    -                  const struct tnl_ptk_info *tpi)
    -{
    -       return PACKET_REJECT;
    -}
    -#endif
     static struct dst_ops md_dst_ops = {
            .family =               AF_UNSPEC,
     };
    @@ -354,7 +346,6 @@ static void __gre_xmit(struct sk_buff *skb,
    struct net_device *dev,
            ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
     }

    -#ifndef HAVE_DEMUX_PARSE_GRE_HEADER
     static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info
    *unused_tpi)
     {
            struct tnl_ptk_info tpi;
    @@ -379,28 +370,9 @@ drop:
            kfree_skb(skb);
            return 0;
     }
    -#else
    -static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info
    *__tpi)
    -{
    -       struct tnl_ptk_info tpi = *__tpi;
    -
    -       if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
    -                    tpi.proto == htons(ETH_P_ERSPAN2))) {
    -               if (erspan_rcv(skb, &tpi, 0) == PACKET_RCVD)
    -                       return 0;
    -               goto drop;
    -       }
    -
    -       if (ipgre_rcv(skb, &tpi, 0) == PACKET_RCVD)
    -               return 0;
    -drop:
    -
    -       kfree_skb(skb);
    -       return 0;
    -}
    -#endif

     #if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
    +#include "gso.h"
     /* gre_handle_offloads() has different return type on older
    kernsl. */
     static void gre_nop_fix(struct sk_buff *skb) { }

    @@ -418,11 +390,6 @@ static void gre_csum_fix(struct sk_buff *skb)
     skb->len - gre_offset, 0));
     }

    -static bool is_gre_gso(struct sk_buff *skb)
    -{
    -       return skb_is_gso(skb);
    -}
    -
     #define gre_handle_offloads rpl_gre_handle_offloads
     static int rpl_gre_handle_offloads(struct sk_buff *skb, bool
    gre_csum)
     {
    @@ -437,6 +404,12 @@ static int rpl_gre_handle_offloads(struct
    sk_buff *skb, bool gre_csum)
            return ovs_iptunnel_handle_offloads(skb, type, fix_segment);
     }
     #else
    +static int gre_handle_offloads(struct sk_buff *skb, bool csum)
    +{
    +       return iptunnel_handle_offloads(skb, csum,
    +                                       csum ? SKB_GSO_GRE_CSUM :
    SKB_GSO_GRE);
    +}
    +#endif

     static bool is_gre_gso(struct sk_buff *skb)
     {
    @@ -444,16 +417,6 @@ static bool is_gre_gso(struct sk_buff *skb)
                    (SKB_GSO_GRE | SKB_GSO_GRE_CSUM);
     }

    -static int rpl_gre_handle_offloads(struct sk_buff *skb, bool
    gre_csum)
    -{
    -       if (skb_is_gso(skb) && skb_is_encapsulated(skb))
    -               return -ENOSYS;
    -
    -#undef gre_handle_offloads
    -       return gre_handle_offloads(skb, gre_csum);
    -}
    -#endif
    -
     static void build_header(struct sk_buff *skb, int hdr_len, __be16
    flags,
                             __be16 proto, __be32 key, __be32 seq)
     {
    @@ -589,14 +552,14 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb)
                            goto err_free_rt;
            }

    -       skb = vlan_hwaccel_push_inside(skb);
    +       skb = __vlan_hwaccel_push_inside(skb);
            if (unlikely(!skb)) {
                    err = -ENOMEM;
                    goto err_free_rt;
            }

            /* Push Tunnel header. */
    -       err = rpl_gre_handle_offloads(skb,
    !!(tun_info->key.tun_flags & TUNNEL_CSUM));
    +       err = gre_handle_offloads(skb, !!(tun_info->key.tun_flags
    & TUNNEL_CSUM));
            if (err)
                    goto err_free_rt;

    @@ -747,14 +710,6 @@ static void __gre_tunnel_init(struct
    net_device *dev)
            }
     }

    -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
    -static struct gre_cisco_protocol ipgre_cisco_protocol = {
    -       .handler        = gre_rcv,
    -       .err_handler    = gre_err,
    -       .priority       = 1,
    -};
    -#endif
    -
     static int __gre_rcv(struct sk_buff *skb)
     {
            return gre_rcv(skb, NULL);
    @@ -789,7 +744,12 @@ static struct pernet_operations ipgre_net_ops = {
            .size = sizeof(struct ip_tunnel_net),
     };

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int ipgre_tunnel_validate(struct nlattr *tb[], struct
    nlattr *data[],
    +                                struct netlink_ext_ack *extack)
    +#else
     static int ipgre_tunnel_validate(struct nlattr *tb[], struct
    nlattr *data[])
    +#endif
     {
            __be16 flags;

    @@ -807,7 +767,12 @@ static int ipgre_tunnel_validate(struct
    nlattr *tb[], struct nlattr *data[])
            return 0;
     }

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr
    *data[],
    +                             struct netlink_ext_ack *extack)
    +#else
     static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr
    *data[])
    +#endif
     {
            __be32 daddr;

    @@ -828,7 +793,11 @@ static int ipgre_tap_validate(struct nlattr
    *tb[], struct nlattr *data[])
            }

     out:
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       return ipgre_tunnel_validate(tb, data, NULL);
    +#else
            return ipgre_tunnel_validate(tb, data);
    +#endif
     }

     enum {
    @@ -859,7 +828,12 @@ enum {

     #define RPL_IFLA_GRE_MAX (IFLA_GRE_ERSPAN_HWID + 1)

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int erspan_validate(struct nlattr *tb[], struct nlattr
    *data[],
    +                          struct netlink_ext_ack *extack)
    +#else
     static int erspan_validate(struct nlattr *tb[], struct nlattr
    *data[])
    +#endif
     {
            __be16 flags = 0;
            int ret;
    @@ -867,7 +841,11 @@ static int erspan_validate(struct nlattr
    *tb[], struct nlattr *data[])
            if (!data)
                    return 0;

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       ret = ipgre_tap_validate(tb, data, NULL);
    +#else
            ret = ipgre_tap_validate(tb, data);
    +#endif
            if (ret)
                    return ret;

    @@ -1194,7 +1172,7 @@ static const struct net_device_ops
    gre_tap_netdev_ops = {
     #else
            .ndo_change_mtu         = ip_tunnel_change_mtu,
     #endif
    -       .ndo_get_stats64        = rpl_ip_tunnel_get_stats64,
    +       .ndo_get_stats64        = ip_tunnel_get_stats64,
     #ifdef HAVE_NDO_GET_IFLINK
            .ndo_get_iflink         = rpl_ip_tunnel_get_iflink,
     #endif
    @@ -1210,7 +1188,7 @@ static const struct net_device_ops
    erspan_netdev_ops = {
            .ndo_set_mac_address    = eth_mac_addr,
            .ndo_validate_addr      = eth_validate_addr,
            .ndo_change_mtu         = ip_tunnel_change_mtu,
    -       .ndo_get_stats64        = rpl_ip_tunnel_get_stats64,
    +       .ndo_get_stats64        = ip_tunnel_get_stats64,
     #ifdef HAVE_NDO_GET_IFLINK
            .ndo_get_iflink         = rpl_ip_tunnel_get_iflink,
     #endif
    @@ -1247,8 +1225,14 @@ static void erspan_setup(struct net_device
    *dev)
            ip_tunnel_setup(dev, erspan_net_id);
     }

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int ipgre_newlink(struct net *src_net, struct net_device *dev,
    +                        struct nlattr *tb[], struct nlattr *data[],
    +                        struct netlink_ext_ack *extack)
    +#else
     static int ipgre_newlink(struct net *src_net, struct net_device *dev,
                             struct nlattr *tb[], struct nlattr *data[])
    +#endif
     {
            struct ip_tunnel_parm p;
            int err;
    @@ -1424,7 +1408,11 @@ struct net_device
    *rpl_gretap_fb_dev_create(struct net *net, const char *name,
            t = netdev_priv(dev);
            t->collect_md = true;
            /* Configure flow based GRE device. */
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       err = ipgre_newlink(net, dev, tb, NULL, NULL);
    +#else
            err = ipgre_newlink(net, dev, tb, NULL);
    +#endif
            if (err < 0) {
                    free_netdev(dev);
                    return ERR_PTR(err);
    @@ -1504,7 +1492,11 @@ static struct net_device
    *erspan_fb_dev_create(struct net *net,
            t = netdev_priv(dev);
            t->collect_md = true;
            /* Configure flow based GRE device. */
    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +       err = ipgre_newlink(net, dev, tb, NULL, NULL);
    +#else
            err = ipgre_newlink(net, dev, tb, NULL);
    +#endif
            if (err < 0) {
                    free_netdev(dev);
                    return ERR_PTR(err);
    @@ -1648,19 +1640,11 @@ int rpl_ipgre_init(void)
            if (err < 0)
                    goto pnet_ipgre_failed;

    -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
    -       err = gre_cisco_register(&ipgre_cisco_protocol);
    -       if (err < 0) {
    -               pr_info("%s: can't add protocol\n", __func__);
    -               goto add_proto_failed;
    -       }
    -#else
            err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
            if (err < 0) {
                    pr_info("%s: can't add protocol\n", __func__);
                    goto add_proto_failed;
            }
    -#endif

            pr_info("GRE over IPv4 tunneling driver\n");

    @@ -1683,11 +1667,7 @@ void rpl_ipgre_fini(void)
     {
            ovs_vport_ops_unregister(&ovs_erspan_vport_ops);
            ovs_vport_ops_unregister(&ovs_ipgre_vport_ops);
    -#ifdef HAVE_DEMUX_PARSE_GRE_HEADER
    -       gre_cisco_unregister(&ipgre_cisco_protocol);
    -#else
            gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
    -#endif
            unregister_pernet_device(&ipgre_net_ops);
            unregister_pernet_device(&erspan_net_ops);
            unregister_pernet_device(&ipgre_tap_net_ops);
    diff --git a/datapath/linux/compat/ip_tunnel.c
    b/datapath/linux/compat/ip_tunnel.c
    index 58870bc..5ab6035 100644
    --- a/datapath/linux/compat/ip_tunnel.c
    +++ b/datapath/linux/compat/ip_tunnel.c
    @@ -470,7 +470,9 @@ EXPORT_SYMBOL_GPL(rpl_ip_tunnel_xmit);
     static void ip_tunnel_dev_free(struct net_device *dev)
     {
            free_percpu(dev->tstats);
    +#ifndef HAVE_NEEDS_FREE_NETDEV
            free_netdev(dev);
    +#endif
     }

     void rpl_ip_tunnel_dellink(struct net_device *dev, struct
    list_head *head)
    diff --git a/datapath/linux/compat/ip_tunnels_core.c
    b/datapath/linux/compat/ip_tunnels_core.c
    index 90e838a..fcb0890 100644
    --- a/datapath/linux/compat/ip_tunnels_core.c
    +++ b/datapath/linux/compat/ip_tunnels_core.c
    @@ -129,9 +129,16 @@ error:
     }
     EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads);

    +
    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
     struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
                                                 bool csum_help,
                                                 int gso_type_mask)
    +#else
    +int rpl_iptunnel_handle_offloads(struct sk_buff *skb,
    +                                bool csum_help,
    +                                int gso_type_mask)
    +#endif
     {
            int err;

    @@ -145,7 +152,7 @@ struct sk_buff
    *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
                    if (unlikely(err))
                            goto error;
                    skb_shinfo(skb)->gso_type |= gso_type_mask;
    -               return skb;
    +               goto out;
            }

            /* If packet is not gso and we are resolving any partial
    checksum,
    @@ -163,10 +170,17 @@ struct sk_buff
    *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
            } else if (skb->ip_summed != CHECKSUM_PARTIAL)
                    skb->ip_summed = CHECKSUM_NONE;

    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
    +out:
            return skb;
     error:
            kfree_skb(skb);
            return ERR_PTR(err);
    +#else
    +out:
    +error:
    +       return 0;
    +#endif
     }
     EXPORT_SYMBOL_GPL(rpl_iptunnel_handle_offloads);

    @@ -258,9 +272,15 @@ static void netdev_stats_to_stats64(struct
    rtnl_link_stats64 *stats64,
                    dst[i] = src[i];
     #endif
     }
    +#endif

    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
     struct rtnl_link_stats64 *rpl_ip_tunnel_get_stats64(struct
    net_device *dev,
                                                    struct
    rtnl_link_stats64 *tot)
    +#else
    +void rpl_ip_tunnel_get_stats64(struct net_device *dev,
    +                                               struct
    rtnl_link_stats64 *tot)
    +#endif
     {
            int i;

    @@ -286,9 +306,10 @@ struct rtnl_link_stats64
    *rpl_ip_tunnel_get_stats64(struct net_device *dev,
                    tot->tx_bytes   += tx_bytes;
            }

    +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)
            return tot;
    -}
     #endif
    +}

     void rpl_ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
                        struct net_device *dev)
    diff --git a/datapath/linux/compat/vxlan.c
    b/datapath/linux/compat/vxlan.c
    index fa4e7b1..7f5d5ce 100644
    --- a/datapath/linux/compat/vxlan.c
    +++ b/datapath/linux/compat/vxlan.c
    @@ -844,7 +844,8 @@ static int vxlan_build_skb(struct sk_buff
    *skb, struct dst_entry *dst,
            if (unlikely(err))
                    goto out_free;

    -       skb = vlan_hwaccel_push_inside(skb);
    +       if (skb_vlan_tag_present(skb))
    +               skb = __vlan_hwaccel_push_inside(skb);
            if (WARN_ON(!skb))
                    return -ENOMEM;

    @@ -1556,7 +1557,11 @@ static void vxlan_setup(struct net_device *dev)
            eth_hw_addr_random(dev);
            ether_setup(dev);

    +#ifndef HAVE_NEEDS_FREE_NETDEV
            dev->destructor = free_netdev;
    +#else
    +       dev->needs_free_netdev = true;
    +#endif
            SET_NETDEV_DEVTYPE(dev, &vxlan_type);

            dev->features   |= NETIF_F_LLTX;
    @@ -1636,7 +1641,12 @@ static const struct nla_policy
    vxlan_policy[IFLA_VXLAN_MAX + 1] = {
            [IFLA_VXLAN_REMCSUM_NOPARTIAL]  = { .type = NLA_FLAG },
     };

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
    +                         struct netlink_ext_ack *extack)
    +#else
     static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
    +#endif
     {
            if (tb[IFLA_ADDRESS]) {
                    if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
    @@ -1955,8 +1965,14 @@ static int vxlan_dev_configure(struct net
    *src_net, struct net_device *dev,
            return 0;
     }

    +#ifdef HAVE_EXT_ACK_IN_RTNL_LINKOPS
    +static int vxlan_newlink(struct net *src_net, struct net_device *dev,
    +                        struct nlattr *tb[], struct nlattr *data[],
    +                        struct netlink_ext_ack *extack)
    +#else
     static int vxlan_newlink(struct net *src_net, struct net_device *dev,
                             struct nlattr *tb[], struct nlattr *data[])
    +#endif
     {
            pr_info("unsupported operation\n");
            return -EINVAL;
-- 1.8.3.1

    _______________________________________________
    dev mailing list
    d...@openvswitch.org <mailto:d...@openvswitch.org>
    https://mail.openvswitch.org/mailman/listinfo/ovs-dev
    <https://mail.openvswitch.org/mailman/listinfo/ovs-dev>



_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to