Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Dec 2011 08:57:59 +0000 (UTC)
From:      Lawrence Stewart <lstewart@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228986 - in head: share/man/man4 sys/net
Message-ID:  <201112300857.pBU8vxfP004914@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: lstewart
Date: Fri Dec 30 08:57:58 2011
New Revision: 228986
URL: http://svn.freebsd.org/changeset/base/228986

Log:
  - Introduce the net.bpf.tscfg sysctl tree and associated code so as to make one
    aspect of time stamp configuration per interface rather than per BPF
    descriptor. Prior to this, the order in which BPF devices were opened and the
    per descriptor time stamp configuration settings could cause non-deterministic
    and unintended behaviour with respect to time stamping. With the new scheme, a
    BPF attached interface's tscfg sysctl entry can be set to "default", "none",
    "fast", "normal" or "external". Setting "default" means use the system default
    option (set with the net.bpf.tscfg.default sysctl), "none" means do not
    generate time stamps for tapped packets, "fast" means generate time stamps for
    tapped packets using a hz granularity system clock read, "normal" means
    generate time stamps for tapped packets using a full timecounter granularity
    system clock read and "external" (currently unimplemented) means use the time
    stamp provided with the packet from an underlying source.
  
  - Utilise the recently introduced sysclock_getsnapshot() and
    sysclock_snap2bintime() KPIs to ensure the system clock is only read once per
    packet, regardless of the number of BPF descriptors and time stamp formats
    requested. Use the per BPF attached interface time stamp configuration to
    control if sysclock_getsnapshot() is called and whether the system clock read
    is fast or normal. The per BPF descriptor time stamp configuration is then
    used to control how the system clock snapshot is converted to a bintime by
    sysclock_snap2bintime().
  
  - Remove all FAST related BPF descriptor flag variants. Performing a "fast"
    read of the system clock is now controlled per BPF attached interface using
    the net.bpf.tscfg sysctl tree.
  
  - Update the bpf.4 man page.
  
  Committed on behalf of Julien Ridoux and Darryl Veitch from the University of
  Melbourne, Australia, as part of the FreeBSD Foundation funded "Feed-Forward
  Clock Synchronization Algorithms" project.
  
  For more information, see http://www.synclab.org/radclock/
  
  In collaboration with:	Julien Ridoux (jridoux at unimelb edu au)

Modified:
  head/share/man/man4/bpf.4
  head/sys/net/bpf.c
  head/sys/net/bpf.h

Modified: head/share/man/man4/bpf.4
==============================================================================
--- head/share/man/man4/bpf.4	Fri Dec 30 06:24:59 2011	(r228985)
+++ head/share/man/man4/bpf.4	Fri Dec 30 08:57:58 2011	(r228986)
@@ -49,7 +49,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 15, 2010
+.Dd December 30, 2011
 .Dt BPF 4
 .Os
 .Sh NAME
@@ -516,61 +516,48 @@ 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 and resolution of time stamps returned by BPF.
+The per-BPF descriptor configuration provided by the
+.Dv BIOCSTSTAMP
+IOCTL complements the per-interface time stamp configuration detailed in the
+.Sx CONFIGURATION
+section.
+.Pp
 Set to
-.Dv BPF_T_MICROTIME ,
-.Dv BPF_T_MICROTIME_FAST ,
-.Dv BPF_T_MICROTIME_MONOTONIC ,
+.Dv BPF_T_MICROTIME
 or
-.Dv BPF_T_MICROTIME_MONOTONIC_FAST
+.Dv BPF_T_MICROTIME_MONOTONIC
 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 ,
+.Dv BPF_T_NANOTIME
 or
-.Dv BPF_T_NANOTIME_MONOTONIC_FAST
+.Dv BPF_T_NANOTIME_MONOTONIC
 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 ,
+.Dv BPF_T_BINTIME
 or
-.Dv BPF_T_BINTIME_MONOTONIC_FAST
+.Dv BPF_T_BINTIME_MONOTONIC
 to get time stamps in 64-bit
 .Vt struct bintime
 format.
 Set to
 .Dv BPF_T_NONE
-to ignore time stamp.
+to not set a time stamp.
+By default, time stamps are 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_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
+.Dv BPF_T_BINTIME_MONOTONIC
 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.
@@ -692,14 +679,14 @@ 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,
+for backward compatibility reasons.
+Otherwise,
 .Vt bpf_xhdr
-is used.  However,
+is used.
+However,
 .Vt bpf_hdr
 may be deprecated in the near future.
 Suitable precautions
@@ -952,6 +939,48 @@ array initializers:
 .Fn BPF_STMT opcode operand
 and
 .Fn BPF_JUMP opcode operand true_offset false_offset .
+.Sh CONFIGURATION
+Per-interface BPF time stamp configuration is possible via the
+.Va net.bpf.tscfg
+.Xr sysctl 8
+tree which provides the following variables:
+.Bl -tag -width "    " -offset indent
+.It Va net.bpf.tscfg.default
+The default time stamp configuration setting used by all BPF attached interfaces
+which have not been explicitly changed.
+Valid values are "none", "fast", "normal" and "external".
+The default is "normal".
+.It Va net.bpf.tscfg.<interface>
+The time stamp configuration setting used by a specific BPF attached interface.
+There will be a separate entry in the
+.Va net.bpf.tscfg
+sysctl tree for each BPF attached interface.
+Valid values are "default", "none", "fast", "normal" and "external".
+The default is "default", which means the system wide default setting specified
+by the
+.Va net.bpf.tscfg.default
+sysctl is used.
+.El
+.Pp
+The meaning of each per-interface time stamp configuration option is as follows:
+.Bl -tag -width "    " -offset indent
+.It none	
+Do not generate a time stamp for all packets tapped from this interface.
+.It fast	
+Generate a time stamp for all packets tapped from this interface by doing a fast
+read of the system clock.
+Fast reads have a granularity equivalent to the underlying kernel tick rate.
+.It normal
+Generate a time stamp for all packets tapped from this interface by doing a full
+read of the system clock.
+Full reads are slower than fast reads, but provide full hardware time counter
+granularity for the time stamp.
+.It external
+Something external to BPF is capable of generating time stamps for all packets
+tapped from this interface and BPF should use these external time stamps.
+Currently unimplemented, but will become useful when drivers for NICs which
+support hardware packet time stamping add support for this feature.
+.El
 .Sh FILES
 .Bl -tag -compact -width /dev/bpf
 .It Pa /dev/bpf

Modified: head/sys/net/bpf.c
==============================================================================
--- head/sys/net/bpf.c	Fri Dec 30 06:24:59 2011	(r228985)
+++ head/sys/net/bpf.c	Fri Dec 30 08:57:58 2011	(r228986)
@@ -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:
@@ -55,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/signalvar.h>
 #include <sys/filio.h>
 #include <sys/sockio.h>
+#include <sys/timeffc.h>
 #include <sys/ttycom.h>
 #include <sys/uio.h>
 
@@ -112,7 +118,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 +136,28 @@ 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
+#endif /* COMPAT_FREEBSD32 */
+
+static const char *bpfiftstypes[] = {
+	"default",
+#define	BPF_TSTAMP_DEFAULT	0
+	"none",
+#define	BPF_TSTAMP_NONE		1
+	"fast",
+#define	BPF_TSTAMP_FAST		2
+	"normal",
+#define	BPF_TSTAMP_NORMAL	3
+	"external"
+#define	BPF_TSTAMP_EXTERNAL	4
+};
+#define	NUM_BPFIFTSTYPES	(sizeof(bpfiftstypes) / sizeof(*bpfiftstypes))
+
+#define	SET_CLOCKCFG_FLAGS(tstype, active, clock, flags) do {		\
+	(flags) = 0;							\
+	(clock) = SYSCLOCK_FBCK;					\
+	if ((tstype) & BPF_T_MONOTONIC)					\
+		(flags) |= FBCLOCK_UPTIME;				\
+} while (0)
 
 /*
  * bpf_iflist is a list of BPF interface structures, each corresponding to a
@@ -162,6 +189,7 @@ static void	filt_bpfdetach(struct knote 
 static int	filt_bpfread(struct knote *, long);
 static void	bpf_drvinit(void *);
 static int	bpf_stats_sysctl(SYSCTL_HANDLER_ARGS);
+static int	bpf_tscfg_sysctl_handler(SYSCTL_HANDLER_ARGS);
 
 SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl");
 int bpf_maxinsns = BPF_MAXINSNS;
@@ -172,6 +200,12 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_
     &bpf_zerocopy_enable, 0, "Enable new zero-copy BPF buffer sessions");
 static SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_MPSAFE | CTLFLAG_RW,
     bpf_stats_sysctl, "bpf statistics portal");
+static SYSCTL_NODE(_net_bpf, OID_AUTO, tscfg, CTLFLAG_RW, NULL,
+    "Per-interface timestamp configuration");
+static int bpf_default_tstype = BPF_TSTAMP_NORMAL;
+SYSCTL_PROC(_net_bpf_tscfg, OID_AUTO, default,
+    CTLTYPE_STRING | CTLFLAG_RW, NULL, 0, bpf_tscfg_sysctl_handler, "A",
+    "Per-interface system wide default timestamp configuration");
 
 static	d_open_t	bpfopen;
 static	d_read_t	bpfread;
@@ -1759,48 +1793,6 @@ 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
@@ -1811,14 +1803,23 @@ void
 bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen)
 {
 	struct bintime bt;
+	struct sysclock_snap cs;
 	struct bpf_d *d;
+	int tstype, whichclock;
+	u_int clockflags, slen;
 #ifdef BPF_JITTER
 	bpf_jit_filter *bf;
 #endif
-	u_int slen;
-	int gottime;
 
-	gottime = BPF_TSTAMP_NONE;
+	tstype = bp->tstype;
+	if (tstype == BPF_TSTAMP_DEFAULT)
+		tstype = bpf_default_tstype;
+
+	if (tstype == BPF_TSTAMP_NORMAL || tstype == BPF_TSTAMP_FAST)
+		sysclock_getsnapshot(&cs, tstype == BPF_TSTAMP_FAST ? 1 : 0);
+	else
+		bzero(&bt, sizeof(bt));
+
 	BPFIF_LOCK(bp);
 	LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
 		BPFD_LOCK(d);
@@ -1838,8 +1839,16 @@ 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 < bpf_ts_quality(d->bd_tstamp))
-				gottime = bpf_gettime(&bt, d->bd_tstamp, NULL);
+			if (tstype == BPF_TSTAMP_NORMAL ||
+			    tstype == BPF_TSTAMP_FAST) {
+				whichclock = -1;
+				SET_CLOCKCFG_FLAGS(d->bd_tstamp,
+				    cs.sysclock_active, whichclock, clockflags);
+				KASSERT(whichclock >= 0, ("Bogus BPF tstamp "
+				    "configuration: 0x%04x", d->bd_tstamp));
+				sysclock_snap2bintime(&cs, &bt, whichclock,
+				    clockflags);
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
@@ -1862,12 +1871,13 @@ void
 bpf_mtap(struct bpf_if *bp, struct mbuf *m)
 {
 	struct bintime bt;
+	struct sysclock_snap cs;
 	struct bpf_d *d;
+	u_int clockflags, pktlen, slen;
+	int tstype, whichclock;
 #ifdef BPF_JITTER
 	bpf_jit_filter *bf;
 #endif
-	u_int pktlen, slen;
-	int gottime;
 
 	/* Skip outgoing duplicate packets. */
 	if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1875,9 +1885,22 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 
 		return;
 	}
 
+	tstype = bp->tstype;
+	if (tstype == BPF_TSTAMP_DEFAULT)
+		tstype = bpf_default_tstype;
+
+	if (tstype == BPF_TSTAMP_NORMAL || tstype == BPF_TSTAMP_FAST)
+		sysclock_getsnapshot(&cs, tstype == BPF_TSTAMP_FAST ?
+		    1 : 0);
+#ifdef notyet
+	else if (tstype == BPF_TSTAMP_EXTERNAL)
+		/* XXX: Convert external tstamp to bintime. */
+#endif
+	else
+		bzero(&bt, sizeof(bt));
+
 	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))
@@ -1894,8 +1917,16 @@ 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 < bpf_ts_quality(d->bd_tstamp))
-				gottime = bpf_gettime(&bt, d->bd_tstamp, m);
+			if (tstype == BPF_TSTAMP_NORMAL ||
+			    tstype == BPF_TSTAMP_FAST) {
+				whichclock = -1;
+				SET_CLOCKCFG_FLAGS(d->bd_tstamp,
+				    cs.sysclock_active, whichclock, clockflags);
+				KASSERT(whichclock >= 0, ("Bogus BPF tstamp "
+				    "configuration: 0x%04x", d->bd_tstamp));
+				sysclock_snap2bintime(&cs, &bt, whichclock,
+				    clockflags);
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
@@ -1915,10 +1946,11 @@ void
 bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m)
 {
 	struct bintime bt;
+	struct sysclock_snap cs;
 	struct mbuf mb;
 	struct bpf_d *d;
-	u_int pktlen, slen;
-	int gottime;
+	u_int clockflags, pktlen, slen;
+	int tstype, whichclock;
 
 	/* Skip outgoing duplicate packets. */
 	if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
@@ -1926,6 +1958,20 @@ bpf_mtap2(struct bpf_if *bp, void *data,
 		return;
 	}
 
+	tstype = bp->tstype;
+	if (tstype == BPF_TSTAMP_DEFAULT)
+		tstype = bpf_default_tstype;
+
+	if (tstype == BPF_TSTAMP_NORMAL || tstype == BPF_TSTAMP_FAST)
+		sysclock_getsnapshot(&cs, tstype == BPF_TSTAMP_FAST ?
+		    1 : 0);
+#ifdef notyet
+	else if (tstype == BPF_TSTAMP_EXTERNAL)
+		/* XXX: Convert extern tstamp to bintime. */
+#endif
+	else
+		bzero(&bt, sizeof(bt));
+
 	pktlen = m_length(m, NULL);
 	/*
 	 * Craft on-stack mbuf suitable for passing to bpf_filter.
@@ -1937,7 +1983,6 @@ 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))
@@ -1947,8 +1992,16 @@ 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 < bpf_ts_quality(d->bd_tstamp))
-				gottime = bpf_gettime(&bt, d->bd_tstamp, m);
+			if (tstype == BPF_TSTAMP_NORMAL ||
+			    tstype == BPF_TSTAMP_FAST) {
+				whichclock = -1;
+				SET_CLOCKCFG_FLAGS(d->bd_tstamp,
+				    cs.sysclock_active, whichclock, clockflags);
+				KASSERT(whichclock >= 0, ("Bogus BPF tstamp "
+				    "configuration: 0x%04x", d->bd_tstamp));
+				sysclock_snap2bintime(&cs, &bt, whichclock,
+				    clockflags);
+			}
 #ifdef MAC
 			if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0)
 #endif
@@ -1962,11 +2015,6 @@ 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)
 {
@@ -1998,15 +2046,9 @@ bpf_hdrlen(struct bpf_d *d)
 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);
@@ -2200,6 +2242,64 @@ bpf_freed(struct bpf_d *d)
 }
 
 /*
+ * Show or change the per bpf_if or system wide default timestamp configuration.
+ */
+static int
+bpf_tscfg_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+	char tstype_name[16];
+	struct bpf_if *bp;
+	int error, tstype;
+
+	bp = (struct bpf_if *)arg1;
+
+	if (req->newptr == NULL) {
+		/*
+		 * Return the name of the BPF interface's timestamp setting, or
+		 * the system wide default if bp is NULL.
+		 */
+		strlcpy(tstype_name,
+		    bpfiftstypes[bp ? bp->tstype : bpf_default_tstype],
+		    sizeof(tstype_name));
+		error = sysctl_handle_string(oidp, tstype_name,
+		    sizeof(tstype_name), req);
+	} else {
+		/*
+		 * Change the timestamp configuration for this BPF interface or
+		 * the system wide default setting.
+		 */
+		error = EINVAL;
+		for (tstype = 0; tstype < NUM_BPFIFTSTYPES; tstype++) {
+			if (strncmp((char *)req->newptr, bpfiftstypes[tstype],
+			    strlen(bpfiftstypes[tstype])) == 0) {
+				/* User specified type found in bpfiftstypes. */
+				if (strcmp(oidp->oid_name, "default") == 0) {
+					/*
+					 * Don't allow BPF_TSTAMP_DEFAULT to be
+					 * assigned to the
+					 * "net.bpf.tscfg.default" OID.
+					 */
+					if (tstype != BPF_TSTAMP_DEFAULT) {
+						bpf_default_tstype = tstype;
+						error = 0;
+					}
+				} else {
+					/*
+					 * Valid tstype for
+					 * "net.bpf.tscfg.<iface>" OID.
+					 */
+					bp->tstype = tstype;
+					error = 0;
+				}
+				break;
+			}
+		}
+	}
+
+	return (error);
+}
+
+/*
  * Attach an interface to bpf.  dlt is the link layer type; hdrlen is the
  * fixed size of the link header (variable length headers not yet supported).
  */
@@ -2225,6 +2325,17 @@ bpfattach2(struct ifnet *ifp, u_int dlt,
 	if (bp == NULL)
 		panic("bpfattach");
 
+	bp->tscfgoid = SYSCTL_ADD_PROC(NULL,
+	    SYSCTL_STATIC_CHILDREN(_net_bpf_tscfg), OID_AUTO, ifp->if_xname,
+	    CTLTYPE_STRING | CTLFLAG_RW, bp, sizeof(bp),
+	    bpf_tscfg_sysctl_handler, "A",
+	    "Interface BPF timestamp configuration");
+	if (bp->tscfgoid == NULL) {
+		free(bp, M_BPF);
+		panic("bpfattach tscfgoid");
+	}
+
+	bp->tstype = BPF_TSTAMP_DEFAULT;
 	LIST_INIT(&bp->bif_dlist);
 	bp->bif_ifp = ifp;
 	bp->bif_dlt = dlt;
@@ -2278,6 +2389,7 @@ bpfdetach(struct ifnet *ifp)
 		BPFD_UNLOCK(d);
 	}
 
+	sysctl_remove_oid(bp->tscfgoid, 1, 0);
 	mtx_destroy(&bp->bif_mtx);
 	free(bp, M_BPF);
 }

Modified: head/sys/net/bpf.h
==============================================================================
--- head/sys/net/bpf.h	Fri Dec 30 06:24:59 2011	(r228985)
+++ head/sys/net/bpf.h	Fri Dec 30 08:57:58 2011	(r228986)
@@ -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:
@@ -166,25 +171,17 @@ enum bpf_direction {
 #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_MONOTONIC		0x0100
+#define	BPF_T_FLAG_MASK		0x0100
 #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.
@@ -1100,6 +1097,8 @@ struct bpf_if {
 	u_int bif_hdrlen;		/* length of link header */
 	struct ifnet *bif_ifp;		/* corresponding interface */
 	struct mtx	bif_mtx;	/* mutex for interface */
+	struct sysctl_oid *tscfgoid;	/* timestamp sysctl oid for interface */
+	int tstype;			/* timestamp setting for interface */
 };
 
 void	 bpf_bufheld(struct bpf_d *d);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112300857.pBU8vxfP004914>