update to 4.4 (RHEL-58210)
Resolves: RHEL-58210
This commit is contained in:
parent
9673178c45
commit
4e077c337d
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
/linuxptp-4.3.tgz
|
||||
/linuxptp-4.4.tgz
|
||||
/linuxptp-testsuite-d27dbd.tar.gz
|
||||
/clknetsim-633a0b.tar.gz
|
||||
/clknetsim-64df92.tar.gz
|
||||
|
@ -1,351 +0,0 @@
|
||||
commit 9c48f5d7765f63d54669d202adbd2cf959abd2cf
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Thu May 16 15:52:48 2024 +0200
|
||||
|
||||
ts2phc: Avoid unnecessary call of getppstime().
|
||||
|
||||
Don't get the ToD timestamp for the pulse polarity detection if it won't
|
||||
be needed (i.e. extts_polarity is not "both"). This allows PPS
|
||||
timestamps to be saved even when the ToD source fails.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||
index 8f7745c..e3e9caf 100644
|
||||
--- a/ts2phc_pps_sink.c
|
||||
+++ b/ts2phc_pps_sink.c
|
||||
@@ -275,21 +275,22 @@ static enum extts_result ts2phc_pps_sink_event(struct ts2phc_private *priv,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- err = ts2phc_pps_source_getppstime(priv->src, &source_ts);
|
||||
- if (err < 0) {
|
||||
- pr_debug("source ts not valid");
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- if (sink->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE) &&
|
||||
- ts2phc_pps_sink_ignore(priv, sink, source_ts)) {
|
||||
+ if (sink->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE)) {
|
||||
+ err = ts2phc_pps_source_getppstime(priv->src, &source_ts);
|
||||
+ if (err < 0) {
|
||||
+ pr_debug("source ts not valid");
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- pr_debug("%s SKIP extts index %u at %lld.%09u src %" PRIi64 ".%ld",
|
||||
- sink->name, event.index, event.t.sec, event.t.nsec,
|
||||
- (int64_t) source_ts.tv_sec, source_ts.tv_nsec);
|
||||
+ if (ts2phc_pps_sink_ignore(priv, sink, source_ts)) {
|
||||
+ pr_debug("%s SKIP extts index %u at %lld.%09u src %" PRIi64 ".%ld",
|
||||
+ sink->name, event.index, event.t.sec,
|
||||
+ event.t.nsec, (int64_t)source_ts.tv_sec,
|
||||
+ source_ts.tv_nsec);
|
||||
|
||||
- result = EXTTS_IGNORE;
|
||||
- goto out;
|
||||
+ result = EXTTS_IGNORE;
|
||||
+ goto out;
|
||||
+ }
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
commit 5ce45bd1a93674fc9cf48552c7a4d2e07b286be5
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Thu May 16 15:52:49 2024 +0200
|
||||
|
||||
ts2phc: Add holdover support.
|
||||
|
||||
If the external PPS signal is generated by a clock with better long-term
|
||||
stability than the clock synchronizing to it, it can work as a good time
|
||||
source for some period of time after losing its own time source (e.g.
|
||||
GPS receiver losing its signal).
|
||||
|
||||
Add an option to specify a holdover interval where ts2phc can continue
|
||||
synchronizing the clock without any ToD information. Allow that only in
|
||||
the LOCKED_STABLE servo state, which needs to be enabled by the
|
||||
servo_num_offset_values option.
|
||||
|
||||
This is supported only in the non-automatic mode and when the pulse
|
||||
polarity detection is disabled.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index edda408..5dcf7ca 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -370,6 +370,7 @@ struct config_item config_tab[] = {
|
||||
PORT_ITEM_INT("ts2phc.channel", 0, 0, INT_MAX),
|
||||
PORT_ITEM_INT("ts2phc.extts_correction", 0, INT_MIN, INT_MAX),
|
||||
PORT_ITEM_ENU("ts2phc.extts_polarity", PTP_RISING_EDGE, extts_polarity_enu),
|
||||
+ PORT_ITEM_INT("ts2phc.holdover", 0, 0, INT_MAX),
|
||||
PORT_ITEM_INT("ts2phc.master", 0, 0, 1),
|
||||
PORT_ITEM_INT("ts2phc.nmea_baudrate", 9600, 300, INT_MAX),
|
||||
GLOB_ITEM_STR("ts2phc.nmea_remote_host", ""),
|
||||
diff --git a/ts2phc.8 b/ts2phc.8
|
||||
index 7d781c9..8b5bd8b 100644
|
||||
--- a/ts2phc.8
|
||||
+++ b/ts2phc.8
|
||||
@@ -170,6 +170,16 @@ with the log level of the message as a number. The default is an empty string
|
||||
(which cannot be set in the configuration file as the option requires an
|
||||
argument).
|
||||
|
||||
+.TP
|
||||
+.B ts2phc.holdover
|
||||
+The holdover interval, specified in seconds. When the ToD information stops
|
||||
+working (e.g. GNSS receiver lost its fix), ts2phc is allowed for the specified
|
||||
+interval to continue synchronizing the target clock as long as the servo is in
|
||||
+the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
||||
+\fBservo_num_offset_values\fP option. The holdover is not supported with the
|
||||
+\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
||||
+The default is 0 (disabled).
|
||||
+
|
||||
.TP
|
||||
.B sa_file
|
||||
Specifies the location of the file containing Security Associations used
|
||||
diff --git a/ts2phc.c b/ts2phc.c
|
||||
index ccbf772..9fca34d 100644
|
||||
--- a/ts2phc.c
|
||||
+++ b/ts2phc.c
|
||||
@@ -435,9 +435,10 @@ static int ts2phc_pps_source_implicit_tstamp(struct ts2phc_private *priv,
|
||||
|
||||
static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
||||
{
|
||||
+ struct timespec source_ts, now;
|
||||
tmv_t source_tmv;
|
||||
struct ts2phc_clock *c;
|
||||
- int valid, err;
|
||||
+ int holdover, valid;
|
||||
|
||||
if (autocfg) {
|
||||
if (!priv->ref_clock) {
|
||||
@@ -451,9 +452,20 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
- err = ts2phc_pps_source_implicit_tstamp(priv, &source_tmv);
|
||||
- if (err < 0)
|
||||
+ valid = !ts2phc_pps_source_implicit_tstamp(priv, &source_tmv);
|
||||
+ }
|
||||
+
|
||||
+ if (valid) {
|
||||
+ priv->holdover_start = 0;
|
||||
+ holdover = 0;
|
||||
+ } else {
|
||||
+ clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
+
|
||||
+ if (!priv->holdover_start)
|
||||
+ priv->holdover_start = now.tv_sec;
|
||||
+ if (now.tv_sec >= priv->holdover_start + priv->holdover_length)
|
||||
return;
|
||||
+ holdover = 1;
|
||||
}
|
||||
|
||||
LIST_FOREACH(c, &priv->clocks, list) {
|
||||
@@ -470,6 +482,16 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (holdover) {
|
||||
+ if (c->servo_state != SERVO_LOCKED_STABLE)
|
||||
+ continue;
|
||||
+ source_ts = tmv_to_timespec(ts);
|
||||
+ if (source_ts.tv_nsec > NS_PER_SEC / 2)
|
||||
+ source_ts.tv_sec++;
|
||||
+ source_ts.tv_nsec = 0;
|
||||
+ source_tmv = timespec_to_tmv(source_ts);
|
||||
+ }
|
||||
+
|
||||
offset = tmv_to_nanoseconds(tmv_sub(ts, source_tmv));
|
||||
|
||||
if (c->no_adj) {
|
||||
@@ -481,8 +503,15 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
|
||||
adj = servo_sample(c->servo, offset, tmv_to_nanoseconds(ts),
|
||||
SAMPLE_WEIGHT, &c->servo_state);
|
||||
|
||||
- pr_info("%s offset %10" PRId64 " s%d freq %+7.0f",
|
||||
- c->name, offset, c->servo_state, adj);
|
||||
+ if (holdover && c->servo_state != SERVO_LOCKED_STABLE) {
|
||||
+ pr_info("%s lost holdover lock (offset %10" PRId64 ")",
|
||||
+ c->name, offset);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ pr_info("%s offset %10" PRId64 " s%d freq %+7.0f%s",
|
||||
+ c->name, offset, c->servo_state, adj,
|
||||
+ holdover ? " holdover" : "");
|
||||
|
||||
switch (c->servo_state) {
|
||||
case SERVO_UNLOCKED:
|
||||
@@ -751,6 +780,9 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ priv.holdover_length = config_get_int(cfg, NULL, "ts2phc.holdover");
|
||||
+ priv.holdover_start = 0;
|
||||
+
|
||||
while (is_running()) {
|
||||
struct ts2phc_clock *clk;
|
||||
|
||||
diff --git a/ts2phc.h b/ts2phc.h
|
||||
index 4833ded..5dbde9b 100644
|
||||
--- a/ts2phc.h
|
||||
+++ b/ts2phc.h
|
||||
@@ -55,6 +55,8 @@ struct ts2phc_private {
|
||||
bool state_changed;
|
||||
LIST_HEAD(port_head, ts2phc_port) ports;
|
||||
LIST_HEAD(clock_head, ts2phc_clock) clocks;
|
||||
+ int holdover_length;
|
||||
+ time_t holdover_start;
|
||||
};
|
||||
|
||||
struct ts2phc_clock *ts2phc_clock_add(struct ts2phc_private *priv,
|
||||
|
||||
commit 7ff632d9177d6024e5a340c7766562cb6bca696a
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Thu Jul 25 12:50:51 2024 +0200
|
||||
|
||||
ts2phc: Describe servo options in man page.
|
||||
|
||||
Copy and adapt missing servo options used by ts2phc from the ptp4l man
|
||||
page.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
diff --git a/ts2phc.8 b/ts2phc.8
|
||||
index 8b5bd8b..38e5be2 100644
|
||||
--- a/ts2phc.8
|
||||
+++ b/ts2phc.8
|
||||
@@ -126,6 +126,16 @@ are read from the file specified by \fBsa_file\fR. Requires \fBspp\fR
|
||||
and \fBsa_file\fR directives. Must be in the range of 1 to 2^32-1,
|
||||
inclusive. The default is 0 (disabled).
|
||||
|
||||
+.TP
|
||||
+.B clock_servo
|
||||
+The servo which is used to synchronize the local clock. Valid values
|
||||
+are "pi" for a PI controller, "linreg" for an adaptive controller
|
||||
+using linear regression, "ntpshm" and "refclock_sock" for the NTP SHM and
|
||||
+chrony SOCK reference clocks respectively to allow another process to
|
||||
+synchronize the local clock, and "nullf" for a servo that always dials
|
||||
+frequency offset zero (for use in SyncE nodes).
|
||||
+The default is "pi".
|
||||
+
|
||||
.TP
|
||||
.B first_step_threshold
|
||||
The maximum offset, specified in seconds, that the servo will correct by
|
||||
@@ -170,6 +180,65 @@ with the log level of the message as a number. The default is an empty string
|
||||
(which cannot be set in the configuration file as the option requires an
|
||||
argument).
|
||||
|
||||
+.TP
|
||||
+.B ntpshm_segment
|
||||
+The number of the SHM segment used by ntpshm servo.
|
||||
+The default is 0.
|
||||
+
|
||||
+.TP
|
||||
+.B pi_integral_const
|
||||
+The integral constant of the PI controller. When set to 0.0, the
|
||||
+integral constant will be set by the following formula from the current
|
||||
+sync interval.
|
||||
+The default is 0.0.
|
||||
+
|
||||
+ki = min(ki_scale * sync^ki_exponent, ki_norm_max / sync)
|
||||
+
|
||||
+.TP
|
||||
+.B pi_integral_exponent
|
||||
+The ki_exponent constant in the formula used to set the integral constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is 0.4.
|
||||
+
|
||||
+.TP
|
||||
+.B pi_integral_norm_max
|
||||
+The ki_norm_max constant in the formula used to set the integral constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is 0.3.
|
||||
+
|
||||
+.TP
|
||||
+.B pi_integral_scale
|
||||
+The ki_scale constant in the formula used to set the integral constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is 0.3.
|
||||
+
|
||||
+.TP
|
||||
+.B pi_proportional_const
|
||||
+The proportional constant of the PI controller. When set to 0.0, the
|
||||
+proportional constant will be set by the following formula from the current
|
||||
+sync interval.
|
||||
+The default is 0.0.
|
||||
+
|
||||
+kp = min(kp_scale * sync^kp_exponent, kp_norm_max / sync)
|
||||
+
|
||||
+.TP
|
||||
+.B pi_proportional_exponent
|
||||
+The kp_exponent constant in the formula used to set the proportional constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is \-0.3.
|
||||
+
|
||||
+.TP
|
||||
+.B pi_proportional_norm_max
|
||||
+The kp_norm_max constant in the formula used to set the proportional constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is 0.7
|
||||
+
|
||||
+.TP
|
||||
+.B pi_proportional_scale
|
||||
+The kp_scale constant in the formula used to set the proportional constant of
|
||||
+the PI controller from the sync interval.
|
||||
+The default is 0.7.
|
||||
+
|
||||
.TP
|
||||
.B ts2phc.holdover
|
||||
The holdover interval, specified in seconds. When the ToD information stops
|
||||
@@ -188,6 +257,21 @@ the optional security mechanism defined in ieee1588-2019 ch 14.16. See
|
||||
\fBSECURITY ASSOCIATION OPTIONS\fR for more info on file contents.
|
||||
The default is an empty string. (disabled).
|
||||
|
||||
+.TP
|
||||
+.B servo_num_offset_values
|
||||
+The number of offset values considered in order to transition from the
|
||||
+SERVO_LOCKED to the SERVO_LOCKED_STABLE state.
|
||||
+The transition occurs once the last 'servo_num_offset_values' offsets
|
||||
+are all below the 'servo_offset_threshold' value.
|
||||
+The default value is 10.
|
||||
+
|
||||
+.TP
|
||||
+.B servo_offset_threshold
|
||||
+The offset threshold used in order to transition from the SERVO_LOCKED
|
||||
+to the SERVO_LOCKED_STABLE state. The transition occurs once the
|
||||
+last 'servo_num_offset_values' offsets are all below the threshold value.
|
||||
+The default value of offset_threshold is 0 (disabled).
|
||||
+
|
||||
.TP
|
||||
.B step_threshold
|
||||
The maximum offset, specified in seconds, that the servo will correct
|
||||
|
||||
commit 772e59695ce3144fbc290a178df6ee2f7369ddc7
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Thu Jul 25 12:50:52 2024 +0200
|
||||
|
||||
ts2phc: Fix description of holdover option in man page.
|
||||
|
||||
Fix the man page to explain that the LOCKED_STABLE servo state is
|
||||
enabled by setting the servo_offset_threshold, not
|
||||
servo_num_offset_values, which is already enabled by default.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
diff --git a/ts2phc.8 b/ts2phc.8
|
||||
index 38e5be2..41f91d9 100644
|
||||
--- a/ts2phc.8
|
||||
+++ b/ts2phc.8
|
||||
@@ -245,7 +245,7 @@ The holdover interval, specified in seconds. When the ToD information stops
|
||||
working (e.g. GNSS receiver lost its fix), ts2phc is allowed for the specified
|
||||
interval to continue synchronizing the target clock as long as the servo is in
|
||||
the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
||||
-\fBservo_num_offset_values\fP option. The holdover is not supported with the
|
||||
+\fBservo_offset_threshold\fP option. The holdover is not supported with the
|
||||
\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
||||
The default is 0 (disabled).
|
||||
|
@ -1,342 +0,0 @@
|
||||
commit c4d00cfd9a611c9157f57a97babde11255f4b4e4
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon Jun 3 16:43:50 2024 +0200
|
||||
|
||||
ts2phc: Provide source type.
|
||||
|
||||
Save the PPS source type in the instance and add a function to retrieve
|
||||
it. This will be needed for NMEA-specific rounding of timestamps.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/ts2phc_pps_source.c b/ts2phc_pps_source.c
|
||||
index c333f65..ae2ad46 100644
|
||||
--- a/ts2phc_pps_source.c
|
||||
+++ b/ts2phc_pps_source.c
|
||||
@@ -26,6 +26,8 @@ struct ts2phc_pps_source *ts2phc_pps_source_create(struct ts2phc_private *priv,
|
||||
src = ts2phc_phc_pps_source_create(priv, dev);
|
||||
break;
|
||||
}
|
||||
+ if (src)
|
||||
+ src->type = type;
|
||||
return src;
|
||||
}
|
||||
|
||||
@@ -46,3 +48,8 @@ struct ts2phc_clock *ts2phc_pps_source_get_clock(struct ts2phc_pps_source *src)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+enum ts2phc_pps_source_type ts2phc_pps_source_get_type(struct ts2phc_pps_source *src)
|
||||
+{
|
||||
+ return src->type;
|
||||
+}
|
||||
diff --git a/ts2phc_pps_source.h b/ts2phc_pps_source.h
|
||||
index 293c693..c87e3af 100644
|
||||
--- a/ts2phc_pps_source.h
|
||||
+++ b/ts2phc_pps_source.h
|
||||
@@ -53,4 +53,11 @@ int ts2phc_pps_source_getppstime(struct ts2phc_pps_source *src, struct timespec
|
||||
|
||||
struct ts2phc_clock *ts2phc_pps_source_get_clock(struct ts2phc_pps_source *src);
|
||||
|
||||
+/**
|
||||
+ * Returns the type of the PPS source
|
||||
+ * @param src Pointer to a source obtained via @ref ts2phc_pps_source_create().
|
||||
+ * @return The type of the clock.
|
||||
+ */
|
||||
+enum ts2phc_pps_source_type ts2phc_pps_source_get_type(struct ts2phc_pps_source *src);
|
||||
+
|
||||
#endif
|
||||
diff --git a/ts2phc_pps_source_private.h b/ts2phc_pps_source_private.h
|
||||
index 99e6a78..ea6a8ad 100644
|
||||
--- a/ts2phc_pps_source_private.h
|
||||
+++ b/ts2phc_pps_source_private.h
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "ts2phc_pps_source.h"
|
||||
|
||||
struct ts2phc_pps_source {
|
||||
+ enum ts2phc_pps_source_type type;
|
||||
void (*destroy)(struct ts2phc_pps_source *src);
|
||||
int (*getppstime)(struct ts2phc_pps_source *src, struct timespec *ts);
|
||||
struct ts2phc_clock *(*get_clock)(struct ts2phc_pps_source *src);
|
||||
|
||||
commit e9f8d8fa119109f15e2377aef0ce4c62e261cba4
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon Jun 3 16:43:51 2024 +0200
|
||||
|
||||
ts2phc: Fix edge rejection for pulse widths over 0.5s.
|
||||
|
||||
If the configured pulse width is longer than 0.5 seconds, the calculated
|
||||
range of ignored offsets is too small to cover the wrong edge. Fix the
|
||||
calculation of the limits to use the minimum of pulsewidth and
|
||||
(1.0s - pulsewidth). A pulsewidth of 0.5s should give the shortest interval.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||
index e3e9caf..33df968 100644
|
||||
--- a/ts2phc_pps_sink.c
|
||||
+++ b/ts2phc_pps_sink.c
|
||||
@@ -175,6 +175,8 @@ static struct ts2phc_pps_sink *ts2phc_pps_sink_create(struct ts2phc_private *pri
|
||||
sink->correction = nanoseconds_to_tmv(correction);
|
||||
|
||||
pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth");
|
||||
+ if (pulsewidth > 500000000)
|
||||
+ pulsewidth = 1000000000 - pulsewidth;
|
||||
pulsewidth /= 2;
|
||||
sink->ignore_upper = 1000000000 - pulsewidth;
|
||||
sink->ignore_lower = pulsewidth;
|
||||
|
||||
commit 81c447a24c75d56d414bf318ea5b5a6fc35d5129
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon Jun 3 16:43:52 2024 +0200
|
||||
|
||||
ts2phc: Move upper/lower rejection limit calculation.
|
||||
|
||||
The ignore_upper and ignore_lower fields of the ts2phc_pps_sink struct
|
||||
are calculated when the PPS source is not known yet. Replace the fields
|
||||
with the configured pulsewidth and calculate the limits locally later
|
||||
when needed in ts2phc_pps_sink_ignore(). This will allow an
|
||||
NMEA-specific calculation of the limits.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||
index 33df968..be3bd9a 100644
|
||||
--- a/ts2phc_pps_sink.c
|
||||
+++ b/ts2phc_pps_sink.c
|
||||
@@ -30,8 +30,7 @@ struct ts2phc_pps_sink {
|
||||
struct ptp_pin_desc pin_desc;
|
||||
unsigned int polarity;
|
||||
tmv_t correction;
|
||||
- uint32_t ignore_lower;
|
||||
- uint32_t ignore_upper;
|
||||
+ uint32_t pulsewidth;
|
||||
struct ts2phc_clock *clock;
|
||||
};
|
||||
|
||||
@@ -153,8 +152,8 @@ static struct ts2phc_pps_sink *ts2phc_pps_sink_create(struct ts2phc_private *pri
|
||||
struct config *cfg = priv->cfg;
|
||||
struct ptp_extts_request extts;
|
||||
struct ts2phc_pps_sink *sink;
|
||||
- int err, pulsewidth;
|
||||
int32_t correction;
|
||||
+ int err;
|
||||
|
||||
sink = calloc(1, sizeof(*sink));
|
||||
if (!sink) {
|
||||
@@ -174,12 +173,9 @@ static struct ts2phc_pps_sink *ts2phc_pps_sink_create(struct ts2phc_private *pri
|
||||
correction = config_get_int(cfg, device, "ts2phc.extts_correction");
|
||||
sink->correction = nanoseconds_to_tmv(correction);
|
||||
|
||||
- pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth");
|
||||
- if (pulsewidth > 500000000)
|
||||
- pulsewidth = 1000000000 - pulsewidth;
|
||||
- pulsewidth /= 2;
|
||||
- sink->ignore_upper = 1000000000 - pulsewidth;
|
||||
- sink->ignore_lower = pulsewidth;
|
||||
+ sink->pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth");
|
||||
+ if (sink->pulsewidth > 500000000)
|
||||
+ sink->pulsewidth = 1000000000 - sink->pulsewidth;
|
||||
|
||||
sink->clock = ts2phc_clock_add(priv, device);
|
||||
if (!sink->clock) {
|
||||
@@ -248,12 +244,16 @@ static bool ts2phc_pps_sink_ignore(struct ts2phc_private *priv,
|
||||
struct timespec source_ts)
|
||||
{
|
||||
tmv_t source_tmv = timespec_to_tmv(source_ts);
|
||||
+ uint32_t ignore_lower, ignore_upper;
|
||||
|
||||
source_tmv = tmv_sub(source_tmv, priv->perout_phase);
|
||||
source_ts = tmv_to_timespec(source_tmv);
|
||||
|
||||
- return source_ts.tv_nsec > sink->ignore_lower &&
|
||||
- source_ts.tv_nsec < sink->ignore_upper;
|
||||
+ ignore_upper = 1000000000 - sink->pulsewidth / 2;
|
||||
+ ignore_lower = sink->pulsewidth / 2;
|
||||
+
|
||||
+ return source_ts.tv_nsec > ignore_lower &&
|
||||
+ source_ts.tv_nsec < ignore_upper;
|
||||
}
|
||||
|
||||
static enum extts_result ts2phc_pps_sink_event(struct ts2phc_private *priv,
|
||||
|
||||
commit 683f66aa46b7f9a5bd434e65a2d5703145c43b09
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon Jun 3 16:43:53 2024 +0200
|
||||
|
||||
ts2phc: Allow longer NMEA delays.
|
||||
|
||||
Timestamps from PPS sources are rounded to the nearest pulse, i.e. for
|
||||
correct synchronization the offset between the source timestamp and
|
||||
external PPS event timestamp needs to be between -0.5 and +0.5 seconds.
|
||||
For the pulse edge rejection to work correctly it needs to be even
|
||||
smaller, between -pulsewidth/2 and +pulsewidth/2.
|
||||
|
||||
With the NMEA PPS source the offset is the delay in the reception of the
|
||||
RMC message. This message is not expected to come exactly on time with
|
||||
the corresponding pulse. A positive delay is expected, typically at
|
||||
least few tens of milliseconds, but some receivers have delays longer
|
||||
than 0.5 seconds.
|
||||
|
||||
Add NMEA-specific rounding of the offset to not expect negative delays
|
||||
and allow positive delays of up to 1 second, or whole pulsewidth if the
|
||||
edge rejection is enabled.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/ts2phc.c b/ts2phc.c
|
||||
index 9fca34d..39d31b6 100644
|
||||
--- a/ts2phc.c
|
||||
+++ b/ts2phc.c
|
||||
@@ -420,9 +420,16 @@ static int ts2phc_pps_source_implicit_tstamp(struct ts2phc_private *priv,
|
||||
* deduce the timestamp (actually only seconds part, nanoseconds are by
|
||||
* construction zero) of this edge at the emitter based on the
|
||||
* emitter's current time.
|
||||
+ *
|
||||
+ * With an NMEA source assume its messages always follow the pulse, i.e.
|
||||
+ * assign the timestamp to the previous pulse instead of nearest pulse.
|
||||
*/
|
||||
- if (source_ts.tv_nsec > NS_PER_SEC / 2)
|
||||
+ if (ts2phc_pps_source_get_type(priv->src) == TS2PHC_PPS_SOURCE_NMEA) {
|
||||
source_ts.tv_sec++;
|
||||
+ } else {
|
||||
+ if (source_ts.tv_nsec > NS_PER_SEC / 2)
|
||||
+ source_ts.tv_sec++;
|
||||
+ }
|
||||
source_ts.tv_nsec = 0;
|
||||
|
||||
tmv = timespec_to_tmv(source_ts);
|
||||
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||
index be3bd9a..f285c2b 100644
|
||||
--- a/ts2phc_pps_sink.c
|
||||
+++ b/ts2phc_pps_sink.c
|
||||
@@ -249,8 +249,13 @@ static bool ts2phc_pps_sink_ignore(struct ts2phc_private *priv,
|
||||
source_tmv = tmv_sub(source_tmv, priv->perout_phase);
|
||||
source_ts = tmv_to_timespec(source_tmv);
|
||||
|
||||
- ignore_upper = 1000000000 - sink->pulsewidth / 2;
|
||||
- ignore_lower = sink->pulsewidth / 2;
|
||||
+ if (ts2phc_pps_source_get_type(priv->src) == TS2PHC_PPS_SOURCE_NMEA) {
|
||||
+ ignore_upper = sink->pulsewidth;
|
||||
+ ignore_lower = 0;
|
||||
+ } else {
|
||||
+ ignore_upper = 1000000000 - sink->pulsewidth / 2;
|
||||
+ ignore_lower = sink->pulsewidth / 2;
|
||||
+ }
|
||||
|
||||
return source_ts.tv_nsec > ignore_lower &&
|
||||
source_ts.tv_nsec < ignore_upper;
|
||||
|
||||
commit 50f5a22df7a9a3f361e42bd29f84e26af04ac78b
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon Jun 3 16:43:54 2024 +0200
|
||||
|
||||
ts2phc: Add option to correct for NMEA delay.
|
||||
|
||||
Add an option to specify the minimum expected delay of NMEA RMC messages
|
||||
to correct timestamps returned by the NMEA PPS time source.
|
||||
|
||||
This enables operation with receivers that have delays outside of the
|
||||
expected 0-1.0s interval, or 0-pulsewidth if the PPS edge rejection is
|
||||
enabled.
|
||||
|
||||
[ RPC: Preserve alphabetical ordering in the ts2phc man page. ]
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index 5dcf7ca..d0bc32c 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -373,6 +373,7 @@ struct config_item config_tab[] = {
|
||||
PORT_ITEM_INT("ts2phc.holdover", 0, 0, INT_MAX),
|
||||
PORT_ITEM_INT("ts2phc.master", 0, 0, 1),
|
||||
PORT_ITEM_INT("ts2phc.nmea_baudrate", 9600, 300, INT_MAX),
|
||||
+ PORT_ITEM_INT("ts2phc.nmea_delay", 0, INT_MIN, INT_MAX),
|
||||
GLOB_ITEM_STR("ts2phc.nmea_remote_host", ""),
|
||||
GLOB_ITEM_STR("ts2phc.nmea_remote_port", ""),
|
||||
GLOB_ITEM_STR("ts2phc.nmea_serialport", "/dev/ttyS0"),
|
||||
diff --git a/ts2phc.8 b/ts2phc.8
|
||||
index 41f91d9..177586d 100644
|
||||
--- a/ts2phc.8
|
||||
+++ b/ts2phc.8
|
||||
@@ -239,16 +239,6 @@ The kp_scale constant in the formula used to set the proportional constant of
|
||||
the PI controller from the sync interval.
|
||||
The default is 0.7.
|
||||
|
||||
-.TP
|
||||
-.B ts2phc.holdover
|
||||
-The holdover interval, specified in seconds. When the ToD information stops
|
||||
-working (e.g. GNSS receiver lost its fix), ts2phc is allowed for the specified
|
||||
-interval to continue synchronizing the target clock as long as the servo is in
|
||||
-the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
||||
-\fBservo_offset_threshold\fP option. The holdover is not supported with the
|
||||
-\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
||||
-The default is 0 (disabled).
|
||||
-
|
||||
.TP
|
||||
.B sa_file
|
||||
Specifies the location of the file containing Security Associations used
|
||||
@@ -288,6 +278,26 @@ for all messages in accordance to the corresponding security association
|
||||
sourced via the \fBsa_file\fR directive. Not compatible with one step ports.
|
||||
Must be in the range of -1 to 255, inclusive. The default is -1 (disabled).
|
||||
|
||||
+.TP
|
||||
+.B ts2phc.holdover
|
||||
+The holdover interval, specified in seconds. When the ToD information stops
|
||||
+working (e.g. GNSS receiver lost its fix), ts2phc is allowed for the specified
|
||||
+interval to continue synchronizing the target clock as long as the servo is in
|
||||
+the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
||||
+\fBservo_num_offset_values\fP option. The holdover is not supported with the
|
||||
+\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
||||
+The default is 0 (disabled).
|
||||
+
|
||||
+.TP
|
||||
+.B ts2phc.nmea_delay
|
||||
+Specifies the minimum expected delay of NMEA RMC messages in nanoseconds.
|
||||
+If the maximum delay is longer than 1 second, or 'ts2phc.pulsewidth'
|
||||
+if 'ts2phc.extts_polarity' is set to "both", this option needs to be set
|
||||
+accordingly to allow the timestamps from NMEA messages to be correctly
|
||||
+assigned to pulses from the PPS signal and wrong PPS edges to be rejected if
|
||||
+the edge rejection is enabled.
|
||||
+The default is 0 nanoseconds.
|
||||
+
|
||||
.TP
|
||||
.B ts2phc.nmea_remote_host, ts2phc.nmea_remote_port
|
||||
Specifies the remote host providing ToD information when using the
|
||||
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
||||
index 7a28433..3385e39 100644
|
||||
--- a/ts2phc_nmea_pps_source.c
|
||||
+++ b/ts2phc_nmea_pps_source.c
|
||||
@@ -33,6 +33,7 @@ struct ts2phc_nmea_pps_source {
|
||||
pthread_t worker;
|
||||
/* Protects anonymous struct fields, below, from concurrent access. */
|
||||
pthread_mutex_t mutex;
|
||||
+ tmv_t delay_correction;
|
||||
struct {
|
||||
struct timespec local_monotime;
|
||||
struct timespec local_utctime;
|
||||
@@ -187,6 +188,7 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||
return -1;
|
||||
}
|
||||
rmc = tmv_add(rmc, duration_since_rmc);
|
||||
+ rmc = tmv_add(rmc, m->delay_correction);
|
||||
utc_time = tmv_to_nanoseconds(rmc);
|
||||
utc_time /= (int64_t) 1000000000;
|
||||
*ts = tmv_to_timespec(rmc);
|
||||
@@ -232,6 +234,8 @@ struct ts2phc_pps_source *ts2phc_nmea_pps_source_create(struct ts2phc_private *p
|
||||
s->pps_source.destroy = ts2phc_nmea_pps_source_destroy;
|
||||
s->pps_source.getppstime = ts2phc_nmea_pps_source_getppstime;
|
||||
s->config = priv->cfg;
|
||||
+ s->delay_correction = nanoseconds_to_tmv(
|
||||
+ config_get_int(priv->cfg, NULL, "ts2phc.nmea_delay"));
|
||||
pthread_mutex_init(&s->mutex, NULL);
|
||||
err = pthread_create(&s->worker, NULL, monitor_nmea_status, s);
|
||||
if (err) {
|
@ -1,80 +0,0 @@
|
||||
commit a3d3f4687f25688140f5a391b437af1dca8e0d5c
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Tue Jun 11 16:17:37 2024 +0200
|
||||
|
||||
nmea: Fix conversion of leap second.
|
||||
|
||||
When a leap second is inserted, the RMC message reports time of
|
||||
23:59:60, which overflows in mktime() to 0:00:00 after the leap second
|
||||
with an incremented TAI-UTC offset. This causes a one-second error in
|
||||
the offset meaured by ts2phc.
|
||||
|
||||
Check the seconds field of the RMC message and convert 60 to 59 to make
|
||||
the timestamp ambiguous per is_utc_ambiguous() and ignored by ts2phc to
|
||||
avoid updating the clock with the one-second error.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/nmea.c b/nmea.c
|
||||
index 7f1d9a2..b84b42e 100644
|
||||
--- a/nmea.c
|
||||
+++ b/nmea.c
|
||||
@@ -155,6 +155,9 @@ static int nmea_scan_rmc(struct nmea_parser *np, struct nmea_rmc *result)
|
||||
if (cnt != 3) {
|
||||
return -1;
|
||||
}
|
||||
+ /* Convert an inserted leap second to ambiguous 23:59:59 */
|
||||
+ if (tm.tm_sec == 60)
|
||||
+ tm.tm_sec = 59;
|
||||
tm.tm_year += 100;
|
||||
tm.tm_mon--;
|
||||
tm.tm_isdst = 0;
|
||||
|
||||
commit 6dcb8eda9fa7b2e3d486a3903c5c7b2568b30605
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Tue Jun 11 16:17:38 2024 +0200
|
||||
|
||||
ts2phc: Fix timestamp conversion for leap seconds.
|
||||
|
||||
The UTC timestamp parsed from the RMC message needs to be converted to
|
||||
TAI in order to calculate the PHC offset. This conversion was done after
|
||||
adjusting the timestamp for the measured delay between the reception of
|
||||
the message and the following pulse, which caused the offset measured by
|
||||
ts2phc to have a one-second error if the message expected during or
|
||||
after a leap second was missed.
|
||||
|
||||
Apply the TAI-UTC offset to the timestamp parsed from the RMC message
|
||||
before any adjustments are made to avoid the error.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
||||
index 3385e39..e345969 100644
|
||||
--- a/ts2phc_nmea_pps_source.c
|
||||
+++ b/ts2phc_nmea_pps_source.c
|
||||
@@ -187,11 +187,9 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||
pr_err("nmea: rmc time stamp stale");
|
||||
return -1;
|
||||
}
|
||||
- rmc = tmv_add(rmc, duration_since_rmc);
|
||||
- rmc = tmv_add(rmc, m->delay_correction);
|
||||
+
|
||||
utc_time = tmv_to_nanoseconds(rmc);
|
||||
utc_time /= (int64_t) 1000000000;
|
||||
- *ts = tmv_to_timespec(rmc);
|
||||
|
||||
result = lstab_utc2tai(m->lstab, utc_time, &tai_offset);
|
||||
switch (result) {
|
||||
@@ -208,6 +206,10 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||
pr_err("nmea: utc time stamp is ambiguous");
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ rmc = tmv_add(rmc, duration_since_rmc);
|
||||
+ rmc = tmv_add(rmc, m->delay_correction);
|
||||
+ *ts = tmv_to_timespec(rmc);
|
||||
ts->tv_sec += tai_offset;
|
||||
|
||||
return lstab_error;
|
@ -1,26 +0,0 @@
|
||||
commit 293ca74b9df22a75951eea72426869a7ee9eb023
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Tue Jun 11 16:17:36 2024 +0200
|
||||
|
||||
ts2phc: Reset parser after RMC message.
|
||||
|
||||
When the receiver was configured to generate only RMC messages, every
|
||||
other message was skipped due to the parser not being in the right
|
||||
state to process another message. Reset the parser to correctly parse
|
||||
every valid message.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
diff --git a/nmea.c b/nmea.c
|
||||
index 44c7c01..7f1d9a2 100644
|
||||
--- a/nmea.c
|
||||
+++ b/nmea.c
|
||||
@@ -171,6 +171,7 @@ int nmea_parse(struct nmea_parser *np, const char *ptr, int buflen,
|
||||
while (buflen) {
|
||||
if (!nmea_parse_symbol(np, *ptr)) {
|
||||
if (!nmea_scan_rmc(np, result)) {
|
||||
+ nmea_reset(np);
|
||||
*parsed = count + 1;
|
||||
return 0;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
%global _hardened_build 1
|
||||
%global testsuite_ver d27dbd
|
||||
%global clknetsim_ver 633a0b
|
||||
%global clknetsim_ver 64df92
|
||||
%global selinuxtype targeted
|
||||
%bcond_without selinux
|
||||
|
||||
Name: linuxptp
|
||||
Version: 4.3
|
||||
Version: 4.4
|
||||
Release: 2%{?dist}
|
||||
Summary: PTP implementation for Linux
|
||||
|
||||
@ -29,14 +29,6 @@ Source22: linuxptp.te
|
||||
|
||||
# limit unicast message rate per address and grant duration
|
||||
Patch1: linuxptp-ucastrate.patch
|
||||
# add holdover support to ts2phc
|
||||
Patch2: linuxptp-holdover.patch
|
||||
# fix ts2phc to reset NMEA parser after RMC message
|
||||
Patch3: linuxptp-nmeareset.patch
|
||||
# fix ts2phc to handle large NMEA delay
|
||||
Patch4: linuxptp-nmeadelay.patch
|
||||
# fix ts2phc to correctly handle leap seconds
|
||||
Patch5: linuxptp-nmealeap.patch
|
||||
|
||||
BuildRequires: gcc gcc-c++ gnutls-devel make systemd
|
||||
|
||||
|
4
sources
4
sources
@ -1,3 +1,3 @@
|
||||
SHA512 (linuxptp-4.3.tgz) = 1cd5a65f53080ddbe01a1125cbf21c20cebed06f727e76a7d1cddee2514c229a7efd9b465bad839ffd923d0679da84316936368b3740d64c085d9f09e5b683df
|
||||
SHA512 (linuxptp-4.4.tgz) = f9c8ac0c812d9829b3bc4595412afbeea0cade4937c46efbe47789d0ced38894a65f38a174a65a59c51b4d85a7bbf970b5d575ae1389c504fbd36eb7f96bd282
|
||||
SHA512 (linuxptp-testsuite-d27dbd.tar.gz) = e289f63d522eaac3deb1db81442805fb602ae5423c02afb2200e59518e9c3db8dcaa00e42a57f0d81d51bb2e7cbd4b82c1d3522abbb5e5569cfd795ba403d659
|
||||
SHA512 (clknetsim-633a0b.tar.gz) = e58ff5914074f6c9333692fd078e6d70a65c9af32b9f67e8993ea8eeb8910083e91fb29ce4fc68134380e53c0b73a892cda989f87bc7d3f1b9a4d3e6a455be55
|
||||
SHA512 (clknetsim-64df92.tar.gz) = 91b7a9c9d4e8eaa8903f1f612cdaa2865d094e1c3531e039da9ad75595f4f4cd6fdbce9afdb0dafa18573d8afcb33a0e101170fc02c6585a231133a10b0890ff
|
||||
|
Loading…
Reference in New Issue
Block a user