This patchset adds support to do GRO/GSO by chaining packets
of the same flow at the SKB frag_list pointer. This avoids
the overhead to merge payloads into one big packet, and
on the other end, if GSO is needed it avoids the overhead
of splitting the big packet back to the native form.
Patch 1 Enables UDP GRO by default.
Patch 2 adds netdev feature flags to enable listifyed GRO,
this implements one of the configuration options discussed
at netconf 2019.
Patch 3 adds a netdev software feature set that defaults to off
and assigns the new listifyed GRO feature flag to it.
Patch 4 adds the core infrastructure to do fraglist GRO/GSO.
Patch 5 enables UDP to use fraglist GRO/GSO if configured and no
GRO supported socket is found.
I have only meaningful forwarding performance measurements.
I did some tests for the local receive path with netperf and iperf,
but in this case the sender that generates the packets is the
bottleneck. So the benchmarks are not that meaningful for the
receive path.
Paolo Abeni did some benchmarks of the local receive path for the v2
version of this pachset, results can be found here:
https://www.spinics.net/lists/netdev/msg551158.html
I used my IPsec forwarding test setup for the performance measurements:
------------ ------------
-->| router 1 |-------->| router 2 |--
| ------------ ------------ |
| |
| -------------------- |
--------|Spirent Testcenter|<----------
--------------------
net-next (September 7th):
Single stream UDP frame size 1460 Bytes: 1.161.000 fps (13.5 Gbps).
----------------------------------------------------------------------
net-next (September 7th) + standard UDP GRO/GSO:
Single stream UDP frame size 1460 Bytes: 1.801.000 fps (21 Gbps).
----------------------------------------------------------------------
net-next (September 7th) + fraglist UDP GRO/GSO:
Single stream UDP frame size 1460 Bytes: 2.860.000 fps (33.4 Gbps).
-----------------------------------------------------------------------
Changes from v1:
- Add IPv6 support.
- Split patchset to enable UDP GRO by default before adding
fraglist GRO support.
- Mark fraglist GRO packets as CHECKSUM_NONE.
- Take a refcount on the first segment skb when doing fraglist
segmentation. With this we can use the same error handling
path as with standard segmentation.
Changes from v2:
- Add a netdev feature flag to configure listifyed GRO.
- Fix UDP GRO enabling for IPv6.
- Fix a rcu_read_lock() imbalance.
- Fix error path in skb_segment_list().
Changes from v3:
- Rename NETIF_F_GRO_LIST to NETIF_F_GRO_FRAGLIST and add
NETIF_F_GSO_FRAGLIST.
- Move introduction of SKB_GSO_FRAGLIST to patch 2.
- Use udpv6_encap_needed_key instead of udp_encap_needed_key in IPv6.
- Move some missplaced code from patch 5 to patch 1 where it belongs to.
The previous patch added the NETIF_F_GRO_FRAGLIST feature.
This is a software feature that should default to off.
Current software features default to on, so add a new
feature set that defaults to off.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/linux/netdev_features.h | 3 +++
net/core/dev.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
@@ -230,6 +230,9 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)/* changeable features with no special hardware requirements */#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO)+/* Changeable features with no special hardware requirements that defaults to off. */+#define NETIF_F_SOFT_FEATURES_OFF NETIF_F_GRO_FRAGLIST+#define NETIF_F_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \NETIF_F_HW_VLAN_CTAG_RX|\NETIF_F_HW_VLAN_CTAG_TX|\
@@ -8730,7 +8730,7 @@ int register_netdevice(struct net_device *dev)/* Transfer changeable features to wanted_features and enable*softwareoffloads(GSOandGRO).*/-dev->hw_features|=NETIF_F_SOFT_FEATURES;+dev->hw_features|=(NETIF_F_SOFT_FEATURES|NETIF_F_SOFT_FEATURES_OFF);dev->features|=NETIF_F_SOFT_FEATURES;if(dev->netdev_ops->ndo_udp_tunnel_add){
This patch adds the core functions to chain/unchain
GSO skbs at the frag_list pointer. This also adds
a new GSO type SKB_GSO_FRAGLIST and a is_flist
flag to napi_gro_cb which indicates that this
flow will be GROed by fraglist chaining.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/linux/netdevice.h | 4 +-
include/linux/skbuff.h | 2 +
net/core/dev.c | 2 +-
net/core/skbuff.c | 106 ++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+), 2 deletions(-)
@@ -2306,7 +2306,8 @@ struct napi_gro_cb {/* Number of gro_receive callbacks this packet already went through */u8recursion_counter:4;-/* 1 bit hole */+/* GRO is done by frag_list pointer chaining. */+u8is_flist:1;/* used to support CHECKSUM_COMPLETE for tunneling protocols */__wsumcsum;
@@ -2656,6 +2657,7 @@ struct net_device *dev_get_by_napi_id(unsigned int napi_id);intnetdev_get_name(structnet*net,char*name,intifindex);intdev_restart(structnet_device*dev);intskb_gro_receive(structsk_buff*p,structsk_buff*skb);+intskb_gro_receive_list(structsk_buff*p,structsk_buff*skb);staticinlineunsignedintskb_gro_offset(conststructsk_buff*skb){
This patch enables UDP GRO regardless if a GRO capable
socket is present. With this GRO is done by default
for the local input and forwarding path.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/udp.h | 2 +-
net/ipv4/udp_offload.c | 38 ++++++++++++++++----------------------
net/ipv6/udp_offload.c | 10 ++++++++--
3 files changed, 25 insertions(+), 25 deletions(-)
@@ -401,36 +401,25 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,returnNULL;}-INDIRECT_CALLABLE_DECLARE(structsock*udp6_lib_lookup_skb(structsk_buff*skb,-__be16sport,__be16dport));structsk_buff*udp_gro_receive(structlist_head*head,structsk_buff*skb,-structudphdr*uh,udp_lookup_tlookup)+structudphdr*uh,structsock*sk){structsk_buff*pp=NULL;structsk_buff*p;structudphdr*uh2;unsignedintoff=skb_gro_offset(skb);intflush=1;-structsock*sk;-rcu_read_lock();-sk=INDIRECT_CALL_INET(lookup,udp6_lib_lookup_skb,-udp4_lib_lookup_skb,skb,uh->source,uh->dest);-if(!sk)-gotoout_unlock;--if(udp_sk(sk)->gro_enabled){+if(!sk||!udp_sk(sk)->gro_receive){pp=call_gro_receive(udp_gro_receive_segment,head,skb);-rcu_read_unlock();returnpp;}if(NAPI_GRO_CB(skb)->encap_mark||(skb->ip_summed!=CHECKSUM_PARTIAL&&NAPI_GRO_CB(skb)->csum_cnt==0&&-!NAPI_GRO_CB(skb)->csum_valid)||-!udp_sk(sk)->gro_receive)-gotoout_unlock;+!NAPI_GRO_CB(skb)->csum_valid))+gotoout;/* mark that this skb passed once through the tunnel gro layer */NAPI_GRO_CB(skb)->encap_mark=1;
@@ -517,9 +511,7 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff,rcu_read_lock();sk=INDIRECT_CALL_INET(lookup,udp6_lib_lookup_skb,udp4_lib_lookup_skb,skb,uh->source,uh->dest);-if(sk&&udp_sk(sk)->gro_enabled){-err=udp_gro_complete_segment(skb);-}elseif(sk&&udp_sk(sk)->gro_complete){+if(sk&&udp_sk(sk)->gro_complete){skb_shinfo(skb)->gso_type=uh->check?SKB_GSO_UDP_TUNNEL_CSUM:SKB_GSO_UDP_TUNNEL;
@@ -529,6 +521,8 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff,skb->encapsulation=1;err=udp_sk(sk)->gro_complete(sk,skb,nhoff+sizeof(structudphdr));+}else{+err=udp_gro_complete_segment(skb);}rcu_read_unlock();
This adds new Fraglist GRO/GSO feature flags. They will be used
to configure fraglist GRO/GSO what will be implemented with some
followup paches.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/linux/netdev_features.h | 6 +++++-
include/linux/netdevice.h | 1 +
include/linux/skbuff.h | 2 ++
net/core/ethtool.c | 1 +
4 files changed, 9 insertions(+), 1 deletion(-)
@@ -150,6 +152,8 @@ enum {#define NETIF_F_GSO_UDP_L4 __NETIF_F(GSO_UDP_L4)#define NETIF_F_HW_TLS_TX __NETIF_F(HW_TLS_TX)#define NETIF_F_HW_TLS_RX __NETIF_F(HW_TLS_RX)+#define NETIF_F_GRO_FRAGLIST __NETIF_F(GRO_FRAGLIST)+#define NETIF_F_GSO_FRAGLIST __NETIF_F(GSO_FRAGLIST)/* Finds the next feature with the highest number of the range of start till 0.*/
This patch extends UDP GRO to support fraglist GRO/GSO
by using the previously introduced infrastructure.
All UDP packets that are not targeted to a GRO capable
UDP sockets are going to fraglist GRO now (local input
and forward).
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/udp_offload.c | 56 +++++++++++++++++++++++++++++++++++++++---
net/ipv6/udp_offload.c | 9 +++++++
2 files changed, 62 insertions(+), 3 deletions(-)
@@ -354,6 +371,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,structudphdr*uh2;structsk_buff*p;unsignedintulen;+intret=0;/* requires non zero csum, for symmetry with GSO */if(!uh->check){
@@ -383,14 +400,35 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,continue;}+if(NAPI_GRO_CB(skb)->is_flist!=NAPI_GRO_CB(p)->is_flist){+NAPI_GRO_CB(skb)->flush=1;+returnp;+}+/* Terminate the flow on len mismatch or if it grow "too much".*UndersmallpacketfloodGROcountcouldelsewheregrowalot*leadingtoexcessivetruesizevalues.*Onlenmismatchmergethefirstpacketshorterthangso_size,*otherwisecompletetheGROpacket.*/-if(ulen>ntohs(uh2->len)||skb_gro_receive(p,skb)||-ulen!=ntohs(uh2->len)||+if(ulen>ntohs(uh2->len)){+pp=p;+}else{+if(NAPI_GRO_CB(skb)->is_flist){+if(!pskb_may_pull(skb,skb_gro_offset(skb))){+NAPI_GRO_CB(skb)->flush=1;+returnNULL;+}+ret=skb_gro_receive_list(p,skb);+}else{+skb_gro_postpull_rcsum(skb,uh,+sizeof(structudphdr));++ret=skb_gro_receive(p,skb);+}+}++if(ret||ulen!=ntohs(uh2->len)||NAPI_GRO_CB(p)->count>=UDP_GRO_CNT_MAX)pp=p;
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-09-23 12:39:39
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
quoted hunk
The previous patch added the NETIF_F_GRO_FRAGLIST feature.
This is a software feature that should default to off.
Current software features default to on, so add a new
feature set that defaults to off.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/linux/netdev_features.h | 3 +++
net/core/dev.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
@@ -230,6 +230,9 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)/* changeable features with no special hardware requirements */#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO)+/* Changeable features with no special hardware requirements that defaults to off. */+#define NETIF_F_SOFT_FEATURES_OFF NETIF_F_GRO_FRAGLIST+
NETIF_F_GRO_FRAGLIST is not really a device feature, but a way to
configure which form of UDP GRO to apply.
The UDP GRO benchmarks were largely positive, but not a strict win if
I read Paolo's previous results correctly. Even if enabling to by
default, it probably should come with a sysctl to disable for specific
workloads.
If so, how about a ternary per-netns sysctl {off, on without gro-list,
on with gro-list} instead of configuring through ethtool?
Alternative, the choice between gro-list or not could perhaps be
informed by whether ip_forward is set. I think we discussed that and
it was rejected, but I cannot remember why.
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-09-23 12:54:21
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
quoted hunk
This patch enables UDP GRO regardless if a GRO capable
socket is present. With this GRO is done by default
for the local input and forwarding path.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
Not critical, but the use of sk->gro_enabled and sk->gro_receive to
signal whether sockets are willing to accept large packets or are udp
tunnels, respectively, is subtle and possibly confusing.
Wrappers udp_sock_is_tunnel and udp_sock_accepts_gso could perhaps
help document the logic a bit.
static inline bool udp_sock_is_tunnel(struct udp_sock *up)
{
return up->gro_receive;
}
And perhaps only pass a non-zero sk to udp_gro_receive if it is a
tunnel and thus skips the new default path:
static inline struct sock *sk = udp4_lookup_tunnel(const struct
sk_buff *skb, __be16 sport, __be16_dport)
{
struct sock *sk;
if (!static_branch_unlikely(&udp_encap_needed_key))
return NULL;
rcu_read_lock();
sk = udp4_lib_lookup_skb(skb, source, dest);
rcu_read_unlock();
return udp_sock_is_tunnel(udp_sk(sk)) ? sk : NULL;
}
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-09-23 12:56:14
On Mon, Sep 23, 2019 at 8:53 AM Willem de Bruijn
[off-list ref] wrote:
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
quoted
This patch enables UDP GRO regardless if a GRO capable
socket is present. With this GRO is done by default
for the local input and forwarding path.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
Not critical, but the use of sk->gro_enabled and sk->gro_receive to
signal whether sockets are willing to accept large packets or are udp
tunnels, respectively, is subtle and possibly confusing.
Wrappers udp_sock_is_tunnel and udp_sock_accepts_gso could perhaps
help document the logic a bit.
static inline bool udp_sock_is_tunnel(struct udp_sock *up)
{
return up->gro_receive;
}
And perhaps only pass a non-zero sk to udp_gro_receive if it is a
tunnel and thus skips the new default path:
static inline struct sock *sk = udp4_lookup_tunnel(const struct
sk_buff *skb, __be16 sport, __be16_dport)
{
struct sock *sk;
if (!static_branch_unlikely(&udp_encap_needed_key))
return NULL;
rcu_read_lock();
sk = udp4_lib_lookup_skb(skb, source, dest);
rcu_read_unlock();
return udp_sock_is_tunnel(udp_sk(sk)) ? sk : NULL;
}
From: Willem de Bruijn <willemb@google.com> Date: 2019-09-23 13:01:53
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
This patch extends UDP GRO to support fraglist GRO/GSO
by using the previously introduced infrastructure.
All UDP packets that are not targeted to a GRO capable
UDP sockets are going to fraglist GRO now (local input
and forward).
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
@@ -230,6 +230,9 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)/* changeable features with no special hardware requirements */#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO)+/* Changeable features with no special hardware requirements that defaults to off. */+#define NETIF_F_SOFT_FEATURES_OFF NETIF_F_GRO_FRAGLIST+
NETIF_F_GRO_FRAGLIST is not really a device feature, but a way to
configure which form of UDP GRO to apply.
NETIF_F_GRO is also not really a device feature. It is a feature with
no special hardware requirements, as NETIF_F_GRO_FRAGLIST is.
Fraglist GRO is a special way to do GRO and should be configured in the
same way we configure standard GRO.
The UDP GRO benchmarks were largely positive, but not a strict win if
I read Paolo's previous results correctly. Even if enabling to by
default, it probably should come with a sysctl to disable for specific
workloads.
Maybe we can just keep the default for the local input path
as is and enable GRO as this:
For standard UDP GRO on local input, do GRO only if a GRO enabled
socket is found.
If there is no local socket found and forwarding is enabled,
assume forwarding and do standard GRO.
If fraglist GRO is enabled, do it as default on local input and
forwarding because it is explicitly configured.
Would such a policy make semse?
If so, how about a ternary per-netns sysctl {off, on without gro-list,
on with gro-list} instead of configuring through ethtool?
I'd not like to have a global knob to configure this.
On some devices it might make sense to enable fraglist
GRO, but on others not. Also it would be nice if we can
configure both vatiants with the same tool (ethtool).
On Mon, Sep 23, 2019 at 09:01:13AM -0400, Willem de Bruijn wrote:
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
quoted
This patch extends UDP GRO to support fraglist GRO/GSO
by using the previously introduced infrastructure.
All UDP packets that are not targeted to a GRO capable
UDP sockets are going to fraglist GRO now (local input
and forward).
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
@@ -230,6 +230,9 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)/* changeable features with no special hardware requirements */#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO)+/* Changeable features with no special hardware requirements that defaults to off. */+#define NETIF_F_SOFT_FEATURES_OFF NETIF_F_GRO_FRAGLIST+
NETIF_F_GRO_FRAGLIST is not really a device feature, but a way to
configure which form of UDP GRO to apply.
NETIF_F_GRO is also not really a device feature. It is a feature with
no special hardware requirements, as NETIF_F_GRO_FRAGLIST is.
Fraglist GRO is a special way to do GRO and should be configured in the
same way we configure standard GRO.
quoted
The UDP GRO benchmarks were largely positive, but not a strict win if
I read Paolo's previous results correctly. Even if enabling to by
default, it probably should come with a sysctl to disable for specific
workloads.
Maybe we can just keep the default for the local input path
as is and enable GRO as this:
For standard UDP GRO on local input, do GRO only if a GRO enabled
socket is found.
If there is no local socket found and forwarding is enabled,
assume forwarding and do standard GRO.
If fraglist GRO is enabled, do it as default on local input and
forwarding because it is explicitly configured.
Would such a policy make semse?
Making the choice between fraglist or non-fraglist GRO explicitly
configurable sounds great. Per device through ethtool over global
sysctl, too.
My main concern is not this patch, but 1/5 that enables UDP GRO by
default. There should be a way to disable it, at least.
I guess your suggestion is to only enable it with forwarding, which is
unlikely to see a cycle regression. And if there is a latency
regression, disable all GRO to disable UDP GRO.
Instead, how about adding a UDP GRO ethtool feature independent of
forwarding, analogous to fraglist GRO? Then both are explicitly under
admin control. And can be enabled by default (either now, or after
getting more data).
quoted
If so, how about a ternary per-netns sysctl {off, on without gro-list,
on with gro-list} instead of configuring through ethtool?
I'd not like to have a global knob to configure this.
On some devices it might make sense to enable fraglist
GRO, but on others not. Also it would be nice if we can
configure both vatiants with the same tool (ethtool).
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-09-30 15:32:48
On Mon, Sep 30, 2019 at 2:30 AM Steffen Klassert
[off-list ref] wrote:
On Mon, Sep 23, 2019 at 09:01:13AM -0400, Willem de Bruijn wrote:
quoted
On Fri, Sep 20, 2019 at 12:49 AM Steffen Klassert
[off-list ref] wrote:
quoted
This patch extends UDP GRO to support fraglist GRO/GSO
by using the previously introduced infrastructure.
All UDP packets that are not targeted to a GRO capable
UDP sockets are going to fraglist GRO now (local input
and forward).
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
On Mon, Sep 30, 2019 at 11:26:55AM -0400, Willem de Bruijn wrote:
On Mon, Sep 30, 2019 at 2:24 AM Steffen Klassert
[off-list ref] wrote:
quoted
On Mon, Sep 23, 2019 at 08:38:56AM -0400, Willem de Bruijn wrote:
quoted
The UDP GRO benchmarks were largely positive, but not a strict win if
I read Paolo's previous results correctly. Even if enabling to by
default, it probably should come with a sysctl to disable for specific
workloads.
Maybe we can just keep the default for the local input path
as is and enable GRO as this:
For standard UDP GRO on local input, do GRO only if a GRO enabled
socket is found.
If there is no local socket found and forwarding is enabled,
assume forwarding and do standard GRO.
If fraglist GRO is enabled, do it as default on local input and
forwarding because it is explicitly configured.
Would such a policy make semse?
Making the choice between fraglist or non-fraglist GRO explicitly
configurable sounds great. Per device through ethtool over global
sysctl, too.
My main concern is not this patch, but 1/5 that enables UDP GRO by
default. There should be a way to disable it, at least.
I guess your suggestion is to only enable it with forwarding, which is
unlikely to see a cycle regression. And if there is a latency
regression, disable all GRO to disable UDP GRO.
Yes, do GRO only for forwarding or if there is a GRO capable socket.
In this case it can be disabled only by disable all GRO.
It might be a disadvantage, but that's how it is with other
protocols too.
Instead, how about adding a UDP GRO ethtool feature independent of
forwarding, analogous to fraglist GRO? Then both are explicitly under
admin control. And can be enabled by default (either now, or after
getting more data).
We could add a protocol specific feature, but what would it mean
if UDP GRO is enabled?
Would it be enabled for forwarding, and for local input only if there
is a GRO capable socket? Or would it be enabled even if there
is no GRO capable socket? Same question when UDP GRO is disabled.
Also, what means enabling GRO then? Enable GRO for all protocols
but UDP? Either UDP becomes something special then, or we need
to create protocol specific features for the other protocols
too. Same would apply for fraglist GRO.
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-10-01 12:43:47
On Tue, Oct 1, 2019 at 2:18 AM Steffen Klassert
[off-list ref] wrote:
On Mon, Sep 30, 2019 at 11:26:55AM -0400, Willem de Bruijn wrote:
quoted
On Mon, Sep 30, 2019 at 2:24 AM Steffen Klassert
[off-list ref] wrote:
quoted
On Mon, Sep 23, 2019 at 08:38:56AM -0400, Willem de Bruijn wrote:
quoted
The UDP GRO benchmarks were largely positive, but not a strict win if
I read Paolo's previous results correctly. Even if enabling to by
default, it probably should come with a sysctl to disable for specific
workloads.
Maybe we can just keep the default for the local input path
as is and enable GRO as this:
For standard UDP GRO on local input, do GRO only if a GRO enabled
socket is found.
If there is no local socket found and forwarding is enabled,
assume forwarding and do standard GRO.
If fraglist GRO is enabled, do it as default on local input and
forwarding because it is explicitly configured.
Would such a policy make semse?
Making the choice between fraglist or non-fraglist GRO explicitly
configurable sounds great. Per device through ethtool over global
sysctl, too.
My main concern is not this patch, but 1/5 that enables UDP GRO by
default. There should be a way to disable it, at least.
I guess your suggestion is to only enable it with forwarding, which is
unlikely to see a cycle regression. And if there is a latency
regression, disable all GRO to disable UDP GRO.
Yes, do GRO only for forwarding or if there is a GRO capable socket.
In this case it can be disabled only by disable all GRO.
It might be a disadvantage, but that's how it is with other
protocols too.
quoted
Instead, how about adding a UDP GRO ethtool feature independent of
forwarding, analogous to fraglist GRO? Then both are explicitly under
admin control. And can be enabled by default (either now, or after
getting more data).
We could add a protocol specific feature, but what would it mean
if UDP GRO is enabled?
Would it be enabled for forwarding, and for local input only if there
is a GRO capable socket? Or would it be enabled even if there
is no GRO capable socket? Same question when UDP GRO is disabled.
Enable UDP GRO for all traffic if GRO and UDP GRO are set, and only
then. That seems like the easiest to understand behavior to me, and
gives administrators an opt-out for workloads where UDP GRO causes a
regression. We cannot realistically turn off all GRO on a mixed
TCP/UDP workload (like, say, hosting TCP and QUIC).
Also, what means enabling GRO then? Enable GRO for all protocols
but UDP? Either UDP becomes something special then,
Yes and true. But it is something special. We don't know whether UDP
GRO is safe to deploy everywhere.
Only enabling it for the forwarding case is more conservative, but
gives no path to enabling it systemwide, is arguably confusing and
still lacks the admin control to turn off in case of unexpected
regressions. I do think that for a time this needs to be configurable
unless you're confident that the forwarding path is such a win that
no plan B is needed. But especially without fraglist, I'm not sure.
or we need
to create protocol specific features for the other protocols
too. Same would apply for fraglist GRO.
We don't need it for other protocols after the fact, but it's a good
question: I don't know how it was enabled for them. Perhaps confidence
was gained based on testing. Or it was enabled for -rc1, no one
complained and stayed turned on. In which case you could do the same.
On Tue, Oct 01, 2019 at 08:43:05AM -0400, Willem de Bruijn wrote:
On Tue, Oct 1, 2019 at 2:18 AM Steffen Klassert
[off-list ref] wrote:
quoted
On Mon, Sep 30, 2019 at 11:26:55AM -0400, Willem de Bruijn wrote:
quoted
Instead, how about adding a UDP GRO ethtool feature independent of
forwarding, analogous to fraglist GRO? Then both are explicitly under
admin control. And can be enabled by default (either now, or after
getting more data).
We could add a protocol specific feature, but what would it mean
if UDP GRO is enabled?
Would it be enabled for forwarding, and for local input only if there
is a GRO capable socket? Or would it be enabled even if there
is no GRO capable socket? Same question when UDP GRO is disabled.
Enable UDP GRO for all traffic if GRO and UDP GRO are set, and only
then.
But this means that we would need to enable UDP GRO by default then.
Currently, if an application uses a UDP GRO capable socket, it
can expect that it gets GROed packets without doing any additional
configuration. This would change if we disable it by default.
Unfortunately, enabling UDP GRO by default has the biggest
risk because most applications don't use UDP GRO capable sockets.
The most condervative way would be to leave standard GRO as it is.
But on some workloads standard GRO might be preferable, in
particular on forwarding to a NIC that can do UDP segmentation
in hardware.
That seems like the easiest to understand behavior to me, and
gives administrators an opt-out for workloads where UDP GRO causes a
regression. We cannot realistically turn off all GRO on a mixed
TCP/UDP workload (like, say, hosting TCP and QUIC).
quoted
Also, what means enabling GRO then? Enable GRO for all protocols
but UDP? Either UDP becomes something special then,
Yes and true. But it is something special. We don't know whether UDP
GRO is safe to deploy everywhere.
Only enabling it for the forwarding case is more conservative, but
gives no path to enabling it systemwide, is arguably confusing and
still lacks the admin control to turn off in case of unexpected
regressions. I do think that for a time this needs to be configurable
unless you're confident that the forwarding path is such a win that
no plan B is needed. But especially without fraglist, I'm not sure.
On my tests it was a win on forwarding, but there might be
usecases where it is not. I guess the only way to find this out
is to enable is and wait what happens.
I'm a bit hesitating on adding a feature flag that might be only
temporary usefull. In particular on the background of the talk
that Jesse Brandeburg gave on the LPC last year. Maybe you
remember the slide where he showed the output of
ethtool --show-offloads, it filled the whole page.
quoted
or we need
to create protocol specific features for the other protocols
too. Same would apply for fraglist GRO.
We don't need it for other protocols after the fact, but it's a good
question: I don't know how it was enabled for them. Perhaps confidence
was gained based on testing. Or it was enabled for -rc1, no one
complained and stayed turned on. In which case you could do the same.
Maybe we should go that way to enable it and wait whether somebody
complains. A patch to add the feature flag could be prepared
beforehand for that case.
It is easy to make a suboptimal design decision here, so
some more opinions would be helpfull.
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: 2019-10-02 12:32:53
On Wed, Oct 2, 2019 at 4:27 AM Steffen Klassert
[off-list ref] wrote:
On Tue, Oct 01, 2019 at 08:43:05AM -0400, Willem de Bruijn wrote:
quoted
On Tue, Oct 1, 2019 at 2:18 AM Steffen Klassert
[off-list ref] wrote:
quoted
On Mon, Sep 30, 2019 at 11:26:55AM -0400, Willem de Bruijn wrote:
quoted
Instead, how about adding a UDP GRO ethtool feature independent of
forwarding, analogous to fraglist GRO? Then both are explicitly under
admin control. And can be enabled by default (either now, or after
getting more data).
We could add a protocol specific feature, but what would it mean
if UDP GRO is enabled?
Would it be enabled for forwarding, and for local input only if there
is a GRO capable socket? Or would it be enabled even if there
is no GRO capable socket? Same question when UDP GRO is disabled.
Enable UDP GRO for all traffic if GRO and UDP GRO are set, and only
then.
But this means that we would need to enable UDP GRO by default then.
That is what your patch 1/5 does. My concern was that that is a bold
change without an admin opt-out.
Currently, if an application uses a UDP GRO capable socket, it
can expect that it gets GROed packets without doing any additional
configuration. This would change if we disable it by default.
Unfortunately, enabling UDP GRO by default has the biggest
risk because most applications don't use UDP GRO capable sockets.
The most condervative way would be to leave standard GRO as it is.
But on some workloads standard GRO might be preferable, in
particular on forwarding to a NIC that can do UDP segmentation
in hardware.
quoted
That seems like the easiest to understand behavior to me, and
gives administrators an opt-out for workloads where UDP GRO causes a
regression. We cannot realistically turn off all GRO on a mixed
TCP/UDP workload (like, say, hosting TCP and QUIC).
quoted
Also, what means enabling GRO then? Enable GRO for all protocols
but UDP? Either UDP becomes something special then,
Yes and true. But it is something special. We don't know whether UDP
GRO is safe to deploy everywhere.
Only enabling it for the forwarding case is more conservative, but
gives no path to enabling it systemwide, is arguably confusing and
still lacks the admin control to turn off in case of unexpected
regressions. I do think that for a time this needs to be configurable
unless you're confident that the forwarding path is such a win that
no plan B is needed. But especially without fraglist, I'm not sure.
On my tests it was a win on forwarding, but there might be
usecases where it is not. I guess the only way to find this out
is to enable is and wait what happens.
I'm a bit hesitating on adding a feature flag that might be only
temporary usefull. In particular on the background of the talk
that Jesse Brandeburg gave on the LPC last year. Maybe you
remember the slide where he showed the output of
ethtool --show-offloads, it filled the whole page.
I was using ethtool -K just yesterday to debug a peculiar mix of
tunneling protocols. And yes, used grep on it ;) But I don't have much
of a problem with this.
But agreed that if default on works in all cases, then it's unnecessary.
quoted
quoted
or we need
to create protocol specific features for the other protocols
too. Same would apply for fraglist GRO.
We don't need it for other protocols after the fact, but it's a good
question: I don't know how it was enabled for them. Perhaps confidence
was gained based on testing. Or it was enabled for -rc1, no one
complained and stayed turned on. In which case you could do the same.
Maybe we should go that way to enable it and wait whether somebody
complains. A patch to add the feature flag could be prepared
beforehand for that case.
This early in the cycle, that may work. Yes, it's definitely good to
have the plan B at the ready.
It is easy to make a suboptimal design decision here, so
some more opinions would be helpfull.