Skip to content

Commit 229740c

Browse files
Jarno Rajahalmedavem330
authored andcommitted
udp_offload: Set encapsulation before inner completes.
UDP tunnel segmentation code relies on the inner offsets being set for an UDP tunnel GSO packet, but the inner *_complete() functions will set the inner offsets only if 'encapsulation' is set before calling them. Currently, udp_gro_complete() sets 'encapsulation' only after the inner *_complete() functions are done. This causes the inner offsets having invalid values after udp_gro_complete() returns, which in turn will make it impossible to properly segment the packet in case it needs to be forwarded, which would be visible to the user either as invalid packets being sent or as packet loss. This patch fixes this by setting skb's 'encapsulation' in udp_gro_complete() before calling into the inner complete functions, and by making each possible UDP tunnel gro_complete() callback set the inner_mac_header to the beginning of the tunnel payload. Signed-off-by: Jarno Rajahalme <[email protected]> Reviewed-by: Alexander Duyck <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 43b8448 commit 229740c

File tree

5 files changed

+18
-3
lines changed

5 files changed

+18
-3
lines changed

drivers/net/geneve.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,9 @@ static int geneve_gro_complete(struct sk_buff *skb, int nhoff,
514514
err = ptype->callbacks.gro_complete(skb, nhoff + gh_len);
515515

516516
rcu_read_unlock();
517+
518+
skb_set_inner_mac_header(skb, nhoff + gh_len);
519+
517520
return err;
518521
}
519522

drivers/net/vxlan.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head,
616616
static int vxlan_gro_complete(struct sk_buff *skb, int nhoff,
617617
struct udp_offload *uoff)
618618
{
619+
/* Sets 'skb->inner_mac_header' since we are always called with
620+
* 'skb->encapsulation' set.
621+
*/
619622
return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
620623
}
621624

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,6 +2164,9 @@ struct packet_offload {
21642164

21652165
struct udp_offload;
21662166

2167+
/* 'skb->encapsulation' is set before gro_complete() is called. gro_complete()
2168+
* must set 'skb->inner_mac_header' to the beginning of tunnel payload.
2169+
*/
21672170
struct udp_offload_callbacks {
21682171
struct sk_buff **(*gro_receive)(struct sk_buff **head,
21692172
struct sk_buff *skb,

net/ipv4/fou.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ static int fou_gro_complete(struct sk_buff *skb, int nhoff,
236236

237237
err = ops->callbacks.gro_complete(skb, nhoff);
238238

239+
skb_set_inner_mac_header(skb, nhoff);
240+
239241
out_unlock:
240242
rcu_read_unlock();
241243

@@ -412,6 +414,8 @@ static int gue_gro_complete(struct sk_buff *skb, int nhoff,
412414

413415
err = ops->callbacks.gro_complete(skb, nhoff + guehlen);
414416

417+
skb_set_inner_mac_header(skb, nhoff + guehlen);
418+
415419
out_unlock:
416420
rcu_read_unlock();
417421
return err;

net/ipv4/udp_offload.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,11 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff)
399399

400400
uh->len = newlen;
401401

402+
/* Set encapsulation before calling into inner gro_complete() functions
403+
* to make them set up the inner offsets.
404+
*/
405+
skb->encapsulation = 1;
406+
402407
rcu_read_lock();
403408

404409
uo_priv = rcu_dereference(udp_offload_base);
@@ -421,9 +426,6 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff)
421426
if (skb->remcsum_offload)
422427
skb_shinfo(skb)->gso_type |= SKB_GSO_TUNNEL_REMCSUM;
423428

424-
skb->encapsulation = 1;
425-
skb_set_inner_mac_header(skb, nhoff + sizeof(struct udphdr));
426-
427429
return err;
428430
}
429431

0 commit comments

Comments
 (0)