Skip to content

Commit 622e32b

Browse files
LorenzoBianconidavem330
authored andcommitted
net: gre: recompute gre csum for sctp over gre tunnels
The GRE tunnel can be used to transport traffic that does not rely on a Internet checksum (e.g. SCTP). The issue can be triggered creating a GRE or GRETAP tunnel and transmitting SCTP traffic ontop of it where CRC offload has been disabled. In order to fix the issue we need to recompute the GRE csum in gre_gso_segment() not relying on the inner checksum. The issue is still present when we have the CRC offload enabled. In this case we need to disable the CRC offload if we require GRE checksum since otherwise skb_checksum() will report a wrong value. Fixes: 90017ac ("sctp: Add GSO support") Signed-off-by: Lorenzo Bianconi <[email protected]> Reviewed-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fd65e5a commit 622e32b

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

net/ipv4/gre_offload.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
1515
netdev_features_t features)
1616
{
1717
int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
18+
bool need_csum, need_recompute_csum, gso_partial;
1819
struct sk_buff *segs = ERR_PTR(-EINVAL);
1920
u16 mac_offset = skb->mac_header;
2021
__be16 protocol = skb->protocol;
2122
u16 mac_len = skb->mac_len;
2223
int gre_offset, outer_hlen;
23-
bool need_csum, gso_partial;
2424

2525
if (!skb->encapsulation)
2626
goto out;
@@ -41,6 +41,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
4141
skb->protocol = skb->inner_protocol;
4242

4343
need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM);
44+
need_recompute_csum = skb->csum_not_inet;
4445
skb->encap_hdr_csum = need_csum;
4546

4647
features &= skb->dev->hw_enc_features;
@@ -98,7 +99,15 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
9899
}
99100

100101
*(pcsum + 1) = 0;
101-
*pcsum = gso_make_checksum(skb, 0);
102+
if (need_recompute_csum && !skb_is_gso(skb)) {
103+
__wsum csum;
104+
105+
csum = skb_checksum(skb, gre_offset,
106+
skb->len - gre_offset, 0);
107+
*pcsum = csum_fold(csum);
108+
} else {
109+
*pcsum = gso_make_checksum(skb, 0);
110+
}
102111
} while ((skb = skb->next));
103112
out:
104113
return segs;

0 commit comments

Comments
 (0)