@@ -34,6 +34,7 @@ struct resources {
3434
3535static bool cfg_quiet = false;
3636static bool cfg_rx_timestamping = false;
37+ static bool cfg_intf_stats = false;
3738static struct resources res ;
3839
3940/* Mutex to protect printing from different threads */
@@ -52,6 +53,7 @@ static void usage_msg(FILE* f)
5253 fprintf (f , " -r Enable rx timestamping\n" );
5354 fprintf (f , " -q Quiet -- do not emit progress messages\n" );
5455 fprintf (f , " -p Print zf attributes after stack startup\n" );
56+ fprintf (f , " -s Print interfaces drop stats\n" );
5557}
5658
5759
@@ -61,18 +63,6 @@ static void usage_err(void)
6163 exit (1 );
6264}
6365
64-
65- static void vlog (const char * fmt , ...)
66- {
67- va_list args ;
68- va_start (args , fmt );
69- pthread_mutex_lock (& printf_mutex );
70- vprintf (fmt , args );
71- pthread_mutex_unlock (& printf_mutex );
72- va_end (args );
73- }
74-
75-
7666static void try_recv (struct zfur * ur )
7767{
7868 struct {
@@ -98,10 +88,12 @@ static void try_recv(struct zfur* ur)
9888 struct timespec ts ;
9989 int rc = zfur_pkt_get_timestamp (ur , & rd .msg , & ts , 0 , & flags );
10090
91+ pthread_mutex_lock (& printf_mutex );
10192 if ( rc == 0 )
102- vlog ("Hardware timestamp: %lld .%.9ld\n" , ts .tv_sec , ts .tv_nsec );
93+ printf ("Hardware timestamp: %ld .%.9ld\n" , ts .tv_sec , ts .tv_nsec );
10394 else
104- vlog ("Error retrieving timestamp! Return code: %d\n" , rc );
95+ printf ("Error retrieving timestamp! Return code: %d\n" , rc );
96+ pthread_mutex_unlock (& printf_mutex );
10597 }
10698
10799 zfur_zc_recv_done (ur , & rd .msg );
@@ -243,14 +235,72 @@ void print_attrs(struct zf_attr* attr)
243235}
244236
245237
246- static void monitor ()
238+ static void zf_stats_header_print (struct zf_stack * stack ,
239+ zf_layout_collection * stats_collection )
240+ {
241+ int i ;
242+
243+ if ( stats_collection -> num_intfs > 1 )
244+ printf ("\n#" );
245+
246+ /* only display names for the first NIC and assume others are the same */
247+ for ( i = 0 ; i < stats_collection -> layout [0 ]-> evsl_fields_num ; ++ i )
248+ printf (" %10s" , stats_collection -> layout [0 ]-> evsl_fields [i ].evsfl_name );
249+ }
250+
251+
252+ static void zf_stats_print (struct zf_stack * stack , uint8_t * stats_data ,
253+ zf_layout_collection * stats_collection )
254+ {
255+ int i , n , n_pad ;
256+ uint8_t * cur_data = stats_data ;
257+ const zf_stats_layout * layout ;
258+
259+ for ( n = 0 ; n < stats_collection -> num_intfs ; n ++ ) {
260+ if ( stats_collection -> num_intfs > 1 )
261+ printf ("\n " );
262+
263+ layout = stats_collection -> layout [n ];
264+ for ( i = 0 ; i < layout -> evsl_fields_num ; ++ i ) {
265+ const zf_stats_field_layout * f = & layout -> evsl_fields [i ];
266+ n_pad = strlen (f -> evsfl_name );
267+ if ( n_pad < 10 )
268+ n_pad = 10 ;
269+ switch ( f -> evsfl_size ) {
270+ case sizeof (uint32_t ):
271+ printf (" %*d" , n_pad , * (uint32_t * )(cur_data + f -> evsfl_offset ));
272+ break ;
273+ default :
274+ printf (" %*s" , n_pad , "." );
275+ };
276+ }
277+ cur_data += layout -> evsl_data_size ;
278+ }
279+ }
280+
281+
282+ static void monitor (struct zf_stack * stack )
247283{
248284 uint64_t now_bytes , prev_bytes ;
249285 struct timeval start , end ;
250286 uint64_t prev_pkts , now_pkts ;
251287 int ms , pkt_rate , mbps ;
252288
253- vlog ("#%9s %16s %16s" , "pkt-rate" , "bandwidth(Mbps)" , "total-pkts\n" );
289+ zf_layout_collection * stats_collection ;
290+ uint8_t * stats_data = NULL ;
291+
292+ pthread_mutex_lock (& printf_mutex );
293+ printf ("#%9s %16s %16s" , "pkt-rate" , "bandwidth(Mbps)" , "total-pkts" );
294+
295+ if ( cfg_intf_stats ) {
296+ ZF_TEST (zf_stats_alloc_layout_collection (stack , & stats_collection ) == 0 );
297+ zf_stats_header_print (stack , stats_collection );
298+
299+ ZF_TEST ((stats_data = malloc (stats_collection -> total_data_size )) != NULL );
300+ }
301+
302+ printf ("\n" );
303+ pthread_mutex_unlock (& printf_mutex );
254304
255305 prev_pkts = res .n_rx_pkts ;
256306 prev_bytes = res .n_rx_bytes ;
@@ -265,18 +315,35 @@ static void monitor()
265315 ms += (end .tv_usec - start .tv_usec ) / 1000 ;
266316 pkt_rate = (int ) ((now_pkts - prev_pkts ) * 1000 / ms );
267317 mbps = (int ) ((now_bytes - prev_bytes ) * 8 / 1000 / ms );
268- vlog ("%10d %16d %16" PRIu64 "\n" , pkt_rate , mbps , now_pkts );
318+
319+ if ( cfg_intf_stats )
320+ zf_stats_query (stack , stats_data , stats_collection , 1 );
321+
322+ pthread_mutex_lock (& printf_mutex );
323+ printf ("%10d %16d %16" PRIu64 , pkt_rate , mbps , now_pkts );
324+
325+ if ( cfg_intf_stats )
326+ zf_stats_print (stack , stats_data , stats_collection );
327+
328+ printf ("\n" );
269329 fflush (stdout );
330+ pthread_mutex_unlock (& printf_mutex );
331+
270332 prev_pkts = now_pkts ;
271333 prev_bytes = now_bytes ;
272334 start = end ;
273335 }
336+
337+ if ( cfg_intf_stats ) {
338+ free (stats_data );
339+ zf_stats_free_layout_collection (stats_collection );
340+ }
274341}
275342
276343
277344static void * monitor_fn (void * arg )
278345{
279- monitor ();
346+ monitor ( ( struct zf_stack * ) arg );
280347 return NULL ;
281348}
282349
@@ -289,7 +356,7 @@ int main(int argc, char* argv[])
289356 bool cfg_print_attrs = false;
290357
291358 int c ;
292- while ( (c = getopt (argc , argv , "hmrwqp " )) != -1 )
359+ while ( (c = getopt (argc , argv , "hmrwqps " )) != -1 )
293360 switch ( c ) {
294361 case 'h' :
295362 usage_msg (stdout );
@@ -309,6 +376,9 @@ int main(int argc, char* argv[])
309376 case 'p' :
310377 cfg_print_attrs = true;
311378 break ;
379+ case 's' :
380+ cfg_intf_stats = true;
381+ break ;
312382 case '?' :
313383 exit (1 );
314384 default :
@@ -374,7 +444,7 @@ int main(int argc, char* argv[])
374444 res .n_rx_pkts = 0 ;
375445
376446 if ( ! cfg_quiet )
377- ZF_TRY (pthread_create (& thread_id , NULL , monitor_fn , NULL ) == 0 );
447+ ZF_TRY (pthread_create (& thread_id , NULL , monitor_fn , stack ) == 0 );
378448
379449 if ( cfg_waitable_fd )
380450 ev_loop_waitable_fd (stack , muxer );
0 commit comments