diff options
author | Alexander Duyck <aduyck@mirantis.com> | 2016-04-05 12:13:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-07 16:56:33 -0400 |
commit | a0ca153f98db8cf25298565a09e11fe9d82846ad (patch) | |
tree | 5f7773cd6e2dbf30f3af97194a8b7d04b99fd1a0 | |
parent | 0a1a37b6d62e6864a77a82e925217c720f91f963 (diff) |
GRE: Disable segmentation offloads w/ CSUM and we are encapsulated via FOU
This patch fixes an issue I found in which we were dropping frames if we
had enabled checksums on GRE headers that were encapsulated by either FOU
or GUE. Without this patch I was barely able to get 1 Gb/s of throughput.
With this patch applied I am now at least getting around 6 Gb/s.
The issue is due to the fact that with FOU or GUE applied we do not provide
a transport offset pointing to the GRE header, nor do we offload it in
software as the GRE header is completely skipped by GSO and treated like a
VXLAN or GENEVE type header. As such we need to prevent the stack from
generating it and also prevent GRE from generating it via any interface we
create.
Fixes: c3483384ee511 ("gro: Allow tunnel stacking in the case of FOU/GUE")
Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netdevice.h | 5 | ||||
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/ipv4/fou.c | 6 | ||||
-rw-r--r-- | net/ipv4/gre_offload.c | 8 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 13 |
5 files changed, 29 insertions, 4 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cb0d5d09c2e4..8395308a2445 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2120,7 +2120,10 @@ struct napi_gro_cb { | |||
2120 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ | 2120 | /* Used in foo-over-udp, set in udp[46]_gro_receive */ |
2121 | u8 is_ipv6:1; | 2121 | u8 is_ipv6:1; |
2122 | 2122 | ||
2123 | /* 7 bit hole */ | 2123 | /* Used in GRE, set in fou/gue_gro_receive */ |
2124 | u8 is_fou:1; | ||
2125 | |||
2126 | /* 6 bit hole */ | ||
2124 | 2127 | ||
2125 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ | 2128 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ |
2126 | __wsum csum; | 2129 | __wsum csum; |
diff --git a/net/core/dev.c b/net/core/dev.c index b9bcbe77d913..77a71cd68535 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4439,6 +4439,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
4439 | NAPI_GRO_CB(skb)->flush = 0; | 4439 | NAPI_GRO_CB(skb)->flush = 0; |
4440 | NAPI_GRO_CB(skb)->free = 0; | 4440 | NAPI_GRO_CB(skb)->free = 0; |
4441 | NAPI_GRO_CB(skb)->encap_mark = 0; | 4441 | NAPI_GRO_CB(skb)->encap_mark = 0; |
4442 | NAPI_GRO_CB(skb)->is_fou = 0; | ||
4442 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; | 4443 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; |
4443 | 4444 | ||
4444 | /* Setup for GRO checksum validation */ | 4445 | /* Setup for GRO checksum validation */ |
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 5a94aea280d3..a39068b4a4d9 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c | |||
@@ -203,6 +203,9 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head, | |||
203 | */ | 203 | */ |
204 | NAPI_GRO_CB(skb)->encap_mark = 0; | 204 | NAPI_GRO_CB(skb)->encap_mark = 0; |
205 | 205 | ||
206 | /* Flag this frame as already having an outer encap header */ | ||
207 | NAPI_GRO_CB(skb)->is_fou = 1; | ||
208 | |||
206 | rcu_read_lock(); | 209 | rcu_read_lock(); |
207 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; | 210 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; |
208 | ops = rcu_dereference(offloads[proto]); | 211 | ops = rcu_dereference(offloads[proto]); |
@@ -368,6 +371,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, | |||
368 | */ | 371 | */ |
369 | NAPI_GRO_CB(skb)->encap_mark = 0; | 372 | NAPI_GRO_CB(skb)->encap_mark = 0; |
370 | 373 | ||
374 | /* Flag this frame as already having an outer encap header */ | ||
375 | NAPI_GRO_CB(skb)->is_fou = 1; | ||
376 | |||
371 | rcu_read_lock(); | 377 | rcu_read_lock(); |
372 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; | 378 | offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; |
373 | ops = rcu_dereference(offloads[guehdr->proto_ctype]); | 379 | ops = rcu_dereference(offloads[guehdr->proto_ctype]); |
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index c47539d04b88..6a5bd4317866 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -150,6 +150,14 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, | |||
150 | if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0) | 150 | if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0) |
151 | goto out; | 151 | goto out; |
152 | 152 | ||
153 | /* We can only support GRE_CSUM if we can track the location of | ||
154 | * the GRE header. In the case of FOU/GUE we cannot because the | ||
155 | * outer UDP header displaces the GRE header leaving us in a state | ||
156 | * of limbo. | ||
157 | */ | ||
158 | if ((greh->flags & GRE_CSUM) && NAPI_GRO_CB(skb)->is_fou) | ||
159 | goto out; | ||
160 | |||
153 | type = greh->protocol; | 161 | type = greh->protocol; |
154 | 162 | ||
155 | rcu_read_lock(); | 163 | rcu_read_lock(); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 31936d387cfd..af5d1f38217f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -862,9 +862,16 @@ static void __gre_tunnel_init(struct net_device *dev) | |||
862 | dev->hw_features |= GRE_FEATURES; | 862 | dev->hw_features |= GRE_FEATURES; |
863 | 863 | ||
864 | if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { | 864 | if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { |
865 | /* TCP offload with GRE SEQ is not supported. */ | 865 | /* TCP offload with GRE SEQ is not supported, nor |
866 | dev->features |= NETIF_F_GSO_SOFTWARE; | 866 | * can we support 2 levels of outer headers requiring |
867 | dev->hw_features |= NETIF_F_GSO_SOFTWARE; | 867 | * an update. |
868 | */ | ||
869 | if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || | ||
870 | (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { | ||
871 | dev->features |= NETIF_F_GSO_SOFTWARE; | ||
872 | dev->hw_features |= NETIF_F_GSO_SOFTWARE; | ||
873 | } | ||
874 | |||
868 | /* Can use a lockless transmit, unless we generate | 875 | /* Can use a lockless transmit, unless we generate |
869 | * output sequences | 876 | * output sequences |
870 | */ | 877 | */ |