Skip to content

Commit 012363f

Browse files
joshhunt-akamaigregkh
authored andcommitted
udp: only do GSO if # of segs > 1
[ Upstream commit 4094871 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5c08d7e commit 012363f

3 files changed

Lines changed: 18 additions & 20 deletions

File tree

net/ipv4/udp.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
775775
int is_udplite = IS_UDPLITE(sk);
776776
int offset = skb_transport_offset(skb);
777777
int len = skb->len - offset;
778+
int datalen = len - sizeof(*uh);
778779
__wsum csum = 0;
779780

780781
/*
@@ -808,10 +809,12 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
808809
return -EIO;
809810
}
810811

811-
skb_shinfo(skb)->gso_size = cork->gso_size;
812-
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
813-
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(len - sizeof(*uh),
814-
cork->gso_size);
812+
if (datalen > cork->gso_size) {
813+
skb_shinfo(skb)->gso_size = cork->gso_size;
814+
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
815+
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen,
816+
cork->gso_size);
817+
}
815818
goto csum_partial;
816819
}
817820

net/ipv6/udp.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
10471047
__wsum csum = 0;
10481048
int offset = skb_transport_offset(skb);
10491049
int len = skb->len - offset;
1050+
int datalen = len - sizeof(*uh);
10501051

10511052
/*
10521053
* Create a UDP header
@@ -1079,10 +1080,12 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
10791080
return -EIO;
10801081
}
10811082

1082-
skb_shinfo(skb)->gso_size = cork->gso_size;
1083-
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
1084-
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(len - sizeof(*uh),
1085-
cork->gso_size);
1083+
if (datalen > cork->gso_size) {
1084+
skb_shinfo(skb)->gso_size = cork->gso_size;
1085+
skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
1086+
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen,
1087+
cork->gso_size);
1088+
}
10861089
goto csum_partial;
10871090
}
10881091

tools/testing/selftests/net/udpgso.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,9 @@ struct testcase testcases_v4[] = {
9090
.tfail = true,
9191
},
9292
{
93-
/* send a single MSS: will fail with GSO, because the segment
94-
* logic in udp4_ufo_fragment demands a gso skb to be > MTU
95-
*/
93+
/* send a single MSS: will fall back to no GSO */
9694
.tlen = CONST_MSS_V4,
9795
.gso_len = CONST_MSS_V4,
98-
.tfail = true,
9996
.r_num_mss = 1,
10097
},
10198
{
@@ -140,10 +137,9 @@ struct testcase testcases_v4[] = {
140137
.tfail = true,
141138
},
142139
{
143-
/* send a single 1B MSS: will fail, see single MSS above */
140+
/* send a single 1B MSS: will fall back to no GSO */
144141
.tlen = 1,
145142
.gso_len = 1,
146-
.tfail = true,
147143
.r_num_mss = 1,
148144
},
149145
{
@@ -197,12 +193,9 @@ struct testcase testcases_v6[] = {
197193
.tfail = true,
198194
},
199195
{
200-
/* send a single MSS: will fail with GSO, because the segment
201-
* logic in udp4_ufo_fragment demands a gso skb to be > MTU
202-
*/
196+
/* send a single MSS: will fall back to no GSO */
203197
.tlen = CONST_MSS_V6,
204198
.gso_len = CONST_MSS_V6,
205-
.tfail = true,
206199
.r_num_mss = 1,
207200
},
208201
{
@@ -247,10 +240,9 @@ struct testcase testcases_v6[] = {
247240
.tfail = true,
248241
},
249242
{
250-
/* send a single 1B MSS: will fail, see single MSS above */
243+
/* send a single 1B MSS: will fall back to no GSO */
251244
.tlen = 1,
252245
.gso_len = 1,
253-
.tfail = true,
254246
.r_num_mss = 1,
255247
},
256248
{

0 commit comments

Comments
 (0)