Skip to content

Commit ada641f

Browse files
Paolo Abenidavem330
authored andcommitted
selftests: fixes for UDP GRO
The current implementation for UDP GRO tests is racy: the receiver may flush the RX queue while the sending is still transmitting and incorrectly report RX errors, with a wrong number of packet received. Add explicit timeouts to the receiver for both connection activation (first packet received for UDP) and reception completion, so that in the above critical scenario the receiver will wait for the transfer completion. Fixes: 3327a9c ("selftests: add functionals test for UDP GRO") Signed-off-by: Paolo Abeni <pabeni@redhat.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d235c48 commit ada641f

File tree

2 files changed

+33
-17
lines changed

2 files changed

+33
-17
lines changed

tools/testing/selftests/net/udpgro.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ run_one() {
3737

3838
cfg_veth
3939

40-
ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} && \
40+
ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \
4141
echo "ok" || \
4242
echo "failed" &
4343

@@ -81,7 +81,7 @@ run_one_nat() {
8181
# will land on the 'plain' one
8282
ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 &
8383
pid=$!
84-
ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${family} -b ${addr2%/*} ${rx_args} && \
84+
ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \
8585
echo "ok" || \
8686
echo "failed"&
8787

@@ -99,8 +99,8 @@ run_one_2sock() {
9999

100100
cfg_veth
101101

102-
ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} -p 12345 &
103-
ip netns exec "${PEER_NS}" ./udpgso_bench_rx ${rx_args} && \
102+
ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 &
103+
ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \
104104
echo "ok" || \
105105
echo "failed" &
106106

tools/testing/selftests/net/udpgso_bench_rx.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ static int cfg_alen = sizeof(struct sockaddr_in6);
4545
static int cfg_expected_pkt_nr;
4646
static int cfg_expected_pkt_len;
4747
static int cfg_expected_gso_size;
48+
static int cfg_connect_timeout_ms;
49+
static int cfg_rcv_timeout_ms;
4850
static struct sockaddr_storage cfg_bind_addr;
4951

5052
static bool interrupted;
@@ -87,7 +89,7 @@ static unsigned long gettimeofday_ms(void)
8789
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
8890
}
8991

90-
static void do_poll(int fd)
92+
static void do_poll(int fd, int timeout_ms)
9193
{
9294
struct pollfd pfd;
9395
int ret;
@@ -102,8 +104,16 @@ static void do_poll(int fd)
102104
break;
103105
if (ret == -1)
104106
error(1, errno, "poll");
105-
if (ret == 0)
106-
continue;
107+
if (ret == 0) {
108+
if (!timeout_ms)
109+
continue;
110+
111+
timeout_ms -= 10;
112+
if (timeout_ms <= 0) {
113+
interrupted = true;
114+
break;
115+
}
116+
}
107117
if (pfd.revents != POLLIN)
108118
error(1, errno, "poll: 0x%x expected 0x%x\n",
109119
pfd.revents, POLLIN);
@@ -134,7 +144,7 @@ static int do_socket(bool do_tcp)
134144
if (listen(accept_fd, 1))
135145
error(1, errno, "listen");
136146

137-
do_poll(accept_fd);
147+
do_poll(accept_fd, cfg_connect_timeout_ms);
138148
if (interrupted)
139149
exit(0);
140150

@@ -273,7 +283,9 @@ static void do_flush_udp(int fd)
273283

274284
static void usage(const char *filepath)
275285
{
276-
error(1, 0, "Usage: %s [-Grtv] [-b addr] [-p port] [-l pktlen] [-n packetnr] [-S gsosize]", filepath);
286+
error(1, 0, "Usage: %s [-C connect_timeout] [-Grtv] [-b addr] [-p port]"
287+
" [-l pktlen] [-n packetnr] [-R rcv_timeout] [-S gsosize]",
288+
filepath);
277289
}
278290

279291
static void parse_opts(int argc, char **argv)
@@ -282,7 +294,7 @@ static void parse_opts(int argc, char **argv)
282294

283295
/* bind to any by default */
284296
setup_sockaddr(PF_INET6, "::", &cfg_bind_addr);
285-
while ((c = getopt(argc, argv, "4b:Gl:n:p:rS:tv")) != -1) {
297+
while ((c = getopt(argc, argv, "4b:C:Gl:n:p:rR:S:tv")) != -1) {
286298
switch (c) {
287299
case '4':
288300
cfg_family = PF_INET;
@@ -292,6 +304,9 @@ static void parse_opts(int argc, char **argv)
292304
case 'b':
293305
setup_sockaddr(cfg_family, optarg, &cfg_bind_addr);
294306
break;
307+
case 'C':
308+
cfg_connect_timeout_ms = strtoul(optarg, NULL, 0);
309+
break;
295310
case 'G':
296311
cfg_gro_segment = true;
297312
break;
@@ -307,6 +322,9 @@ static void parse_opts(int argc, char **argv)
307322
case 'r':
308323
cfg_read_all = true;
309324
break;
325+
case 'R':
326+
cfg_rcv_timeout_ms = strtoul(optarg, NULL, 0);
327+
break;
310328
case 'S':
311329
cfg_expected_gso_size = strtol(optarg, NULL, 0);
312330
break;
@@ -329,8 +347,9 @@ static void parse_opts(int argc, char **argv)
329347

330348
static void do_recv(void)
331349
{
350+
int timeout_ms = cfg_tcp ? cfg_rcv_timeout_ms : cfg_connect_timeout_ms;
332351
unsigned long tnow, treport;
333-
int fd, loop = 0;
352+
int fd;
334353

335354
fd = do_socket(cfg_tcp);
336355

@@ -342,12 +361,7 @@ static void do_recv(void)
342361

343362
treport = gettimeofday_ms() + 1000;
344363
do {
345-
/* force termination after the second poll(); this cope both
346-
* with sender slower than receiver and missing packet errors
347-
*/
348-
if (cfg_expected_pkt_nr && loop++)
349-
interrupted = true;
350-
do_poll(fd);
364+
do_poll(fd, timeout_ms);
351365

352366
if (cfg_tcp)
353367
do_flush_tcp(fd);
@@ -365,6 +379,8 @@ static void do_recv(void)
365379
treport = tnow + 1000;
366380
}
367381

382+
timeout_ms = cfg_rcv_timeout_ms;
383+
368384
} while (!interrupted);
369385

370386
if (cfg_expected_pkt_nr && (packets != cfg_expected_pkt_nr))

0 commit comments

Comments
 (0)