summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-06-15 19:28:44 +0000
committerjkim <jkim@FreeBSD.org>2010-06-15 19:28:44 +0000
commit14f08fd6272b6042eef9e52239ed552feb9c126c (patch)
tree7fbda1d0820b3e7d313b910158875757fdde63ff /sys/net
parent3571902304966f5edad4bceddc7fb3170f4ff982 (diff)
downloadFreeBSD-src-14f08fd6272b6042eef9e52239ed552feb9c126c.zip
FreeBSD-src-14f08fd6272b6042eef9e52239ed552feb9c126c.tar.gz
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@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c263
-rw-r--r--sys/net/bpf.h112
-rw-r--r--sys/net/bpfdesc.h1
3 files changed, 281 insertions, 95 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 16245c9..ab2ba1f 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -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, caddr_t addr, int flags,
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, caddr_t addr, int flags,
}
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, u_int pktlen)
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, u_int pktlen)
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 *m)
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 *m)
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 *m)
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, u_int dlen, struct mbuf *m)
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, u_int dlen, struct mbuf *m)
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, u_int dlen, struct mbuf *m)
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, u_int dlen, struct mbuf *m)
#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, u_int dlen, struct mbuf *m)
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
- int totlen, curlen;
- int hdrlen = d->bd_bif->bif_hdrlen;
+#endif
+ 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, u_int pktlen, u_int snaplen,
* 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, u_int pktlen, u_int snaplen,
* 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, u_int pktlen, u_int snaplen,
* 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, u_int hdrlen, struct bpf_if **driverp)
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");
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index 726483a..b1aad51 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -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 */
};
diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h
index 03cb20d..14a895c 100644
--- a/sys/net/bpfdesc.h
+++ b/sys/net/bpfdesc.h
@@ -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 */
OpenPOWER on IntegriCloud