Skip to content

Commit a0ca153

Browse files
Alexander Duyckdavem330
authored andcommitted
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: c348338 ("gro: Allow tunnel stacking in the case of FOU/GUE") Signed-off-by: Alexander Duyck <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0a1a37b commit a0ca153

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

include/linux/netdevice.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,10 @@ struct napi_gro_cb {
21202120
/* Used in foo-over-udp, set in udp[46]_gro_receive */
21212121
u8 is_ipv6:1;
21222122

2123-
/* 7 bit hole */
2123+
/* Used in GRE, set in fou/gue_gro_receive */
2124+
u8 is_fou:1;
2125+
2126+
/* 6 bit hole */
21242127

21252128
/* used to support CHECKSUM_COMPLETE for tunneling protocols */
21262129
__wsum csum;

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4439,6 +4439,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
44394439
NAPI_GRO_CB(skb)->flush = 0;
44404440
NAPI_GRO_CB(skb)->free = 0;
44414441
NAPI_GRO_CB(skb)->encap_mark = 0;
4442+
NAPI_GRO_CB(skb)->is_fou = 0;
44424443
NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
44434444

44444445
/* Setup for GRO checksum validation */

net/ipv4/fou.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head,
203203
*/
204204
NAPI_GRO_CB(skb)->encap_mark = 0;
205205

206+
/* Flag this frame as already having an outer encap header */
207+
NAPI_GRO_CB(skb)->is_fou = 1;
208+
206209
rcu_read_lock();
207210
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
208211
ops = rcu_dereference(offloads[proto]);
@@ -368,6 +371,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
368371
*/
369372
NAPI_GRO_CB(skb)->encap_mark = 0;
370373

374+
/* Flag this frame as already having an outer encap header */
375+
NAPI_GRO_CB(skb)->is_fou = 1;
376+
371377
rcu_read_lock();
372378
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
373379
ops = rcu_dereference(offloads[guehdr->proto_ctype]);

net/ipv4/gre_offload.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
150150
if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0)
151151
goto out;
152152

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+
153161
type = greh->protocol;
154162

155163
rcu_read_lock();

net/ipv4/ip_gre.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -862,9 +862,16 @@ static void __gre_tunnel_init(struct net_device *dev)
862862
dev->hw_features |= GRE_FEATURES;
863863

864864
if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
865-
/* TCP offload with GRE SEQ is not supported. */
866-
dev->features |= NETIF_F_GSO_SOFTWARE;
867-
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
865+
/* TCP offload with GRE SEQ is not supported, nor
866+
* can we support 2 levels of outer headers requiring
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+
868875
/* Can use a lockless transmit, unless we generate
869876
* output sequences
870877
*/

0 commit comments

Comments
 (0)