Index: share/man/man4/bpf.4 =================================================================== --- share/man/man4/bpf.4 (revision 208968) +++ share/man/man4/bpf.4 (working copy) @@ -49,7 +49,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 26, 2007 +.Dd June 9, 2010 .Dt BPF 4 .Os .Sh NAME @@ -513,6 +513,44 @@ to see only outgoing packets on the interface. 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 +or +.Dv BPF_T_MICROTIME_FAST +to get time stamps in +.Vt struct timeval +format. +Set to +.Dv BPF_T_NANOTIME +or +.Dv BPF_T_NANOTIME_FAST +to get time stamps in +.Vt struct timespec +format. +Set to +.Dv BPF_T_BINTIME +or +.Dv BPF_T_BINTIME_FAST +to get time stamps in +.Vt struct bintime +format. +Set to +.Dv BPF_T_NONE +to ignore time stamp. +The +.Dv BPF_T_MICROTIME_FAST , +.Dv BPF_T_NANOTIME_FAST +and +.Dv BPF_T_BINTIME_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. +This setting is initialized to +.Dv BPF_T_MICROTIME +by default. .It Dv BIOCFEEDBACK .Pq Li u_int Set packet feedback mode. @@ -575,16 +613,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 +651,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 +664,22 @@ The purpose here is to guarantee proper alignment 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 +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. Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 208968) +++ sys/net/bpf.c (working copy) @@ -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 #include #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 add case BIOCVERSION: case BIOCGRSIG: case BIOCGHDRCMPLT: + case BIOCSTSTAMP: case BIOCFEEDBACK: case FIONREAD: case BIOCLOCK: @@ -1383,6 +1391,37 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t add } 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; + switch (func) { + case BPF_T_MICROTIME: + case BPF_T_NANOTIME: + case BPF_T_BINTIME: + case BPF_T_MICROTIME_FAST: + case BPF_T_NANOTIME_FAST: + case BPF_T_BINTIME_FAST: + case BPF_T_NONE: + d->bd_tstamp = func; + break; + default: + error = EINVAL; + } + } + break; + case BIOCFEEDBACK: d->bd_feedback = *(u_int *)addr; break; @@ -1729,6 +1768,54 @@ 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) +{ + + switch (tstype) { + case BPF_T_MICROTIME: + case BPF_T_NANOTIME: + case BPF_T_BINTIME: + return (BPF_TSTAMP_NORMAL); + case BPF_T_MICROTIME_FAST: + case BPF_T_NANOTIME_FAST: + case BPF_T_BINTIME_FAST: + return (BPF_TSTAMP_FAST); + default: + return (BPF_TSTAMP_NONE); + } +} + +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) + bintime(bt); + else + getbintime(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 +1825,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 +1853,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktl 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 +1876,13 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktl 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 +1890,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 +1909,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 +1929,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 +1941,6 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle return; } - gottime = 0; - pktlen = m_length(m, NULL); /* * Craft on-stack mbuf suitable for passing to bpf_filter. @@ -1872,6 +1952,7 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle 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 +1962,13 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle 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 +1977,67 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle #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_MICROTIME || + d->bd_tstamp == BPF_T_MICROTIME_FAST || + d->bd_tstamp == BPF_T_NONE) +#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 timeval tsm; + struct timespec tsn; + + switch (tstype) { + case BPF_T_MICROTIME: + case BPF_T_MICROTIME_FAST: + bintime2timeval(bt, &tsm); + ts->bt_sec = tsm.tv_sec; + ts->bt_frac = tsm.tv_usec; + break; + case BPF_T_NANOTIME: + case BPF_T_NANOTIME_FAST: + bintime2timespec(bt, &tsn); + ts->bt_sec = tsn.tv_sec; + ts->bt_frac = tsn.tv_nsec; + break; + case BPF_T_BINTIME: + case BPF_T_BINTIME_FAST: + 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,14 +2048,16 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle 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; BPFD_LOCK_ASSERT(d); @@ -1940,6 +2082,7 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pk * 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 +2122,36 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pk * reader should be woken up. */ do_wakeup = 1; + caplen = totlen - hdrlen; +#ifndef BURN_BRIDGES + if (d->bd_tstamp == BPF_T_MICROTIME || + d->bd_tstamp == BPF_T_MICROTIME_FAST || + d->bd_tstamp == BPF_T_NONE) { #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 (d->bd_tstamp != BPF_T_NONE) { + struct timeval tv; + bintime2timeval(bt, &tv); + hdr32_old.bh_tstamp.tv_sec = tv.tv_sec; + hdr32_old.bh_tstamp.tv_usec = tv.tv_usec; + } + 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 (d->bd_tstamp != BPF_T_NONE) + bintime2timeval(bt, &hdr_old.bh_tstamp); + 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 +2161,20 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pk * move forward the length of the header plus padding. */ bzero(&hdr, sizeof(hdr)); - hdr.bh_tstamp = *tv; + if (d->bd_tstamp != BPF_T_NONE) + bpf_bintime2ts(bt, &hdr.bh_tstamp, d->bd_tstamp); 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 +2244,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdr 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"); Index: sys/net/bpfdesc.h =================================================================== --- sys/net/bpfdesc.h (revision 208968) +++ sys/net/bpfdesc.h (working copy) @@ -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 */ Index: sys/net/bpf.h =================================================================== --- sys/net/bpf.h (revision 208968) +++ sys/net/bpf.h (working copy) @@ -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,32 @@ enum bpf_direction { BPF_D_OUT /* See outgoing packets */ }; +/* Time stamping functions */ +enum bpf_tstype { + BPF_T_MICROTIME, /* microtime(9) */ + BPF_T_NANOTIME, /* nanotime(9) */ + BPF_T_BINTIME, /* bintime(9) */ + BPF_T_MICROTIME_FAST, /* getmicrotime(9) */ + BPF_T_NANOTIME_FAST, /* getnanotime(9) */ + BPF_T_BINTIME_FAST, /* getbintime(9) */ + BPF_T_NONE /* no time stamp */ +}; + /* * 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 +192,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 +944,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 */ };