[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 23:08:59 UTC 2019



On 3/29/2019 4:01 PM, Yifeng Sun wrote:
> Hi Greg,
>
> I tried 4.20.17 on 16.04 and it is still working.
> Do you mind sharing your .config file? Maybe there is some config
> differences between our test machines?

Really?  Huh, well now I suspect I did something wrong.  Let me recheck 
and get back.

Thanks,

- Greg

>
> Thanks,
> Yifeng
>
> On Fri, Mar 29, 2019 at 3:28 PM Gregory Rose <gvrose8192 at gmail.com> wrote:
>>
>>
>> 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