@@ -62,6 +62,7 @@ static int do_ipv4 = 1;
62
62
static int do_ipv6 = 1 ;
63
63
static int cfg_payload_len = 10 ;
64
64
static int cfg_poll_timeout = 100 ;
65
+ static bool cfg_wake_every_msec = true;
65
66
static int cfg_delay_snd ;
66
67
static int cfg_delay_ack ;
67
68
static int cfg_delay_tolerance_usec = 500 ;
@@ -286,6 +287,16 @@ static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
286
287
daddr ? inet_ntop (family , daddr , da , sizeof (da )) : "unknown" );
287
288
}
288
289
290
+ static int64_t get_time_now_us64 (void )
291
+ {
292
+ static struct timespec ts ;
293
+
294
+ if (clock_gettime (CLOCK_REALTIME , & ts ))
295
+ error (1 , errno , "clock_gettime" );
296
+
297
+ return timespec_to_us64 (& ts );
298
+ }
299
+
289
300
static void __epoll (int epfd )
290
301
{
291
302
struct epoll_event events ;
@@ -300,11 +311,19 @@ static void __epoll(int epfd)
300
311
static void __poll (int fd )
301
312
{
302
313
struct pollfd pollfd ;
314
+ int64_t end_of_wait ;
315
+ int timeout ;
303
316
int ret ;
304
317
305
- memset (& pollfd , 0 , sizeof (pollfd ));
306
- pollfd .fd = fd ;
307
- ret = poll (& pollfd , 1 , cfg_poll_timeout );
318
+ timeout = cfg_wake_every_msec ? 1 : cfg_poll_timeout ;
319
+ end_of_wait = get_time_now_us64 () + cfg_poll_timeout * 1000 ;
320
+
321
+ do {
322
+ memset (& pollfd , 0 , sizeof (pollfd ));
323
+ pollfd .fd = fd ;
324
+ ret = poll (& pollfd , 1 , timeout );
325
+ } while (!ret && get_time_now_us64 () < end_of_wait );
326
+
308
327
if (ret != 1 )
309
328
error (1 , errno , "poll" );
310
329
}
@@ -707,6 +726,7 @@ static void __attribute__((noreturn)) usage(const char *filepath)
707
726
" -P: use PF_PACKET\n"
708
727
" -r: use raw\n"
709
728
" -R: use raw (IP_HDRINCL)\n"
729
+ " -s: single sleep until timeout (from -S), by default wake every 1msec\n"
710
730
" -S N: usec to sleep before reading error queue\n"
711
731
" -t N: tolerance (usec) for timestamp validation\n"
712
732
" -u: use udp\n"
@@ -723,7 +743,7 @@ static void parse_opt(int argc, char **argv)
723
743
int c ;
724
744
725
745
while ((c = getopt (argc , argv ,
726
- "46bc:CeEFhIl:LnNo:p:PrRS :t:uv:V:x" )) != -1 ) {
746
+ "46bc:CeEFhIl:LnNo:p:PrRsS :t:uv:V:x" )) != -1 ) {
727
747
switch (c ) {
728
748
case '4' :
729
749
do_ipv6 = 0 ;
@@ -787,6 +807,9 @@ static void parse_opt(int argc, char **argv)
787
807
cfg_proto = SOCK_RAW ;
788
808
cfg_ipproto = IPPROTO_RAW ;
789
809
break ;
810
+ case 's' : /* sleep 'till timeout */
811
+ cfg_wake_every_msec = false;
812
+ break ;
790
813
case 'S' :
791
814
cfg_sleep_usec = strtoul (optarg , NULL , 10 );
792
815
break ;
@@ -825,6 +848,8 @@ static void parse_opt(int argc, char **argv)
825
848
error (1 , 0 , "cannot ask for pktinfo over pf_packet" );
826
849
if (cfg_busy_poll && cfg_use_epoll )
827
850
error (1 , 0 , "pass epoll or busy_poll, not both" );
851
+ if (cfg_wake_every_msec && cfg_use_epoll )
852
+ error (1 , 0 , "periodic wake not implemented for epoll, use -s" );
828
853
if (cfg_proto == SOCK_STREAM && cfg_use_cmsg_opt_id )
829
854
error (1 , 0 , "TCP sockets don't support SCM_TS_OPT_ID" );
830
855
0 commit comments