svn commit: r209216 - in head: share/man/man4 sys/kern sys/net sys/sys

Jung-uk Kim jkim at FreeBSD.org
Tue Jun 15 19:28:45 UTC 2010


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;
 
 /*


More information about the svn-src-head mailing list