diff mbox series

[ovs-dev,V2,02/11] compat: Fix up changes to inet frags in 5.1+

Message ID 1582738882-15842-3-git-send-email-gvrose8192@gmail.com
State Superseded
Headers show
Series Add Linux kernel datapath support up to 5.5 | expand

Commit Message

Gregory Rose Feb. 26, 2020, 5:41 p.m. UTC
Since Linux kernel release 5.1 the fragments field of the inet_frag_queue
structure is removed and now only the rb_fragments structure with an
rb_node pointer is used for both ipv4 and ipv6.  In addition, the
atomic_sub and atomic_add functions are replaced with their
equivalent long counterparts.

Signed-off-by: Greg Rose <gvrose8192@gmail.com>
---
 acinclude.m4                                  |  2 ++
 datapath/linux/compat/include/net/inet_frag.h | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+)

Comments

Yi-Hung Wei Feb. 27, 2020, 11:54 p.m. UTC | #1
On Wed, Feb 26, 2020 at 9:41 AM Greg Rose <gvrose8192@gmail.com> wrote:
>
> Since Linux kernel release 5.1 the fragments field of the inet_frag_queue
> structure is removed and now only the rb_fragments structure with an
> rb_node pointer is used for both ipv4 and ipv6.  In addition, the
> atomic_sub and atomic_add functions are replaced with their
> equivalent long counterparts.
>
> Signed-off-by: Greg Rose <gvrose8192@gmail.com>
> ---
>  acinclude.m4                                  |  2 ++
>  datapath/linux/compat/include/net/inet_frag.h | 21 +++++++++++++++++++++
>  2 files changed, 23 insertions(+)
>
> diff --git a/acinclude.m4 b/acinclude.m4
> index db64267..cad76c7 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -1067,6 +1067,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
>                    [OVS_DEFINE([HAVE_RBTREE_RB_LINK_NODE_RCU])])
>    OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool confirm_neigh],
>                    [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
> +  OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [fqdir],
> +                  [OVS_DEFINE([HAVE_INET_FRAG_FQDIR])])
>
>    if cmp -s datapath/linux/kcompat.h.new \
>              datapath/linux/kcompat.h >/dev/null 2>&1; then
> diff --git a/datapath/linux/compat/include/net/inet_frag.h b/datapath/linux/compat/include/net/inet_frag.h
> index 124c8be..e3c6df3 100644
> --- a/datapath/linux/compat/include/net/inet_frag.h
> +++ b/datapath/linux/compat/include/net/inet_frag.h
> @@ -18,7 +18,16 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>  #ifdef HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR
>         return !hlist_unhashed(&q->list_evictor);
>  #else
> +/*
> + * We can't use acinclude.m4 to check this as the field 'fragments'
> + * also matches 'rb_fragments'.
> + */
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
>         return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != NULL;
> +#else
> +       return (q_flags(q) & INET_FRAG_FIRST_IN) &&
> +                       q->rb_fragments.rb_node != NULL;
> +#endif
>  #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>  }
>  #endif /* HAVE_INET_FRAG_EVICTING */

Yes, it's a bummer if we can not check some fields in the acinclude.m4.

It looks like inet_frag_evicting() has been removed by upstream commit
399d1404be66 ("inet: frags: get rif of inet_frag_evicting()") since
kernel 4.17, and the only place that we use is in rpl_ipfrag_init() ->
ip_expire() when HAVE_CORRECT_MRU_HANDLING is not available.
Therefore, how about the following approach that avoids the less
reliable kernel version check.

--- a/datapath/linux/compat/include/net/inet_frag.h
+++ b/datapath/linux/compat/include/net/inet_frag.h
@@ -12,6 +12,7 @@
 #define qp_flags(qp) (qp->q.flags)
 #endif

+#ifndef HAVE_CORRECT_MRU_HANDLING
 #ifndef HAVE_INET_FRAG_EVICTING
 static inline bool inet_frag_evicting(struct inet_frag_queue *q)
 {
@@ -22,6 +23,7 @@ static inline bool inet_frag_evicting(struct
inet_frag_queue *q)
 #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
 }
 #endif /* HAVE_INET_FRAG_EVICTING */
+#endif /* HAVE_CORRECT_MRU_HANDLING */


I am good with the rest of the backports in this patch.

Thanks,

-Yi-Hung


> @@ -29,6 +38,10 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>  #define inet_frag_lru_move(q)
>  #endif
>
> +#ifdef HAVE_INET_FRAG_FQDIR
> +#define netns_frags fqdir
> +#endif
> +
>  #ifndef HAVE_SUB_FRAG_MEM_LIMIT_ARG_STRUCT_NETNS_FRAGS
>  #ifdef HAVE_FRAG_PERCPU_COUNTER_BATCH
>  static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
> @@ -45,13 +58,21 @@ static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
>  #else /* !frag_percpu_counter_batch */
>  static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
>  {
> +#ifdef HAVE_INET_FRAG_FQDIR
> +       atomic_long_sub(i, &nf->mem);
> +#else
>         atomic_sub(i, &nf->mem);
> +#endif
>  }
>  #define sub_frag_mem_limit rpl_sub_frag_mem_limit
>
>  static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
>  {
> +#ifdef HAVE_INET_FRAG_FQDIR
> +       atomic_long_add(i, &nf->mem);
> +#else
>         atomic_add(i, &nf->mem);
> +#endif
>  }
>  #define add_frag_mem_limit rpl_add_frag_mem_limit
>  #endif /* frag_percpu_counter_batch */
> --
> 1.8.3.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Gregory Rose Feb. 28, 2020, 5:02 p.m. UTC | #2
On 2/27/2020 3:54 PM, Yi-Hung Wei wrote:
> On Wed, Feb 26, 2020 at 9:41 AM Greg Rose <gvrose8192@gmail.com> wrote:
>> Since Linux kernel release 5.1 the fragments field of the inet_frag_queue
>> structure is removed and now only the rb_fragments structure with an
>> rb_node pointer is used for both ipv4 and ipv6.  In addition, the
>> atomic_sub and atomic_add functions are replaced with their
>> equivalent long counterparts.
>>
>> Signed-off-by: Greg Rose <gvrose8192@gmail.com>
>> ---
>>   acinclude.m4                                  |  2 ++
>>   datapath/linux/compat/include/net/inet_frag.h | 21 +++++++++++++++++++++
>>   2 files changed, 23 insertions(+)
>>
>> diff --git a/acinclude.m4 b/acinclude.m4
>> index db64267..cad76c7 100644
>> --- a/acinclude.m4
>> +++ b/acinclude.m4
>> @@ -1067,6 +1067,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
>>                     [OVS_DEFINE([HAVE_RBTREE_RB_LINK_NODE_RCU])])
>>     OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool confirm_neigh],
>>                     [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
>> +  OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [fqdir],
>> +                  [OVS_DEFINE([HAVE_INET_FRAG_FQDIR])])
>>
>>     if cmp -s datapath/linux/kcompat.h.new \
>>               datapath/linux/kcompat.h >/dev/null 2>&1; then
>> diff --git a/datapath/linux/compat/include/net/inet_frag.h b/datapath/linux/compat/include/net/inet_frag.h
>> index 124c8be..e3c6df3 100644
>> --- a/datapath/linux/compat/include/net/inet_frag.h
>> +++ b/datapath/linux/compat/include/net/inet_frag.h
>> @@ -18,7 +18,16 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>>   #ifdef HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR
>>          return !hlist_unhashed(&q->list_evictor);
>>   #else
>> +/*
>> + * We can't use acinclude.m4 to check this as the field 'fragments'
>> + * also matches 'rb_fragments'.
>> + */
>> +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
>>          return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != NULL;
>> +#else
>> +       return (q_flags(q) & INET_FRAG_FIRST_IN) &&
>> +                       q->rb_fragments.rb_node != NULL;
>> +#endif
>>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>>   }
>>   #endif /* HAVE_INET_FRAG_EVICTING */
> Yes, it's a bummer if we can not check some fields in the acinclude.m4.
>
> It looks like inet_frag_evicting() has been removed by upstream commit
> 399d1404be66 ("inet: frags: get rif of inet_frag_evicting()") since
> kernel 4.17, and the only place that we use is in rpl_ipfrag_init() ->
> ip_expire() when HAVE_CORRECT_MRU_HANDLING is not available.
> Therefore, how about the following approach that avoids the less
> reliable kernel version check.
>
> --- a/datapath/linux/compat/include/net/inet_frag.h
> +++ b/datapath/linux/compat/include/net/inet_frag.h
> @@ -12,6 +12,7 @@
>   #define qp_flags(qp) (qp->q.flags)
>   #endif
>
> +#ifndef HAVE_CORRECT_MRU_HANDLING
>   #ifndef HAVE_INET_FRAG_EVICTING
>   static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>   {
> @@ -22,6 +23,7 @@ static inline bool inet_frag_evicting(struct
> inet_frag_queue *q)
>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>   }
>   #endif /* HAVE_INET_FRAG_EVICTING */
> +#endif /* HAVE_CORRECT_MRU_HANDLING */
>
>
> I am good with the rest of the backports in this patch.
>
> Thanks,
>
> -Yi-Hung

Sure, that looks fine to me, I'll update the patch.

- Greg

>
>> @@ -29,6 +38,10 @@ static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>>   #define inet_frag_lru_move(q)
>>   #endif
>>
>> +#ifdef HAVE_INET_FRAG_FQDIR
>> +#define netns_frags fqdir
>> +#endif
>> +
>>   #ifndef HAVE_SUB_FRAG_MEM_LIMIT_ARG_STRUCT_NETNS_FRAGS
>>   #ifdef HAVE_FRAG_PERCPU_COUNTER_BATCH
>>   static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
>> @@ -45,13 +58,21 @@ static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
>>   #else /* !frag_percpu_counter_batch */
>>   static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
>>   {
>> +#ifdef HAVE_INET_FRAG_FQDIR
>> +       atomic_long_sub(i, &nf->mem);
>> +#else
>>          atomic_sub(i, &nf->mem);
>> +#endif
>>   }
>>   #define sub_frag_mem_limit rpl_sub_frag_mem_limit
>>
>>   static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
>>   {
>> +#ifdef HAVE_INET_FRAG_FQDIR
>> +       atomic_long_add(i, &nf->mem);
>> +#else
>>          atomic_add(i, &nf->mem);
>> +#endif
>>   }
>>   #define add_frag_mem_limit rpl_add_frag_mem_limit
>>   #endif /* frag_percpu_counter_batch */
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> dev mailing list
>> dev@openvswitch.org
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
Gregory Rose March 3, 2020, 11:10 p.m. UTC | #3
On 2/28/2020 9:02 AM, Gregory Rose wrote:
> On 2/27/2020 3:54 PM, Yi-Hung Wei wrote:
>> On Wed, Feb 26, 2020 at 9:41 AM Greg Rose <gvrose8192@gmail.com> wrote:
>>> Since Linux kernel release 5.1 the fragments field of the 
>>> inet_frag_queue
>>> structure is removed and now only the rb_fragments structure with an
>>> rb_node pointer is used for both ipv4 and ipv6.  In addition, the
>>> atomic_sub and atomic_add functions are replaced with their
>>> equivalent long counterparts.
>>>
>>> Signed-off-by: Greg Rose <gvrose8192@gmail.com>
>>> ---
>>>   acinclude.m4                                  |  2 ++
>>>   datapath/linux/compat/include/net/inet_frag.h | 21 
>>> +++++++++++++++++++++
>>>   2 files changed, 23 insertions(+)
>>>
>>> diff --git a/acinclude.m4 b/acinclude.m4
>>> index db64267..cad76c7 100644
>>> --- a/acinclude.m4
>>> +++ b/acinclude.m4
>>> @@ -1067,6 +1067,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
>>> [OVS_DEFINE([HAVE_RBTREE_RB_LINK_NODE_RCU])])
>>>     OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool 
>>> confirm_neigh],
>>> [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
>>> +  OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [fqdir],
>>> +                  [OVS_DEFINE([HAVE_INET_FRAG_FQDIR])])
>>>
>>>     if cmp -s datapath/linux/kcompat.h.new \
>>>               datapath/linux/kcompat.h >/dev/null 2>&1; then
>>> diff --git a/datapath/linux/compat/include/net/inet_frag.h 
>>> b/datapath/linux/compat/include/net/inet_frag.h
>>> index 124c8be..e3c6df3 100644
>>> --- a/datapath/linux/compat/include/net/inet_frag.h
>>> +++ b/datapath/linux/compat/include/net/inet_frag.h
>>> @@ -18,7 +18,16 @@ static inline bool inet_frag_evicting(struct 
>>> inet_frag_queue *q)
>>>   #ifdef HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR
>>>          return !hlist_unhashed(&q->list_evictor);
>>>   #else
>>> +/*
>>> + * We can't use acinclude.m4 to check this as the field 'fragments'
>>> + * also matches 'rb_fragments'.
>>> + */
>>> +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
>>>          return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != 
>>> NULL;
>>> +#else
>>> +       return (q_flags(q) & INET_FRAG_FIRST_IN) &&
>>> +                       q->rb_fragments.rb_node != NULL;
>>> +#endif
>>>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>>>   }
>>>   #endif /* HAVE_INET_FRAG_EVICTING */
>> Yes, it's a bummer if we can not check some fields in the acinclude.m4.
>>
>> It looks like inet_frag_evicting() has been removed by upstream commit
>> 399d1404be66 ("inet: frags: get rif of inet_frag_evicting()") since
>> kernel 4.17, and the only place that we use is in rpl_ipfrag_init() ->
>> ip_expire() when HAVE_CORRECT_MRU_HANDLING is not available.
>> Therefore, how about the following approach that avoids the less
>> reliable kernel version check.
>>
>> --- a/datapath/linux/compat/include/net/inet_frag.h
>> +++ b/datapath/linux/compat/include/net/inet_frag.h
>> @@ -12,6 +12,7 @@
>>   #define qp_flags(qp) (qp->q.flags)
>>   #endif
>>
>> +#ifndef HAVE_CORRECT_MRU_HANDLING
>>   #ifndef HAVE_INET_FRAG_EVICTING
>>   static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>>   {
>> @@ -22,6 +23,7 @@ static inline bool inet_frag_evicting(struct
>> inet_frag_queue *q)
>>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>>   }
>>   #endif /* HAVE_INET_FRAG_EVICTING */
>> +#endif /* HAVE_CORRECT_MRU_HANDLING */
>>
>>
>> I am good with the rest of the backports in this patch.

Hi Yi-Hung,

I have a V3 set of patches for this series but I found that the 
inet_frags changes in
this patch (with or without your suggested change) are failing tests 59 
and 60 in
check-kmod on a Ubuntu 18.04 system with the 4.15.0-88-generic kernel.  I'm
investigating that issue and should have the updated V3 patches ready as 
soon
as I sort this out.

Thanks,

- Greg
Gregory Rose March 4, 2020, 9:18 p.m. UTC | #4
On 3/3/2020 3:10 PM, Gregory Rose wrote:
>
> On 2/28/2020 9:02 AM, Gregory Rose wrote:
>> On 2/27/2020 3:54 PM, Yi-Hung Wei wrote:
>>> On Wed, Feb 26, 2020 at 9:41 AM Greg Rose <gvrose8192@gmail.com> wrote:
>>>> Since Linux kernel release 5.1 the fragments field of the 
>>>> inet_frag_queue
>>>> structure is removed and now only the rb_fragments structure with an
>>>> rb_node pointer is used for both ipv4 and ipv6.  In addition, the
>>>> atomic_sub and atomic_add functions are replaced with their
>>>> equivalent long counterparts.
>>>>
>>>> Signed-off-by: Greg Rose <gvrose8192@gmail.com>
>>>> ---
>>>>   acinclude.m4                                  |  2 ++
>>>>   datapath/linux/compat/include/net/inet_frag.h | 21 
>>>> +++++++++++++++++++++
>>>>   2 files changed, 23 insertions(+)
>>>>
>>>> diff --git a/acinclude.m4 b/acinclude.m4
>>>> index db64267..cad76c7 100644
>>>> --- a/acinclude.m4
>>>> +++ b/acinclude.m4
>>>> @@ -1067,6 +1067,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
>>>> [OVS_DEFINE([HAVE_RBTREE_RB_LINK_NODE_RCU])])
>>>>     OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool 
>>>> confirm_neigh],
>>>> [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
>>>> +  OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [fqdir],
>>>> +                  [OVS_DEFINE([HAVE_INET_FRAG_FQDIR])])
>>>>
>>>>     if cmp -s datapath/linux/kcompat.h.new \
>>>>               datapath/linux/kcompat.h >/dev/null 2>&1; then
>>>> diff --git a/datapath/linux/compat/include/net/inet_frag.h 
>>>> b/datapath/linux/compat/include/net/inet_frag.h
>>>> index 124c8be..e3c6df3 100644
>>>> --- a/datapath/linux/compat/include/net/inet_frag.h
>>>> +++ b/datapath/linux/compat/include/net/inet_frag.h
>>>> @@ -18,7 +18,16 @@ static inline bool inet_frag_evicting(struct 
>>>> inet_frag_queue *q)
>>>>   #ifdef HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR
>>>>          return !hlist_unhashed(&q->list_evictor);
>>>>   #else
>>>> +/*
>>>> + * We can't use acinclude.m4 to check this as the field 'fragments'
>>>> + * also matches 'rb_fragments'.
>>>> + */
>>>> +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
>>>>          return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments 
>>>> != NULL;
>>>> +#else
>>>> +       return (q_flags(q) & INET_FRAG_FIRST_IN) &&
>>>> +                       q->rb_fragments.rb_node != NULL;
>>>> +#endif
>>>>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>>>>   }
>>>>   #endif /* HAVE_INET_FRAG_EVICTING */
>>> Yes, it's a bummer if we can not check some fields in the acinclude.m4.
>>>
>>> It looks like inet_frag_evicting() has been removed by upstream commit
>>> 399d1404be66 ("inet: frags: get rif of inet_frag_evicting()") since
>>> kernel 4.17, and the only place that we use is in rpl_ipfrag_init() ->
>>> ip_expire() when HAVE_CORRECT_MRU_HANDLING is not available.
>>> Therefore, how about the following approach that avoids the less
>>> reliable kernel version check.
>>>
>>> --- a/datapath/linux/compat/include/net/inet_frag.h
>>> +++ b/datapath/linux/compat/include/net/inet_frag.h
>>> @@ -12,6 +12,7 @@
>>>   #define qp_flags(qp) (qp->q.flags)
>>>   #endif
>>>
>>> +#ifndef HAVE_CORRECT_MRU_HANDLING
>>>   #ifndef HAVE_INET_FRAG_EVICTING
>>>   static inline bool inet_frag_evicting(struct inet_frag_queue *q)
>>>   {
>>> @@ -22,6 +23,7 @@ static inline bool inet_frag_evicting(struct
>>> inet_frag_queue *q)
>>>   #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
>>>   }
>>>   #endif /* HAVE_INET_FRAG_EVICTING */
>>> +#endif /* HAVE_CORRECT_MRU_HANDLING */
>>>
>>>
>>> I am good with the rest of the backports in this patch.
>
> Hi Yi-Hung,
>
> I have a V3 set of patches for this series but I found that the 
> inet_frags changes in
> this patch (with or without your suggested change) are failing tests 
> 59 and 60 in
> check-kmod on a Ubuntu 18.04 system with the 4.15.0-88-generic 
> kernel.  I'm
> investigating that issue and should have the updated V3 patches ready 
> as soon
> as I sort this out.
>

It turns out the check-kmod (58-60) tests are failing on 
4.15.0-88-generic with
the master branch as well so that is something we'll need to investigate 
and fix.
For now I'll go ahead and prep the V3 patch series and send them on when 
ready.

Thanks,

- Greg
diff mbox series

Patch

diff --git a/acinclude.m4 b/acinclude.m4
index db64267..cad76c7 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1067,6 +1067,8 @@  AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
                   [OVS_DEFINE([HAVE_RBTREE_RB_LINK_NODE_RCU])])
   OVS_GREP_IFELSE([$KSRC/include/net/dst_ops.h], [bool confirm_neigh],
                   [OVS_DEFINE([HAVE_DST_OPS_CONFIRM_NEIGH])])
+  OVS_GREP_IFELSE([$KSRC/include/net/inet_frag.h], [fqdir],
+                  [OVS_DEFINE([HAVE_INET_FRAG_FQDIR])])
 
   if cmp -s datapath/linux/kcompat.h.new \
             datapath/linux/kcompat.h >/dev/null 2>&1; then
diff --git a/datapath/linux/compat/include/net/inet_frag.h b/datapath/linux/compat/include/net/inet_frag.h
index 124c8be..e3c6df3 100644
--- a/datapath/linux/compat/include/net/inet_frag.h
+++ b/datapath/linux/compat/include/net/inet_frag.h
@@ -18,7 +18,16 @@  static inline bool inet_frag_evicting(struct inet_frag_queue *q)
 #ifdef HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR
 	return !hlist_unhashed(&q->list_evictor);
 #else
+/*
+ * We can't use acinclude.m4 to check this as the field 'fragments'
+ * also matches 'rb_fragments'.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0)
 	return (q_flags(q) & INET_FRAG_FIRST_IN) && q->fragments != NULL;
+#else
+	return (q_flags(q) & INET_FRAG_FIRST_IN) &&
+			q->rb_fragments.rb_node != NULL;
+#endif
 #endif /* HAVE_INET_FRAG_QUEUE_WITH_LIST_EVICTOR */
 }
 #endif /* HAVE_INET_FRAG_EVICTING */
@@ -29,6 +38,10 @@  static inline bool inet_frag_evicting(struct inet_frag_queue *q)
 #define inet_frag_lru_move(q)
 #endif
 
+#ifdef HAVE_INET_FRAG_FQDIR
+#define netns_frags fqdir
+#endif
+
 #ifndef HAVE_SUB_FRAG_MEM_LIMIT_ARG_STRUCT_NETNS_FRAGS
 #ifdef HAVE_FRAG_PERCPU_COUNTER_BATCH
 static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
@@ -45,13 +58,21 @@  static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
 #else /* !frag_percpu_counter_batch */
 static inline void rpl_sub_frag_mem_limit(struct netns_frags *nf, int i)
 {
+#ifdef HAVE_INET_FRAG_FQDIR
+	atomic_long_sub(i, &nf->mem);
+#else
 	atomic_sub(i, &nf->mem);
+#endif
 }
 #define sub_frag_mem_limit rpl_sub_frag_mem_limit
 
 static inline void rpl_add_frag_mem_limit(struct netns_frags *nf, int i)
 {
+#ifdef HAVE_INET_FRAG_FQDIR
+	atomic_long_add(i, &nf->mem);
+#else
 	atomic_add(i, &nf->mem);
+#endif
 }
 #define add_frag_mem_limit rpl_add_frag_mem_limit
 #endif /* frag_percpu_counter_batch */