Index: share/man/man4/bpf.4 =================================================================== --- share/man/man4/bpf.4 (revision 228215) +++ share/man/man4/bpf.4 (working copy) @@ -49,7 +49,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 15, 2010 +.Dd December 2, 2011 .Dt BPF 4 .Os .Sh NAME @@ -516,7 +516,26 @@ by default. .It Dv BIOCSTSTAMP .It Dv BIOCGTSTAMP .Pq Li u_int -Set or get format and resolution of the time stamps returned by BPF. +Set or get the format, resolution and source of time stamps returned by BPF. +Note that the +.Dv BPF_T_FBCLOCK , +.Dv BPF_T_FBCLOCK_FAST , +.Dv BPF_T_FBCLOCK_MONOTONIC , +.Dv BPF_T_FBCLOCK_MONOTONIC_FAST , +.Dv BPF_T_FFCLOCK , +.Dv BPF_T_FFCLOCK_FAST , +.Dv BPF_T_FFCLOCK_MONOTONIC , +.Dv BPF_T_FFCLOCK_MONOTONIC_FAST , +and +.Dv BPF_T_FFCOUNTER +options described below are not allowed unless the kernel has been compiled +with feed-forward clock support +.Po +see +.Xr ffclock 4 +for more details +.Pc . +.Pp Set to .Dv BPF_T_MICROTIME , .Dv BPF_T_MICROTIME_FAST , @@ -545,32 +564,58 @@ to get time stamps in 64-bit .Vt struct bintime format. Set to +.Dv BPF_T_FBCLOCK , +.Dv BPF_T_FBCLOCK_FAST , +.Dv BPF_T_FBCLOCK_MONOTONIC_FAST , +.Dv BPF_T_FFCLOCK , +.Dv BPF_T_FFCLOCK_FAST , +or +.Dv BPF_T_FFCLOCK_MONOTONIC_FAST +to specify that the BPF device should explicitly use the feedback or +feed-forward clock respectively for time stamp generation. +Set to +.Dv BPF_T_FFCOUNTER +to get a 64-bit feed-forward counter value. +Set to .Dv BPF_T_NONE to ignore time stamp. +By default, time stamps are derived from the active system clock +.Po +feedback or +feed-forward +.Pc +and initilized to +.Dv BPF_T_MICROTIME . +.Pp All 64-bit time stamp formats are wrapped in .Vt struct bpf_ts . The .Dv BPF_T_MICROTIME_FAST , .Dv BPF_T_NANOTIME_FAST , .Dv BPF_T_BINTIME_FAST , +.Dv BPF_T_FBCLOCK_FAST , +.Dv BPF_T_FFCLOCK_FAST , .Dv BPF_T_MICROTIME_MONOTONIC_FAST , .Dv BPF_T_NANOTIME_MONOTONIC_FAST , +.Dv BPF_T_BINTIME_MONOTONIC_FAST , +.Dv BPF_T_FBCLOCK_MONOTONIC_FAST , and -.Dv BPF_T_BINTIME_MONOTONIC_FAST +.Dv BPF_T_FFCLOCK_MONOTONIC_FAST are analogs of corresponding formats without _FAST suffix but do not perform a full time counter query, so their accuracy is one timer tick. The .Dv BPF_T_MICROTIME_MONOTONIC , .Dv BPF_T_NANOTIME_MONOTONIC , .Dv BPF_T_BINTIME_MONOTONIC , +.Dv BPF_T_FBCLOCK_MONOTONIC , +.Dv BPF_T_FFCLOCK_MONOTONIC , .Dv BPF_T_MICROTIME_MONOTONIC_FAST , .Dv BPF_T_NANOTIME_MONOTONIC_FAST , +.Dv BPF_T_BINTIME_MONOTONIC_FAST , +.Dv BPF_T_FBCLOCK_MONOTONIC_FAST , and -.Dv BPF_T_BINTIME_MONOTONIC_FAST +.Dv BPF_T_FFCLOCK_MONOTONIC_FAST store the time elapsed since kernel boot. -This setting is initialized to -.Dv BPF_T_MICROTIME -by default. .It Dv BIOCFEEDBACK .Pq Li u_int Set packet feedback mode. @@ -1021,6 +1066,7 @@ struct bpf_insn insns[] = { .Xr poll 2 , .Xr select 2 , .Xr byteorder 3 , +.Xr ffclock 4 , .Xr ng_bpf 4 , .Xr bpf 9 .Rs Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 228215) +++ sys/net/bpf.c (working copy) @@ -1,12 +1,17 @@ /*- * Copyright (c) 1990, 1991, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. + * Copyright (c) 2011 The University of Melbourne. + * All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * + * Portions of this software were developed by Julien Ridoux at the University + * of Melbourne under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ffclock.h" #include "opt_netgraph.h" #include @@ -55,6 +61,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef FFCLOCK +#include +#endif #include #include @@ -112,7 +121,7 @@ struct bpf_hdr32 { uint16_t bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ }; -#endif +#endif /* !BURN_BRIDGES */ struct bpf_program32 { u_int bf_len; @@ -130,7 +139,20 @@ struct bpf_dltlist32 { #define BIOCGDLTLIST32 _IOWR('B', 121, struct bpf_dltlist32) #define BIOCSETWF32 _IOW('B', 123, struct bpf_program32) #define BIOCSETFNR32 _IOW('B', 130, struct bpf_program32) +#endif /* COMPAT_FREEBSD32 */ + +#ifdef FFCLOCK +/* + * Safety belt to ensure ABI of structs bpf_hdr32, bpf_hdr and bpf_xhdr are + * preserved when FFCLOCK is enabled, which changes the stamp field in the + * structs to allow storing a regular time stamp or ffcounter stamp. + */ +CTASSERT(sizeof(struct timeval) >= sizeof(ffcounter) && +#if defined(COMPAT_FREEBSD32) && !defined(BURN_BRIDGES) + sizeof(struct timeval32) >= sizeof(ffcounter) && #endif + sizeof(struct bpf_ts) >= sizeof(ffcounter)); +#endif /* * bpf_iflist is a list of BPF interface structures, each corresponding to a @@ -148,6 +170,7 @@ static void bpf_freed(struct bpf_d *); static int bpf_movein(struct uio *, int, struct ifnet *, struct mbuf **, struct sockaddr *, int *, struct bpf_insn *); static int bpf_setif(struct bpf_d *, struct ifreq *); +static bpf_ts_func bpf_tsf(int); static void bpf_timed_out(void *); static __inline void bpf_wakeup(struct bpf_d *); @@ -686,6 +709,7 @@ bpfopen(struct cdev *dev, int flags, int fmt, stru * particular buffer method. */ bpf_buffer_init(d); + d->bd_tsfunc = bpf_tsf(BPF_T_MICROTIME); d->bd_bufmode = BPF_BUFMODE_BUFFER; d->bd_sig = SIGIO; d->bd_direction = BPF_D_INOUT; @@ -1406,9 +1430,16 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t add u_int func; func = *(u_int *)addr; - if (BPF_T_VALID(func)) +#ifndef FFCLOCK + if (BPF_T_FORMAT(func) == BPF_T_FFCOUNTER || + BPF_T_CLOCK(func) != BPF_T_SYSCLOCK) { + error = EINVAL; + } else +#endif + if (BPF_T_VALID(func)) { d->bd_tstamp = func; - else + d->bd_tsfunc = bpf_tsf(func); + } else error = EINVAL; } break; @@ -1776,8 +1807,31 @@ bpf_ts_quality(int tstype) return (BPF_TSTAMP_NORMAL); } +static bpf_ts_func +bpf_tsf(int tstype) +{ + +#ifdef FFCLOCK + if (tstype == BPF_T_FFCOUNTER) + return ((bpf_ts_func)ffclock_read_counter); + switch (BPF_T_CLOCK(tstype)) { + case BPF_T_FBCLOCK: + if (bpf_ts_quality(tstype) == BPF_TSTAMP_FAST) + return ((bpf_ts_func)fbclock_getbinuptime); + return ((bpf_ts_func)fbclock_binuptime); + case BPF_T_FFCLOCK: + if (bpf_ts_quality(tstype) == BPF_TSTAMP_FAST) + return ((bpf_ts_func)ffclock_getbinuptime); + return ((bpf_ts_func)ffclock_binuptime); + } +#endif + if (bpf_ts_quality(tstype) == BPF_TSTAMP_FAST) + return ((bpf_ts_func)getbinuptime); + return ((bpf_ts_func)binuptime); +} + static int -bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m) +bpf_gettime(void *ts, int tstype, bpf_ts_func tsfunc, struct mbuf *m) { struct m_tag *tag; int quality; @@ -1789,15 +1843,11 @@ static int if (m != NULL) { tag = m_tag_locate(m, MTAG_BPF, MTAG_BPF_TIMESTAMP, NULL); if (tag != NULL) { - *bt = *(struct bintime *)(tag + 1); + bcopy(tag + 1, ts, sizeof(struct bintime)); return (BPF_TSTAMP_EXTERN); } } - if (quality == BPF_TSTAMP_NORMAL) - binuptime(bt); - else - getbinuptime(bt); - + tsfunc(ts); return (quality); } @@ -1839,7 +1889,8 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktl if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, NULL); + gottime = bpf_gettime(&bt, d->bd_tstamp, + d->bd_tsfunc, NULL); #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif @@ -1895,7 +1946,8 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m) if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, m); + gottime = bpf_gettime(&bt, d->bd_tstamp, + d->bd_tsfunc, m); #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif @@ -1948,7 +2000,8 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, m); + gottime = bpf_gettime(&bt, d->bd_tstamp, + d->bd_tsfunc, m); #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif @@ -2022,6 +2075,12 @@ bpf_bintime2ts(struct bintime *bt, struct bpf_ts * ts->bt_sec = bt->sec; ts->bt_frac = bt->frac; break; +#ifdef FFCLOCK + case BPF_T_FFCOUNTER: + /* Feed-forward counter uses the same space. */ + bcopy(bt, ts, sizeof(ffcounter)); + break; +#endif } } Index: sys/net/bpf.h =================================================================== --- sys/net/bpf.h (revision 228215) +++ sys/net/bpf.h (working copy) @@ -1,12 +1,17 @@ /*- * Copyright (c) 1990, 1991, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. + * Copyright (c) 2011 The University of Melbourne. + * All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * + * Portions of this software were developed by Julien Ridoux at the University + * of Melbourne under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -164,17 +169,26 @@ enum bpf_direction { #define BPF_T_NANOTIME 0x0001 #define BPF_T_BINTIME 0x0002 #define BPF_T_NONE 0x0003 -#define BPF_T_FORMAT_MASK 0x0003 +#define BPF_T_FFCOUNTER 0x0004 +#define BPF_T_FORMAT_MAX 0x0004 +#define BPF_T_FORMAT_MASK 0x0007 #define BPF_T_NORMAL 0x0000 #define BPF_T_FAST 0x0100 #define BPF_T_MONOTONIC 0x0200 #define BPF_T_MONOTONIC_FAST (BPF_T_FAST | BPF_T_MONOTONIC) #define BPF_T_FLAG_MASK 0x0300 +#define BPF_T_SYSCLOCK 0x0000 +#define BPF_T_FBCLOCK 0x1000 +#define BPF_T_FFCLOCK 0x2000 +#define BPF_T_CLOCK_MAX 0x2000 +#define BPF_T_CLOCK_MASK 0x3000 #define BPF_T_FORMAT(t) ((t) & BPF_T_FORMAT_MASK) #define BPF_T_FLAG(t) ((t) & BPF_T_FLAG_MASK) -#define BPF_T_VALID(t) \ - ((t) == BPF_T_NONE || (BPF_T_FORMAT(t) != BPF_T_NONE && \ - ((t) & ~(BPF_T_FORMAT_MASK | BPF_T_FLAG_MASK)) == 0)) +#define BPF_T_CLOCK(t) ((t) & BPF_T_CLOCK_MASK) +#define BPF_T_VALID(t) \ + ((t) == BPF_T_NONE || (t) == BPF_T_FFCOUNTER || \ + (BPF_T_FORMAT(t) <= BPF_T_BINTIME && BPF_T_CLOCK(t) <= BPF_T_CLOCK_MAX && \ + ((t) & ~(BPF_T_FORMAT_MASK | BPF_T_FLAG_MASK | BPF_T_CLOCK_MASK)) == 0)) #define BPF_T_MICROTIME_FAST (BPF_T_MICROTIME | BPF_T_FAST) #define BPF_T_NANOTIME_FAST (BPF_T_NANOTIME | BPF_T_FAST) @@ -186,6 +200,44 @@ enum bpf_direction { #define BPF_T_NANOTIME_MONOTONIC_FAST (BPF_T_NANOTIME | BPF_T_MONOTONIC_FAST) #define BPF_T_BINTIME_MONOTONIC_FAST (BPF_T_BINTIME | BPF_T_MONOTONIC_FAST) +#define BPF_T_FBCLOCK_MICROTIME_FAST \ + (BPF_T_MICROTIME_FAST | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_NANOTIME_FAST \ + (BPF_T_NANOTIME_FAST | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_BINTIME_FAST \ + (BPF_T_BINTIME_FAST | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_MICROTIME_MONOTONIC \ + (BPF_T_MICROTIME_MONOTONIC | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_NANOTIME_MONOTONIC \ + (BPF_T_NANOTIME_MONOTONIC | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_BINTIME_MONOTONIC \ + (BPF_T_BINTIME_MONOTONIC | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_MICROTIME_MONOTONIC_FAST \ + (BPF_T_MICROTIME_MONOTONIC_FAST | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_NANOTIME_MONOTONIC_FAST \ + (BPF_T_NANOTIME_MONOTONIC_FAST | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_BINTIME_MONOTONIC_FAST \ + (BPF_T_BINTIME_MONOTONIC_FAST | BPF_T_FBCLOCK) + +#define BPF_T_FFCLOCK_MICROTIME_FAST \ + (BPF_T_MICROTIME_FAST | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_NANOTIME_FAST \ + (BPF_T_NANOTIME_FAST | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_BINTIME_FAST \ + (BPF_T_BINTIME_FAST | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_MICROTIME_MONOTONIC \ + (BPF_T_MICROTIME_MONOTONIC | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_NANOTIME_MONOTONIC \ + (BPF_T_NANOTIME_MONOTONIC | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_BINTIME_MONOTONIC \ + (BPF_T_BINTIME_MONOTONIC | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_MICROTIME_MONOTONIC_FAST \ + (BPF_T_MICROTIME_MONOTONIC_FAST | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_NANOTIME_MONOTONIC_FAST \ + (BPF_T_NANOTIME_MONOTONIC_FAST | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_BINTIME_MONOTONIC_FAST \ + (BPF_T_BINTIME_MONOTONIC_FAST | BPF_T_FFCLOCK) + /* * Structure prepended to each packet. */ @@ -213,7 +265,14 @@ struct bpf_hdr { #define MTAG_BPF_TIMESTAMP 0 #endif +#ifdef FFCLOCK /* + * Feed-foward counter accessor. + */ +#define BPF_FFCOUNT(bh) (*(ffcounter *)&(bh)->bh_tstamp) +#endif + +/* * When using zero-copy BPF buffers, a shared memory header is present * allowing the kernel BPF implementation and user process to synchronize * without using system calls. This structure defines that header. When Index: sys/net/bpfdesc.h =================================================================== --- sys/net/bpfdesc.h (revision 228215) +++ sys/net/bpfdesc.h (working copy) @@ -46,6 +46,11 @@ #include /* + * Timestamping function. + */ +typedef void (*bpf_ts_func)(void *); + +/* * Descriptor associated with each open bpf file. */ struct zbuf; @@ -73,6 +78,7 @@ struct bpf_d { struct bpf_insn *bd_rfilter; /* read filter code */ struct bpf_insn *bd_wfilter; /* write filter code */ void *bd_bfilter; /* binary filter code */ + bpf_ts_func bd_tsfunc; /* timestamping function */ u_int64_t bd_rcount; /* number of packets received */ u_int64_t bd_dcount; /* number of packets dropped */