@@ -128,6 +128,7 @@ static void print_usage(void)
128
128
fprintf (stderr , "Options:\n" );
129
129
fprintf (stderr , " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n" );
130
130
fprintf (stderr , " -H (read hardware timestamps instead of system timestamps)\n" );
131
+ fprintf (stderr , " -N (log nanosecond timestamps instead of microseconds)\n" );
131
132
fprintf (stderr , " -c (increment color mode level)\n" );
132
133
fprintf (stderr , " -i (binary output - may exceed 80 chars/line)\n" );
133
134
fprintf (stderr , " -a (enable additional ASCII output)\n" );
@@ -220,49 +221,66 @@ static int idx2dindex(int ifidx, int socket)
220
221
return i ;
221
222
}
222
223
223
- static int sprint_timestamp (char * ts_buffer , const char timestamp ,
224
- const struct timeval * tv , struct timeval * const last_tv )
224
+ static int sprint_timestamp (char * ts_buffer , const char timestamp , const char use_ns ,
225
+ const struct timespec * ts , struct timespec * const last_ts )
225
226
{
226
227
int numchars = 0 ;
227
228
228
229
switch (timestamp ) {
229
230
case 'a' : /* absolute with timestamp */
230
- numchars = sprintf (ts_buffer , "(%010llu.%06llu) " ,
231
- (unsigned long long )tv -> tv_sec ,
232
- (unsigned long long )tv -> tv_usec );
231
+ if (use_ns ) {
232
+ numchars = sprintf (ts_buffer , "(%010llu.%09llu) " ,
233
+ (unsigned long long )ts -> tv_sec ,
234
+ (unsigned long long )ts -> tv_nsec );
235
+ } else {
236
+ numchars = sprintf (ts_buffer , "(%010llu.%06llu) " ,
237
+ (unsigned long long )ts -> tv_sec ,
238
+ (unsigned long long )ts -> tv_nsec / 1000 );
239
+ }
233
240
break ;
234
241
235
242
case 'A' : /* absolute with date */
236
243
{
237
244
struct tm tm ;
238
245
char timestring [25 ];
239
246
240
- tm = * localtime (& tv -> tv_sec );
247
+ tm = * localtime (& ts -> tv_sec );
241
248
strftime (timestring , 24 , "%Y-%m-%d %H:%M:%S" , & tm );
242
- numchars = sprintf (ts_buffer , "(%s.%06llu) " , timestring ,
243
- (unsigned long long )tv -> tv_usec );
249
+ if (use_ns ) {
250
+ numchars = sprintf (ts_buffer , "(%s.%09llu) " , timestring ,
251
+ (unsigned long long )ts -> tv_nsec );
252
+ } else {
253
+ numchars = sprintf (ts_buffer , "(%s.%06llu) " , timestring ,
254
+ (unsigned long long )ts -> tv_nsec / 1000 );
255
+ }
244
256
}
245
257
break ;
246
258
247
259
case 'd' : /* delta */
248
260
case 'z' : /* starting with zero */
249
261
{
250
- struct timeval diff ;
251
-
252
- if (last_tv -> tv_sec == 0 ) /* first init */
253
- * last_tv = * tv ;
254
- diff .tv_sec = tv -> tv_sec - last_tv -> tv_sec ;
255
- diff .tv_usec = tv -> tv_usec - last_tv -> tv_usec ;
256
- if (diff .tv_usec < 0 )
257
- diff .tv_sec -- , diff .tv_usec += 1000000 ;
262
+ struct timespec diff ;
263
+
264
+ if (last_ts -> tv_sec == 0 ) /* first init */
265
+ * last_ts = * ts ;
266
+ diff .tv_sec = ts -> tv_sec - last_ts -> tv_sec ;
267
+ diff .tv_nsec = ts -> tv_nsec - last_ts -> tv_nsec ;
268
+ if (diff .tv_nsec < 0 )
269
+ diff .tv_sec -- , diff .tv_nsec += 1000000000 ;
258
270
if (diff .tv_sec < 0 )
259
- diff .tv_sec = diff .tv_usec = 0 ;
260
- numchars = sprintf (ts_buffer , "(%03llu.%06llu) " ,
261
- (unsigned long long )diff .tv_sec ,
262
- (unsigned long long )diff .tv_usec );
271
+ diff .tv_sec = diff .tv_nsec = 0 ;
272
+ if (use_ns ) {
273
+ numchars = sprintf (ts_buffer , "(%03llu.%09llu) " ,
274
+ (unsigned long long )diff .tv_sec ,
275
+ (unsigned long long )diff .tv_nsec );
276
+ } else {
277
+ numchars = sprintf (ts_buffer , "(%03llu.%06llu) " ,
278
+ (unsigned long long )diff .tv_sec ,
279
+ (unsigned long long )diff .tv_nsec / 1000 );
280
+ }
263
281
264
282
if (timestamp == 'd' )
265
- * last_tv = * tv ; /* update for delta calculation */
283
+ * last_ts = * ts ; /* update for delta calculation */
266
284
}
267
285
break ;
268
286
@@ -288,6 +306,7 @@ int main(int argc, char **argv)
288
306
unsigned char timestamp = 0 ;
289
307
unsigned char logtimestamp = 'a' ;
290
308
unsigned char hwtimestamp = 0 ;
309
+ unsigned char use_ns = 0 ;
291
310
unsigned char down_causes_exit = 1 ;
292
311
unsigned char dropmonitor = 0 ;
293
312
unsigned char extra_msg_info = 0 ;
@@ -322,7 +341,7 @@ int main(int argc, char **argv)
322
341
static cu_t cu ; /* union for CAN CC/FD/XL frames */
323
342
int nbytes , i ;
324
343
struct ifreq ifr ;
325
- struct timeval tv , last_tv ;
344
+ struct timespec ts , last_ts ;
326
345
int timeout_ms = -1 ; /* default to no timeout */
327
346
FILE * logfile = NULL ;
328
347
char fname [83 ]; /* suggested by -Wformat-overflow= */
@@ -334,12 +353,12 @@ int main(int argc, char **argv)
334
353
signal (SIGHUP , sigterm );
335
354
signal (SIGINT , sigterm );
336
355
337
- last_tv .tv_sec = 0 ;
338
- last_tv . tv_usec = 0 ;
356
+ last_ts .tv_sec = 0 ;
357
+ last_ts . tv_nsec = 0 ;
339
358
340
359
progname = basename (argv [0 ]);
341
360
342
- while ((opt = getopt (argc , argv , "t:HciaSs :lf:Ln:r:Dde8xT:h?" )) != -1 ) {
361
+ while ((opt = getopt (argc , argv , "t:HNciaSs :lf:Ln:r:Dde8xT:h?" )) != -1 ) {
343
362
switch (opt ) {
344
363
case 't' :
345
364
timestamp = optarg [0 ];
@@ -359,6 +378,10 @@ int main(int argc, char **argv)
359
378
hwtimestamp = 1 ;
360
379
break ;
361
380
381
+ case 'N' :
382
+ use_ns = 1 ;
383
+ break ;
384
+
362
385
case 'c' :
363
386
color ++ ;
364
387
break ;
@@ -784,7 +807,11 @@ int main(int argc, char **argv)
784
807
cmsg && (cmsg -> cmsg_level == SOL_SOCKET );
785
808
cmsg = CMSG_NXTHDR (& msg ,cmsg )) {
786
809
if (cmsg -> cmsg_type == SO_TIMESTAMP ) {
810
+ struct timeval tv ;
787
811
memcpy (& tv , CMSG_DATA (cmsg ), sizeof (tv ));
812
+ ts .tv_sec = tv .tv_sec ;
813
+ ts .tv_nsec = tv .tv_usec ;
814
+ ts .tv_nsec *= 1000 ;
788
815
} else if (cmsg -> cmsg_type == SO_TIMESTAMPING ) {
789
816
struct timespec * stamp = (struct timespec * )CMSG_DATA (cmsg );
790
817
@@ -795,8 +822,7 @@ int main(int argc, char **argv)
795
822
* See chapter 2.1.2 Receive timestamps in
796
823
* linux/Documentation/networking/timestamping.txt
797
824
*/
798
- tv .tv_sec = stamp [2 ].tv_sec ;
799
- tv .tv_usec = stamp [2 ].tv_nsec / 1000 ;
825
+ ts = stamp [2 ];
800
826
} else if (cmsg -> cmsg_type == SO_RXQ_OVFL ) {
801
827
memcpy (& obj -> dropcnt , CMSG_DATA (cmsg ), sizeof (__u32 ));
802
828
}
@@ -831,11 +857,9 @@ int main(int argc, char **argv)
831
857
/* build common log format output */
832
858
if ((log ) || ((logfrmt ) && (silent == SILENT_OFF ))) {
833
859
834
- alen = sprint_timestamp (afrbuf , logtimestamp ,
835
- & tv , & last_tv );
860
+ alen = sprint_timestamp (afrbuf , logtimestamp , use_ns , & ts , & last_ts );
836
861
837
- alen += sprintf (afrbuf + alen , "%*s " ,
838
- max_devname_len , devname [idx ]);
862
+ alen += sprintf (afrbuf + alen , "%*s " , max_devname_len , devname [idx ]);
839
863
840
864
alen += snprintf_canframe (afrbuf + alen , sizeof (afrbuf ) - alen , & cu , 0 );
841
865
}
@@ -861,7 +885,7 @@ int main(int argc, char **argv)
861
885
862
886
/* print (colored) long CAN frame style to stdout */
863
887
alen = sprintf (afrbuf , " %s" , (color > 2 ) ? col_on [idx % MAXCOL ] : "" );
864
- alen += sprint_timestamp (afrbuf + alen , timestamp , & tv , & last_tv );
888
+ alen += sprint_timestamp (afrbuf + alen , timestamp , use_ns , & ts , & last_ts );
865
889
alen += sprintf (afrbuf + alen , " %s%*s" ,
866
890
(color && (color < 3 )) ? col_on [idx % MAXCOL ] : "" ,
867
891
max_devname_len , devname [idx ]);
0 commit comments