[ovs-dev] [PATCH 2/2] datapath: Add support for kernel 4.19.x and 4.20.x

Gregory Rose gvrose8192 at gmail.com
Fri Mar 29 22:27:55 UTC 2019



On 3/29/2019 3:16 PM, Yifeng Sun wrote:
> Hi Greg, I tried new kernel 4.20.17 on ubuntu 8.10 but everything works fine.
> Do you mind telling me what Linux were you using?
>
> Thanks,
> Yifeng

It was a  Ubuntu Xenial 16.04 with the custom built 4.20.17 kernel from 
kernel.org.  I'm not sure what difference
that should make though.

- Greg

>
> On Fri, Mar 29, 2019 at 9:21 AM Yifeng Sun <pkusunyifeng at gmail.com> wrote:
>> Hi Greg, thanks for the review. I will check on it.
>> Yifeng
>>
>> On Fri, Mar 29, 2019 at 8:19 AM Gregory Rose <gvrose8192 at gmail.com> wrote:
>>>
>>> On 3/15/2019 7:20 PM, Yifeng Sun wrote:
>>>> This patch introduces changes needed by OVS to support latest
>>>> Linux kernels (4.19.x and 4.20.x). Recent kernels changed many
>>>> APIs used by OVS. One major change is that struct nf_conntrack_l3proto
>>>> became unvisible outside of kernel, so the needed get_l4proto
>>>> function is added in file compact/nf_conntrack_core.c to
>>>> accommodate this issue.
>>>>
>>>> This patch doesn't introduce new failed tests when running
>>>> 'make check-kmod' for kernels listed below:
>>>>       3.10.0-957.5.1.el7.x86_64
>>>>       4.4.0-142-generic
>>>>       4.17.14
>>>>       4.18.0-16-generic
>>>>       4.19.26
>>>>       4.20.13
>>>>
>>>> Travis passed at
>>>> https://travis-ci.org/yifsun/ovs-travis/builds/507034016
>>> Hi Yifeng,
>>>
>>> thanks for doing this work!  However, I am seeing an issue when
>>> compiling on 4.20.17 and then installing
>>> the kernel modules:
>>>
>>> make -C /lib/modules/4.20.17/build
>>> M=/home/gvrose/prj/ovs-experimental/_build/datapath/linux modules_install
>>> make[2]: Entering directory '/home/gvrose/prj/linux-4.20.17'
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/openvswitch.ko
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/vport-geneve.ko
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/vport-gre.ko
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/vport-lisp.ko
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/vport-stt.ko
>>>     INSTALL
>>> /home/gvrose/prj/ovs-experimental/_build/datapath/linux/vport-vxlan.ko
>>>     DEPMOD  4.20.17
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-lisp.ko needs unknown
>>> symbol rpl_rtnl_delete_link
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-lisp.ko needs unknown
>>> symbol rpl_lisp_xmit
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-lisp.ko needs unknown
>>> symbol rpl_lisp_dev_create_fb
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-stt.ko needs unknown
>>> symbol rpl_rtnl_delete_link
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-stt.ko needs unknown
>>> symbol ovs_stt_dev_create_fb
>>> depmod: WARNING: /lib/modules/4.20.17/extra/vport-stt.ko needs unknown
>>> symbol ovs_stt_xmit
>>> make[2]: Leaving directory '/home/gvrose/prj/linux-4.20.17'
>>>
>>> Could you check that?  Maybe there were changes from 4.20.13 to 4.20.17?
>>>
>>> Thanks,
>>>
>>> - Greg
>>>
>>>> Signed-off-by: Yifeng Sun <pkusunyifeng at gmail.com>
>>>> ---
>>>>    .travis.yml                                   |  2 +
>>>>    NEWS                                          |  2 +
>>>>    acinclude.m4                                  | 20 ++++-
>>>>    datapath/conntrack.c                          | 72 ++++++++++++++++-
>>>>    .../include/net/netfilter/nf_conntrack_core.h |  6 ++
>>>>    .../net/netfilter/nf_conntrack_count.h        |  2 +
>>>>    datapath/linux/compat/nf_conncount.c          |  6 +-
>>>>    datapath/linux/compat/nf_conntrack_core.c     | 80 +++++++++++++++++++
>>>>    datapath/linux/compat/nf_conntrack_proto.c    |  3 +
>>>>    9 files changed, 186 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/.travis.yml b/.travis.yml
>>>> index 32d5f1918..dc7a20b6e 100644
>>>> --- a/.travis.yml
>>>> +++ b/.travis.yml
>>>> @@ -35,6 +35,8 @@ env:
>>>>      - KERNEL=3.16.54 TESTSUITE=1 DPDK=1
>>>>      - KERNEL=3.16.54 DPDK_SHARED=1
>>>>      - KERNEL=3.16.54 DPDK_SHARED=1 OPTS="--enable-shared"
>>>> +  - KERNEL=4.20.16
>>>> +  - KERNEL=4.19.29
>>>>      - KERNEL=4.18.20
>>>>      - KERNEL=4.17.19
>>>>      - KERNEL=4.16.18
>>>> diff --git a/NEWS b/NEWS
>>>> index 1e4744dbd..af5b5222f 100644
>>>> --- a/NEWS
>>>> +++ b/NEWS
>>>> @@ -25,6 +25,8 @@ Post-v2.11.0
>>>>       - OVN:
>>>>         * Select IPAM mac_prefix in a random manner if not provided by the user
>>>>       - New QoS type "linux-netem" on Linux.
>>>> +   - Linux datapath:
>>>> +     * Support for the kernel versions 4.19.x, 4.20.x.
>>>>
>>>>    v2.11.0 - 19 Feb 2019
>>>>    ---------------------
>>>> diff --git a/acinclude.m4 b/acinclude.m4
>>>> index 3cd6ea730..7b11b7740 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 18; then
>>>> +       if test "$version" = 4 && test "$patchlevel" -le 20; then
>>>>              : # Linux 4.x
>>>>           else
>>>> -          AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.18.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.20.x is not supported (please refer to the FAQ for advice)])
>>>>           fi
>>>>        elif test "$version" = 3 && test "$patchlevel" -ge 10; then
>>>>           : # Linux 3.x
>>>> @@ -583,6 +583,22 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
>>>>                      [OVS_DEFINE([HAVE_VOID_INET_FRAGS_INIT])])
>>>>      OVS_GREP_IFELSE([$KSRC/include/net/inetpeer.h], [vif],
>>>>                      [OVS_DEFINE([HAVE_INETPEER_VIF_SUPPORT])])
>>>> +  OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_helper.h],
>>>> +                        [nf_ct_helper_ext_add], [nf_conntrack_helper],
>>>> +                        [OVS_DEFINE([HAVE_NF_CT_HELPER_EXT_ADD_TAKES_HELPER])])
>>>> +  OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_core.h],
>>>> +                        [nf_ct_invert_tuple], [l3proto],
>>>> +                        [OVS_DEFINE([HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO])])
>>>> +  OVS_GREP_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_core.h], [nf_ct_get_tuple],
>>>> +                  [OVS_DEFINE([HAVE_NF_CT_GET_TUPLE])])
>>>> +  OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_core.h],
>>>> +                        [nf_conntrack_in], [net],
>>>> +                        [OVS_DEFINE([HAVE_NF_CONNTRACK_IN_TAKES_NET])])
>>>> +  OVS_GREP_IFELSE([$KSRC/include/net/ipv6_frag.h], [IP6_DEFRAG_CONNTRACK_IN],
>>>> +                  [OVS_DEFINE([HAVE_IPV6_FRAG_H])])
>>>> +  OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/nf_conntrack_l4proto.h],
>>>> +                        [__nf_ct_l4proto_find], [l3proto],
>>>> +                        [OVS_DEFINE([HAVE_NF_CT_L4PROTO_FIND_TAKES_L3PROTO])])
>>>>
>>>>      dnl Check for dst_cache and ipv6 lable to use backported tunnel infrastructure.
>>>>      dnl OVS does not really need ipv6 label field, but its presence signifies that
>>>> diff --git a/datapath/conntrack.c b/datapath/conntrack.c
>>>> index a7dc9e0c3..b9b79e2cc 100644
>>>> --- a/datapath/conntrack.c
>>>> +++ b/datapath/conntrack.c
>>>> @@ -38,6 +38,10 @@
>>>>    #include <net/netfilter/nf_nat_l3proto.h>
>>>>    #endif
>>>>
>>>> +#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) && defined(HAVE_IPV6_FRAG_H)
>>>> +#include <net/ipv6_frag.h>
>>>> +#endif
>>>> +
>>>>    #include "datapath.h"
>>>>    #include "conntrack.h"
>>>>    #include "flow.h"
>>>> @@ -645,32 +649,62 @@ static struct nf_conn *
>>>>    ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
>>>>                     u8 l3num, struct sk_buff *skb, bool natted)
>>>>    {
>>>> -     const struct nf_conntrack_l3proto *l3proto;
>>>>        const struct nf_conntrack_l4proto *l4proto;
>>>>        struct nf_conntrack_tuple tuple;
>>>>        struct nf_conntrack_tuple_hash *h;
>>>>        struct nf_conn *ct;
>>>> -     unsigned int dataoff;
>>>>        u8 protonum;
>>>>
>>>> +#ifdef HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO
>>>> +     const struct nf_conntrack_l3proto *l3proto;
>>>> +     unsigned int dataoff;
>>>> +
>>>>        l3proto = __nf_ct_l3proto_find(l3num);
>>>>        if (l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff,
>>>>                                 &protonum) <= 0) {
>>>>                pr_debug("ovs_ct_find_existing: Can't get protonum\n");
>>>>                return NULL;
>>>>        }
>>>> +#else
>>>> +     int protooff;
>>>> +
>>>> +     protooff = get_l4proto(skb, skb_network_offset(skb),
>>>> +                            l3num, &protonum);
>>>> +     if (protooff <= 0) {
>>>> +             pr_warn("ovs_ct_find_existing: Can't get protonum\n");
>>>> +             return NULL;
>>>> +     }
>>>> +#endif
>>>> +
>>>> +#ifdef HAVE_NF_CT_L4PROTO_FIND_TAKES_L3PROTO
>>>>        l4proto = __nf_ct_l4proto_find(l3num, protonum);
>>>> -     if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num,
>>>> -                          protonum, net, &tuple, l3proto, l4proto)) {
>>>> +#else
>>>> +     l4proto = __nf_ct_l4proto_find(protonum);
>>>> +#endif
>>>> +
>>>> +#ifdef HAVE_NF_CT_GET_TUPLE
>>>> +     if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
>>>> +                                    l3num, net, &tuple)) {
>>>> +             pr_debug("ovs_ct_find_existing: Can't get tuple\n");
>>>> +             return NULL;
>>>> +     }
>>>> +#else
>>>> +     if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
>>>> +                                    l3num, net, &tuple)) {
>>>>                pr_debug("ovs_ct_find_existing: Can't get tuple\n");
>>>>                return NULL;
>>>>        }
>>>> +#endif
>>>>
>>>>        /* Must invert the tuple if skb has been transformed by NAT. */
>>>>        if (natted) {
>>>>                struct nf_conntrack_tuple inverse;
>>>>
>>>> +#ifdef HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO
>>>>                if (!nf_ct_invert_tuple(&inverse, &tuple, l3proto, l4proto)) {
>>>> +#else
>>>> +             if (!nf_ct_invert_tuple(&inverse, &tuple, l4proto)) {
>>>> +#endif
>>>>                        pr_debug("ovs_ct_find_existing: Inversion failed!\n");
>>>>                        return NULL;
>>>>                }
>>>> @@ -989,6 +1023,9 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
>>>>        if (!cached) {
>>>>                struct nf_conn *tmpl = info->ct;
>>>>                int err;
>>>> +#ifndef HAVE_NF_CONNTRACK_IN_TAKES_NET
>>>> +             struct nf_hook_state state = {};
>>>> +#endif
>>>>
>>>>                /* Associate skb with specified zone. */
>>>>                if (tmpl) {
>>>> @@ -998,8 +1035,15 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
>>>>                        nf_ct_set(skb, tmpl, IP_CT_NEW);
>>>>                }
>>>>
>>>> +#ifdef HAVE_NF_CONNTRACK_IN_TAKES_NET
>>>>                err = nf_conntrack_in(net, info->family,
>>>>                                      NF_INET_PRE_ROUTING, skb);
>>>> +#else
>>>> +             state.hook = NF_INET_PRE_ROUTING,
>>>> +             state.pf = info->family,
>>>> +             state.net = net,
>>>> +             err = nf_conntrack_in(skb, &state);
>>>> +#endif
>>>>                if (err != NF_ACCEPT)
>>>>                        return -ENOENT;
>>>>
>>>> @@ -1307,9 +1351,17 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
>>>>    {
>>>>        int nh_ofs;
>>>>        int err;
>>>> +     /* From kernel 4.19.0+, Function handle_fragments may shrink skb's
>>>> +      * headroom, which will result in loss of ethernet header data.
>>>> +      * This buf is used to backup the header data before calling
>>>> +      * handle_fragments. */
>>>> +     char buf[32];
>>>>
>>>>        /* The conntrack module expects to be working at L3. */
>>>>        nh_ofs = skb_network_offset(skb);
>>>> +     if (nh_ofs > sizeof(buf))
>>>> +             return -EINVAL;
>>>> +     memcpy(buf, skb->data, nh_ofs);
>>>>        skb_pull_rcsum(skb, nh_ofs);
>>>>
>>>>        err = ovs_skb_network_trim(skb);
>>>> @@ -1326,8 +1378,16 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
>>>>                err = ovs_ct_commit(net, key, info, skb);
>>>>        else
>>>>                err = ovs_ct_lookup(net, key, info, skb);
>>>> +     if (err)
>>>> +             return err;
>>>>
>>>> +     if (skb_headroom(skb) < nh_ofs) {
>>>> +             err = pskb_expand_head(skb, nh_ofs, 0, GFP_ATOMIC);
>>>> +             if (err)
>>>> +                     return err;
>>>> +     }
>>>>        skb_push(skb, nh_ofs);
>>>> +     memcpy(skb->data, buf, nh_ofs);
>>>>        skb_postpush_rcsum(skb, skb->data, nh_ofs);
>>>>        if (err)
>>>>                kfree_skb(skb);
>>>> @@ -1362,7 +1422,11 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
>>>>                return -EINVAL;
>>>>        }
>>>>
>>>> +#ifdef HAVE_NF_CT_HELPER_EXT_ADD_TAKES_HELPER
>>>>        help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
>>>> +#else
>>>> +     help = nf_ct_helper_ext_add(info->ct, GFP_KERNEL);
>>>> +#endif
>>>>        if (!help) {
>>>>                nf_conntrack_helper_put(helper);
>>>>                return -ENOMEM;
>>>> diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
>>>> index 7834c8c25..7fca7dc55 100644
>>>> --- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
>>>> +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
>>>> @@ -104,4 +104,10 @@ static inline bool rpl_nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
>>>>    #define nf_ct_delete rpl_nf_ct_delete
>>>>    #endif /* HAVE_NF_CONN_TIMER */
>>>>
>>>> +#ifndef HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO
>>>> +int rpl_get_l4proto(const struct sk_buff *skb,
>>>> +                 unsigned int nhoff, u8 pf, u8 *l4num);
>>>> +#define get_l4proto rpl_get_l4proto
>>>> +#endif
>>>> +
>>>>    #endif /* _NF_CONNTRACK_CORE_WRAPPER_H */
>>>> diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_count.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_count.h
>>>> index fd536f3e1..a26eb9f87 100644
>>>> --- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_count.h
>>>> +++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_count.h
>>>> @@ -4,6 +4,8 @@
>>>>    #include <linux/list.h>
>>>>
>>>>    #ifdef HAVE_UPSTREAM_NF_CONNCOUNT
>>>> +#include <net/netfilter/nf_conntrack_tuple.h>
>>>> +#include <net/netfilter/nf_conntrack_zones.h>
>>>>    #include_next <net/netfilter/nf_conntrack_count.h>
>>>>
>>>>    static inline int rpl_nf_conncount_modinit(void)
>>>> diff --git a/datapath/linux/compat/nf_conncount.c b/datapath/linux/compat/nf_conncount.c
>>>> index 0bee96274..eeae440f8 100644
>>>> --- a/datapath/linux/compat/nf_conncount.c
>>>> +++ b/datapath/linux/compat/nf_conncount.c
>>>> @@ -13,6 +13,8 @@
>>>>     *          only ignore TIME_WAIT or gone connections
>>>>     *   (C) CC Computer Consultants GmbH, 2007
>>>>     */
>>>> +#ifndef HAVE_UPSTREAM_NF_CONNCOUNT
>>>> +
>>>>    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>>>>    #include <linux/in.h>
>>>>    #include <linux/in6.h>
>>>> @@ -138,7 +140,7 @@ static bool conn_free(struct nf_conncount_list *list,
>>>>
>>>>        if (list->count == 0) {
>>>>                spin_unlock(&list->list_lock);
>>>> -                return free_entry;
>>>> +             return free_entry;
>>>>        }
>>>>
>>>>        list->count--;
>>>> @@ -635,3 +637,5 @@ void rpl_nf_conncount_modexit(void)
>>>>        kmem_cache_destroy(conncount_conn_cachep);
>>>>        kmem_cache_destroy(conncount_rb_cachep);
>>>>    }
>>>> +
>>>> +#endif /* HAVE_UPSTREAM_NF_CONNCOUNT */
>>>> diff --git a/datapath/linux/compat/nf_conntrack_core.c b/datapath/linux/compat/nf_conntrack_core.c
>>>> index a7d3d4331..ecfeae1a0 100644
>>>> --- a/datapath/linux/compat/nf_conntrack_core.c
>>>> +++ b/datapath/linux/compat/nf_conntrack_core.c
>>>> @@ -1,4 +1,7 @@
>>>> +#include <linux/types.h>
>>>>    #include <linux/version.h>
>>>> +#include <net/ip.h>
>>>> +#include <net/ipv6.h>
>>>>
>>>>    #ifndef HAVE_NF_CT_ZONE_INIT
>>>>
>>>> @@ -11,3 +14,80 @@ const struct nf_conntrack_zone nf_ct_zone_dflt = {
>>>>    };
>>>>
>>>>    #endif /* HAVE_NF_CT_ZONE_INIT */
>>>> +
>>>> +#ifndef HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO
>>>> +static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
>>>> +                         u_int8_t *protonum)
>>>> +{
>>>> +     int dataoff = -1;
>>>> +     const struct iphdr *iph;
>>>> +     struct iphdr _iph;
>>>> +
>>>> +     iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
>>>> +     if (!iph)
>>>> +             return -1;
>>>> +
>>>> +     /* Conntrack defragments packets, we might still see fragments
>>>> +      * inside ICMP packets though.
>>>> +      */
>>>> +     if (iph->frag_off & htons(IP_OFFSET))
>>>> +             return -1;
>>>> +
>>>> +     dataoff = nhoff + (iph->ihl << 2);
>>>> +     *protonum = iph->protocol;
>>>> +
>>>> +     /* Check bogus IP headers */
>>>> +     if (dataoff > skb->len) {
>>>> +             pr_debug("bogus IPv4 packet: nhoff %u, ihl %u, skblen %u\n",
>>>> +                      nhoff, iph->ihl << 2, skb->len);
>>>> +             return -1;
>>>> +     }
>>>> +     return dataoff;
>>>> +}
>>>> +
>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>> +static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
>>>> +                         u8 *protonum)
>>>> +{
>>>> +     int protoff = -1;
>>>> +     unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
>>>> +     __be16 frag_off;
>>>> +     u8 nexthdr;
>>>> +
>>>> +     if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
>>>> +                       &nexthdr, sizeof(nexthdr)) != 0) {
>>>> +             pr_debug("can't get nexthdr\n");
>>>> +             return -1;
>>>> +     }
>>>> +     protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off);
>>>> +     /*
>>>> +      * (protoff == skb->len) means the packet has not data, just
>>>> +      * IPv6 and possibly extensions headers, but it is tracked anyway
>>>> +      */
>>>> +     if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
>>>> +             pr_debug("can't find proto in pkt\n");
>>>> +             return -1;
>>>> +     }
>>>> +
>>>> +     *protonum = nexthdr;
>>>> +     return protoff;
>>>> +}
>>>> +#endif
>>>> +
>>>> +int rpl_get_l4proto(const struct sk_buff *skb,
>>>> +                 unsigned int nhoff, u8 pf, u8 *l4num)
>>>> +{
>>>> +     switch (pf) {
>>>> +     case NFPROTO_IPV4:
>>>> +             return ipv4_get_l4proto(skb, nhoff, l4num);
>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>> +     case NFPROTO_IPV6:
>>>> +             return ipv6_get_l4proto(skb, nhoff, l4num);
>>>> +#endif
>>>> +     default:
>>>> +             *l4num = 0;
>>>> +             break;
>>>> +     }
>>>> +     return -1;
>>>> +}
>>>> +#endif /* HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO */
>>>> diff --git a/datapath/linux/compat/nf_conntrack_proto.c b/datapath/linux/compat/nf_conntrack_proto.c
>>>> index 4ac66f61c..89c2f5422 100644
>>>> --- a/datapath/linux/compat/nf_conntrack_proto.c
>>>> +++ b/datapath/linux/compat/nf_conntrack_proto.c
>>>> @@ -1,7 +1,10 @@
>>>>    #include <linux/types.h>
>>>>
>>>>    #include <net/netfilter/nf_conntrack.h>
>>>> +
>>>> +#ifdef HAVE_NF_CT_INVERT_TUPLE_TAKES_L3PROTO
>>>>    #include <net/netfilter/nf_conntrack_l3proto.h>
>>>> +#endif
>>>>
>>>>    /*
>>>>     * Upstream net-next commmit 7e35ec0e8044



More information about the dev mailing list