Index: share/man/man4/bpf.4 =================================================================== --- share/man/man4/bpf.4 (revision 228435) +++ share/man/man4/bpf.4 (working copy) @@ -49,7 +49,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 15, 2010 +.Dd December 15, 2011 .Dt BPF 4 .Os .Sh NAME @@ -516,61 +516,74 @@ 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, resolution and source 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. +Note that the +.Dv BPF_T_FBCLOCK , +.Dv BPF_T_FFCLOCK , +and +.Dv BPF_T_FFCOUNTER +options described below are not allowed unless the kernel has been compiled +with feed-forward clock support +.Po +see +.Xr ffclock 4 +for more details +.Pc . +.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 either of the +.Dv BPF_T_FBCLOCK +or +.Dv BPF_T_FFCLOCK +flags to specify that the BPF device should explicitly use the feedback or +feed-forward clock respectively for time stamp generation. Set to +.Dv BPF_T_FFCOUNTER +to get a 64-bit feed-forward counter value. +Set to .Dv BPF_T_NONE -to ignore time stamp. +to not set a time stamp. +By default, time stamps are derived from the active system clock +.Po +feedback or +feed-forward +.Pc +and 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 +705,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 +965,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. +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 @@ -1021,6 +1076,7 @@ struct bpf_insn insns[] = { .Xr poll 2 , .Xr select 2 , .Xr byteorder 3 , +.Xr ffclock 4 , .Xr ng_bpf 4 , .Xr bpf 9 .Rs Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 228435) +++ sys/net/bpf.c (working copy) @@ -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: @@ -39,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ffclock.h" #include "opt_netgraph.h" #include @@ -55,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -112,7 +119,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,9 +137,51 @@ 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 */ /* + * Safety belt to ensure ABI of structs bpf_hdr32, bpf_hdr and bpf_xhdr are + * preserved for use with FFCLOCK, which changes the stamp field in the + * structs to allow storing a regular time stamp or ffcounter stamp. + */ +CTASSERT(sizeof(struct bpf_ts) >= sizeof(ffcounter) && + sizeof(struct bintime) >= sizeof(ffcounter)); + +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_BPFTSTYPES (sizeof(bpfiftstypes) / sizeof(*bpfiftstypes)) + +#define SET_CLOCKCFG_FLAGS(tstype, active, clock, flags) do { \ + (flags) = 0; \ + if ((BPF_T_CLOCK((tstype)) == BPF_T_SYSCLOCK && \ + (active) == SYSCLOCK_FBCK) || \ + (BPF_T_CLOCK((tstype)) == BPF_T_FBCLOCK)) { \ + (clock) = SYSCLOCK_FBCK; \ + if ((tstype) & BPF_T_MONOTONIC) \ + (flags) |= FBCLOCK_UPTIME; \ + } else if ((BPF_T_CLOCK((tstype)) == BPF_T_SYSCLOCK && \ + (active) == SYSCLOCK_FFWD) || \ + (BPF_T_CLOCK((tstype)) == BPF_T_FFCLOCK)) { \ + (clock) = SYSCLOCK_FFWD; \ + (flags) |= FFCLOCK_LERP; \ + if ((tstype) & BPF_T_MONOTONIC) \ + (flags) |= FFCLOCK_UPTIME; \ + else \ + (flags) |= FFCLOCK_LEAPSEC; \ + } \ +} while (0) + +/* * bpf_iflist is a list of BPF interface structures, each corresponding to a * specific DLT. The same network interface might have several BPF interface * structures registered by different layers in the stack (i.e., 802.11 @@ -162,6 +211,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 +222,12 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_enable, CT &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; @@ -1406,6 +1462,12 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t add u_int func; func = *(u_int *)addr; +#ifndef FFCLOCK + if (BPF_T_FORMAT(func) == BPF_T_FFCOUNTER || + BPF_T_CLOCK(func) != BPF_T_SYSCLOCK) { + error = EINVAL; + } else +#endif if (BPF_T_VALID(func)) d->bd_tstamp = func; else @@ -1759,48 +1821,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 +1831,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 +1867,21 @@ 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 < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, NULL); +#ifdef FFCLOCK + if (d->bd_tstamp & BPF_T_FFCOUNTER) + bcopy(&cs.ffcount, &bt, sizeof(ffcounter)); + else +#endif + 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 +1904,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 +1918,22 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m) 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 +1950,21 @@ 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 < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#ifdef FFCLOCK + if (d->bd_tstamp & BPF_T_FFCOUNTER) + bcopy(&cs.ffcount, &bt, sizeof(ffcounter)); + else +#endif + 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 +1984,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 +1996,20 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dle 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 +2021,6 @@ 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)) @@ -1947,8 +2030,21 @@ 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 < bpf_ts_quality(d->bd_tstamp)) - gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#ifdef FFCLOCK + if (d->bd_tstamp & BPF_T_FFCOUNTER) + bcopy(&cs.ffcount, &bt, sizeof(ffcounter)); + else +#endif + 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 +2058,6 @@ 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) { @@ -1998,15 +2089,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); @@ -2153,8 +2238,16 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pk * move forward the length of the header plus padding. */ bzero(&hdr, sizeof(hdr)); - if (do_timestamp) - bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype); + if (do_timestamp) { +#ifdef FFCLOCK + if (tstype & BPF_T_FFCOUNTER) + bcopy(bt, &hdr.bh_tstamp, sizeof(ffcounter)); + else +#endif + bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype); + } + + hdr.bh_datalen = pktlen; hdr.bh_hdrlen = hdrlen; hdr.bh_caplen = caplen; @@ -2200,6 +2293,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_BPFTSTYPES; 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." 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 +2376,17 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdr 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 +2440,7 @@ bpfdetach(struct ifnet *ifp) BPFD_UNLOCK(d); } + sysctl_remove_oid(bp->tscfgoid, 1, 0); mtx_destroy(&bp->bif_mtx); free(bp, M_BPF); } Index: sys/net/bpf.h =================================================================== --- sys/net/bpf.h (revision 228435) +++ sys/net/bpf.h (working copy) @@ -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: @@ -164,28 +169,43 @@ enum bpf_direction { #define BPF_T_NANOTIME 0x0001 #define BPF_T_BINTIME 0x0002 #define BPF_T_NONE 0x0003 -#define BPF_T_FORMAT_MASK 0x0003 +#define BPF_T_FFCOUNTER 0x0004 +#define BPF_T_FORMAT_MAX 0x0004 +#define BPF_T_FORMAT_MASK 0x0007 #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_SYSCLOCK 0x0000 +#define BPF_T_FBCLOCK 0x1000 +#define BPF_T_FFCLOCK 0x2000 +#define BPF_T_CLOCK_MAX 0x2000 +#define BPF_T_CLOCK_MASK 0x3000 #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_CLOCK(t) ((t) & BPF_T_CLOCK_MASK) +#define BPF_T_VALID(t) \ + ((t) == BPF_T_NONE || (t) == BPF_T_FFCOUNTER || \ + (BPF_T_FORMAT(t) <= BPF_T_BINTIME && BPF_T_CLOCK(t) <= BPF_T_CLOCK_MAX && \ + ((t) & ~(BPF_T_FORMAT_MASK | BPF_T_FLAG_MASK | BPF_T_CLOCK_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) +#define BPF_T_FBCLOCK_MICROTIME_MONOTONIC \ + (BPF_T_MICROTIME_MONOTONIC | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_NANOTIME_MONOTONIC \ + (BPF_T_NANOTIME_MONOTONIC | BPF_T_FBCLOCK) +#define BPF_T_FBCLOCK_BINTIME_MONOTONIC \ + (BPF_T_BINTIME_MONOTONIC | BPF_T_FBCLOCK) + +#define BPF_T_FFCLOCK_MICROTIME_MONOTONIC \ + (BPF_T_MICROTIME_MONOTONIC | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_NANOTIME_MONOTONIC \ + (BPF_T_NANOTIME_MONOTONIC | BPF_T_FFCLOCK) +#define BPF_T_FFCLOCK_BINTIME_MONOTONIC \ + (BPF_T_BINTIME_MONOTONIC | BPF_T_FFCLOCK) + /* * Structure prepended to each packet. */ @@ -193,6 +213,7 @@ 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 */ @@ -213,6 +234,13 @@ struct bpf_hdr { #define MTAG_BPF_TIMESTAMP 0 #endif +#ifdef FFCLOCK + /* + * Feed-foward counter accessor. + */ +#define BPF_FFCOUNT(bh) (*(ffcounter *)&(bh)->bh_tstamp) +#endif + /* * When using zero-copy BPF buffers, a shared memory header is present * allowing the kernel BPF implementation and user process to synchronize @@ -1100,6 +1128,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);