Author: jkim
Date: Tue Jun 15 19:28:44 2010
New Revision: 209216
URL: http://svn.freebsd.org/changeset/base/209216

Log:
  Implement flexible BPF timestamping framework.
  
  - Allow setting format, resolution and accuracy of BPF time stamps per
  listener.  Previously, we were only able to use microtime(9).  Now we can
  set various resolutions and accuracies with ioctl(2) BIOCSTSTAMP command.
  Similarly, we can get the current resolution and accuracy with BIOCGTSTAMP
  command.  Document all supported options in bpf(4) and their uses.
  
  - Introduce new time stamp 'struct bpf_ts' and header 'struct bpf_xhdr'.
  The new time stamp has both 64-bit second and fractional parts.  bpf_xhdr
  has this time stamp instead of 'struct timeval' for bh_tstamp.  The new
  structures let us use bh_tstamp of same size on both 32-bit and 64-bit
  platforms without adding additional shims for 32-bit binaries.  On 64-bit
  platforms, size of BPF header does not change compared to bpf_hdr as its
  members are already all 64-bit long.  On 32-bit platforms, the size may
  increase by 8 bytes.  For backward compatibility, struct bpf_hdr with
  struct timeval is still the default header unless new time stamp format is
  explicitly requested.  However, the behaviour may change in the future and
  all relevant code is wrapped around "#ifdef BURN_BRIDGES" for now.
  
  - Add experimental support for tagging mbufs with time stamps from a lower
  layer, e.g., device driver.  Currently, mbuf_tags(9) is used to tag mbufs.
  The time stamps must be uptime in 'struct bintime' format as binuptime(9)
  and getbinuptime(9) do.
  
  Reviewed by:  net@

Modified:
  head/share/man/man4/bpf.4
  head/sys/kern/kern_tc.c
  head/sys/net/bpf.c
  head/sys/net/bpf.h
  head/sys/net/bpfdesc.h
  head/sys/sys/time.h

Modified: head/share/man/man4/bpf.4
==============================================================================
--- head/share/man/man4/bpf.4   Tue Jun 15 19:28:37 2010        (r209215)
+++ head/share/man/man4/bpf.4   Tue Jun 15 19:28:44 2010        (r209216)
@@ -49,7 +49,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 26, 2007
+.Dd June 15, 2010
 .Dt BPF 4
 .Os
 .Sh NAME
@@ -513,6 +513,64 @@ to see only outgoing packets on the inte
 This setting is initialized to
 .Dv BPF_D_INOUT
 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 to
+.Dv BPF_T_MICROTIME ,
+.Dv BPF_T_MICROTIME_FAST ,
+.Dv BPF_T_MICROTIME_MONOTONIC ,
+or
+.Dv BPF_T_MICROTIME_MONOTONIC_FAST
+to get time stamps in 64-bit
+.Vt struct timeval
+format.
+Set to
+.Dv BPF_T_NANOTIME ,
+.Dv BPF_T_NANOTIME_FAST ,
+.Dv BPF_T_NANOTIME_MONOTONIC ,
+or
+.Dv BPF_T_NANOTIME_MONOTONIC_FAST
+to get time stamps in 64-bit
+.Vt struct timespec
+format.
+Set to
+.Dv BPF_T_BINTIME ,
+.Dv BPF_T_BINTIME_FAST ,
+.Dv BPF_T_NANOTIME_MONOTONIC ,
+or
+.Dv BPF_T_BINTIME_MONOTONIC_FAST
+to get time stamps in 64-bit
+.Vt struct bintime
+format.
+Set to
+.Dv BPF_T_NONE
+to ignore time stamp.
+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_MICROTIME_MONOTONIC_FAST ,
+.Dv BPF_T_NANOTIME_MONOTONIC_FAST ,
+and
+.Dv BPF_T_BINTIME_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_MICROTIME_MONOTONIC_FAST ,
+.Dv BPF_T_NANOTIME_MONOTONIC_FAST ,
+and
+.Dv BPF_T_BINTIME_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.
@@ -575,16 +633,24 @@ against
 .Vt bzh_user_gen .
 .El
 .Sh BPF HEADER
-The following structure is prepended to each packet returned by
+One of the following structures is prepended to each packet returned by
 .Xr read 2
 or via a zero-copy buffer:
 .Bd -literal
+struct bpf_xhdr {
+       struct bpf_ts   bh_tstamp;     /* time stamp */
+       uint32_t        bh_caplen;     /* length of captured portion */
+       uint32_t        bh_datalen;    /* original length of packet */
+       u_short         bh_hdrlen;     /* length of bpf header (this struct
+                                         plus alignment padding */
+};
+
 struct bpf_hdr {
-        struct timeval bh_tstamp;     /* time stamp */
-        u_long bh_caplen;             /* length of captured portion */
-        u_long bh_datalen;            /* original length of packet */
-        u_short bh_hdrlen;            /* length of bpf header (this struct
-                                        plus alignment padding */
+       struct timeval  bh_tstamp;     /* time stamp */
+       uint32_t        bh_caplen;     /* length of captured portion */
+       uint32_t        bh_datalen;    /* original length of packet */
+       u_short         bh_hdrlen;     /* length of bpf header (this struct
+                                         plus alignment padding */
 };
 .Ed
 .Pp
@@ -605,6 +671,8 @@ The length of the
 .Nm
 header, which may not be equal to
 .\" XXX - not really a function call
+.Fn sizeof "struct bpf_xhdr"
+or
 .Fn sizeof "struct bpf_hdr" .
 .El
 .Pp
@@ -616,9 +684,24 @@ The purpose here is to guarantee proper 
 data structures, which is required on alignment sensitive
 architectures and improves performance on many other architectures.
 The packet filter insures that the
-.Li bpf_hdr
+.Vt bpf_xhdr ,
+.Vt bpf_hdr
 and the network layer
 header will be word aligned.
+Currently,
+.Vt bpf_hdr
+is used when the time stamp is set to
+.Dv BPF_T_MICROTIME ,
+.Dv BPF_T_MICROTIME_FAST ,
+.Dv BPF_T_MICROTIME_MONOTONIC ,
+.Dv BPF_T_MICROTIME_MONOTONIC_FAST ,
+or
+.Dv BPF_T_NONE
+for backward compatibility reasons.  Otherwise,
+.Vt bpf_xhdr
+is used.  However,
+.Vt bpf_hdr
+may be deprecated in the near future.
 Suitable precautions
 must be taken when accessing the link layer protocol fields on alignment
 restricted machines.

Modified: head/sys/kern/kern_tc.c
==============================================================================
--- head/sys/kern/kern_tc.c     Tue Jun 15 19:28:37 2010        (r209215)
+++ head/sys/kern/kern_tc.c     Tue Jun 15 19:28:44 2010        (r209216)
@@ -90,7 +90,7 @@ static struct timecounter *timecounters 
 time_t time_second = 1;
 time_t time_uptime = 1;
 
-static struct bintime boottimebin;
+struct bintime boottimebin;
 struct timeval boottime;
 static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
 SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD,

Modified: head/sys/net/bpf.c
==============================================================================
--- head/sys/net/bpf.c  Tue Jun 15 19:28:37 2010        (r209215)
+++ head/sys/net/bpf.c  Tue Jun 15 19:28:44 2010        (r209216)
@@ -90,12 +90,16 @@ MALLOC_DEFINE(M_BPF, "BPF", "BPF data");
 
 #define PRINET  26                     /* interruptible */
 
+#define        SIZEOF_BPF_HDR(type)    \
+    (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen))
+
 #ifdef COMPAT_FREEBSD32
 #include <sys/mount.h>
 #include <compat/freebsd32/freebsd32.h>
 #define BPF_ALIGNMENT32 sizeof(int32_t)
 #define BPF_WORDALIGN32(x) (((x)+(BPF_ALIGNMENT32-1))&~(BPF_ALIGNMENT32-1))
 
+#ifndef BURN_BRIDGES
 /*
  * 32-bit version of structure prepended to each packet.  We use this header
  * instead of the standard one for 32-bit streams.  We mark the a stream as
@@ -108,6 +112,7 @@ struct bpf_hdr32 {
        uint16_t        bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
 };
+#endif
 
 struct bpf_program32 {
        u_int bf_len;
@@ -120,11 +125,11 @@ struct bpf_dltlist32 {
 };
 
 #define        BIOCSETF32      _IOW('B', 103, struct bpf_program32)
-#define        BIOCSRTIMEOUT32 _IOW('B',109, struct timeval32)
-#define        BIOCGRTIMEOUT32 _IOR('B',110, struct timeval32)
-#define        BIOCGDLTLIST32  _IOWR('B',121, struct bpf_dltlist32)
-#define        BIOCSETWF32     _IOW('B',123, struct bpf_program32)
-#define        BIOCSETFNR32    _IOW('B',130, struct bpf_program32)
+#define        BIOCSRTIMEOUT32 _IOW('B', 109, struct timeval32)
+#define        BIOCGRTIMEOUT32 _IOR('B', 110, struct timeval32)
+#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
 
 /*
@@ -148,7 +153,7 @@ static __inline void
                bpf_wakeup(struct bpf_d *);
 static void    catchpacket(struct bpf_d *, u_char *, u_int, u_int,
                    void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int),
-                   struct timeval *);
+                   struct bintime *);
 static void    reset_d(struct bpf_d *);
 static int      bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
 static int     bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1007,6 +1012,8 @@ reset_d(struct bpf_d *d)
  *  BIOCSHDRCMPLT      Set "header already complete" flag
  *  BIOCGDIRECTION     Get packet direction flag
  *  BIOCSDIRECTION     Set packet direction flag
+ *  BIOCGTSTAMP                Get time stamp format and resolution.
+ *  BIOCSTSTAMP                Set time stamp format and resolution.
  *  BIOCLOCK           Set "locked" flag
  *  BIOCFEEDBACK       Set packet feedback mode.
  *  BIOCSETZBUF                Set current zero-copy buffer locations.
@@ -1055,6 +1062,7 @@ bpfioctl(struct cdev *dev, u_long cmd, c
                case BIOCVERSION:
                case BIOCGRSIG:
                case BIOCGHDRCMPLT:
+               case BIOCSTSTAMP:
                case BIOCFEEDBACK:
                case FIONREAD:
                case BIOCLOCK:
@@ -1383,6 +1391,28 @@ bpfioctl(struct cdev *dev, u_long cmd, c
                }
                break;
 
+       /*
+        * Set packet timestamp format and resolution.
+        */
+       case BIOCGTSTAMP:
+               *(u_int *)addr = d->bd_tstamp;
+               break;
+
+       /*
+        * Set packet timestamp format and resolution.
+        */
+       case BIOCSTSTAMP:
+               {
+                       u_int   func;
+
+                       func = *(u_int *)addr;
+                       if (BPF_T_VALID(func))
+                               d->bd_tstamp = func;
+                       else
+                               error = EINVAL;
+               }
+               break;
+
        case BIOCFEEDBACK:
                d->bd_feedback = *(u_int *)addr;
                break;
@@ -1729,6 +1759,48 @@ filt_bpfread(struct knote *kn, long hint
        return (ready);
 }
 
+#define        BPF_TSTAMP_NONE         0
+#define        BPF_TSTAMP_FAST         1
+#define        BPF_TSTAMP_NORMAL       2
+#define        BPF_TSTAMP_EXTERN       3
+
+static int
+bpf_ts_quality(int tstype)
+{
+
+       if (tstype == BPF_T_NONE)
+               return (BPF_TSTAMP_NONE);
+       if ((tstype & BPF_T_FAST) != 0)
+               return (BPF_TSTAMP_FAST);
+
+       return (BPF_TSTAMP_NORMAL);
+}
+
+static int
+bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m)
+{
+       struct m_tag *tag;
+       int quality;
+
+       quality = bpf_ts_quality(tstype);
+       if (quality == BPF_TSTAMP_NONE)
+               return (quality);
+
+       if (m != NULL) {
+               tag = m_tag_locate(m, MTAG_BPF, MTAG_BPF_TIMESTAMP, NULL);
+               if (tag != NULL) {
+                       *bt = *(struct bintime *)(tag + 1);
+                       return (BPF_TSTAMP_EXTERN);
+               }
+       }
+       if (quality == BPF_TSTAMP_NORMAL)
+               binuptime(bt);
+       else
+               getbinuptime(bt);
+
+       return (quality);
+}
+
 /*
  * Incoming linkage from device drivers.  Process the packet pkt, of length
  * pktlen, which is stored in a contiguous buffer.  The packet is parsed
@@ -1738,15 +1810,15 @@ filt_bpfread(struct knote *kn, long hint
 void
 bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
 {
+       struct bintime bt;
        struct bpf_d *d;
 #ifdef BPF_JITTER
        bpf_jit_filter *bf;
 #endif
        u_int slen;
        int gottime;
-       struct timeval tv;
 
-       gottime = 0;
+       gottime = BPF_TSTAMP_NONE;
        BPFIF_LOCK(bp);
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                BPFD_LOCK(d);
@@ -1766,15 +1838,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, 
                slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
                if (slen != 0) {
                        d->bd_fcount++;
-                       if (!gottime) {
-                               microtime(&tv);
-                               gottime = 1;
-                       }
+                       if (gottime < bpf_ts_quality(d->bd_tstamp))
+                               gottime = bpf_gettime(&bt, d->bd_tstamp, NULL);
 #ifdef MAC
                        if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, pkt, pktlen, slen,
-                                   bpf_append_bytes, &tv);
+                                   bpf_append_bytes, &bt);
                }
                BPFD_UNLOCK(d);
        }
@@ -1791,13 +1861,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, 
 void
 bpf_mtap(struct bpf_if *bp, struct mbuf *m)
 {
+       struct bintime bt;
        struct bpf_d *d;
 #ifdef BPF_JITTER
        bpf_jit_filter *bf;
 #endif
        u_int pktlen, slen;
        int gottime;
-       struct timeval tv;
 
        /* Skip outgoing duplicate packets. */
        if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1805,10 +1875,9 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
                return;
        }
 
-       gottime = 0;
-
        pktlen = m_length(m, NULL);
 
+       gottime = BPF_TSTAMP_NONE;
        BPFIF_LOCK(bp);
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
@@ -1825,15 +1894,13 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
                slen = bpf_filter(d->bd_rfilter, (u_char *)m, pktlen, 0);
                if (slen != 0) {
                        d->bd_fcount++;
-                       if (!gottime) {
-                               microtime(&tv);
-                               gottime = 1;
-                       }
+                       if (gottime < bpf_ts_quality(d->bd_tstamp))
+                               gottime = bpf_gettime(&bt, d->bd_tstamp, m);
 #ifdef MAC
                        if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)m, pktlen, slen,
-                                   bpf_append_mbuf, &tv);
+                                   bpf_append_mbuf, &bt);
                }
                BPFD_UNLOCK(d);
        }
@@ -1847,11 +1914,11 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
 void
 bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
 {
+       struct bintime bt;
        struct mbuf mb;
        struct bpf_d *d;
        u_int pktlen, slen;
        int gottime;
-       struct timeval tv;
 
        /* Skip outgoing duplicate packets. */
        if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1859,8 +1926,6 @@ bpf_mtap2(struct bpf_if *bp, void *data,
                return;
        }
 
-       gottime = 0;
-
        pktlen = m_length(m, NULL);
        /*
         * Craft on-stack mbuf suitable for passing to bpf_filter.
@@ -1872,6 +1937,7 @@ bpf_mtap2(struct bpf_if *bp, void *data,
        mb.m_len = dlen;
        pktlen += dlen;
 
+       gottime = BPF_TSTAMP_NONE;
        BPFIF_LOCK(bp);
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp))
@@ -1881,15 +1947,13 @@ bpf_mtap2(struct bpf_if *bp, void *data,
                slen = bpf_filter(d->bd_rfilter, (u_char *)&mb, pktlen, 0);
                if (slen != 0) {
                        d->bd_fcount++;
-                       if (!gottime) {
-                               microtime(&tv);
-                               gottime = 1;
-                       }
+                       if (gottime < bpf_ts_quality(d->bd_tstamp))
+                               gottime = bpf_gettime(&bt, d->bd_tstamp, m);
 #ifdef MAC
                        if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)&mb, pktlen, slen,
-                                   bpf_append_mbuf, &tv);
+                                   bpf_append_mbuf, &bt);
                }
                BPFD_UNLOCK(d);
        }
@@ -1898,6 +1962,69 @@ bpf_mtap2(struct bpf_if *bp, void *data,
 
 #undef BPF_CHECK_DIRECTION
 
+#undef BPF_TSTAMP_NONE
+#undef BPF_TSTAMP_FAST
+#undef BPF_TSTAMP_NORMAL
+#undef BPF_TSTAMP_EXTERN
+
+static int
+bpf_hdrlen(struct bpf_d *d)
+{
+       int hdrlen;
+
+       hdrlen = d->bd_bif->bif_hdrlen;
+#ifndef BURN_BRIDGES
+       if (d->bd_tstamp == BPF_T_NONE ||
+           BPF_T_FORMAT(d->bd_tstamp) == BPF_T_MICROTIME)
+#ifdef COMPAT_FREEBSD32
+               if (d->bd_compat32)
+                       hdrlen += SIZEOF_BPF_HDR(struct bpf_hdr32);
+               else
+#endif
+                       hdrlen += SIZEOF_BPF_HDR(struct bpf_hdr);
+       else
+#endif
+               hdrlen += SIZEOF_BPF_HDR(struct bpf_xhdr);
+#ifdef COMPAT_FREEBSD32
+       if (d->bd_compat32)
+               hdrlen = BPF_WORDALIGN32(hdrlen);
+       else
+#endif
+               hdrlen = BPF_WORDALIGN(hdrlen);
+
+       return (hdrlen - d->bd_bif->bif_hdrlen);
+}
+
+static void
+bpf_bintime2ts(struct bintime *bt, struct bpf_ts *ts, int tstype)
+{
+       struct bintime bt2;
+       struct timeval tsm;
+       struct timespec tsn;
+
+       if ((tstype & BPF_T_MONOTONIC) == 0) {
+               bt2 = *bt;
+               bintime_add(&bt2, &boottimebin);
+               bt = &bt2;
+       }
+       switch (BPF_T_FORMAT(tstype)) {
+       case BPF_T_MICROTIME:
+               bintime2timeval(bt, &tsm);
+               ts->bt_sec = tsm.tv_sec;
+               ts->bt_frac = tsm.tv_usec;
+               break;
+       case BPF_T_NANOTIME:
+               bintime2timespec(bt, &tsn);
+               ts->bt_sec = tsn.tv_sec;
+               ts->bt_frac = tsn.tv_nsec;
+               break;
+       case BPF_T_BINTIME:
+               ts->bt_sec = bt->sec;
+               ts->bt_frac = bt->frac;
+               break;
+       }
+}
+
 /*
  * Move the packet data from interface memory (pkt) into the
  * store buffer.  "cpfn" is the routine called to do the actual data
@@ -1908,15 +2035,19 @@ bpf_mtap2(struct bpf_if *bp, void *data,
 static void
 catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
     void (*cpfn)(struct bpf_d *, caddr_t, u_int, void *, u_int),
-    struct timeval *tv)
+    struct bintime *bt)
 {
-       struct bpf_hdr hdr;
+       struct bpf_xhdr hdr;
+#ifndef BURN_BRIDGES
+       struct bpf_hdr hdr_old;
 #ifdef COMPAT_FREEBSD32
-       struct bpf_hdr32 hdr32;
+       struct bpf_hdr32 hdr32_old;
+#endif
 #endif
-       int totlen, curlen;
-       int hdrlen = d->bd_bif->bif_hdrlen;
+       int caplen, curlen, hdrlen, totlen;
        int do_wakeup = 0;
+       int do_timestamp;
+       int tstype;
 
        BPFD_LOCK_ASSERT(d);
 
@@ -1940,6 +2071,7 @@ catchpacket(struct bpf_d *d, u_char *pkt
         * much.  Otherwise, transfer the whole packet (unless
         * we hit the buffer size limit).
         */
+       hdrlen = bpf_hdrlen(d);
        totlen = hdrlen + min(snaplen, pktlen);
        if (totlen > d->bd_bufsize)
                totlen = d->bd_bufsize;
@@ -1979,19 +2111,39 @@ catchpacket(struct bpf_d *d, u_char *pkt
                 * reader should be woken up.
                 */
                do_wakeup = 1;
+       caplen = totlen - hdrlen;
+       tstype = d->bd_tstamp;
+       do_timestamp = tstype != BPF_T_NONE;
+#ifndef BURN_BRIDGES
+       if (tstype == BPF_T_NONE || BPF_T_FORMAT(tstype) == BPF_T_MICROTIME) {
+               struct bpf_ts ts;
+               if (do_timestamp)
+                       bpf_bintime2ts(bt, &ts, tstype);
 #ifdef COMPAT_FREEBSD32
-       /*
-        * If this is a 32-bit stream, then stick a 32-bit header at the
-        * front and copy the data into the buffer.
-        */
-       if (d->bd_compat32) {
-               bzero(&hdr32, sizeof(hdr32));
-               hdr32.bh_tstamp.tv_sec = tv->tv_sec;
-               hdr32.bh_tstamp.tv_usec = tv->tv_usec;
-               hdr32.bh_datalen = pktlen;
-               hdr32.bh_hdrlen = hdrlen;
-               hdr.bh_caplen = hdr32.bh_caplen = totlen - hdrlen;
-               bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr32, sizeof(hdr32));
+               if (d->bd_compat32) {
+                       bzero(&hdr32_old, sizeof(hdr32_old));
+                       if (do_timestamp) {
+                               hdr32_old.bh_tstamp.tv_sec = ts.bt_sec;
+                               hdr32_old.bh_tstamp.tv_usec = ts.bt_frac;
+                       }
+                       hdr32_old.bh_datalen = pktlen;
+                       hdr32_old.bh_hdrlen = hdrlen;
+                       hdr32_old.bh_caplen = caplen;
+                       bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr32_old,
+                           sizeof(hdr32_old));
+                       goto copy;
+               }
+#endif
+               bzero(&hdr_old, sizeof(hdr_old));
+               if (do_timestamp) {
+                       hdr_old.bh_tstamp.tv_sec = ts.bt_sec;
+                       hdr_old.bh_tstamp.tv_usec = ts.bt_frac;
+               }
+               hdr_old.bh_datalen = pktlen;
+               hdr_old.bh_hdrlen = hdrlen;
+               hdr_old.bh_caplen = caplen;
+               bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr_old,
+                   sizeof(hdr_old));
                goto copy;
        }
 #endif
@@ -2001,19 +2153,20 @@ catchpacket(struct bpf_d *d, u_char *pkt
         * move forward the length of the header plus padding.
         */
        bzero(&hdr, sizeof(hdr));
-       hdr.bh_tstamp = *tv;
+       if (do_timestamp)
+               bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype);
        hdr.bh_datalen = pktlen;
        hdr.bh_hdrlen = hdrlen;
-       hdr.bh_caplen = totlen - hdrlen;
+       hdr.bh_caplen = caplen;
        bpf_append_bytes(d, d->bd_sbuf, curlen, &hdr, sizeof(hdr));
 
        /*
         * Copy the packet data into the store buffer and update its length.
         */
-#ifdef COMPAT_FREEBSD32
- copy:
+#ifndef BURN_BRIDGES
+copy:
 #endif
-       (*cpfn)(d, d->bd_sbuf, curlen + hdrlen, pkt, hdr.bh_caplen);
+       (*cpfn)(d, d->bd_sbuf, curlen + hdrlen, pkt, caplen);
        d->bd_slen = curlen + totlen;
 
        if (do_wakeup)
@@ -2083,13 +2236,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt,
        LIST_INSERT_HEAD(&bpf_iflist, bp, bif_next);
        mtx_unlock(&bpf_mtx);
 
-       /*
-        * Compute the length of the bpf header.  This is not necessarily
-        * equal to SIZEOF_BPF_HDR because we want to insert spacing such
-        * that the network layer header begins on a longword boundary (for
-        * performance reasons and to alleviate alignment restrictions).
-        */
-       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
+       bp->bif_hdrlen = hdrlen;
 
        if (bootverbose)
                if_printf(ifp, "bpf attached\n");

Modified: head/sys/net/bpf.h
==============================================================================
--- head/sys/net/bpf.h  Tue Jun 15 19:28:37 2010        (r209215)
+++ head/sys/net/bpf.h  Tue Jun 15 19:28:44 2010        (r209216)
@@ -45,6 +45,8 @@
 
 typedef        int32_t   bpf_int32;
 typedef        u_int32_t bpf_u_int32;
+typedef        int64_t   bpf_int64;
+typedef        u_int64_t bpf_u_int64;
 
 /*
  * Alignment macros.  BPF_WORDALIGN rounds up to the next
@@ -113,36 +115,38 @@ struct bpf_zbuf {
        size_t   bz_buflen;     /* Size of zero-copy buffers. */
 };
 
-#define        BIOCGBLEN       _IOR('B',102, u_int)
-#define        BIOCSBLEN       _IOWR('B',102, u_int)
-#define        BIOCSETF        _IOW('B',103, struct bpf_program)
-#define        BIOCFLUSH       _IO('B',104)
-#define BIOCPROMISC    _IO('B',105)
-#define        BIOCGDLT        _IOR('B',106, u_int)
-#define BIOCGETIF      _IOR('B',107, struct ifreq)
-#define BIOCSETIF      _IOW('B',108, struct ifreq)
-#define BIOCSRTIMEOUT  _IOW('B',109, struct timeval)
-#define BIOCGRTIMEOUT  _IOR('B',110, struct timeval)
-#define BIOCGSTATS     _IOR('B',111, struct bpf_stat)
-#define BIOCIMMEDIATE  _IOW('B',112, u_int)
-#define BIOCVERSION    _IOR('B',113, struct bpf_version)
-#define BIOCGRSIG      _IOR('B',114, u_int)
-#define BIOCSRSIG      _IOW('B',115, u_int)
-#define BIOCGHDRCMPLT  _IOR('B',116, u_int)
-#define BIOCSHDRCMPLT  _IOW('B',117, u_int)
-#define BIOCGDIRECTION _IOR('B',118, u_int)
-#define BIOCSDIRECTION _IOW('B',119, u_int)
-#define        BIOCSDLT        _IOW('B',120, u_int)
-#define        BIOCGDLTLIST    _IOWR('B',121, struct bpf_dltlist)
+#define        BIOCGBLEN       _IOR('B', 102, u_int)
+#define        BIOCSBLEN       _IOWR('B', 102, u_int)
+#define        BIOCSETF        _IOW('B', 103, struct bpf_program)
+#define        BIOCFLUSH       _IO('B', 104)
+#define        BIOCPROMISC     _IO('B', 105)
+#define        BIOCGDLT        _IOR('B', 106, u_int)
+#define        BIOCGETIF       _IOR('B', 107, struct ifreq)
+#define        BIOCSETIF       _IOW('B', 108, struct ifreq)
+#define        BIOCSRTIMEOUT   _IOW('B', 109, struct timeval)
+#define        BIOCGRTIMEOUT   _IOR('B', 110, struct timeval)
+#define        BIOCGSTATS      _IOR('B', 111, struct bpf_stat)
+#define        BIOCIMMEDIATE   _IOW('B', 112, u_int)
+#define        BIOCVERSION     _IOR('B', 113, struct bpf_version)
+#define        BIOCGRSIG       _IOR('B', 114, u_int)
+#define        BIOCSRSIG       _IOW('B', 115, u_int)
+#define        BIOCGHDRCMPLT   _IOR('B', 116, u_int)
+#define        BIOCSHDRCMPLT   _IOW('B', 117, u_int)
+#define        BIOCGDIRECTION  _IOR('B', 118, u_int)
+#define        BIOCSDIRECTION  _IOW('B', 119, u_int)
+#define        BIOCSDLT        _IOW('B', 120, u_int)
+#define        BIOCGDLTLIST    _IOWR('B', 121, struct bpf_dltlist)
 #define        BIOCLOCK        _IO('B', 122)
-#define        BIOCSETWF       _IOW('B',123, struct bpf_program)
-#define        BIOCFEEDBACK    _IOW('B',124, u_int)
-#define        BIOCGETBUFMODE  _IOR('B',125, u_int)
-#define        BIOCSETBUFMODE  _IOW('B',126, u_int)
-#define        BIOCGETZMAX     _IOR('B',127, size_t)
-#define        BIOCROTZBUF     _IOR('B',128, struct bpf_zbuf)
-#define        BIOCSETZBUF     _IOW('B',129, struct bpf_zbuf)
-#define        BIOCSETFNR      _IOW('B',130, struct bpf_program)
+#define        BIOCSETWF       _IOW('B', 123, struct bpf_program)
+#define        BIOCFEEDBACK    _IOW('B', 124, u_int)
+#define        BIOCGETBUFMODE  _IOR('B', 125, u_int)
+#define        BIOCSETBUFMODE  _IOW('B', 126, u_int)
+#define        BIOCGETZMAX     _IOR('B', 127, size_t)
+#define        BIOCROTZBUF     _IOR('B', 128, struct bpf_zbuf)
+#define        BIOCSETZBUF     _IOW('B', 129, struct bpf_zbuf)
+#define        BIOCSETFNR      _IOW('B', 130, struct bpf_program)
+#define        BIOCGTSTAMP     _IOR('B', 131, u_int)
+#define        BIOCSTSTAMP     _IOW('B', 132, u_int)
 
 /* Obsolete */
 #define        BIOCGSEESENT    BIOCGDIRECTION
@@ -155,9 +159,48 @@ enum bpf_direction {
        BPF_D_OUT       /* See outgoing packets */
 };
 
+/* Time stamping functions */
+#define        BPF_T_MICROTIME         0x0000
+#define        BPF_T_NANOTIME          0x0001
+#define        BPF_T_BINTIME           0x0002
+#define        BPF_T_NONE              0x0003
+#define        BPF_T_FORMAT_MASK       0x0003
+#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_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_MICROTIME_FAST            (BPF_T_MICROTIME | BPF_T_FAST)
+#define        BPF_T_NANOTIME_FAST             (BPF_T_NANOTIME | BPF_T_FAST)
+#define        BPF_T_BINTIME_FAST              (BPF_T_BINTIME | BPF_T_FAST)
+#define        BPF_T_MICROTIME_MONOTONIC       (BPF_T_MICROTIME | 
BPF_T_MONOTONIC)
+#define        BPF_T_NANOTIME_MONOTONIC        (BPF_T_NANOTIME | 
BPF_T_MONOTONIC)
+#define        BPF_T_BINTIME_MONOTONIC         (BPF_T_BINTIME | 
BPF_T_MONOTONIC)
+#define        BPF_T_MICROTIME_MONOTONIC_FAST  (BPF_T_MICROTIME | 
BPF_T_MONOTONIC_FAST)
+#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)
+
 /*
  * Structure prepended to each packet.
  */
+struct bpf_ts {
+       bpf_int64       bt_sec;         /* seconds */
+       bpf_u_int64     bt_frac;        /* fraction */
+};
+struct bpf_xhdr {
+       struct bpf_ts   bh_tstamp;      /* time stamp */
+       bpf_u_int32     bh_caplen;      /* length of captured portion */
+       bpf_u_int32     bh_datalen;     /* original length of packet */
+       u_short         bh_hdrlen;      /* length of bpf header (this struct
+                                          plus alignment padding) */
+};
+/* Obsolete */
 struct bpf_hdr {
        struct timeval  bh_tstamp;      /* time stamp */
        bpf_u_int32     bh_caplen;      /* length of captured portion */
@@ -165,14 +208,9 @@ struct bpf_hdr {
        u_short         bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
 };
-/*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
- */
 #ifdef _KERNEL
-#define        SIZEOF_BPF_HDR  (sizeof(struct bpf_hdr) <= 20 ? 18 : \
-    sizeof(struct bpf_hdr))
+#define        MTAG_BPF                0x627066
+#define        MTAG_BPF_TIMESTAMP      0
 #endif
 
 /*
@@ -922,7 +960,7 @@ struct bpf_if {
        LIST_ENTRY(bpf_if)      bif_next;       /* list of all interfaces */
        LIST_HEAD(, bpf_d)      bif_dlist;      /* descriptor list */
        u_int bif_dlt;                          /* link layer type */
-       u_int bif_hdrlen;               /* length of header (with padding) */
+       u_int bif_hdrlen;               /* length of link header */
        struct ifnet *bif_ifp;          /* corresponding interface */
        struct mtx      bif_mtx;        /* mutex for interface */
 };

Modified: head/sys/net/bpfdesc.h
==============================================================================
--- head/sys/net/bpfdesc.h      Tue Jun 15 19:28:37 2010        (r209215)
+++ head/sys/net/bpfdesc.h      Tue Jun 15 19:28:44 2010        (r209216)
@@ -81,6 +81,7 @@ struct bpf_d {
        u_char          bd_immediate;   /* true to return on packet arrival */
        int             bd_hdrcmplt;    /* false to fill in src lladdr 
automatically */
        int             bd_direction;   /* select packet direction */
+       int             bd_tstamp;      /* select time stamping function */
        int             bd_feedback;    /* true to feed back sent packets */
        int             bd_async;       /* non-zero if packet reception should 
generate signal */
        int             bd_sig;         /* signal to send upon packet reception 
*/

Modified: head/sys/sys/time.h
==============================================================================
--- head/sys/sys/time.h Tue Jun 15 19:28:37 2010        (r209215)
+++ head/sys/sys/time.h Tue Jun 15 19:28:44 2010        (r209216)
@@ -264,6 +264,7 @@ void        resettodr(void);
 
 extern time_t  time_second;
 extern time_t  time_uptime;
+extern struct bintime boottimebin;
 extern struct timeval boottime;
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to