Page MenuHomeFreeBSD

bpf: Full support for sysclock timestamping
Needs ReviewPublic

Authored by Darryl.Veitch_uts.edu.au on Dec 7 2023, 12:41 AM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Oct 9, 7:37 AM
Unknown Object (File)
Sat, Sep 20, 9:42 PM
Unknown Object (File)
Sep 12 2025, 2:06 AM
Unknown Object (File)
Aug 15 2025, 12:19 AM
Unknown Object (File)
Jul 26 2025, 6:45 PM
Unknown Object (File)
Jul 17 2025, 11:36 PM
Unknown Object (File)
Jul 4 2025, 10:44 PM
Unknown Object (File)
Jun 28 2025, 11:29 PM

Details

Reviewers
phk
imp
Summary

Context: Packet timestamping in bpf is based on standard system clock
uptime functions {get}binuptime, that read the currently active system
clock. Although this could be the FFclock (monoFFC to be precise)
if sysclock_active == SYSCLOCK_FF, it fails to support many other
timestamping options available under the sysclock paradigm, and FFclock
in particular. Further, one of the main features of the FFclock paradigm
is the ability to take a raw timestamp (counter read), and to convert it
to a timestamp in seconds at some later time. Benefits include fast event
timestamping, flexible re-reading, reliable event comparison, fair clock
comparison on perfectly shared events, and enabling use of the difference
clock. Existing packet timestamping does not support raw reads, only
absolute times are returned.

This commit re-engineers the BPF_T_* timestamp flags defined in bpf.h to
establish a language rich enough to express full support for sysclock
timestamping. It is backward compatible in that all existing symbols
are retained (with unchanged values), but reorganised. The generation
of timestamps is now provided by kern_tc.c:sysclock_snap2bintime,
based on clock state captured by sysclock_getsnapshot.

  • To support the simultaneous return of both traditional and raw

timestamps, an additional ffcounter member is appended to bpf header
structures. This alters the bpf ABI.

bpf.h :
The flags cover four independent dimensions (all combinations allowed):
FORMAT: the format of returned absolute time timestamps, or no timestamp
FFRAW: specifying if a raw timestamp will be returned
FLAG: specifying the FAST or UPTIME variants of the absolute timestamp
CLOCK: specifying the specific clock desired, or by opting to use

whatever is the current sysclock.

Additional preset macros are added to cover the most important use cases
for the FFclock family, namely reading all three of the FF absolute UTC
clocks, returning bintime FORMAT for maximum resolution, and all with
the raw timestamp in addition.

The addition of a ffcounter member to structs bpf_hdr and bpf_xhdr.
The member is also added to struct bpf_hdr32 in bpf.c . To ease
adaptation to the new ABI, the new members are placed at to the end in
each case, and are unconditional (not guarded by #ifdef FFCLOCK).

bpf.c :
Timestamping performed in bpf_{tap,mtap,mtap2}, and their
interaction with catchpacket, has been restructured. Former helper
functions bpf_ts_quality and bpf_gettime and supporting macros, that
managed special cases, have been removed in favour of the following
approach shown in pseudocode:

bpf_TAP(,,,)
{ ...

/* Obtain state data and tc counter timestamp for FF and FB clocks */
sysclock_getsnapshot(&cs, 0);  // full sysclock state, including raw
for (each descriptor d) {      // state reused, shared raw timestamp

      /* No normal timestamp desired, skip ahead. */
      clear bt;
      goto ts_filled;

      /* Use the externally supplied ts, if available. */
      fill bt with external;
      goto ts_filled;

      /* Prepare a ts from the requested clock. */
      translate_clock_flags(d->bd_tstamp, &clockfamily, &flags);
      sysclock_snap2bintime(&cs, &bt, clockfamily, flags);

ts_filled:

      catchpacket(d,..., &bt, &ffcount);  // ffcount=0 if !FFRAW

}
...

}

The translate_clock_flags function performs translation between the
BPF_T_* and sysclock flags, see comment block for details. The roles of
these flag systems are inherently different, so translation is essential.

The above completes processing of the FFRAW, FLAG and CLOCK processing
in a single location, and supports all possible flag values. The FORMAT
dimension is now the sole responsbility of catchpacket, and is performed
within bpf_bintime2ts (the partial FLAG processing including there has
been removed). An additional ffcounter argument is appended to
catchpacket to transport the raw timestamp. The raw timestamp can be
recovered from userland using the pcap library, though there is no
explicit support as yet.

It is now possible for multiple applications to tap the same packets,
and based off a single captured state, to request timestamps that are
fully independent with respect to all dimensions (FORMAT, FFRAW, FLAG
and CLOCK), yet perfectly aligned in that they are all based off a
single shared raw timestamp.

bpf.4 manpage :
Updated with respect to the FFclock code revisions and terminology,
including the ffcounter members of structs bpf_xhdr and bpf_hdr.
The much broader timestamp choices now available are described under
BIOCSTSTAMP with reference to the FORMAT and CLOCK timestamp dimensions.
Three FFclock specific presets are supplied to complement the existing
3*4=12 given for the FBclock: BPF_T_BINTIME_FFC_{NAT,MONO,DIFF}FFC ,
and a guide is given for when diffFFC should be used.

typo: BPF_T_NANOTIME_MONOTONIC was corrected to BPF_T_BINTIME_MONOTONIC

in one place

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 54837
Build 51726: arc lint + arc unit

Event Timeline

brooks added inline comments.
share/man/man4/bpf.4
587
597–599
606–608
sys/net/bpf.c
138–139

I think the weird computation of sizeof was to allow the 2-byte length to be packed. I'm not sure that makes sense here. It might make sense to explicitly pad between bh_hdrlen and bh_ffcounter to avoid having i386 be weird.

sys/net/bpf.h
171

Whitespace changes make this part hard to review