Skip to content

Commit 469a65a

Browse files
Alexander DuyckLee Jones
authored andcommitted
GRE: Disable segmentation offloads w/ CSUM and we are encapsulated via FOU
commit a0ca153 upstream. 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]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Lee Jones <[email protected]> Change-Id: I94cac056417f7ed550544c85ac74335b93b4475d
1 parent 0df8ecc commit 469a65a

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
@@ -1920,7 +1920,10 @@ struct napi_gro_cb {
19201920
/* Used in foo-over-udp, set in udp[46]_gro_receive */
19211921
u8 is_ipv6:1;
19221922

1923-
/* 7 bit hole */
1923+
/* Used in GRE, set in fou/gue_gro_receive */
1924+
u8 is_fou:1;
1925+
1926+
/* 6 bit hole */
19241927

19251928
/* used to support CHECKSUM_COMPLETE for tunneling protocols */
19261929
__wsum csum;

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4052,6 +4052,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
40524052
NAPI_GRO_CB(skb)->flush = 0;
40534053
NAPI_GRO_CB(skb)->free = 0;
40544054
NAPI_GRO_CB(skb)->encap_mark = 0;
4055+
NAPI_GRO_CB(skb)->is_fou = 0;
40554056

40564057
/* Setup for GRO checksum validation */
40574058
switch (skb->ip_summed) {

net/ipv4/fou.c

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

124+
/* Flag this frame as already having an outer encap header */
125+
NAPI_GRO_CB(skb)->is_fou = 1;
126+
124127
rcu_read_lock();
125128
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
126129
ops = rcu_dereference(offloads[proto]);
@@ -236,6 +239,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
236239
/* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
237240
skb_gro_postpull_rcsum(skb, guehdr, guehlen);
238241

242+
/* Flag this frame as already having an outer encap header */
243+
NAPI_GRO_CB(skb)->is_fou = 1;
244+
239245
pp = ops->callbacks.gro_receive(head, skb);
240246

241247
out_unlock:

net/ipv4/gre_offload.c

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

154+
/* We can only support GRE_CSUM if we can track the location of
155+
* the GRE header. In the case of FOU/GUE we cannot because the
156+
* outer UDP header displaces the GRE header leaving us in a state
157+
* of limbo.
158+
*/
159+
if ((greh->flags & GRE_CSUM) && NAPI_GRO_CB(skb)->is_fou)
160+
goto out;
161+
154162
type = greh->protocol;
155163

156164
rcu_read_lock();

net/ipv4/ip_gre.c

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

492492
if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
493-
/* TCP offload with GRE SEQ is not supported. */
494-
dev->features |= NETIF_F_GSO_SOFTWARE;
495-
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
493+
/* TCP offload with GRE SEQ is not supported, nor
494+
* can we support 2 levels of outer headers requiring
495+
* an update.
496+
*/
497+
if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
498+
(tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
499+
dev->features |= NETIF_F_GSO_SOFTWARE;
500+
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
501+
}
502+
496503
/* Can use a lockless transmit, unless we generate
497504
* output sequences
498505
*/

0 commit comments

Comments
 (0)