From: Stephen Hemminger <stephen@networkplumber.org>
To: Soumyadeep Hore <soumyadeep.hore@intel.com>
Cc: dev@dpdk.org, bruce.richardson@intel.com,
rajesh3.kumar@intel.com, aman.deep.singh@intel.com,
manoj.kumar.subbarao@intel.com
Subject: Re: [PATCH v2] examples/ptpclient: compensate for clock frequency drift
Date: Tue, 13 Oct 2026 15:13:35 -0700 [thread overview]
Message-ID: <20261013151335.40429bc2@phoenix.local> (raw)
In-Reply-To: <20261013220145.880388-1-soumyadeep.hore@intel.com>
On Wed, 14 Oct 2026 03:31:45 +0530
Soumyadeep Hore <soumyadeep.hore@intel.com> wrote:
> The ptpclient example corrected only the instantaneous phase offset by
> calling rte_eth_timesync_adjust_time() once per DELAY_RESP. It never
> compensated for oscillator frequency drift, so the transmitter/receiver
> offset settled at a non-zero steady-state value (proportional to the
> drift rate times the sync interval) instead of converging towards zero.
>
> Replace the one-shot phase step with a PI clock servo, using the same
> model as linuxptp. The servo output is a frequency correction that is
> applied through the best mechanism the PMD provides:
>
> - When the driver supports hardware frequency adjustment, the correction
> is applied with rte_eth_timesync_adjust_freq() (for example the E810
> INCVAL register).
> - Otherwise the same correction is realized in software as an
> incremental phase step over the elapsed interval using
> rte_eth_timesync_adjust_time(), which every timesync-capable PMD
> provides.
>
> Hardware support is probed once at runtime, so any PMD that implements
> the adjust_freq operation in the future uses the hardware path without
> further changes. The servo state is kept per port and the selected path
> is logged once per port.
>
> Bugzilla ID: 1474
>
> Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
> ---
> v2:
> - Use transmitter/receiver instead of master/slave terminology
More detail AI review.
Review: [PATCH] examples/ptpclient: compensate for clock frequency drift
Builds clean with -Werror. Sign convention checked: delta_eval()
returns master - slave, so feeding it to the servo with a positive
output applied as +ppb is correct (linuxptp negates because its
offset is slave - master).
Warnings
--------
1. Integral term has no limit.
drift_ppb accumulates KI * offset forever. linuxptp clamps the
drift and the output to max_frequency (900000 ppb) because the
hardware range is finite; ice turns an unbounded ppm into an
incval that can run off the end. Clamp after the update:
#define PTP_SERVO_MAX_PPB 900000.0
...
if (servo->drift_ppb > PTP_SERVO_MAX_PPB)
servo->drift_ppb = PTP_SERVO_MAX_PPB;
else if (servo->drift_ppb < -PTP_SERVO_MAX_PPB)
servo->drift_ppb = -PTP_SERVO_MAX_PPB;
and the same for ppb before applying it.
2. Gains assume a 1 s sync interval.
KP = 0.7 and KI = 0.3 are linuxptp's values for sync interval
1 s; linuxptp scales them as kp * interval^-0.3 and
ki * interval^0.4 for other rates. Here both the integral update
and the slope seed run once per DELAY_RESP with no time scaling,
so at -3 or -4 log sync interval the integral runs 8-16x too
fast and the loop is under-damped. The SYNC header carries
logMessageInterval; use it:
int8_t lmi = ptp_msg->sync.hdr.log_message_interval;
double interval = ldexp(1.0, lmi);
servo->kp = PTP_SERVO_KP_SCALE * pow(interval, -0.3);
servo->ki = PTP_SERVO_KI_SCALE * pow(interval, 0.4);
Or at minimum document that the constants are only correct for
1 s sync.
3. Step branch leaves last_local pointing before the step.
local is read before rte_eth_timesync_adjust_time(), so the next
interval is measured as elapsed + step. On the first sync the
NIC clock is usually at 0, so the step is ~56 years and the
slope seed in case 1 comes out as 0. For a negative step larger
than the elapsed time, local <= last_local and the software
correction is silently skipped that sample. Account for the
step:
rte_eth_timesync_adjust_time(ptp->portid, offset);
servo->last_offset = 0;
servo->last_local = local + offset;
4. Software path does not remove the drift.
In software mode the correction is a phase step applied at the
end of each interval, so the clock free-runs for the whole
interval and is pulled back afterwards. This moves the sawtooth
so that the offset measured at sample time converges to 0, but
the peak error is still drift * interval, same as before the
patch. The commit message claims the frequency correction is
"realized" in software; say what it actually does, otherwise
users on PMDs without adjust_freq will expect a flat offset and
not get one.
5. Documentation not updated.
doc/guides/sample_app_ug/ptpclient.rst still describes the
adjustment as a one-shot adj = -[(T2-T1)-(T4-T3)]/2 and "we
adjust the PTP time receiver clock". Add a short paragraph on
the PI servo, the step threshold and the hardware/software
selection.
Info
----
6. The "\n" added to the print_clock_info() header line is an
unrelated change; either mention it in the commit message or
drop it.
7. Probing adjust_freq inside the servo and initialising
freq_adj_supported = -1 over all RTE_MAX_ETHPORTS in lcore_main()
is roundabout. Probe in port_init() where timesync is enabled,
which also removes the tri-state int:
ret = rte_eth_timesync_adjust_freq(port, 0);
ptp_servo[port].freq_adj_hw = (ret == 0);
8. Double blank line after the ptp_servo[] definition.
prev parent reply other threads:[~2026-10-13 22:13 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 21:46 [PATCH] examples/ptpclient: compensate for clock frequency drift Soumyadeep Hore
2026-10-13 22:01 ` [PATCH v2] " Soumyadeep Hore
2026-10-13 22:13 ` Stephen Hemminger [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013151335.40429bc2@phoenix.local \
--to=stephen@networkplumber.org \
--cc=aman.deep.singh@intel.com \
--cc=bruce.richardson@intel.com \
--cc=dev@dpdk.org \
--cc=manoj.kumar.subbarao@intel.com \
--cc=rajesh3.kumar@intel.com \
--cc=soumyadeep.hore@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.