--- Extend BPF timestamping capabilities when feed-forward clock support is --- enabled: --- --- - Change the various BPF header structs in an ABI preserving way to support --- storing either a regular timestamp or feed-forward counter stamp. --- --- - Add BPF_T_FBCLOCK and BPF_T_FFCLOCK to specify which system clock --- timestamps should be read from. Leaving both of these options unset --- (the default) means the system's current default clock will be used to --- generate timestamps. In contrast, setting one of these options bypasses --- the default clock setting, and will cause the specified system clock to be --- directly queried instead. --- --- - Add BPF_T_FFCOUNTER to specify that the BPF header's bh_stamp union should --- be used to store a feed-forward counter stamp instead of a regular --- timestamp. --- --- BPF consumers can use ioctl() to select the new timestamping options/formats --- per BPF device as required. --- --- 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/ --- --- Discussed with: Julien Ridoux (jridoux at unimelb edu au) --- Submitted by: Julien Ridoux (jridoux at unimelb edu au) --- Index: sys/net/bpf.c =================================================================== --- sys/net/bpf.c (revision 228132) +++ 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 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 @@ #include "opt_bpf.h" #include "opt_compat.h" +#include "opt_ffclock.h" #include "opt_netgraph.h" #include @@ -55,6 +61,9 @@ #include #include #include +#ifdef FFCLOCK +#include +#endif #include #include @@ -106,7 +115,14 @@ * 32-bit the first time we see a 32-bit compat ioctl request. */ struct bpf_hdr32 { +#ifdef FFCLOCK + union { + struct timeval32 time_stamp; /* time stamp */ + ffcounter ffcount_stamp; /* f-forward counter */ + } bh_stamp; +#else struct timeval32 bh_tstamp; /* time stamp */ +#endif uint32_t bh_caplen; /* length of captured portion */ uint32_t bh_datalen; /* original length of packet */ uint16_t bh_hdrlen; /* length of bpf header (this struct @@ -153,7 +169,11 @@ 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), +#ifdef FFCLOCK + struct bintime *, ffcounter *); +#else 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 *); @@ -1777,10 +1797,17 @@ } static int +#ifdef FFCLOCK +bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m, ffcounter *ffcount) +#else bpf_gettime(struct bintime *bt, int tstype, struct mbuf *m) +#endif { struct m_tag *tag; int quality; +#ifdef FFCLOCK + int ff_flags; +#endif quality = bpf_ts_quality(tstype); if (quality == BPF_TSTAMP_NONE) @@ -1793,11 +1820,37 @@ return (BPF_TSTAMP_EXTERN); } } - if (quality == BPF_TSTAMP_NORMAL) - binuptime(bt); - else - getbinuptime(bt); +#ifdef FFCLOCK + *ffcount = 0; + switch(BPF_T_CLOCK(tstype)) { + case BPF_T_FFCLOCK: + ff_flags = FFCLOCK_LERP; + if (tstype & BPF_T_MONOTONIC) + ff_flags |= FFCLOCK_UPTIME; + else + ff_flags |= FFCLOCK_LEAPSEC; + if (quality == BPF_TSTAMP_FAST) + ff_flags |= FFCLOCK_FAST; + ffclock_abstime(ffcount, bt, NULL, ff_flags); + break; + case BPF_T_FBCLOCK: + if (quality == BPF_TSTAMP_NORMAL) + binuptime_fromclock(bt, SYSCLOCK_FBCK); + else + getbinuptime_fromclock(bt, SYSCLOCK_FBCK); + break; + default: +#endif + if (quality == BPF_TSTAMP_NORMAL) + binuptime(bt); + else + getbinuptime(bt); +#ifdef FFCLOCK + break; + } +#endif + return (quality); } @@ -1817,6 +1870,9 @@ #endif u_int slen; int gottime; +#ifdef FFCLOCK + ffcounter ffcount; +#endif gottime = BPF_TSTAMP_NONE; BPFIF_LOCK(bp); @@ -1838,13 +1894,23 @@ 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, d->bd_tstamp, NULL, + &ffcount); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, NULL); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif catchpacket(d, pkt, pktlen, slen, +#ifdef FFCLOCK + bpf_append_bytes, &bt, &ffcount); +#else bpf_append_bytes, &bt); +#endif } BPFD_UNLOCK(d); } @@ -1868,6 +1934,9 @@ #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 +1964,23 @@ if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) + { +#ifdef FFCLOCK + gottime = bpf_gettime(&bt, d->bd_tstamp, m, + &ffcount); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif catchpacket(d, (u_char *)m, pktlen, slen, +#ifdef FFCLOCK + bpf_append_mbuf, &bt, &ffcount); +#else bpf_append_mbuf, &bt); +#endif } BPFD_UNLOCK(d); } @@ -1919,6 +1999,9 @@ 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 +2031,23 @@ if (slen != 0) { d->bd_fcount++; if (gottime < bpf_ts_quality(d->bd_tstamp)) + { +#ifdef FFCLOCK + gottime = bpf_gettime(&bt, d->bd_tstamp, m, + &ffcount); +#else gottime = bpf_gettime(&bt, d->bd_tstamp, m); +#endif + } #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif catchpacket(d, (u_char *)&mb, pktlen, slen, +#ifdef FFCLOCK + bpf_append_mbuf, &bt, &ffcount); +#else bpf_append_mbuf, &bt); +#endif } BPFD_UNLOCK(d); } @@ -2002,11 +2096,15 @@ 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; + } + switch (BPF_T_FORMAT(tstype)) { case BPF_T_MICROTIME: bintime2timeval(bt, &tsm); @@ -2035,7 +2133,11 @@ 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), +#ifdef FFCLOCK + struct bintime *bt, ffcounter *ffcount) +#else struct bintime *bt) +#endif { struct bpf_xhdr hdr; #ifndef BURN_BRIDGES @@ -2153,8 +2255,14 @@ * 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) + hdr.bh_stamp.ffcount_stamp = *ffcount; + else +#endif + bpf_bintime2ts(bt, &hdr.bh_tstamp, tstype); + } hdr.bh_datalen = pktlen; hdr.bh_hdrlen = hdrlen; hdr.bh_caplen = caplen; Index: sys/net/bpf.h =================================================================== --- sys/net/bpf.h (revision 228132) +++ 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 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: @@ -164,17 +169,34 @@ #define BPF_T_NANOTIME 0x0001 #define BPF_T_BINTIME 0x0002 #define BPF_T_NONE 0x0003 +#ifdef FFCLOCK +#define BPF_T_FFCOUNTER 0x0004 +#define BPF_T_FORMAT_MASK 0x0007 +#else #define BPF_T_FORMAT_MASK 0x0003 +#endif #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 +#ifdef FFCLOCK +#define BPF_T_FBCLOCK 0x1000 +#define BPF_T_FFCLOCK 0x2000 +#define BPF_T_CLOCK_MASK 0x3000 +#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_CLOCK(t) ((t) & BPF_T_CLOCK_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 | 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) @@ -193,8 +215,20 @@ bpf_int64 bt_sec; /* seconds */ bpf_u_int64 bt_frac; /* fraction */ }; + +#ifdef FFCLOCK +#define bh_tstamp bh_stamp.time_stamp +#endif + struct bpf_xhdr { +#ifdef FFCLOCK + union { + struct bpf_ts time_stamp; /* time stamp */ + ffcounter ffcount_stamp; /* feed-forward counter */ + } bh_stamp; +#else struct bpf_ts bh_tstamp; /* time stamp */ +#endif 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 @@ -202,7 +236,14 @@ }; /* Obsolete */ struct bpf_hdr { +#ifdef FFCLOCK + union { + struct timeval time_stamp; /* time stamp */ + ffcounter ffcount_stamp; /* feed-forward counter */ + } bh_stamp; +#else struct timeval bh_tstamp; /* time stamp */ +#endif 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