Compare commits
No commits in common. "c8" and "c9" have entirely different histories.
3
.linuxptp.metadata
Normal file
3
.linuxptp.metadata
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
3ae72eb0ddafd8d8aeea7eac382d6e4a958717ef SOURCES/clknetsim-5d1dc0.tar.gz
|
||||||
|
309e6ab1fa3f61b3deb1735c3082dc2070870be1 SOURCES/linuxptp-4.2.tgz
|
||||||
|
7594d0705a1a648d5f7380d476bb3afebff21f6c SOURCES/linuxptp-testsuite-bf8ead.tar.gz
|
176
SOURCES/linuxptp-addropts.patch
Normal file
176
SOURCES/linuxptp-addropts.patch
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
commit 073faba77e8a82c54210941cee6023dc9e719329
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Thu Apr 25 14:25:57 2024 +0200
|
||||||
|
|
||||||
|
udp+udp6: Make IP addresses configurable.
|
||||||
|
|
||||||
|
Allow configuration of the multicast IPv4/IPv6 addresses, which can be
|
||||||
|
useful for testing. This complements the L2-specific ptp_dst_mac and
|
||||||
|
p2p_dst_mac options.
|
||||||
|
|
||||||
|
[ RPC: removed unused #defines PTP_PRIMARY_MCAST_IPADDR and PTP_PDELAY_MCAST_IPADDR ]
|
||||||
|
|
||||||
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||||
|
|
||||||
|
diff --git a/config.c b/config.c
|
||||||
|
index d7775c0..c220a3e 100644
|
||||||
|
--- a/config.c
|
||||||
|
+++ b/config.c
|
||||||
|
@@ -299,6 +299,9 @@ struct config_item config_tab[] = {
|
||||||
|
GLOB_ITEM_INT("offsetScaledLogVariance", 0xffff, 0, UINT16_MAX),
|
||||||
|
PORT_ITEM_INT("operLogPdelayReqInterval", 0, INT8_MIN, INT8_MAX),
|
||||||
|
PORT_ITEM_INT("operLogSyncInterval", 0, INT8_MIN, INT8_MAX),
|
||||||
|
+ PORT_ITEM_STR("p2p_dst_ipv4", "224.0.0.107"),
|
||||||
|
+ PORT_ITEM_STR("p2p_dst_ipv6", "FF02:0:0:0:0:0:0:6B"),
|
||||||
|
+ PORT_ITEM_STR("p2p_dst_mac", "01:80:C2:00:00:0E"),
|
||||||
|
PORT_ITEM_INT("path_trace_enabled", 0, 0, 1),
|
||||||
|
PORT_ITEM_INT("phc_index", -1, -1, INT_MAX),
|
||||||
|
GLOB_ITEM_DBL("pi_integral_const", 0.0, 0.0, DBL_MAX),
|
||||||
|
@@ -317,8 +320,9 @@ struct config_item config_tab[] = {
|
||||||
|
GLOB_ITEM_INT("priority1", 128, 0, UINT8_MAX),
|
||||||
|
GLOB_ITEM_INT("priority2", 128, 0, UINT8_MAX),
|
||||||
|
GLOB_ITEM_STR("productDescription", ";;"),
|
||||||
|
+ PORT_ITEM_STR("ptp_dst_ipv4", "224.0.1.129"),
|
||||||
|
+ PORT_ITEM_STR("ptp_dst_ipv6", "FF0E:0:0:0:0:0:0:181"),
|
||||||
|
PORT_ITEM_STR("ptp_dst_mac", "01:1B:19:00:00:00"),
|
||||||
|
- PORT_ITEM_STR("p2p_dst_mac", "01:80:C2:00:00:0E"),
|
||||||
|
GLOB_ITEM_INT("ptp_minor_version", 0, 0, 1),
|
||||||
|
GLOB_ITEM_STR("refclock_sock_address", "/var/run/refclock.ptp.sock"),
|
||||||
|
GLOB_ITEM_STR("revisionData", ";;"),
|
||||||
|
diff --git a/configs/default.cfg b/configs/default.cfg
|
||||||
|
index 8f94c16..54ce62a 100644
|
||||||
|
--- a/configs/default.cfg
|
||||||
|
+++ b/configs/default.cfg
|
||||||
|
@@ -94,6 +94,10 @@ write_phase_mode 0
|
||||||
|
# Transport options
|
||||||
|
#
|
||||||
|
transportSpecific 0x0
|
||||||
|
+ptp_dst_ipv4 224.0.1.129
|
||||||
|
+p2p_dst_ipv4 224.0.0.107
|
||||||
|
+ptp_dst_ipv6 FF0E:0:0:0:0:0:0:181
|
||||||
|
+p2p_dst_ipv6 FF02:0:0:0:0:0:0:6B
|
||||||
|
ptp_dst_mac 01:1B:19:00:00:00
|
||||||
|
p2p_dst_mac 01:80:C2:00:00:0E
|
||||||
|
udp_ttl 1
|
||||||
|
diff --git a/ptp4l.8 b/ptp4l.8
|
||||||
|
index c59b0b4..a4eb603 100644
|
||||||
|
--- a/ptp4l.8
|
||||||
|
+++ b/ptp4l.8
|
||||||
|
@@ -397,6 +397,27 @@ This value may be changed dynamically using the
|
||||||
|
POWER_PROFILE_SETTINGS_NP management message.
|
||||||
|
The default is "none".
|
||||||
|
|
||||||
|
+.TP
|
||||||
|
+.B ptp_dst_ipv4
|
||||||
|
+The IPv4 address to which PTP messages should be sent.
|
||||||
|
+Relevant only with UDPv4 transport. The default is 224.0.1.129.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B p2p_dst_ipv4
|
||||||
|
+The IPv4 address to which peer delay messages should be sent.
|
||||||
|
+Relevant only with UDPv4 transport. The default is 224.0.0.107.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B ptp_dst_ipv6
|
||||||
|
+The IPv6 address to which PTP messages should be sent.
|
||||||
|
+The second byte of the address is substituted with udp6_scope.
|
||||||
|
+Relevant only with UDPv6 transport. The default is FF0E:0:0:0:0:0:0:181.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B p2p_dst_ipv6
|
||||||
|
+The IPv6 address to which peer delay messages should be sent.
|
||||||
|
+Relevant only with UDPv6 transport. The default is FF02:0:0:0:0:0:0:6B.
|
||||||
|
+
|
||||||
|
.TP
|
||||||
|
.B ptp_dst_mac
|
||||||
|
The MAC address to which PTP messages should be sent.
|
||||||
|
diff --git a/udp.c b/udp.c
|
||||||
|
index 7c9402e..38d0ec4 100644
|
||||||
|
--- a/udp.c
|
||||||
|
+++ b/udp.c
|
||||||
|
@@ -39,8 +39,6 @@
|
||||||
|
|
||||||
|
#define EVENT_PORT 319
|
||||||
|
#define GENERAL_PORT 320
|
||||||
|
-#define PTP_PRIMARY_MCAST_IPADDR "224.0.1.129"
|
||||||
|
-#define PTP_PDELAY_MCAST_IPADDR "224.0.0.107"
|
||||||
|
|
||||||
|
struct udp {
|
||||||
|
struct transport t;
|
||||||
|
@@ -157,6 +155,7 @@ static int udp_open(struct transport *t, struct interface *iface,
|
||||||
|
const char *name = interface_name(iface);
|
||||||
|
uint8_t event_dscp, general_dscp;
|
||||||
|
int efd, gfd, ttl;
|
||||||
|
+ char *str;
|
||||||
|
|
||||||
|
ttl = config_get_int(t->cfg, name, "udp_ttl");
|
||||||
|
udp->mac.len = 0;
|
||||||
|
@@ -165,11 +164,17 @@ static int udp_open(struct transport *t, struct interface *iface,
|
||||||
|
udp->ip.len = 0;
|
||||||
|
sk_interface_addr(name, AF_INET, &udp->ip);
|
||||||
|
|
||||||
|
- if (!inet_aton(PTP_PRIMARY_MCAST_IPADDR, &mcast_addr[MC_PRIMARY]))
|
||||||
|
+ str = config_get_string(t->cfg, name, "ptp_dst_ipv4");
|
||||||
|
+ if (!inet_aton(str, &mcast_addr[MC_PRIMARY])) {
|
||||||
|
+ pr_err("invalid ptp_dst_ipv4 %s", str);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (!inet_aton(PTP_PDELAY_MCAST_IPADDR, &mcast_addr[MC_PDELAY]))
|
||||||
|
+ str = config_get_string(t->cfg, name, "p2p_dst_ipv4");
|
||||||
|
+ if (!inet_aton(str, &mcast_addr[MC_PDELAY])) {
|
||||||
|
+ pr_err("invalid p2p_dst_ipv4 %s", str);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
efd = open_socket(name, mcast_addr, EVENT_PORT, ttl);
|
||||||
|
if (efd < 0)
|
||||||
|
diff --git a/udp6.c b/udp6.c
|
||||||
|
index bde1710..188d20e 100644
|
||||||
|
--- a/udp6.c
|
||||||
|
+++ b/udp6.c
|
||||||
|
@@ -40,10 +40,6 @@
|
||||||
|
#define EVENT_PORT 319
|
||||||
|
#define GENERAL_PORT 320
|
||||||
|
|
||||||
|
-/* The 0x0e in second byte is substituted with udp6_scope at runtime. */
|
||||||
|
-#define PTP_PRIMARY_MCAST_IP6ADDR "FF0E:0:0:0:0:0:0:181"
|
||||||
|
-#define PTP_PDELAY_MCAST_IP6ADDR "FF02:0:0:0:0:0:0:6B"
|
||||||
|
-
|
||||||
|
enum { MC_PRIMARY, MC_PDELAY };
|
||||||
|
|
||||||
|
struct udp6 {
|
||||||
|
@@ -167,6 +163,7 @@ static int udp6_open(struct transport *t, struct interface *iface,
|
||||||
|
const char *name = interface_name(iface);
|
||||||
|
uint8_t event_dscp, general_dscp;
|
||||||
|
int efd, gfd, hop_limit;
|
||||||
|
+ char *str;
|
||||||
|
|
||||||
|
hop_limit = config_get_int(t->cfg, name, "udp_ttl");
|
||||||
|
udp6->mac.len = 0;
|
||||||
|
@@ -175,16 +172,20 @@ static int udp6_open(struct transport *t, struct interface *iface,
|
||||||
|
udp6->ip.len = 0;
|
||||||
|
sk_interface_addr(name, AF_INET6, &udp6->ip);
|
||||||
|
|
||||||
|
- if (1 != inet_pton(AF_INET6, PTP_PRIMARY_MCAST_IP6ADDR,
|
||||||
|
- &udp6->mc6_addr[MC_PRIMARY]))
|
||||||
|
+ str = config_get_string(t->cfg, name, "ptp_dst_ipv6");
|
||||||
|
+ if (1 != inet_pton(AF_INET6, str, &udp6->mc6_addr[MC_PRIMARY])) {
|
||||||
|
+ pr_err("invalid ptp_dst_ipv6 %s", str);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
udp6->mc6_addr[MC_PRIMARY].s6_addr[1] = config_get_int(t->cfg, name,
|
||||||
|
"udp6_scope");
|
||||||
|
|
||||||
|
- if (1 != inet_pton(AF_INET6, PTP_PDELAY_MCAST_IP6ADDR,
|
||||||
|
- &udp6->mc6_addr[MC_PDELAY]))
|
||||||
|
+ str = config_get_string(t->cfg, name, "p2p_dst_ipv6");
|
||||||
|
+ if (1 != inet_pton(AF_INET6, str, &udp6->mc6_addr[MC_PDELAY])) {
|
||||||
|
+ pr_err("invalid p2p_dst_ipv6 %s", str);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
efd = open_socket_ipv6(name, udp6->mc6_addr, EVENT_PORT, &udp6->index,
|
||||||
|
hop_limit);
|
360
SOURCES/linuxptp-holdover.patch
Normal file
360
SOURCES/linuxptp-holdover.patch
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
commit c7acd4b5bdb95e45d93833ffaac9cac51dfe934b
|
||||||
|
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 0d399b8..76912a2 100644
|
||||||
|
--- a/ts2phc_pps_sink.c
|
||||||
|
+++ b/ts2phc_pps_sink.c
|
||||||
|
@@ -277,21 +277,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 9880cccc928351a42a3fa9e018949442aca7ddae
|
||||||
|
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 c220a3e..58481db 100644
|
||||||
|
--- a/config.c
|
||||||
|
+++ b/config.c
|
||||||
|
@@ -344,6 +344,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 852a527..bcc6f61 100644
|
||||||
|
--- a/ts2phc.8
|
||||||
|
+++ b/ts2phc.8
|
||||||
|
@@ -168,6 +168,16 @@ by changing the clock frequency instead of stepping the clock. When
|
||||||
|
set to 0.0, the servo will never step the clock except on start.
|
||||||
|
The default is 0.0.
|
||||||
|
|
||||||
|
+.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_remote_host, ts2phc.nmea_remote_port
|
||||||
|
Specifies the remote host providing ToD information when using the
|
||||||
|
diff --git a/ts2phc.c b/ts2phc.c
|
||||||
|
index 4817c85..d552e0f 100644
|
||||||
|
--- a/ts2phc.c
|
||||||
|
+++ b/ts2phc.c
|
||||||
|
@@ -440,9 +440,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) {
|
||||||
|
@@ -456,9 +457,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) {
|
||||||
|
@@ -475,6 +487,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) {
|
||||||
|
@@ -486,8 +508,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 *c;
|
||||||
|
|
||||||
|
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 bf237fd55d4983a42d9344890dd861f18bea70ca
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Thu Jul 25 12:43:59 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 bcc6f61..4c54576 100644
|
||||||
|
--- a/ts2phc.8
|
||||||
|
+++ b/ts2phc.8
|
||||||
|
@@ -117,6 +117,16 @@ command line option.
|
||||||
|
|
||||||
|
.SH GLOBAL OPTIONS
|
||||||
|
|
||||||
|
+.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
|
||||||
|
@@ -162,12 +172,64 @@ with the log level of the message as a number. The default is an empty string
|
||||||
|
argument).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
-.B step_threshold
|
||||||
|
-The maximum offset, specified in seconds, that the servo will correct
|
||||||
|
-by changing the clock frequency instead of stepping the clock. When
|
||||||
|
-set to 0.0, the servo will never step the clock except on start.
|
||||||
|
+.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
|
||||||
|
@@ -178,6 +240,28 @@ the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
|
||||||
|
\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
|
||||||
|
The default is 0 (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
|
||||||
|
+by changing the clock frequency instead of stepping the clock. When
|
||||||
|
+set to 0.0, the servo will never step the clock except on start.
|
||||||
|
+The default is 0.0.
|
||||||
|
+
|
||||||
|
.TP
|
||||||
|
.B ts2phc.nmea_remote_host, ts2phc.nmea_remote_port
|
||||||
|
Specifies the remote host providing ToD information when using the
|
||||||
|
|
||||||
|
commit 7734d2fe8ac52afaa233262548615f79021ae6ee
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Thu Jul 25 12:46:43 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 4c54576..c0b718b 100644
|
||||||
|
--- a/ts2phc.8
|
||||||
|
+++ b/ts2phc.8
|
||||||
|
@@ -236,7 +236,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,29 +1,365 @@
|
|||||||
commit 0404c1924254c9162222dd5000a140165d21250c
|
commit 0c406008b530140ed6d992915a6c8a1e5abf15d5
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
Date: Thu Jan 25 15:23:44 2024 +0100
|
Date: Thu Jan 25 11:26:15 2024 +0100
|
||||||
|
|
||||||
ts2phc: Fix offset for NMEA delays over 0.5 seconds.
|
ts2phc: Don't switch system clock to nanosecond mode.
|
||||||
|
|
||||||
The current code of ts2phc assumes that the NMEA RMC message is received
|
ts2phc is not synchronizing the system clock and should not switch the
|
||||||
within 0.5 seconds of the pulse the timestamp in the message is refering
|
clock to the nanosecond mode with adjtimex(modes=ADJ_NANO) or make any
|
||||||
to. However, with most receivers NMEA messages are referenced to the
|
other modifications to it. The process that is controlling the clock
|
||||||
previous pulse. This causes a 1-second error in the measured offset for
|
(e.g. an NTP client) might not be using the nanosecond mode.
|
||||||
receivers with delays over 0.5 seconds.
|
|
||||||
|
|
||||||
Add a 0.5 second correction to map the whole interval between pulses to
|
There are two instances of the adjtimex() call in the code. One is used
|
||||||
the preceding pulse.
|
only to read the clock and can be replaced with faster clock_gettime().
|
||||||
|
The other instance is also reading the TAI offset. Instead of switching
|
||||||
|
to the nanosecond mode, change the timestamp conversion to handle both
|
||||||
|
microsecond and nanosecond modes according to the current clock status.
|
||||||
|
|
||||||
|
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||||
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/ts2phc_generic_pps_source.c b/ts2phc_generic_pps_source.c
|
||||||
|
index d503aac..e6b8145 100644
|
||||||
|
--- a/ts2phc_generic_pps_source.c
|
||||||
|
+++ b/ts2phc_generic_pps_source.c
|
||||||
|
@@ -38,7 +38,6 @@ static int get_ntx(struct timex *ntx)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memset(ntx, 0, sizeof(*ntx));
|
||||||
|
- ntx->modes = ADJ_NANO;
|
||||||
|
code = adjtimex(ntx);
|
||||||
|
if (code == -1) {
|
||||||
|
pr_err("adjtimex failed: %m");
|
||||||
|
@@ -93,7 +92,10 @@ static int ts2phc_generic_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->tv_sec = ntx.time.tv_sec + tai_offset;
|
||||||
|
- ts->tv_nsec = ntx.time.tv_usec;
|
||||||
|
+ if (ntx.status & STA_NANO)
|
||||||
|
+ ts->tv_nsec = ntx.time.tv_usec;
|
||||||
|
+ else
|
||||||
|
+ ts->tv_nsec = ntx.time.tv_usec * 1000;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
||||||
|
index 3a4267d..5b2e06b 100644
|
||||||
|
--- a/ts2phc_nmea_pps_source.c
|
||||||
|
+++ b/ts2phc_nmea_pps_source.c
|
||||||
|
@@ -62,14 +62,13 @@ static int open_nmea_connection(const char *host, const char *port,
|
||||||
|
|
||||||
|
static void *monitor_nmea_status(void *arg)
|
||||||
|
{
|
||||||
|
+ struct timespec rxtime, rxtime_rt, tmo = { 2, 0 };
|
||||||
|
struct nmea_parser *np = nmea_parser_create();
|
||||||
|
struct pollfd pfd = { -1, POLLIN | POLLPRI };
|
||||||
|
char *host, input[256], *port, *ptr, *uart;
|
||||||
|
struct ts2phc_nmea_pps_source *s = arg;
|
||||||
|
- struct timespec rxtime, tmo = { 2, 0 };
|
||||||
|
int cnt, num, parsed, baud;
|
||||||
|
struct nmea_rmc rmc;
|
||||||
|
- struct timex ntx;
|
||||||
|
|
||||||
|
if (!np) {
|
||||||
|
pr_err("failed to create NMEA parser");
|
||||||
|
@@ -79,8 +78,6 @@ static void *monitor_nmea_status(void *arg)
|
||||||
|
port = config_get_string(s->config, NULL, "ts2phc.nmea_remote_port");
|
||||||
|
uart = config_get_string(s->config, NULL, "ts2phc.nmea_serialport");
|
||||||
|
baud = config_get_int(s->config, NULL, "ts2phc.nmea_baudrate");
|
||||||
|
- memset(&ntx, 0, sizeof(ntx));
|
||||||
|
- ntx.modes = ADJ_NANO;
|
||||||
|
|
||||||
|
while (is_running()) {
|
||||||
|
if (pfd.fd == -1) {
|
||||||
|
@@ -92,7 +89,7 @@ static void *monitor_nmea_status(void *arg)
|
||||||
|
}
|
||||||
|
num = poll(&pfd, 1, NMEA_TMO);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &rxtime);
|
||||||
|
- adjtimex(&ntx);
|
||||||
|
+ clock_gettime(CLOCK_REALTIME, &rxtime_rt);
|
||||||
|
if (num < 0) {
|
||||||
|
pr_err("poll failed");
|
||||||
|
break;
|
||||||
|
@@ -124,8 +121,7 @@ static void *monitor_nmea_status(void *arg)
|
||||||
|
if (!nmea_parse(np, ptr, cnt, &rmc, &parsed)) {
|
||||||
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
s->local_monotime = rxtime;
|
||||||
|
- s->local_utctime.tv_sec = ntx.time.tv_sec;
|
||||||
|
- s->local_utctime.tv_nsec = ntx.time.tv_usec;
|
||||||
|
+ s->local_utctime = rxtime_rt;
|
||||||
|
s->rmc_utctime = rmc.ts;
|
||||||
|
s->rmc_fix_valid = rmc.fix_valid;
|
||||||
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
|
commit 72b44bc885e519667a12c89d5b640484807e4946
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Jun 4 08:57:15 2024 +0200
|
||||||
|
|
||||||
|
ts2phc: Use CLOCK_MONOTONIC_RAW for NMEA PPS timestamp.
|
||||||
|
|
||||||
|
In the calculation of the NMEA PPS timestamp is used an interval
|
||||||
|
measured by the CLOCK_MONOTONIC system clock. This clock may have a
|
||||||
|
large frequency error when another process (e.g. phc2sys or an NTP
|
||||||
|
client) is correcting a large time error by slewing.
|
||||||
|
|
||||||
|
This frequency error may cause the timestamp to overflow into the next
|
||||||
|
second and cause a one-second error in the measured offset, or the wrong
|
||||||
|
edge of the pulse to be rejected.
|
||||||
|
|
||||||
|
Switch from CLOCK_MONOTONIC to CLOCK_MONOTONIC_RAW to avoid the
|
||||||
|
impact of the system clock adjustments.
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
|
||||||
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
||||||
index 3a4267d..274b70a 100644
|
index 5b2e06b..7a28433 100644
|
||||||
--- a/ts2phc_nmea_pps_source.c
|
--- a/ts2phc_nmea_pps_source.c
|
||||||
+++ b/ts2phc_nmea_pps_source.c
|
+++ b/ts2phc_nmea_pps_source.c
|
||||||
@@ -191,6 +191,7 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
@@ -88,7 +88,7 @@ static void *monitor_nmea_status(void *arg)
|
||||||
return -1;
|
}
|
||||||
|
}
|
||||||
|
num = poll(&pfd, 1, NMEA_TMO);
|
||||||
|
- clock_gettime(CLOCK_MONOTONIC, &rxtime);
|
||||||
|
+ clock_gettime(CLOCK_MONOTONIC_RAW, &rxtime);
|
||||||
|
clock_gettime(CLOCK_REALTIME, &rxtime_rt);
|
||||||
|
if (num < 0) {
|
||||||
|
pr_err("poll failed");
|
||||||
|
@@ -160,7 +160,7 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||||
|
int64_t utc_time;
|
||||||
|
bool fix_valid;
|
||||||
|
|
||||||
|
- clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
+ clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||||
|
local_t2 = timespec_to_tmv(now);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&m->mutex);
|
||||||
|
|
||||||
|
commit 30e6c4dba892236d8cfe08dc6c55238e11504c71
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Mon Jun 3 10:32:05 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>
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
rmc = tmv_add(rmc, duration_since_rmc);
|
+ if (src)
|
||||||
+ rmc = tmv_add(rmc, nanoseconds_to_tmv(500000000));
|
+ src->type = type;
|
||||||
utc_time = tmv_to_nanoseconds(rmc);
|
return src;
|
||||||
utc_time /= (int64_t) 1000000000;
|
}
|
||||||
*ts = tmv_to_timespec(rmc);
|
|
||||||
|
@@ -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 bebd15ae90dbfcb74a33e5b428f24c733abf1134
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Mon Jun 3 11:06:16 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>
|
||||||
|
|
||||||
|
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||||
|
index 05ac225..ca9f721 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 435e9fc6ebec8daa8ab9f88c2d590e35ace9b2f6
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Mon Jun 3 13:57:23 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>
|
||||||
|
|
||||||
|
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
|
||||||
|
index ca9f721..8121afb 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) {
|
||||||
|
@@ -243,12 +239,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 0257b245df1a32869f356c0cfbeacfe5f0a522f5
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Mon Jun 3 11:31:45 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>
|
||||||
|
|
||||||
|
diff --git a/ts2phc.c b/ts2phc.c
|
||||||
|
index 03c88b1..4817c85 100644
|
||||||
|
--- a/ts2phc.c
|
||||||
|
+++ b/ts2phc.c
|
||||||
|
@@ -418,9 +418,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 8121afb..0d399b8 100644
|
||||||
|
--- a/ts2phc_pps_sink.c
|
||||||
|
+++ b/ts2phc_pps_sink.c
|
||||||
|
@@ -244,8 +244,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;
|
||||||
|
83
SOURCES/linuxptp-nmeadelay2.patch
Normal file
83
SOURCES/linuxptp-nmeadelay2.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
commit 0d508d8cfb96cc32d3516f1d0d3e80db49f00468
|
||||||
|
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. ]
|
||||||
|
|
||||||
|
(Rebased to 4.2)
|
||||||
|
|
||||||
|
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 58481db..d441d1e 100644
|
||||||
|
--- a/config.c
|
||||||
|
+++ b/config.c
|
||||||
|
@@ -347,6 +347,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 c0b718b..b8383ff 100644
|
||||||
|
--- a/ts2phc.8
|
||||||
|
+++ b/ts2phc.8
|
||||||
|
@@ -262,6 +262,16 @@ by changing the clock frequency instead of stepping the clock. When
|
||||||
|
set to 0.0, the servo will never step the clock except on start.
|
||||||
|
The default is 0.0.
|
||||||
|
|
||||||
|
+.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 bdfaf19..e345969 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;
|
||||||
|
@@ -207,6 +208,7 @@ static int ts2phc_nmea_pps_source_getppstime(struct ts2phc_pps_source *src,
|
||||||
|
}
|
||||||
|
|
||||||
|
rmc = tmv_add(rmc, duration_since_rmc);
|
||||||
|
+ rmc = tmv_add(rmc, m->delay_correction);
|
||||||
|
*ts = tmv_to_timespec(rmc);
|
||||||
|
ts->tv_sec += tai_offset;
|
||||||
|
|
||||||
|
@@ -234,6 +236,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) {
|
76
SOURCES/linuxptp-nmealeap.patch
Normal file
76
SOURCES/linuxptp-nmealeap.patch
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
commit f3c742e24a40cf75272ec39789a2cba35389230d
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Jun 11 15:25:54 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>
|
||||||
|
|
||||||
|
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 b396d361b0d290ce83395851860c2dcd074e0f3b
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Jun 11 15:32:55 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>
|
||||||
|
|
||||||
|
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
|
||||||
|
index 7a28433..bdfaf19 100644
|
||||||
|
--- a/ts2phc_nmea_pps_source.c
|
||||||
|
+++ b/ts2phc_nmea_pps_source.c
|
||||||
|
@@ -186,10 +186,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);
|
||||||
|
+
|
||||||
|
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) {
|
||||||
|
@@ -206,6 +205,9 @@ 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);
|
||||||
|
+ *ts = tmv_to_timespec(rmc);
|
||||||
|
ts->tv_sec += tai_offset;
|
||||||
|
|
||||||
|
return lstab_error;
|
25
SOURCES/linuxptp-nmeareset.patch
Normal file
25
SOURCES/linuxptp-nmeareset.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
commit b4ad9dccf23cef2d79621cd36987428a65f2bcc9
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Jun 11 12:35:10 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>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
73
SOURCES/linuxptp-nowait.patch
Normal file
73
SOURCES/linuxptp-nowait.patch
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
commit e3867eb1ce2282f9ac4cc729a3b1beb74bb017d6
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Tue Nov 26 15:10:34 2024 +0100
|
||||||
|
|
||||||
|
phc2sys: Don't require -O option without -a and -w.
|
||||||
|
|
||||||
|
Allow phc2sys to be started in the static mode without the -O option,
|
||||||
|
meaning it should fetch the UTC offset from ptp4l, even if the -w option
|
||||||
|
is not included on the command line to wait for ptp4l to have a port in
|
||||||
|
the master or slave state.
|
||||||
|
|
||||||
|
This is useful when the PHC is synchronized by ts2phc or other
|
||||||
|
application and the system clock needs to be synchronized to the PHC
|
||||||
|
even when ptp4l has all ports in the faulty state (e.g. all network
|
||||||
|
links are down).
|
||||||
|
|
||||||
|
It's the responsibility of the user to start phc2sys when ptp4l is
|
||||||
|
already running. phc2sys will exit with an error message if it cannot
|
||||||
|
get a response with the 1-second timeout.
|
||||||
|
|
||||||
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/phc2sys.8 b/phc2sys.8
|
||||||
|
index df0608a..5ca467d 100644
|
||||||
|
--- a/phc2sys.8
|
||||||
|
+++ b/phc2sys.8
|
||||||
|
@@ -161,7 +161,10 @@ minimize the error caused by random delays in scheduling and bus utilization.
|
||||||
|
The default is 5.
|
||||||
|
.TP
|
||||||
|
.BI \-O " offset"
|
||||||
|
-Specify the offset between the sink and source times in seconds. Not
|
||||||
|
+Specify the offset between the sink and source times in seconds. If not
|
||||||
|
+specified, the offset will be set according to the currentUtcOffset value
|
||||||
|
+obtained from ptp4l and the direction of synchronization, assuming the system
|
||||||
|
+clock is keeping time in UTC and all used PHCs keep time in TAI. Not
|
||||||
|
compatible with the
|
||||||
|
.B \-a
|
||||||
|
option. See
|
||||||
|
diff --git a/phc2sys.c b/phc2sys.c
|
||||||
|
index 1745558..d8b0991 100644
|
||||||
|
--- a/phc2sys.c
|
||||||
|
+++ b/phc2sys.c
|
||||||
|
@@ -1406,12 +1406,6 @@ int main(int argc, char *argv[])
|
||||||
|
goto bad_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!autocfg && !wait_sync && !settings.forced_sync_offset) {
|
||||||
|
- fprintf(stderr,
|
||||||
|
- "time offset must be specified using -w or -O\n");
|
||||||
|
- goto bad_usage;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (hardpps_configured(pps_fd) && (dst_cnt != 1 ||
|
||||||
|
strcmp(dst_names[0], "CLOCK_REALTIME"))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
@@ -1501,7 +1495,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
|
r = -1;
|
||||||
|
|
||||||
|
- if (wait_sync) {
|
||||||
|
+ if (wait_sync || !domains[0].forced_sync_offset) {
|
||||||
|
snprintf(uds_local, sizeof(uds_local),
|
||||||
|
"/var/run/phc2sys.%d", getpid());
|
||||||
|
|
||||||
|
@@ -1516,7 +1510,7 @@ int main(int argc, char *argv[])
|
||||||
|
phc2sys_recv_subscribed, &domains[0]))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
- while (is_running()) {
|
||||||
|
+ while (wait_sync && is_running()) {
|
||||||
|
r = run_pmc_wait_sync(domains[0].agent, 1000);
|
||||||
|
if (r < 0)
|
||||||
|
goto end;
|
57
SOURCES/linuxptp-vclock.patch
Normal file
57
SOURCES/linuxptp-vclock.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
commit b2ceafdd8e4cde6c0cef67373006049b12f45c4a
|
||||||
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
|
Date: Thu Apr 28 14:23:57 2022 +0200
|
||||||
|
|
||||||
|
timemaster: Check for RH-specific kernel with vclock support.
|
||||||
|
|
||||||
|
diff --git a/timemaster.8 b/timemaster.8
|
||||||
|
index bc0b5b6..50699d6 100644
|
||||||
|
--- a/timemaster.8
|
||||||
|
+++ b/timemaster.8
|
||||||
|
@@ -104,7 +104,7 @@ Enable or disable synchronization with virtual clocks. If enabled,
|
||||||
|
needed by configured PTP domains. This enables hardware time stamping for
|
||||||
|
multiple \fBptp4l\fR instances using the same network interface. The default
|
||||||
|
value is -1, which enables the virtual clocks if running on Linux 5.18 or
|
||||||
|
-later.
|
||||||
|
+later, or the EL9-specific kernel-5.14.0-106 or later release.
|
||||||
|
|
||||||
|
.SS [ntp_server address]
|
||||||
|
|
||||||
|
diff --git a/timemaster.c b/timemaster.c
|
||||||
|
index fab71fc..05f0af4 100644
|
||||||
|
--- a/timemaster.c
|
||||||
|
+++ b/timemaster.c
|
||||||
|
@@ -546,6 +546,23 @@ static int check_kernel_version(int version, int patch)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int check_rh_kernel_version(const char *el, int version, int patch,
|
||||||
|
+ int sub, int release)
|
||||||
|
+{
|
||||||
|
+ struct utsname uts;
|
||||||
|
+ int v, p, sp, r;
|
||||||
|
+
|
||||||
|
+ if (uname(&uts) < 0)
|
||||||
|
+ return 1;
|
||||||
|
+ if (!strstr(uts.release, el))
|
||||||
|
+ return 1;
|
||||||
|
+ if (sscanf(uts.release, "%d.%d.%d-%d", &v, &p, &sp, &r) < 4)
|
||||||
|
+ return 1;
|
||||||
|
+ if (version != v || patch != p || sub != sp || release > r)
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct timemaster_config *config_parse(char *path)
|
||||||
|
{
|
||||||
|
struct timemaster_config *config = xcalloc(1, sizeof(*config));
|
||||||
|
@@ -621,7 +638,8 @@ static struct timemaster_config *config_parse(char *path)
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (config->use_vclocks < 0)
|
||||||
|
- config->use_vclocks = !check_kernel_version(5, 18);
|
||||||
|
+ config->use_vclocks = !check_kernel_version(5, 18) ||
|
||||||
|
+ !check_rh_kernel_version(".el9.", 5, 14, 0, 106);
|
||||||
|
|
||||||
|
if (section_name)
|
||||||
|
free(section_name);
|
14
SOURCES/ptp4l.conf
Normal file
14
SOURCES/ptp4l.conf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# For more information about this file, see the ptp4l(8) man page.
|
||||||
|
# Examples are available in /usr/share/doc/linuxptp/configs.
|
||||||
|
|
||||||
|
[global]
|
||||||
|
domainNumber 0
|
||||||
|
slaveOnly 1
|
||||||
|
time_stamping hardware
|
||||||
|
tx_timestamp_timeout 1
|
||||||
|
logging_level 6
|
||||||
|
summary_interval 0
|
||||||
|
|
||||||
|
[eth0]
|
||||||
|
network_transport UDPv4
|
||||||
|
hybrid_e2e 0
|
@ -14,18 +14,11 @@ ntp_program chronyd
|
|||||||
[chrony.conf]
|
[chrony.conf]
|
||||||
include /etc/chrony.conf
|
include /etc/chrony.conf
|
||||||
|
|
||||||
[ntp.conf]
|
|
||||||
includefile /etc/ntp.conf
|
|
||||||
|
|
||||||
[ptp4l.conf]
|
[ptp4l.conf]
|
||||||
|
|
||||||
[chronyd]
|
[chronyd]
|
||||||
path /usr/sbin/chronyd
|
path /usr/sbin/chronyd
|
||||||
|
|
||||||
[ntpd]
|
|
||||||
path /usr/sbin/ntpd
|
|
||||||
options -u ntp:ntp -g
|
|
||||||
|
|
||||||
[phc2sys]
|
[phc2sys]
|
||||||
path /usr/sbin/phc2sys
|
path /usr/sbin/phc2sys
|
||||||
|
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
Name: linuxptp
|
Name: linuxptp
|
||||||
Version: 4.2
|
Version: 4.2
|
||||||
Release: 1%{?dist}
|
Release: 3%{?dist}.1
|
||||||
Summary: PTP implementation for Linux
|
Summary: PTP implementation for Linux
|
||||||
|
|
||||||
Group: System Environment/Base
|
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: http://linuxptp.sourceforge.net/
|
URL: http://linuxptp.sourceforge.net/
|
||||||
|
|
||||||
@ -16,6 +15,7 @@ Source1: phc2sys.service
|
|||||||
Source2: ptp4l.service
|
Source2: ptp4l.service
|
||||||
Source3: timemaster.service
|
Source3: timemaster.service
|
||||||
Source4: timemaster.conf
|
Source4: timemaster.conf
|
||||||
|
Source5: ptp4l.conf
|
||||||
# external test suite
|
# external test suite
|
||||||
Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver}/linuxptp-testsuite-%{testsuite_ver}.tar.gz
|
Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver}/linuxptp-testsuite-%{testsuite_ver}.tar.gz
|
||||||
# simulator for test suite
|
# simulator for test suite
|
||||||
@ -33,9 +33,22 @@ Patch4: linuxptp-ucastrate.patch
|
|||||||
Patch5: linuxptp-nmeadelay.patch
|
Patch5: linuxptp-nmeadelay.patch
|
||||||
# fix loading and reloading of leapfile
|
# fix loading and reloading of leapfile
|
||||||
Patch6: linuxptp-lstab.patch
|
Patch6: linuxptp-lstab.patch
|
||||||
|
# fix ts2phc to correctly handle leap seconds
|
||||||
|
Patch7: linuxptp-nmealeap.patch
|
||||||
|
# fix ts2phc to reset NMEA parser after RMC message
|
||||||
|
Patch8: linuxptp-nmeareset.patch
|
||||||
|
# add options to configure multicast IP addresses
|
||||||
|
Patch9: linuxptp-addropts.patch
|
||||||
|
# add holdover support to ts2phc
|
||||||
|
Patch10: linuxptp-holdover.patch
|
||||||
|
# add option to ts2phc to specify minimum expected NMEA delay
|
||||||
|
Patch11: linuxptp-nmeadelay2.patch
|
||||||
|
# check for EL-specific kernels with vclock support
|
||||||
|
Patch12: linuxptp-vclock.patch
|
||||||
|
# don't require -O option without -a and -w in phc2sys
|
||||||
|
Patch13: linuxptp-nowait.patch
|
||||||
|
|
||||||
BuildRequires: kernel-headers > 4.18.0-87
|
BuildRequires: gcc gcc-c++ make systemd
|
||||||
BuildRequires: systemd
|
|
||||||
|
|
||||||
%{?systemd_requires}
|
%{?systemd_requires}
|
||||||
|
|
||||||
@ -53,7 +66,7 @@ mv linuxptp-testsuite-%{testsuite_ver}* testsuite
|
|||||||
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
|
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
|
||||||
|
|
||||||
%build
|
%build
|
||||||
make %{?_smp_mflags} \
|
%{make_build} \
|
||||||
EXTRA_CFLAGS="$RPM_OPT_FLAGS" \
|
EXTRA_CFLAGS="$RPM_OPT_FLAGS" \
|
||||||
EXTRA_LDFLAGS="$RPM_LD_FLAGS"
|
EXTRA_LDFLAGS="$RPM_LD_FLAGS"
|
||||||
|
|
||||||
@ -61,11 +74,10 @@ make %{?_smp_mflags} \
|
|||||||
%makeinstall
|
%makeinstall
|
||||||
|
|
||||||
mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/sysconfig,%{_unitdir},%{_mandir}/man5}
|
mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/sysconfig,%{_unitdir},%{_mandir}/man5}
|
||||||
install -m 644 -p configs/default.cfg $RPM_BUILD_ROOT%{_sysconfdir}/ptp4l.conf
|
|
||||||
install -m 644 -p %{SOURCE1} %{SOURCE2} %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir}
|
install -m 644 -p %{SOURCE1} %{SOURCE2} %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir}
|
||||||
install -m 644 -p %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}
|
install -m 644 -p %{SOURCE4} %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}
|
||||||
|
|
||||||
echo 'OPTIONS="-f /etc/ptp4l.conf -i eth0"' > \
|
echo 'OPTIONS="-f /etc/ptp4l.conf"' > \
|
||||||
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ptp4l
|
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ptp4l
|
||||||
echo 'OPTIONS="-a -r"' > $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/phc2sys
|
echo 'OPTIONS="-a -r"' > $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/phc2sys
|
||||||
|
|
||||||
@ -79,7 +91,7 @@ find configs -type f ! -name '*.cfg' -delete
|
|||||||
cd testsuite
|
cd testsuite
|
||||||
# set random seed to get deterministic results
|
# set random seed to get deterministic results
|
||||||
export CLKNETSIM_RANDOM_SEED=26743
|
export CLKNETSIM_RANDOM_SEED=26743
|
||||||
make %{?_smp_mflags} -C clknetsim
|
%{make_build} -C clknetsim
|
||||||
PATH=..:$PATH ./run
|
PATH=..:$PATH ./run
|
||||||
|
|
||||||
%post
|
%post
|
||||||
@ -113,58 +125,112 @@ PATH=..:$PATH ./run
|
|||||||
%{_mandir}/man8/*.8*
|
%{_mandir}/man8/*.8*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Feb 22 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
|
* Thu Jan 02 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.2-3.el9_5.1
|
||||||
- update to 4.2 (RHEL-21326 RHEL-21328 RHEL-21329)
|
- add option to ts2phc to specify minimum expected NMEA delay (RHEL-70168)
|
||||||
- fix ts2phc to handle large NMEA delay (RHEL-23278)
|
- don't require -O option without -a and -w in phc2sys (RHEL-70678)
|
||||||
|
|
||||||
|
* Thu Jul 25 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-3
|
||||||
|
- rework NMEA delay patch to fix PPS edge rejection (RHEL-39387)
|
||||||
|
- fix ts2phc to correctly handle leap seconds (RHEL-40216)
|
||||||
|
- fix ts2phc to reset NMEA parser after RMC message (RHEL-40947)
|
||||||
|
- add options to configure multicast IP addresses (RHEL-31178)
|
||||||
|
- add holdover support to ts2phc (RHEL-50216)
|
||||||
|
|
||||||
|
* Thu Feb 22 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-2
|
||||||
- fix loading and reloading of leapfile
|
- fix loading and reloading of leapfile
|
||||||
|
|
||||||
* Wed May 03 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-6
|
* Tue Jan 30 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
|
||||||
- clear pending errors on sockets (#2192560)
|
- update to 4.2 (RHEL-2026 RHEL-2342 RHEL-12182 RHEL-15929)
|
||||||
|
- fix ts2phc to handle large NMEA delay (RHEL-23208)
|
||||||
|
|
||||||
* Wed Apr 12 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-5
|
* Wed May 03 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-9
|
||||||
- handle EINTR when waiting for transmit timestamp (#2123224)
|
- clear pending errors on sockets (#2192559)
|
||||||
|
|
||||||
* Mon Mar 20 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-4
|
* Mon Mar 20 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-8
|
||||||
- don't re-arm fault clearing timer on unrelated netlink events (#2174900)
|
- don't switch from system clock to PHC with SW timestamping (#2179041)
|
||||||
|
|
||||||
* Wed Jun 29 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-3
|
* Thu Mar 09 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-7
|
||||||
- handle PHC read failing with EBUSY in phc2sys (#2079129)
|
- don't re-arm fault clearing timer on unrelated netlink events (#2172650)
|
||||||
|
|
||||||
* Mon Nov 01 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-2
|
* Thu Jan 05 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-6
|
||||||
- make sanity clock check more reliable (#2007281)
|
- add support for VLAN over bond (#2120521)
|
||||||
|
- handle EINTR when waiting for transmit timestamp (#2128786)
|
||||||
|
- check for unexpected changes in frequency offset (#2150815)
|
||||||
|
|
||||||
* Mon Jul 26 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-1
|
* Thu Jul 28 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-5
|
||||||
- update to 3.1.1 (#1895005 CVE-2021-3571)
|
- disable PHC switch with vclocks (#2066452)
|
||||||
- add read-only UDS port (#1929797)
|
|
||||||
- add option to set clockClass threshold (#1980386)
|
|
||||||
- don't repeat some log messages in multi-port configuration (#1980377)
|
|
||||||
- increase default TX timestamp timeout to 10 ms (#1977136)
|
|
||||||
|
|
||||||
* Thu Jun 24 2021 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5.el8_4.1
|
* Thu Jun 30 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-4
|
||||||
- validate length of forwarded messages (CVE-2021-3570)
|
- handle PHC read failing with EBUSY in phc2sys (#2102568)
|
||||||
|
|
||||||
* Mon Apr 27 2020 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5
|
* Thu Jun 09 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-3
|
||||||
- fix sample timestamps when synchronizing PHC to system clock (#1787376)
|
- add support for virtual clocks (#2067310)
|
||||||
- fix handling of zero-length messages (#1827275)
|
- make sanity clock check more reliable (#2079893)
|
||||||
|
|
||||||
* Thu May 16 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-4
|
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 3.1.1-2
|
||||||
- rebuild with enabled gating (#1680888)
|
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
|
||||||
|
Related: rhbz#1991688
|
||||||
|
|
||||||
* Wed May 15 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-3
|
* Mon Aug 02 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-1
|
||||||
- add support for active-backup team interface (#1685467)
|
- update to 3.1.1 (#1979954 CVE-2021-3570 CVE-2021-3571)
|
||||||
- add support for more accurate synchronization to phc2sys (#1677217)
|
- add read-only UDS port
|
||||||
- add hwts_filter option to ptp4l (#1708554)
|
- add option to set clockClass threshold
|
||||||
- limit unicast message rate per address and grant duration (#1707395)
|
- don't repeat some log messages in multi-port configuration
|
||||||
- fix comparing of unicast addresses (#1707395)
|
- increase default TX timestamp timeout to 10 ms
|
||||||
- fix building with new kernel headers (#1707395)
|
- limit unicast message rate per address and grant duration
|
||||||
- update testsuite (#1707395)
|
|
||||||
- don't leak memory when allocation fails (#1707395)
|
* Tue Jun 22 2021 Mohan Boddu <mboddu@redhat.com> - 3.1-5
|
||||||
|
- Rebuilt for RHEL 9 BETA for openssl 3.0
|
||||||
|
Related: rhbz#1971065
|
||||||
|
|
||||||
|
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.1-4
|
||||||
|
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
||||||
|
|
||||||
|
* Thu Feb 25 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1-3
|
||||||
|
- fix handling of zero-length messages
|
||||||
|
- minimize default configuration
|
||||||
|
- remove obsolete build requirement
|
||||||
|
|
||||||
|
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.1-2
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||||
|
|
||||||
|
* Tue Sep 29 2020 Miroslav Lichvar <mlichvar@redhat.com> 3.1-1
|
||||||
|
- update to 3.1
|
||||||
|
|
||||||
|
* Mon Jul 27 2020 Miroslav Lichvar <mlichvar@redhat.com> 3.0-1
|
||||||
|
- update to 3.0
|
||||||
|
|
||||||
|
* Mon Feb 03 2020 Miroslav Lichvar <mlichvar@redhat.com> 2.0-7.20191225gite05809
|
||||||
|
- update to 20191225gite05809
|
||||||
|
- fix testing with new glibc
|
||||||
|
|
||||||
|
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-6.20190912git48e605
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||||
|
|
||||||
|
* Wed Sep 25 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5.20190912git48e605
|
||||||
|
- update to 20190912git48e605
|
||||||
|
|
||||||
|
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-4
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||||
|
|
||||||
|
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-3
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||||
|
|
||||||
* Tue Nov 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-2
|
* Tue Nov 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-2
|
||||||
- start ptp4l, timemaster and phc2sys after network-online target (#1632282)
|
- start ptp4l, timemaster and phc2sys after network-online target
|
||||||
|
- fix building with new kernel headers
|
||||||
|
|
||||||
* Mon Aug 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-1
|
* Mon Aug 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-1
|
||||||
- update to 2.0 (#1614300)
|
- update to 2.0
|
||||||
|
|
||||||
|
* Thu Aug 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-0.1.20180805gita27407
|
||||||
|
- update to 20180805gita27407
|
||||||
|
|
||||||
|
* Mon Jul 16 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-3
|
||||||
|
- add gcc and gcc-c++ to build requirements
|
||||||
|
|
||||||
|
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.9.2-2
|
||||||
|
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||||
|
|
||||||
* Mon Apr 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-1
|
* Mon Apr 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-1
|
||||||
- update to 1.9.2
|
- update to 1.9.2
|
||||||
|
Loading…
Reference in New Issue
Block a user