@@ -45,6 +45,8 @@ static int cfg_alen = sizeof(struct sockaddr_in6);
45
45
static int cfg_expected_pkt_nr ;
46
46
static int cfg_expected_pkt_len ;
47
47
static int cfg_expected_gso_size ;
48
+ static int cfg_connect_timeout_ms ;
49
+ static int cfg_rcv_timeout_ms ;
48
50
static struct sockaddr_storage cfg_bind_addr ;
49
51
50
52
static bool interrupted ;
@@ -87,7 +89,7 @@ static unsigned long gettimeofday_ms(void)
87
89
return (tv .tv_sec * 1000 ) + (tv .tv_usec / 1000 );
88
90
}
89
91
90
- static void do_poll (int fd )
92
+ static void do_poll (int fd , int timeout_ms )
91
93
{
92
94
struct pollfd pfd ;
93
95
int ret ;
@@ -102,8 +104,16 @@ static void do_poll(int fd)
102
104
break ;
103
105
if (ret == -1 )
104
106
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
+ }
107
117
if (pfd .revents != POLLIN )
108
118
error (1 , errno , "poll: 0x%x expected 0x%x\n" ,
109
119
pfd .revents , POLLIN );
@@ -134,7 +144,7 @@ static int do_socket(bool do_tcp)
134
144
if (listen (accept_fd , 1 ))
135
145
error (1 , errno , "listen" );
136
146
137
- do_poll (accept_fd );
147
+ do_poll (accept_fd , cfg_connect_timeout_ms );
138
148
if (interrupted )
139
149
exit (0 );
140
150
@@ -273,7 +283,9 @@ static void do_flush_udp(int fd)
273
283
274
284
static void usage (const char * filepath )
275
285
{
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 );
277
289
}
278
290
279
291
static void parse_opts (int argc , char * * argv )
@@ -282,7 +294,7 @@ static void parse_opts(int argc, char **argv)
282
294
283
295
/* bind to any by default */
284
296
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 ) {
286
298
switch (c ) {
287
299
case '4' :
288
300
cfg_family = PF_INET ;
@@ -292,6 +304,9 @@ static void parse_opts(int argc, char **argv)
292
304
case 'b' :
293
305
setup_sockaddr (cfg_family , optarg , & cfg_bind_addr );
294
306
break ;
307
+ case 'C' :
308
+ cfg_connect_timeout_ms = strtoul (optarg , NULL , 0 );
309
+ break ;
295
310
case 'G' :
296
311
cfg_gro_segment = true;
297
312
break ;
@@ -307,6 +322,9 @@ static void parse_opts(int argc, char **argv)
307
322
case 'r' :
308
323
cfg_read_all = true;
309
324
break ;
325
+ case 'R' :
326
+ cfg_rcv_timeout_ms = strtoul (optarg , NULL , 0 );
327
+ break ;
310
328
case 'S' :
311
329
cfg_expected_gso_size = strtol (optarg , NULL , 0 );
312
330
break ;
@@ -329,8 +347,9 @@ static void parse_opts(int argc, char **argv)
329
347
330
348
static void do_recv (void )
331
349
{
350
+ int timeout_ms = cfg_tcp ? cfg_rcv_timeout_ms : cfg_connect_timeout_ms ;
332
351
unsigned long tnow , treport ;
333
- int fd , loop = 0 ;
352
+ int fd ;
334
353
335
354
fd = do_socket (cfg_tcp );
336
355
@@ -342,12 +361,7 @@ static void do_recv(void)
342
361
343
362
treport = gettimeofday_ms () + 1000 ;
344
363
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 );
351
365
352
366
if (cfg_tcp )
353
367
do_flush_tcp (fd );
@@ -365,6 +379,8 @@ static void do_recv(void)
365
379
treport = tnow + 1000 ;
366
380
}
367
381
382
+ timeout_ms = cfg_rcv_timeout_ms ;
383
+
368
384
} while (!interrupted );
369
385
370
386
if (cfg_expected_pkt_nr && (packets != cfg_expected_pkt_nr ))
0 commit comments