Skip to content

Commit

Permalink
udp: only do GSO if # of segs > 1
Browse files Browse the repository at this point in the history
Prior to this change an application sending <= 1MSS worth of data and
enabling UDP GSO would fail if the system had SW GSO enabled, but the
same send would succeed if HW GSO offload is enabled. In addition to this
inconsistency the error in the SW GSO case does not get back to the
application if sending out of a real device so the user is unaware of this
failure.

With this change we only perform GSO if the # of segments is > 1 even
if the application has enabled segmentation. I've also updated the
relevant udpgso selftests.

Fixes: bec1f6f ("udp: generate gso with UDP_SEGMENT")
Signed-off-by: Josh Hunt <johunt@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
geauxbears authored and davem330 committed Oct 3, 2019
1 parent 44b321e commit 4094871
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 20 deletions.
11 changes: 7 additions & 4 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
int is_udplite = IS_UDPLITE(sk);
int offset = skb_transport_offset(skb);
int len = skb->len - offset;
int datalen = len - sizeof(*uh);
__wsum csum = 0;

/*
Expand Down Expand Up @@ -854,10 +855,12 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
return -EIO;
}

skb_shinfo(skb)->gso_size = cork->gso_size;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(len - sizeof(*uh),
cork->gso_size);
if (datalen > cork->gso_size) {
skb_shinfo(skb)->gso_size = cork->gso_size;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen,
cork->gso_size);
}
goto csum_partial;
}

Expand Down
11 changes: 7 additions & 4 deletions net/ipv6/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
__wsum csum = 0;
int offset = skb_transport_offset(skb);
int len = skb->len - offset;
int datalen = len - sizeof(*uh);

/*
* Create a UDP header
Expand Down Expand Up @@ -1141,10 +1142,12 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
return -EIO;
}

skb_shinfo(skb)->gso_size = cork->gso_size;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(len - sizeof(*uh),
cork->gso_size);
if (datalen > cork->gso_size) {
skb_shinfo(skb)->gso_size = cork->gso_size;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen,
cork->gso_size);
}
goto csum_partial;
}

Expand Down
16 changes: 4 additions & 12 deletions tools/testing/selftests/net/udpgso.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,9 @@ struct testcase testcases_v4[] = {
.tfail = true,
},
{
/* send a single MSS: will fail with GSO, because the segment
* logic in udp4_ufo_fragment demands a gso skb to be > MTU
*/
/* send a single MSS: will fall back to no GSO */
.tlen = CONST_MSS_V4,
.gso_len = CONST_MSS_V4,
.tfail = true,
.r_num_mss = 1,
},
{
Expand Down Expand Up @@ -139,10 +136,9 @@ struct testcase testcases_v4[] = {
.tfail = true,
},
{
/* send a single 1B MSS: will fail, see single MSS above */
/* send a single 1B MSS: will fall back to no GSO */
.tlen = 1,
.gso_len = 1,
.tfail = true,
.r_num_mss = 1,
},
{
Expand Down Expand Up @@ -196,12 +192,9 @@ struct testcase testcases_v6[] = {
.tfail = true,
},
{
/* send a single MSS: will fail with GSO, because the segment
* logic in udp4_ufo_fragment demands a gso skb to be > MTU
*/
/* send a single MSS: will fall back to no GSO */
.tlen = CONST_MSS_V6,
.gso_len = CONST_MSS_V6,
.tfail = true,
.r_num_mss = 1,
},
{
Expand Down Expand Up @@ -246,10 +239,9 @@ struct testcase testcases_v6[] = {
.tfail = true,
},
{
/* send a single 1B MSS: will fail, see single MSS above */
/* send a single 1B MSS: will fall back to no GSO */
.tlen = 1,
.gso_len = 1,
.tfail = true,
.r_num_mss = 1,
},
{
Expand Down

0 comments on commit 4094871

Please sign in to comment.