diff options
-rw-r--r-- | sys/net/bpf.c | 154 | ||||
-rw-r--r-- | sys/net/bpf.h | 23 |
2 files changed, 165 insertions, 12 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 3dd2f93..f7b73cc 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -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 FreeBSD Foundation. + * 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 <sys/types.h> @@ -55,6 +61,9 @@ __FBSDID("$FreeBSD$"); #include <sys/signalvar.h> #include <sys/filio.h> #include <sys/sockio.h> +#ifdef FFCLOCK +#include <sys/timeffc.h> +#endif #include <sys/ttycom.h> #include <sys/uio.h> @@ -90,8 +99,13 @@ MALLOC_DEFINE(M_BPF, "BPF", "BPF data"); #define PRINET 26 /* interruptible */ +#ifdef FFCLOCK +#define SIZEOF_BPF_HDR(type) \ + (offsetof(type, ffcount_stamp) + sizeof(((type *)0)->ffcount_stamp)) +#else #define SIZEOF_BPF_HDR(type) \ (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen)) +#endif #ifdef COMPAT_FREEBSD32 #include <sys/mount.h> @@ -111,6 +125,9 @@ struct bpf_hdr32 { uint32_t bh_datalen; /* original length of packet */ uint16_t bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ +#ifdef FFCLOCK + ffcounter ffcount_stamp; /* ffcounter timestamp of packet */ +#endif }; #endif @@ -151,9 +168,16 @@ static int bpf_setif(struct bpf_d *, struct ifreq *); static void bpf_timed_out(void *); static __inline void bpf_wakeup(struct bpf_d *); +#ifdef FFCLOCK +static void catchpacket(struct bpf_d *, u_char *, unsigned int, + unsigned int, void (*)(struct bpf_d *, caddr_t, + unsigned int, void *, unsigned int), struct bintime *, + ffcounter *); +#else static void catchpacket(struct bpf_d *, u_char *, u_int, u_int, void (*)(struct bpf_d *, caddr_t, u_int, void *, u_int), struct bintime *); +#endif 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 *); @@ -172,6 +196,12 @@ SYSCTL_INT(_net_bpf, OID_AUTO, zerocopy_enable, CTLFLAG_RW, &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"); +#ifdef FFCLOCK +static int bpf_ffclock_tstamp = 0; +SYSCTL_INT(_net_bpf, OID_AUTO, ffclock_tstamp, CTLFLAG_RW, + &bpf_ffclock_tstamp, 0, + "Set BPF to timestamp using Feed-Forward clock by default"); +#endif static d_open_t bpfopen; static d_read_t bpfread; @@ -698,6 +728,15 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td) callout_init_mtx(&d->bd_callout, &d->bd_mtx, 0); knlist_init_mtx(&d->bd_sel.si_note, &d->bd_mtx); +#ifdef FFCLOCK + /* + * Set the timestamping mode for this device, i.e. which clock is used. + * The default option is to use the feedback/ntpd system clock. + */ + if (bpf_ffclock_tstamp) + d->bd_tstamp = d->bd_tstamp | BPF_T_FFCLOCK; +#endif + return (0); } @@ -1776,8 +1815,13 @@ bpf_ts_quality(int tstype) return (BPF_TSTAMP_NORMAL); } +#ifdef FFCLOCK +static int +bpf_gettime(struct bintime *bt, ffcounter *ffcount, int tstype, struct mbuf *m) +#else static int bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m) +#endif { struct m_tag *tag; int quality; @@ -1793,11 +1837,31 @@ bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m) return (BPF_TSTAMP_EXTERN); } } - if (quality == BPF_TSTAMP_NORMAL) - binuptime(bt); - else - getbinuptime(bt); - + if (quality == BPF_TSTAMP_NORMAL) { +#ifdef FFCLOCK + if ((tstype & BPF_T_FFCLOCK) == 0) { + ffclock_read_counter(ffcount); +#endif + binuptime(bt); +#ifdef FFCLOCK + } else { + if ((tstype & BPF_T_MONOTONIC) == 0) + ffclock_abstime(ffcount, bt, NULL, + (FFCLOCK_LERP | FFCLOCK_LEAPSEC)); + else + ffclock_abstime(ffcount, bt, NULL, + (FFCLOCK_LERP | FFCLOCK_UPTIME)); + } +#endif + } else { +#ifdef FFCLOCK + if ((tstype & BPF_T_FFCLOCK) == BPF_T_FFCLOCK) + ffclock_abstime(ffcount, bt, NULL, + (FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST)); + else +#endif + getbinuptime(bt); + } return (quality); } @@ -1817,6 +1881,9 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, u_int pktlen) #endif u_int slen; int gottime; +#ifdef FFCLOCK + ffcounter ffcount; +#endif gottime = BPF_TSTAMP_NONE; BPFIF_LOCK(bp); @@ -1838,13 +1905,24 @@ 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 < bpf_ts_quality(d->bd_tstamp)) + if (gottime < bpf_ts_quality(d->bd_tstamp)) { +#ifdef FFCLOCK + gottime = bpf_gettime(&bt, &ffcount, + d->bd_tstamp, NULL); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, NULL); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif +#ifdef FFCLOCK + catchpacket(d, pkt, pktlen, slen, + bpf_append_bytes, &bt, &ffcount); +#else catchpacket(d, pkt, pktlen, slen, bpf_append_bytes, &bt); +#endif } BPFD_UNLOCK(d); } @@ -1868,6 +1946,9 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m) #endif u_int pktlen, slen; int gottime; +#ifdef FFCLOCK + ffcounter ffcount; +#endif /* Skip outgoing duplicate packets. */ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) { @@ -1895,12 +1976,24 @@ bpf_mtap(struct bpf_if *bp, struct mbuf *m) if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) + { +#ifdef FFCLOCK + gottime = bpf_gettime(&bt, &ffcount, + d->bd_tstamp, m); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif +#ifdef FFCLOCK + catchpacket(d, (u_char *)m, pktlen, slen, + bpf_append_mbuf, &bt, &ffcount); +#else catchpacket(d, (u_char *)m, pktlen, slen, bpf_append_mbuf, &bt); +#endif } BPFD_UNLOCK(d); } @@ -1919,6 +2012,9 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m) struct bpf_d *d; u_int pktlen, slen; int gottime; +#ifdef FFCLOCK + ffcounter ffcount; +#endif /* Skip outgoing duplicate packets. */ if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) { @@ -1948,12 +2044,24 @@ bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m) if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) + { +#ifdef FFCLOCK + gottime = bpf_gettime(&bt, &ffcount, + d->bd_tstamp, m); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif +#ifdef FFCLOCK + catchpacket(d, (u_char *)m, pktlen, slen, + bpf_append_mbuf, &bt, &ffcount); +#else catchpacket(d, (u_char *)&mb, pktlen, slen, bpf_append_mbuf, &bt); +#endif } BPFD_UNLOCK(d); } @@ -2002,11 +2110,17 @@ bpf_bintime2ts(struct bintime *bt, struct bpf_ts *ts, int tstype) struct timeval tsm; struct timespec tsn; - if ((tstype & BPF_T_MONOTONIC) == 0) { - bt2 = *bt; - bintime_add(&bt2, &boottimebin); - bt = &bt2; +#ifdef FFCLOCK + if ((tstype & BPF_T_FFCLOCK) == 0) { +#endif + if ((tstype & BPF_T_MONOTONIC) == 0) { + bt2 = *bt; + bintime_add(&bt2, &boottimebin); + bt = &bt2; + } +#ifdef FFCLOCK } +#endif switch (BPF_T_FORMAT(tstype)) { case BPF_T_MICROTIME: bintime2timeval(bt, &tsm); @@ -2032,10 +2146,17 @@ bpf_bintime2ts(struct bintime *bt, struct bpf_ts *ts, int tstype) * bpf_append_mbuf is passed in to copy mbuf chains. In the latter case, * pkt is really an mbuf. */ +#ifdef FFCLOCK +static void +catchpacket(struct bpf_d *d, u_char *pkt, unsigned int pktlen, + unsigned int snaplen, void (*cpfn)(struct bpf_d *, caddr_t, unsigned int, + void *, unsigned int), struct bintime *bt, ffcounter *ffcount) +#else 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 bintime *bt) +#endif { struct bpf_xhdr hdr; #ifndef BURN_BRIDGES @@ -2123,6 +2244,9 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen, if (d->bd_compat32) { bzero(&hdr32_old, sizeof(hdr32_old)); if (do_timestamp) { +#ifdef FFCLOCK + hdr32_old.ffcount_stamp = *ffcount; +#endif hdr32_old.bh_tstamp.tv_sec = ts.bt_sec; hdr32_old.bh_tstamp.tv_usec = ts.bt_frac; } @@ -2136,6 +2260,9 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen, #endif bzero(&hdr_old, sizeof(hdr_old)); if (do_timestamp) { +#ifdef FFCLOCK + hdr_old.ffcount_stamp = *ffcount; +#endif hdr_old.bh_tstamp.tv_sec = ts.bt_sec; hdr_old.bh_tstamp.tv_usec = ts.bt_frac; } @@ -2154,7 +2281,12 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen, */ bzero(&hdr, sizeof(hdr)); if (do_timestamp) + { +#ifdef FFCLOCK + hdr.ffcount_stamp = *ffcount; +#endif bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype); + } hdr.bh_datalen = pktlen; hdr.bh_hdrlen = hdrlen; hdr.bh_caplen = caplen; diff --git a/sys/net/bpf.h b/sys/net/bpf.h index d4c369d..8a80514 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -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 FreeBSD Foundation + * 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: @@ -170,11 +175,21 @@ enum bpf_direction { #define BPF_T_MONOTONIC 0x0200 #define BPF_T_MONOTONIC_FAST (BPF_T_FAST | BPF_T_MONOTONIC) #define BPF_T_FLAG_MASK 0x0300 +#ifdef FFCLOCK +#define BPF_T_FFCLOCK 0x8000 +#define BPF_T_CLOCK_MASK 0x8000 +#endif #define BPF_T_FORMAT(t) ((t) & BPF_T_FORMAT_MASK) #define BPF_T_FLAG(t) ((t) & BPF_T_FLAG_MASK) +#ifdef FFCLOCK +#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 | BPF_T_CLOCK_MASK)) == 0)) +#else #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)) +#endif #define BPF_T_MICROTIME_FAST (BPF_T_MICROTIME | BPF_T_FAST) #define BPF_T_NANOTIME_FAST (BPF_T_NANOTIME | BPF_T_FAST) @@ -199,6 +214,9 @@ struct bpf_xhdr { bpf_u_int32 bh_datalen; /* original length of packet */ u_short bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ +#ifdef FFCLOCK + ffcounter ffcount_stamp; /* feed-forward counter timestamp */ +#endif }; /* Obsolete */ struct bpf_hdr { @@ -207,6 +225,9 @@ struct bpf_hdr { bpf_u_int32 bh_datalen; /* original length of packet */ u_short bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ +#ifdef FFCLOCK + ffcounter ffcount_stamp; /* feed-forward counter timestamp */ +#endif }; #ifdef _KERNEL #define MTAG_BPF 0x627066 |