Skip to content

Commit

Permalink
GRE: Disable segmentation offloads w/ CSUM and we are encapsulated vi…
Browse files Browse the repository at this point in the history
…a 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 <aduyck@mirantis.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alexander Duyck authored and davem330 committed Apr 7, 2016
1 parent 0a1a37b commit a0ca153
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 4 deletions.
5 changes: 4 additions & 1 deletion include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,10 @@ struct napi_gro_cb {
/* Used in foo-over-udp, set in udp[46]_gro_receive */
u8 is_ipv6:1;

/* 7 bit hole */
/* Used in GRE, set in fou/gue_gro_receive */
u8 is_fou:1;

/* 6 bit hole */

/* used to support CHECKSUM_COMPLETE for tunneling protocols */
__wsum csum;
Expand Down
1 change: 1 addition & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4439,6 +4439,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
NAPI_GRO_CB(skb)->flush = 0;
NAPI_GRO_CB(skb)->free = 0;
NAPI_GRO_CB(skb)->encap_mark = 0;
NAPI_GRO_CB(skb)->is_fou = 0;
NAPI_GRO_CB(skb)->gro_remcsum_start = 0;

/* Setup for GRO checksum validation */
Expand Down
6 changes: 6 additions & 0 deletions net/ipv4/fou.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head,
*/
NAPI_GRO_CB(skb)->encap_mark = 0;

/* Flag this frame as already having an outer encap header */
NAPI_GRO_CB(skb)->is_fou = 1;

rcu_read_lock();
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
ops = rcu_dereference(offloads[proto]);
Expand Down Expand Up @@ -368,6 +371,9 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
*/
NAPI_GRO_CB(skb)->encap_mark = 0;

/* Flag this frame as already having an outer encap header */
NAPI_GRO_CB(skb)->is_fou = 1;

rcu_read_lock();
offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
ops = rcu_dereference(offloads[guehdr->proto_ctype]);
Expand Down
8 changes: 8 additions & 0 deletions net/ipv4/gre_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
if ((greh->flags & ~(GRE_KEY|GRE_CSUM)) != 0)
goto out;

/* We can only support GRE_CSUM if we can track the location of
* the GRE header. In the case of FOU/GUE we cannot because the
* outer UDP header displaces the GRE header leaving us in a state
* of limbo.
*/
if ((greh->flags & GRE_CSUM) && NAPI_GRO_CB(skb)->is_fou)
goto out;

type = greh->protocol;

rcu_read_lock();
Expand Down
13 changes: 10 additions & 3 deletions net/ipv4/ip_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,9 +862,16 @@ static void __gre_tunnel_init(struct net_device *dev)
dev->hw_features |= GRE_FEATURES;

if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) {
/* TCP offload with GRE SEQ is not supported. */
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
/* TCP offload with GRE SEQ is not supported, nor
* can we support 2 levels of outer headers requiring
* an update.
*/
if (!(tunnel->parms.o_flags & TUNNEL_CSUM) ||
(tunnel->encap.type == TUNNEL_ENCAP_NONE)) {
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
}

/* Can use a lockless transmit, unless we generate
* output sequences
*/
Expand Down

0 comments on commit a0ca153

Please sign in to comment.