Skip to content

Enable TSN pacing for E830 NIC#1635

Merged
Sakoram merged 19 commits into
mainfrom
tx-time-new-patches2
Jul 15, 2026
Merged

Enable TSN pacing for E830 NIC#1635
Sakoram merged 19 commits into
mainfrom
tx-time-new-patches2

Conversation

@Sakoram

@Sakoram Sakoram commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Adds hardware launch-time (TxPP) pacing support for Intel E830 NICs as
an opt-in TSN pacing mode. Hardens the PTP delay-request timestamp path
and TX epoch recovery against a PTP clock step, and raises pacing math
precision to long double to eliminate accumulation error.

Changes

  1. E830 TX time launch support for TSN pacing

Enables HW launch-time pacing on E830: registers the TX
timestamp dynflag/dynfield via the mbuf dynfield API and enables
RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP on port + per-queue config. Drops
the PTP-locked guard in the launch-time tasklet (no TSC fallback) and
widens the timesync retry for slower lock.

Bundles four ICE driver patches (TxPP timer association, PHC
read-clock, launch-time encoding, MMIO PHC update) plus a fifth for the
PHC owner on non-owning ports; bumps DPDK to 26.03.91_mtl.

  1. TSN pacing validation

Rejected at session init on a port without the launch-time
offload, or without PTP synced to the NIC's hardware clock (PHC).
Documents requirements (E830-only, PF-only, --ptp) in design.md; adds
a pacing_way pytest matrix across VF/PF.

  1. Hardened PTP timestamping and TX epoch recovery

Lock-free exactly-once claim for t3/t4 delta processing
against the ICE driver's single timestamp slot, plus stricter
sequence-id and stale-timestamp checks. Fixes a stuck epoch-recovery
stall where a PTP clock step left next_free_epoch stale. Adds PTP,
epoch/pacing, and NoCtx regression tests.

  1. Pacing math standardized to long double

Pacing structures and cursors (trs, frame_time,
tsc_time_cursor, ptp_time_cursor) promoted to long double with
nextafterl() to prevent precision loss.

Comment thread lib/src/dev/mt_dev.c Outdated
Comment thread lib/src/dev/mt_dev.c Outdated
Comment thread lib/src/dev/mt_dev.c
@Sakoram
Sakoram force-pushed the tx-time-new-patches2 branch 6 times, most recently from 619ae11 to 4b53c97 Compare July 8, 2026 10:59

@DawidWesierski4 DawidWesierski4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weak review to NOCTX tests and UNIT tests

Rest looks oki?

Comment thread tests/validation/tests/single/st20p/test_pacing_way.py Outdated
Comment thread tests/validation/tests/single/st20p/test_pacing_way.py
Comment thread doc/chunks/_ptp_setup.md
Comment thread lib/src/dev/mt_dev.c
Comment thread lib/src/dev/mt_dev.c
Comment thread tests/integration_tests/noctx/run.sh Outdated
Comment thread lib/src/mt_ptp.c
Comment thread lib/src/dev/mt_dev.c
Comment thread versions.env
@Sakoram
Sakoram force-pushed the tx-time-new-patches2 branch 3 times, most recently from 04afc92 to 1bd916a Compare July 15, 2026 10:59

@DawidWesierski4 DawidWesierski4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Comment thread tests/validation/tests/single/st20p/test_pacing_way.py
Comment thread lib/src/dev/mt_dev.c
Comment thread lib/src/dev/mt_dev.c
Sakoram added 11 commits July 15, 2026 13:37
Promote pacing structures (audio, video, ancillary, fastmetadata) and
their pacing cursors such as trs, frame_time, tsc_time_cursor, and
ptp_time_cursor to long double. Ensure pacing calculations are carried
out inside high-precision types and utilize nextafterl() instead of
double-precision variants to prevent precision loss. Modify logging and
print patterns to use %Lf for the updated members.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
The out-of-tree ICE driver's single hardware TX timestamp slot can delay
t3 availability or latch older timestamps if they're not drained. This
forces the async polling path to be resilient against stale timestamps
and racing completion.

Stiffened the async polling path:
- Introduced a lock-free claim step (rte_atomic32_t) to ensure exactly-once
  delta result processing when t3 or t4 asynchronously complete.
- Set the polling retry interval to 200us (up from 50us) to significantly
  reduce the PMD call frequency during heavy TX loads, lowering logging
  pressure when the hardware slot is busy.
- Added strict sequence-id check to verify t3 belongs to the current
  measurement cycle, plus an egress guard ensuring the reading exceeds
  the live t2 value to ignore stale buffered logs.
- Downgraded the recoverable single-cycle sync timeout status log level
  from error to warn.
- Corrected unit tests in tests/unit/ptp/ to accurately emulate and
  validate the correct clock synchronization behavior, ensuring robust
  and non-overfitted test execution.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Enable hardware launch-time (TxPP) pacing on E830 NICs used by the TSN
pacing path. Register the TX timestamp dynflag/dynfield via the public
mbuf dynfield API and enable RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP on both
port and per-queue config. Drop the PTP-locked guard in the launch-time
tasklet so pacing no longer falls back to TSC, and widen timesync retry
count for slower lock. Reject ST21_TX_PACING_WAY_TSN at pacing-select time
on ports that don't advertise the offload, instead of silently falling
through to another pacing way.

Carries five ICE driver patches: TxPP timer association, PHC read-clock,
19-bit launch-time encoding, direct MMIO PHC update, and gating the
send-on-timestamp offload to E830 only. Also carries the PHC-owner-init
patch: on multi-port ICE devices only the PCI function reporting
func_caps.ts_func_info.src_tmr_owned may start the shared PHC counter,
but the PMD only does so lazily inside ice_timesync_enable() on the port
the application calls it on -- if timesync is enabled only on a
non-owning port, the owner's PHC never starts and
rte_eth_timesync_read_time() on that port always returns 0. Bundle all
six patches together with a single DPDK bump to 26.03.92_mtl so the
version-gated install check in build_dpdk.sh cannot silently skip
applying a subset of them.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
A PTP step forward that lands the clock beyond max_onward_epochs was
handled inconsistently between the onward and late branches of
calc_frame_count_since_epoch()/tx_ancillary_calc_epoch():

- The onward branch resynced to current_epoch only when required_tai
  was already zero, so a caller-supplied user timestamp kept the stale
  next_free_epoch/next_free_frame_slot forever, never catching up to
  the stepped clock.
- The late branch unconditionally overwrote a valid required_tai with
  frame_count_tai, discarding the caller's timestamp.
- A required_tai that rounds down to epoch/frame_count 0 collided with
  the sentinel used elsewhere to mean "no user timestamp", silently
  falling back to whatever stale epoch was already in flight.
- EXACT_USER_PACING with a zero timestamp went unflagged in
  stat_error_user_timestamp for callers only ever driving the
  frame-level tv_pacing_required_tai()/tx_ancillary_pacing_required_tai()
  path (RTP-level pacing calls calc_frame_count_since_epoch() directly
  with a non-zero required_tai per packet, so flagging it there would
  have produced false positives every packet).

Guard the onward-range resync with the onward-gap check regardless of
required_tai, preserve required_tai through both branches unless it is
absent, fall back to real time when required_tai rounds to zero, and
move the zero-timestamp stat increment to the frame-level helpers.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Adds a white-box harness that includes st_tx_video_session.c directly
so calc_frame_count_since_epoch(), tv_sync_pacing(), and
tv_pacing_required_tai() can be exercised without DPDK EAL, mbuf pools,
or packet I/O. mt_get_tsc() is mocked with a preprocessor seam local to
the harness: mt_main.h is included first under its real name so the
genuine definition compiles normally, then mt_get_tsc is redefined to
the mock before including the production .c file, redirecting only the
call sites written inside it. mt_get_ptp_time() reuses the existing
production ptp_get_time_fn extensibility point instead.

14 epoch-recovery tests and 5 pacing tests cover the onward/late resync
paths, the epoch-0 sentinel collision, required_tai preservation across
resync, and the EXACT_USER_PACING zero-timestamp stat.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Simulates a PHC seeded ahead of the true grandmaster and later
corrected by the servo, reproducing the epoch/pacing stuck-recovery
bug fixed in st_tx_video_session.c. Parametrized over every
st21_tx_pacing_way, since calc_frame_count_since_epoch() runs
identically regardless of pacing way.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Most NoCtxTest cases only need a single TX/RX port pair; only the
redundant-session tests need all 4. Requiring 4 ports up front made it
impossible to run the suite (including TSN/launch-time-pacing tests,
which need a PF rather than a VF) on hosts with just 2 ports bound.

run.sh keeps requiring all 4 TEST_PORT_1..4 slots, since silently
building --port_list from whichever ports happen to be set left the
redundant-session tests failing individually and ambiguously instead
of the script refusing to run up front.

Add a dedicated run_pf.sh for the PF-only TSN/launch-time-pacing case:
it requires just TEST_PF_PORT_1/2 and filters to NoCtxTest cases named
with a `_pf_` infix, so the two port sets are never conflated. Rename
the TSN pacing test to st20p_tx_epoch_onward_recovers_after_ptp_step_pf_tsn_pacing
to match. TSN launch-time pacing is currently only validated on Intel
E830 (PCI device 12d2); note this in noctx.md rather than gating on
device ID in the test itself.

Mirror the same split in the MCP server: run_noctx_tests() keeps the
strict 4-port requirement and excludes `_pf_` tests, and a new
run_noctx_pf_tests() tool auto-discovers 2 PF ports (absence of a
physfn symlink) and runs the `_pf_` tests against them. Its gtest_filter
enumerates by the caller's substring first and requires `_pf_` as a
separate post-filter, instead of a single glob that assumed `_pf_`
always precedes the caller's filter text -- the naming convention puts
the descriptive prefix first (e.g. `st20p_..._pf_tsn_pacing`), so that
glob ordering could never match a filter on that prefix.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
TSN launch-time pacing compares each packet's launch timestamp
against the NIC's hardware clock (PHC). Selecting TSN pacing without
the built-in PTP service enabled, or with it forced to the TSC
source, leaves the timestamp in an unrelated clock domain, so the
NIC releases packets at the wrong time. Reject TSN pacing selection
in that case at session init instead.

Document the full set of TSN launch-time pacing requirements
(E830-only capability, PF-only, ptp-synced phc) in design.md.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
The built-in PTP service disciplines the hardware clock of the
primary port only. If MTL doesn't open/use that primary port (for
example, only a secondary port is passed to mtl_init), --ptp has no
effect on the secondary port's clock.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Parametrize every RxTxApp tx pacing_way (auto, rl, tsc, tsc_narrow,
ptp, be, tsn) against both VF and PF interfaces. VF-tsn is skipped:
tsn launch-time pacing has no HW PHC to compare against on a VF and
is rejected at mtl_init() by dev_if_init_pacing(), so it has no
positive case here.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
E810_DEVICE_ID lived inline in test_pacing_way.py even though NIC device
IDs are cross-test facts, not test-specific state (dma.py follows the
same shared-constant pattern in mtl_engine). Move it to const.py
alongside new E830/E835 IDs so other tests can reuse them.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Sakoram added 8 commits July 15, 2026 13:38
RxTxApp is currently the only backend that takes pacing_way, so add the
same application axis test_interlace.py/test_pacing.py use, with ffmpeg
skipped, instead of hardcoding "rxtxapp" in the test body.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Keep ST20/ST40 user timing authoritative across epoch recovery.
Validate exact targets, unwrap ST40 media clocks, and preserve wait
boundaries and completion metadata. Add deterministic pacing/stat tests.

Fixes: dad214f ("Fix: Prevent stuck epoch recovery on ST20/ST40 TX pacing")
Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
ST40_TX_FLAG_USER_PACING accepted ST10_TIMESTAMP_FMT_MEDIA_CLK and
converted it to TAI by reconstructing the wrap era from the current
media clock, an ambiguous operation whenever scheduling jitter shifts
the target across a 32-bit wrap boundary. ST20 already rejects media
clock for pacing; ST40 now does the same, falling back to the default
epoch-based pacing and counting a user-timestamp error. Media clock is
still accepted for ST40_TX_FLAG_USER_TIMESTAMP, which only affects the
reported RTP timestamp and never TAI conversion.

st10_media_clk_to_ns_u64() is no longer needed and is removed along
with its declaration.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
ST20_TX_FLAG_USER_PACING, ST22_TX_FLAG_USER_PACING, and
ST40_TX_FLAG_USER_PACING (and their pipeline-level equivalents) only
honor ST10_TIMESTAMP_FMT_TAI; ST10_TIMESTAMP_FMT_MEDIA_CLK falls back
to default pacing. Document this on the flags and the tfmt fields of
the associated frame meta structs. ST30_TX_FLAG_USER_PACING is left
unchanged since audio genuinely supports media clock for pacing.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
tx_audio_pacing_required_tai() converted a media-clock timestamp to
nanoseconds with a bare ticks/rate multiplication, treating the tick
count as elapsed time since zero instead of an absolute TAI instant.
Since real TAI is on the order of 10^18 ns and a 32-bit tick count at
audio sampling rates converts to at most ~10^14 ns, the result was
always deep in the past relative to the current PTP time, so pacing
silently collapsed to "send ASAP" on every frame instead of honoring
the requested time.

Reject ST10_TIMESTAMP_FMT_MEDIA_CLK for ST30_TX_FLAG_USER_PACING and
fall back to default epoch-based pacing, matching ST20 and ST40.
Documents the TAI-only restriction on the flag and the tfmt field of
st30_tx_frame_meta.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
st20p_harness.c and st30p_harness.c each define their own
st20_rx_put_framebuff()/st30_rx_put_framebuff() (and get/reset stats)
stubs to avoid touching the real transport layer, but session/
st20_harness.c and session/st30_harness.c pull in the real definitions
of the same symbols by #include-ing the production
st_rx_video_session.c / st_rx_audio_session.c into the same UnitTest
binary. -Wl,--allow-multiple-definition silently resolves the clash by
link order instead of erroring, and it picked the real, HW-backed
symbol over the harness stub.

The pipeline put_frame() path then called the real
st20_rx_put_framebuff()/st30_rx_put_framebuff() with the harness's fake
ctx->transport = 0x1 handle. MT_HANDLE_GUARD dereferenced that fake
handle's type field, reading address 0x9 and crashing with SIGSEGV
under ASan.

Redirect the production pipeline .c's calls to distinctly named local
stub functions via a #define around the #include, so the two
definitions can never collide as global symbols regardless of link
order.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
dev_if_init_pacing() rejects ST21_TX_PACING_WAY_TSN unless the built-in
ptp service is enabled (MTL_FLAG_PTP_ENABLE), since the launch-time
timestamp is only meaningful in the phc-synced clock domain. The
st20p_tx_epoch_onward_recovers_after_ptp_step_pf_tsn_pacing case never
set this flag, so mtl_init() failed with -EINVAL before the repro could
even run. Set the flag for the TSN pacing_way only; TSC pacing does not
compare against the phc and needs no ptp service.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
Adds st20p_tx_packets_are_spread_over_frame_pf_tsn_pacing, which uses
E830 RX hardware timestamps (st20_rx_tp_meta::ipt_avg via
ST20P_RX_FLAG_TIMING_PARSER_META) to confirm TSN launch-time pacing
actually spreads packets across the frame interval on the wire,
instead of only completing session setup like the existing epoch
recovery test.

CollectPacingSpanRatios waits up to 10s for the first complete RX
frame before starting a 6s steady-state sampling window, since real
PF hardware RX session establishment latency varies independently of
steady-state frame arrival.

Signed-off-by: Kasiewicz, Marek <marek.kasiewicz@intel.com>
@Sakoram
Sakoram force-pushed the tx-time-new-patches2 branch from 1bd916a to 73c6049 Compare July 15, 2026 13:40
@Sakoram
Sakoram enabled auto-merge (rebase) July 15, 2026 13:51
@Sakoram
Sakoram merged commit 321181c into main Jul 15, 2026
29 of 30 checks passed
@Sakoram
Sakoram deleted the tx-time-new-patches2 branch July 15, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants