@@ -62,6 +62,7 @@ static int do_ipv4 = 1;
6262static int do_ipv6 = 1 ;
6363static int cfg_payload_len = 10 ;
6464static int cfg_poll_timeout = 100 ;
65+ static bool cfg_wake_every_msec = true;
6566static int cfg_delay_snd ;
6667static int cfg_delay_ack ;
6768static int cfg_delay_tolerance_usec = 500 ;
@@ -284,6 +285,16 @@ static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
284285 daddr ? inet_ntop (family , daddr , da , sizeof (da )) : "unknown" );
285286}
286287
288+ static int64_t get_time_now_us64 (void )
289+ {
290+ static struct timespec ts ;
291+
292+ if (clock_gettime (CLOCK_REALTIME , & ts ))
293+ error (1 , errno , "clock_gettime" );
294+
295+ return timespec_to_us64 (& ts );
296+ }
297+
287298static void __epoll (int epfd )
288299{
289300 struct epoll_event events ;
@@ -298,11 +309,19 @@ static void __epoll(int epfd)
298309static void __poll (int fd )
299310{
300311 struct pollfd pollfd ;
312+ int64_t end_of_wait ;
313+ int timeout ;
301314 int ret ;
302315
303- memset (& pollfd , 0 , sizeof (pollfd ));
304- pollfd .fd = fd ;
305- ret = poll (& pollfd , 1 , cfg_poll_timeout );
316+ timeout = cfg_wake_every_msec ? 1 : cfg_poll_timeout ;
317+ end_of_wait = get_time_now_us64 () + cfg_poll_timeout * 1000 ;
318+
319+ do {
320+ memset (& pollfd , 0 , sizeof (pollfd ));
321+ pollfd .fd = fd ;
322+ ret = poll (& pollfd , 1 , timeout );
323+ } while (!ret && get_time_now_us64 () < end_of_wait );
324+
306325 if (ret != 1 )
307326 error (1 , errno , "poll" );
308327}
@@ -707,6 +726,7 @@ static void __attribute__((noreturn)) usage(const char *filepath)
707726 " -P: use PF_PACKET\n"
708727 " -r: use raw\n"
709728 " -R: use raw (IP_HDRINCL)\n"
729+ " -s: single sleep until timeout (from -S), by default wake every 1msec\n"
710730 " -S N: usec to sleep before reading error queue\n"
711731 " -t N: tolerance (usec) for timestamp validation\n"
712732 " -u: use udp\n"
@@ -723,7 +743,7 @@ static void parse_opt(int argc, char **argv)
723743 int c ;
724744
725745 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 ) {
727747 switch (c ) {
728748 case '4' :
729749 do_ipv6 = 0 ;
@@ -787,6 +807,9 @@ static void parse_opt(int argc, char **argv)
787807 cfg_proto = SOCK_RAW ;
788808 cfg_ipproto = IPPROTO_RAW ;
789809 break ;
810+ case 's' : /* sleep 'till timeout */
811+ cfg_wake_every_msec = false;
812+ break ;
790813 case 'S' :
791814 cfg_sleep_usec = strtoul (optarg , NULL , 10 );
792815 break ;
@@ -825,6 +848,8 @@ static void parse_opt(int argc, char **argv)
825848 error (1 , 0 , "cannot ask for pktinfo over pf_packet" );
826849 if (cfg_busy_poll && cfg_use_epoll )
827850 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" );
828853 if (cfg_proto == SOCK_STREAM && cfg_use_cmsg_opt_id )
829854 error (1 , 0 , "TCP sockets don't support SCM_TS_OPT_ID" );
830855
0 commit comments