Compare commits

...

6 Commits

Author SHA1 Message Date
Miroslav Lichvar 85e049cbcb 4.2-2 2024-02-23 02:57:31 +00:00
Miroslav Lichvar 26eba209f4 fix loading and reloading of leapfile
Related: RHEL-2026
2024-02-22 14:59:18 +01:00
Miroslav Lichvar 0ea9492c8c 4.2-1
Related: RHEL-2026 RHEL-2342 RHEL-12182 RHEL-15929 RHEL-23208
2024-01-30 10:22:40 +01:00
Miroslav Lichvar a5f9f599a2 fix ts2phc to handle large NMEA delay (RHEL-23208)
Resolves: RHEL-23208
2024-01-30 10:21:38 +01:00
Miroslav Lichvar 2c55db4376 update to 4.2 (RHEL-2026 RHEL-2342 RHEL-12182 RHEL-15929)
Resolves: RHEL-2026 RHEL-2342 RHEL-12182 RHEL-15929
2024-01-11 14:10:48 +01:00
Miroslav Lichvar 83b608bdaa 3.1.1-9
Related: #2192559
2023-05-03 16:18:10 +02:00
25 changed files with 252 additions and 4181 deletions

6
.gitignore vendored
View File

@ -1,3 +1,3 @@
/linuxptp-3.1.1.tgz
/linuxptp-testsuite-c66922.tar.gz
/clknetsim-c63e22.tar.gz
/linuxptp-4.2.tgz
/linuxptp-testsuite-bf8ead.tar.gz
/clknetsim-5d1dc0.tar.gz

3
.linuxptp.metadata Normal file
View File

@ -0,0 +1,3 @@
309e6ab1fa3f61b3deb1735c3082dc2070870be1 linuxptp-4.2.tgz
7594d0705a1a648d5f7380d476bb3afebff21f6c linuxptp-testsuite-bf8ead.tar.gz
3ae72eb0ddafd8d8aeea7eac382d6e4a958717ef clknetsim-5d1dc0.tar.gz

View File

@ -1,138 +0,0 @@
Backported commit f774703cb1eee058a346aec3341fee0be329bd6d
Author: Karthikkumar V <kvaloor@altiostar.com>
Date: Fri Feb 26 06:54:07 2021 +0000
Clock Class Threshold Feature addition for PTP4L
This code changes brings in the ability to program the acceptable
clockClass threshold beyond which device will move to holdover/free-run.
Default clockClass threshold is 248.
Example Use-Case:
This is needed in the cases where T-SC/T-BC Slave might want to listen
only on PRC clockCLass and anything beyond that might not be acceptible
and would want to go to holdover (with SyncE backup or internal oscillator).
Signed-off-by: Karthikkumar V <kvaloor@altiostar.com>
Signed-off-by: Ramana Reddy <rreddy@altiostar.com>
diff --git a/clock.c b/clock.c
index c1fcff6..d584748 100644
--- a/clock.c
+++ b/clock.c
@@ -114,6 +114,7 @@ struct clock {
int utc_offset;
int time_flags; /* grand master role */
int time_source; /* grand master role */
+ UInteger8 clock_class_threshold;
UInteger8 max_steps_removed;
enum servo_state servo_state;
enum timestamp_type timestamping;
@@ -978,6 +979,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
c->default_dataset.localPriority =
config_get_int(config, NULL, "G.8275.defaultDS.localPriority");
c->max_steps_removed = config_get_int(config, NULL,"maxStepsRemoved");
+ c->clock_class_threshold = config_get_int(config, NULL, "clock_class_threshold");
/* Harmonize the twoStepFlag with the time_stamping option. */
if (config_harmonize_onestep(config)) {
@@ -1711,6 +1713,11 @@ UInteger8 clock_max_steps_removed(struct clock *c)
return c->max_steps_removed;
}
+UInteger8 clock_get_clock_class_threshold(struct clock *c)
+{
+ return c->clock_class_threshold;
+}
+
UInteger16 clock_steps_removed(struct clock *c)
{
return c->cur.stepsRemoved;
diff --git a/clock.h b/clock.h
index e7daf97..845d54f 100644
--- a/clock.h
+++ b/clock.h
@@ -289,6 +289,13 @@ int clock_slave_only(struct clock *c);
*/
UInteger8 clock_max_steps_removed(struct clock *c);
+/**
+ * Obtain the clock class threshold field from a clock's default data set.
+ * @param c The clock instance.
+ * @return Configured clock class threshold value.
+ */
+UInteger8 clock_get_clock_class_threshold(struct clock *c);
+
/**
* Obtain the steps removed field from a clock's current data set.
* @param c The clock instance.
diff --git a/config.c b/config.c
index c3deddb..bf1049f 100644
--- a/config.c
+++ b/config.c
@@ -231,6 +231,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX),
GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX),
GLOB_ITEM_STR("clockIdentity", "000000.0000.000000"),
+ GLOB_ITEM_INT("clock_class_threshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 6, CLOCK_CLASS_THRESHOLD_DEFAULT),
GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu),
GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu),
GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu),
diff --git a/configs/default.cfg b/configs/default.cfg
index 9604219..b2ffa94 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -60,6 +60,7 @@ verbose 0
summary_interval 0
kernel_leap 1
check_fup_sync 0
+clock_class_threshold 248
#
# Servo Options
#
diff --git a/ds.h b/ds.h
index 9d9c417..dff6d5e 100644
--- a/ds.h
+++ b/ds.h
@@ -87,6 +87,7 @@ struct parent_ds {
#define CURRENT_UTC_OFFSET 37 /* 1 Jan 2017 */
#define INTERNAL_OSCILLATOR 0xA0
+#define CLOCK_CLASS_THRESHOLD_DEFAULT 248
struct timePropertiesDS {
Integer16 currentUtcOffset;
diff --git a/port.c b/port.c
index 2bb974c..eb3b319 100644
--- a/port.c
+++ b/port.c
@@ -1870,6 +1870,14 @@ int process_announce(struct port *p, struct ptp_message *m)
return result;
}
+ if (m->announce.grandmasterClockQuality.clockClass >
+ clock_get_clock_class_threshold(p->clock)) {
+ pl_err(60, "port %hu: Master clock quality received is "
+ "greater than configured, ignoring master!",
+ portnum(p));
+ return result;
+ }
+
switch (p->state) {
case PS_INITIALIZING:
case PS_FAULTY:
diff --git a/ptp4l.8 b/ptp4l.8
index b04936a..ca76175 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -455,6 +455,11 @@ message is greater than or equal to the value of maxStepsRemoved the
Announce message is not considered in the operation of the BMCA.
The default value is 255.
.TP
+.B clock_class_threshold
+The maximum clock class value from master, acceptible to sub-ordinate
+clock beyond which it moves out of lock state.
+The default value is 248.
+.TP
.B domainNumber
The domain attribute of the local clock.

View File

@ -1,187 +0,0 @@
commit 7e8eba5332671abfd95d06dd191059eded1d2cca
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon May 31 11:07:52 2021 +0200
clock: Reset state when switching port with same best clock.
When the best port is changed, but the ID of the best clock doesn't
change (e.g. a passive port is activated on link failure), reset the
current delay and other master/link-specific state to avoid the switch
throwing the clock off.
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index d428ae2..f14006f 100644
--- a/clock.c
+++ b/clock.c
@@ -1940,7 +1940,7 @@ static void handle_state_decision_event(struct clock *c)
best_id = c->dds.clockIdentity;
}
- if (!cid_eq(&best_id, &c->best_id)) {
+ if (!cid_eq(&best_id, &c->best_id) || best != c->best) {
clock_freq_est_reset(c);
tsproc_reset(c->tsproc, 1);
if (!tmv_is_zero(c->initial_delay))
commit 262a49b07eaccc0f0237e3cd4df01b185b8f664f
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon May 31 11:07:53 2021 +0200
clock: Reset clock check on best clock/port change.
Reset the clock check when the best clock or port changes, together with
the other state like current estimated delay and frequency. This avoids
false positives if the clock is controlled by an external process when
not synchronized by PTP (e.g. phc2sys -rr).
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index f14006f..7d0f985 100644
--- a/clock.c
+++ b/clock.c
@@ -1942,6 +1942,8 @@ static void handle_state_decision_event(struct clock *c)
if (!cid_eq(&best_id, &c->best_id) || best != c->best) {
clock_freq_est_reset(c);
+ if (c->sanity_check)
+ clockcheck_reset(c->sanity_check);
tsproc_reset(c->tsproc, 1);
if (!tmv_is_zero(c->initial_delay))
tsproc_set_delay(c->tsproc, c->initial_delay);
diff --git a/clockcheck.c b/clockcheck.c
index d48a578..d0b4714 100644
--- a/clockcheck.c
+++ b/clockcheck.c
@@ -47,9 +47,16 @@ struct clockcheck *clockcheck_create(int freq_limit)
if (!cc)
return NULL;
cc->freq_limit = freq_limit;
+ clockcheck_reset(cc);
+ return cc;
+}
+
+void clockcheck_reset(struct clockcheck *cc)
+{
+ cc->freq_known = 0;
cc->max_freq = -CHECK_MAX_FREQ;
cc->min_freq = CHECK_MAX_FREQ;
- return cc;
+ cc->last_ts = 0;
}
int clockcheck_sample(struct clockcheck *cc, uint64_t ts)
diff --git a/clockcheck.h b/clockcheck.h
index 78aca48..1ff86eb 100644
--- a/clockcheck.h
+++ b/clockcheck.h
@@ -33,6 +33,12 @@ struct clockcheck;
*/
struct clockcheck *clockcheck_create(int freq_limit);
+/**
+ * Reset a clock check.
+ * @param cc Pointer to a clock check obtained via @ref clockcheck_create().
+ */
+void clockcheck_reset(struct clockcheck *cc);
+
/**
* Perform the sanity check on a time stamp.
* @param cc Pointer to a clock check obtained via @ref clockcheck_create().
commit e117e37e379556fa23337db2518bb44d8793e039
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon May 31 11:07:54 2021 +0200
port: Don't check timestamps from non-slave ports.
Don't perform the sanity check on receive timestamps from ports in
non-slave states to avoid false positives in the jbod mode, where
the timestamps can be generated by different clocks.
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/port.c b/port.c
index b5b775f..ec5c92e 100644
--- a/port.c
+++ b/port.c
@@ -2749,7 +2749,10 @@ static enum fsm_event bc_event(struct port *p, int fd_index)
}
if (msg_sots_valid(msg)) {
ts_add(&msg->hwts.ts, -p->rx_timestamp_offset);
- clock_check_ts(p->clock, tmv_to_nanoseconds(msg->hwts.ts));
+ if (p->state == PS_SLAVE) {
+ clock_check_ts(p->clock,
+ tmv_to_nanoseconds(msg->hwts.ts));
+ }
}
switch (msg_type(msg)) {
commit 6df84259647757bc53818a039734f8ff85618c02
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon May 31 11:07:55 2021 +0200
port: Don't renew raw transport.
Renewing of the transport on announce/sync timeout is needed in the
client-only mode to avoid getting stuck with a broken multicast socket
when the link goes down.
This shouldn't be necessary with the raw transport. Closing and binding
of raw sockets can apparently be so slow that it triggers a false
positive in the clock check.
Reported-by: Amar Subramanyam <asubramanyam@altiostar.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/port.c b/port.c
index ec5c92e..c057591 100644
--- a/port.c
+++ b/port.c
@@ -1811,6 +1811,12 @@ static int port_renew_transport(struct port *p)
if (!port_is_enabled(p)) {
return 0;
}
+
+ /* Closing and binding of raw sockets is too slow and unnecessary */
+ if (transport_type(p->trp) == TRANS_IEEE_802_3) {
+ return 0;
+ }
+
transport_close(p->trp, &p->fda);
port_clear_fda(p, FD_FIRST_TIMER);
res = transport_open(p->trp, p->iface, &p->fda, p->timestamping);
commit a082bcd700e4955ebaa00d7039bf4bce92048ac4
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon May 31 11:07:56 2021 +0200
clockcheck: Increase minimum interval.
Increase the minimum check interval to 1 second to measure the frequency
offset more accurately and with default configuration make false
positives less likely due to a heavily overloaded system.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/clockcheck.c b/clockcheck.c
index d0b4714..f0141be 100644
--- a/clockcheck.c
+++ b/clockcheck.c
@@ -23,7 +23,7 @@
#include "clockcheck.h"
#include "print.h"
-#define CHECK_MIN_INTERVAL 100000000
+#define CHECK_MIN_INTERVAL 1000000000
#define CHECK_MAX_FREQ 900000000
struct clockcheck {

View File

@ -1,82 +0,0 @@
commit 1a2dfe9b00b79a59acf905476bbc33c74d5770a3
Author: Jacob Keller <jacob.e.keller@intel.com>
Date: Thu Jul 8 12:59:30 2021 -0700
Increase the default tx_timestamp_timeout to 10
The tx_timestamp_timeout configuration defines the number of
milliseconds to wait for a Tx timestamp from the kernel stack. This
delay is necessary as Tx timestamps are captured after a packet is sent
and reported back via the socket error queue.
The current default is to poll for up to 1 millisecond. In practice, it
turns out that this is not always enough time for hardware and software
to capture the timestamp and report it back. Some hardware designs
require reading timestamps over registers or other slow mechanisms.
This extra delay results in the timestamp not being sent back to
userspace within the default 1 millisecond polling time. If that occurs
the following can be seen from ptp4l:
ptp4l[4756.840]: timed out while polling for tx timestamp
ptp4l[4756.840]: increasing tx_timestamp_timeout may correct this issue,
but it is likely caused by a driver bug
ptp4l[4756.840]: port 1 (p2p1): send sync failed
ptp4l[4756.840]: port 1 (p2p1): MASTER to FAULTY on FAULT_DETECTED
(FT_UNSPECIFIED)
This can confuse users because it implies this is a bug, when the
correct solution in many cases is to just increase the timeout to
a slightly higher value.
Since we know this is a problem for many drivers and hardware designs,
lets increase the default timeout.
Note that a longer timeout should not affect setups which return the
timestamp quickly. On modern kernels, the poll() call will return once
the timestamp is reported back to the socket error queue. (On old
kernels around the 3.x era the poll will sleep for the full duration
before reporting the timestamp, but this is now quite an old kernel
release).
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/config.c b/config.c
index 760b395..03d981e 100644
--- a/config.c
+++ b/config.c
@@ -324,7 +324,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("ts2phc.pulsewidth", 500000000, 1000000, 999000000),
PORT_ITEM_ENU("tsproc_mode", TSPROC_FILTER, tsproc_enu),
GLOB_ITEM_INT("twoStepFlag", 1, 0, 1),
- GLOB_ITEM_INT("tx_timestamp_timeout", 1, 1, INT_MAX),
+ GLOB_ITEM_INT("tx_timestamp_timeout", 10, 1, INT_MAX),
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
diff --git a/configs/default.cfg b/configs/default.cfg
index 64ef3bd..d615610 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -51,7 +51,7 @@ hybrid_e2e 0
inhibit_multicast_service 0
net_sync_monitor 0
tc_spanning_tree 0
-tx_timestamp_timeout 1
+tx_timestamp_timeout 10
unicast_listen 0
unicast_master_table 0
unicast_req_duration 3600
diff --git a/ptp4l.8 b/ptp4l.8
index fe9e150..7ca3474 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -496,7 +496,7 @@ switches all implement this option together with the BMCA.
.B tx_timestamp_timeout
The number of milliseconds to poll waiting for the tx time stamp from the kernel
when a message has recently been sent.
-The default is 1.
+The default is 10.
.TP
.B check_fup_sync
Because of packet reordering that can occur in the network, in the

23
linuxptp-deprecated.patch Normal file
View File

@ -0,0 +1,23 @@
commit 99603cf0ab2413d59ae91101429b18d9ced6f88f
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 11 11:29:34 2024 +0100
config: Disable warnings about deprecated options.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/config.c b/config.c
index ad675c8..398b420 100644
--- a/config.c
+++ b/config.c
@@ -750,8 +750,10 @@ static void check_deprecated_options(const char **option)
}
if (new_option) {
+#if 0
fprintf(stderr, "option %s is deprecated, please use %s instead\n",
*option, new_option);
+#endif
*option = new_option;
}
}

View File

@ -1,30 +0,0 @@
commit c8de9f33e437fb15cff32c0028f651d7cb916a37
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Sep 13 13:44:10 2022 +0200
sk: Handle EINTR when waiting for transmit timestamp.
If ptp4l received a signal in poll() waiting for a transmit timestamp,
multiple (possibly confusing) error messages are logged before exit.
If poll() returns with EINTR, call it once again to get the timestamp
and avoid logging the errors. Don't call it in a loop to avoid getting
stuck in case the timestamp is lost and the signal is repeated before
the poll timeout can be reached.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/sk.c b/sk.c
index 80075be..d27abff 100644
--- a/sk.c
+++ b/sk.c
@@ -354,6 +354,9 @@ int sk_receive(int fd, void *buf, int buflen,
if (flags == MSG_ERRQUEUE) {
struct pollfd pfd = { fd, sk_events, 0 };
res = poll(&pfd, 1, sk_tx_timeout);
+ /* Retry once on EINTR to avoid logging errors before exit */
+ if (res < 0 && errno == EINTR)
+ res = poll(&pfd, 1, sk_tx_timeout);
if (res < 1) {
pr_err(res ? "poll for tx timestamp failed: %m" :
"timed out while polling for tx timestamp");

View File

@ -1,52 +0,0 @@
commit 134dc3c4655fcd9f314a5e56cd50db2f87366f5a
Author: davidjm via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net>
Date: Wed Nov 23 15:50:30 2022 -0800
Don't re-arm fault clearing timer on unrelated netlink events
Set the timer only when an event causes the port to transition to the
FAULTY state, rather than potentially re-arming the timeout when an
event occurs while the port was already FAULTY.
Concretely this occurs when a port is in fault, perhaps due to a
single time out while polling for tx-timestamp. If any other port in the
system (including unrelated ones ptp4l does not even know about) cause
netlink messages to be sent. As it stands, clock_poll() will note that
the port is in fault (from before, not due to the current event) and
reset the timeout to its original value.
If such unrelated netlink messages arrive at a regular enough cadence
the timeout may be repeatedly reset, not trigger on time (if at all) and
the port may not get a chance to clear its fault, perhaps indefinitely.
Signed-off-by: David Mirabito <davidjm@arista.com>
diff --git a/clock.c b/clock.c
index eea7983..451473e 100644
--- a/clock.c
+++ b/clock.c
@@ -1586,6 +1586,7 @@ void clock_set_sde(struct clock *c, int sde)
int clock_poll(struct clock *c)
{
int cnt, i;
+ enum port_state prior_state;
enum fsm_event event;
struct pollfd *cur;
struct port *p;
@@ -1609,6 +1610,7 @@ int clock_poll(struct clock *c)
/* Let the ports handle their events. */
for (i = 0; i < N_POLLFD; i++) {
if (cur[i].revents & (POLLIN|POLLPRI|POLLERR)) {
+ prior_state = port_state(p);
if (cur[i].revents & POLLERR) {
pr_err("port %d: unexpected socket error",
port_number(p));
@@ -1624,7 +1626,7 @@ int clock_poll(struct clock *c)
}
port_dispatch(p, event, 0);
/* Clear any fault after a little while. */
- if (PS_FAULTY == port_state(p)) {
+ if ((PS_FAULTY == port_state(p)) && (prior_state != PS_FAULTY)) {
clock_fault_timeout(p, 1);
break;
}

View File

@ -1,22 +0,0 @@
commit e8a82d1b5be2d5bf9450a9acfe44e957b4867870
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Jul 20 11:41:35 2021 +0200
lstab: Close file after reading.
The lstab_read() function opens a file, but doesn't close it after use.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/lstab.c b/lstab.c
index e6e7ad2..0d6a427 100644
--- a/lstab.c
+++ b/lstab.c
@@ -144,6 +144,7 @@ static int lstab_read(struct lstab *lstab, const char *name)
index++;
}
}
+ fclose(fp);
if (!lstab->expiration_utc) {
fprintf(stderr, "missing expiration date in '%s'\n", name);
return -1;

View File

@ -1,208 +0,0 @@
commit 513c7457865dba262a43e03fbe9178f4b08ba319
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Oct 24 15:25:30 2022 +0200
Drop support for old kernels returning zero frequency.
Kernels before 3.10 had a bug in reading of the system clock frequency,
which was worked around by commit da347d7a36f2 ("ptp4l: Set clock
frequency on start").
Drop this workaround and support for the old kernels to make
clockadj_get_freq() useful.
(Rebased to 3.1.1)
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index f3df220..9079428 100644
--- a/clock.c
+++ b/clock.c
@@ -1147,11 +1147,6 @@ struct clock *clock_create(enum clock_type type, struct config *config,
if (c->clkid != CLOCK_INVALID) {
fadj = (int) clockadj_get_freq(c->clkid);
- /* Due to a bug in older kernels, the reading may silently fail
- and return 0. Set the frequency back to make sure fadj is
- the actual frequency of the clock. */
- clockadj_set_freq(c->clkid, fadj);
-
/* Disable write phase mode if not implemented by driver */
if (c->write_phase_mode && !phc_has_writephase(c->clkid)) {
pr_err("clock does not support write phase mode");
@@ -1746,7 +1741,6 @@ int clock_switch_phc(struct clock *c, int phc_index)
return -1;
}
fadj = (int) clockadj_get_freq(clkid);
- clockadj_set_freq(clkid, fadj);
servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
if (!servo) {
pr_err("Switching PHC, failed to create clock servo");
diff --git a/phc2sys.c b/phc2sys.c
index 5f6fbaa..af948eb 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -147,9 +147,6 @@ static struct servo *servo_add(struct phc2sys_private *priv,
clockadj_init(clock->clkid);
ppb = clockadj_get_freq(clock->clkid);
- /* The reading may silently fail and return 0, reset the frequency to
- make sure ppb is the actual frequency of the clock. */
- clockadj_set_freq(clock->clkid, ppb);
if (clock->clkid == CLOCK_REALTIME) {
sysclk_set_leap(0);
max_ppb = sysclk_max_freq();
diff --git a/ts2phc_slave.c b/ts2phc_slave.c
index 749efe5..5541d91 100644
--- a/ts2phc_slave.c
+++ b/ts2phc_slave.c
@@ -183,10 +183,6 @@ static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char *
pr_debug("PHC slave %s has ptp index %d", device, junk);
fadj = (int) clockadj_get_freq(slave->clk);
- /* Due to a bug in older kernels, the reading may silently fail
- and return 0. Set the frequency back to make sure fadj is
- the actual frequency of the clock. */
- clockadj_set_freq(slave->clk, fadj);
max_adj = phc_max_adj(slave->clk);
commit 80d6875b0072c7ea636a5631e590fa72d169c351
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Oct 24 15:25:31 2022 +0200
Don't accept errors in clockadj_get_freq().
Exit if an error is returned from the clock_adjtime() call in
clockadj_get_freq(). No recoverable errors are expected.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clockadj.c b/clockadj.c
index 957dc57..4c920b9 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <math.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -72,6 +73,7 @@ double clockadj_get_freq(clockid_t clkid)
memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0) {
pr_err("failed to read out the clock frequency adjustment: %m");
+ exit(1);
} else {
f = tx.freq / 65.536;
if (clkid == CLOCK_REALTIME && realtime_nominal_tick && tx.tick)
commit 211cbfe810ef4082d1af8e9b50f65d4f6fd7246a
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Oct 24 15:25:32 2022 +0200
Extend clockcheck to check for changes in frequency.
Before setting the new frequency offset on a clock update, compare the
current frequency returned by the kernel with the value saved from the
previous update. Print a warning message if the difference is larger
than 1 ppb, allowing for rounding errors in conversion to and from
double. The kernel caches the value set by clock_adjtime() in shifted
ppm, it doesn't request it from the driver, which can have a lower
resulution.
This should detect misconfigurations where multiple processes are trying
to control the clock (e.g. another ptp4l/phc2sys instance or an NTP
client), even when they don't step the clock.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index 9079428..eea7983 100644
--- a/clock.c
+++ b/clock.c
@@ -1760,6 +1760,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
static void clock_synchronize_locked(struct clock *c, double adj)
{
+ if (c->sanity_check) {
+ clockcheck_freq(c->sanity_check, clockadj_get_freq(c->clkid));
+ }
clockadj_set_freq(c->clkid, -adj);
if (c->clkid == CLOCK_REALTIME) {
sysclk_set_sync();
diff --git a/clockcheck.c b/clockcheck.c
index f0141be..b5a69cc 100644
--- a/clockcheck.c
+++ b/clockcheck.c
@@ -123,6 +123,16 @@ void clockcheck_set_freq(struct clockcheck *cc, int freq)
cc->freq_known = 1;
}
+int clockcheck_freq(struct clockcheck *cc, int freq)
+{
+ /* Allow difference of 1 ppb due to conversion to/from double */
+ if (cc->freq_known && abs(cc->current_freq - freq) > 1) {
+ pr_warning("clockcheck: clock frequency changed unexpectedly!");
+ return 1;
+ }
+ return 0;
+}
+
void clockcheck_step(struct clockcheck *cc, int64_t step)
{
if (cc->last_ts)
diff --git a/clockcheck.h b/clockcheck.h
index 1ff86eb..4b09b98 100644
--- a/clockcheck.h
+++ b/clockcheck.h
@@ -54,6 +54,14 @@ int clockcheck_sample(struct clockcheck *cc, uint64_t ts);
*/
void clockcheck_set_freq(struct clockcheck *cc, int freq);
+/**
+ * Check whether the frequency correction did not change unexpectedly.
+ * @param cc Pointer to a clock check obtained via @ref clockcheck_create().
+ * @param freq Current reading of the frequency correction in ppb.
+ * @return Zero if the frequency did not change, non-zero otherwise.
+ */
+int clockcheck_freq(struct clockcheck *cc, int freq);
+
/**
* Inform clock check that the clock was stepped.
* @param cc Pointer to a clock check obtained via @ref clockcheck_create().
diff --git a/phc2sys.c b/phc2sys.c
index af948eb..4daa1bf 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -566,6 +566,9 @@ static void update_clock(struct phc2sys_private *priv, struct clock *clock,
/* Fall through. */
case SERVO_LOCKED:
case SERVO_LOCKED_STABLE:
+ if (clock->sanity_check)
+ clockcheck_freq(clock->sanity_check,
+ clockadj_get_freq(clock->clkid));
clockadj_set_freq(clock->clkid, -ppb);
if (clock->clkid == CLOCK_REALTIME)
sysclk_set_sync();
diff --git a/ptp4l.8 b/ptp4l.8
index 4917240..f760e2b 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -605,8 +605,10 @@ This option used to be called
The maximum allowed frequency offset between uncorrected clock and the system
monotonic clock in parts per billion (ppb). This is used as a sanity check of
the synchronized clock. When a larger offset is measured, a warning message
-will be printed and the servo will be reset. When set to 0, the sanity check is
-disabled. The default is 200000000 (20%).
+will be printed and the servo will be reset. If the frequency correction set by
+ptp4l changes unexpectedly between updates of the clock (e.g. due to another
+process trying to control the clock), a warning message will be printed. When
+set to 0, the sanity check is disabled. The default is 200000000 (20%).
.TP
.B initial_delay
The initial path delay of the clock in nanoseconds used for synchronization of

View File

@ -1,96 +0,0 @@
commit 3399fa15ae28610c1b288b573c4233a42c48f762
Author: Amar Subramanyam via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net>
Date: Wed May 26 12:24:06 2021 +0300
Log optimization for ptp4l in jbod and client only mode (clientOnly=1 and boundary_clock_jbod=1)
The LISTENING port prints continuously
"selected best master clock 000000.0000.000003
updating UTC offset to 37"
We limited the log such that now it prints only when there is a
change in the best-master clock.
Signed-off-by: Amar Subramanyam <asubramanyam@altiostar.com>
Signed-off-by: Karthikkumar Valoor <kvaloor@altiostar.com>
Signed-off-by: Ramana Reddy <rreddy@altiostar.com>
diff --git a/clock.c b/clock.c
index e545a9b..d428ae2 100644
--- a/clock.c
+++ b/clock.c
@@ -705,7 +705,8 @@ static void clock_update_slave(struct clock *c)
if (c->tds.currentUtcOffset < c->utc_offset) {
pr_warning("running in a temporal vortex");
}
- if ((c->tds.flags & UTC_OFF_VALID && c->tds.flags & TIME_TRACEABLE) ||
+ if (((c->tds.flags & UTC_OFF_VALID && c->tds.flags & TIME_TRACEABLE) &&
+ (c->tds.currentUtcOffset != c->utc_offset)) ||
(c->tds.currentUtcOffset > c->utc_offset)) {
pr_info("updating UTC offset to %d", c->tds.currentUtcOffset);
c->utc_offset = c->tds.currentUtcOffset;
@@ -1939,14 +1940,6 @@ static void handle_state_decision_event(struct clock *c)
best_id = c->dds.clockIdentity;
}
- if (cid_eq(&best_id, &c->dds.clockIdentity)) {
- pr_notice("selected local clock %s as best master",
- cid2str(&best_id));
- } else {
- pr_notice("selected best master clock %s",
- cid2str(&best_id));
- }
-
if (!cid_eq(&best_id, &c->best_id)) {
clock_freq_est_reset(c);
tsproc_reset(c->tsproc, 1);
@@ -1957,6 +1950,13 @@ static void handle_state_decision_event(struct clock *c)
c->master_local_rr = 1.0;
c->nrr = 1.0;
fresh_best = 1;
+ if (cid_eq(&best_id, &c->dds.clockIdentity)) {
+ pr_notice("selected local clock %s as best master",
+ cid2str(&best_id));
+ } else {
+ pr_notice("selected best master clock %s",
+ cid2str(&best_id));
+ }
}
c->best = best;
commit 766baf345cd4fb025d186f9c9bea5276aba398bc
Author: Amar Subramanyam via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net>
Date: Wed May 26 12:24:07 2021 +0300
Log optimization for ptp4l in jbod and client only mode (clientOnly=1 and boundary_clock_jbod=1)
The port other than SLAVE (LISTENING port) prints an error
"port 1: master state recommended in slave only mode
ptp4l[1205469.356]: port 1: defaultDS.priority1 probably misconfigured"
for every ANNOUNCE RECEIPT Timeout.
This log is printed when the event EV_RS_MASTER is thrown
in clientOnly mode. But single port clientOnly mode will never
hit this event instead EV_RS_GRAND_MASTER will be hit.
EV_RS_MASTER is thrown when clientOnly=1 and boundary_clock_jbod=1
which results in continuous printing. So EV_RS_MASTER check when
clientOnly=1 to print this error can be avoided.
Signed-off-by: Amar Subramanyam <asubramanyam@altiostar.com>
Signed-off-by: Karthikkumar Valoor <kvaloor@altiostar.com>
Signed-off-by: Ramana Reddy <rreddy@altiostar.com>
diff --git a/port.c b/port.c
index 250d46d..b5b775f 100644
--- a/port.c
+++ b/port.c
@@ -2536,7 +2536,7 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff)
static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff)
{
if (clock_slave_only(p->clock)) {
- if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) {
+ if (event == EV_RS_GRAND_MASTER) {
port_slave_priority_warning(p);
}
}

75
linuxptp-lstab.patch Normal file
View File

@ -0,0 +1,75 @@
commit bbfaa1e253b889aeea97702bbbc87e731e0caf87
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 22 13:51:59 2024 +0100
lstab: Limit number of parsed leap seconds.
The lstab structure has a fixed-size array for leap seconds
(currently 28 + 200). Don't read more leap seconds from the leapfile to
avoid corrupting memory.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/lstab.c b/lstab.c
index 24add26..8e35504 100644
--- a/lstab.c
+++ b/lstab.c
@@ -137,7 +137,7 @@ static int lstab_read(struct lstab *lstab, const char *name)
fprintf(stderr, "failed to open '%s' for reading: %m\n", name);
return -1;
}
- while (1) {
+ while (index < N_LEAPS) {
if (!fgets(buf, sizeof(buf), fp)) {
break;
}
commit 90ad2efc74b0f348fb6b417565b3ada7d161641b
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 22 13:56:53 2024 +0100
lstab: Don't free lstab on update.
The modification timestamp of the leapfile is checked with every
call of lstab_utc2tai(). If the file is modified, the provided lstab
structure is freed and a new one is allocated from the updated leapfile.
But the new lstab is not returned to the caller as the function doesn't
accept a pointer to the pointer to lstab. This causes reading from the
freed memory and leak of the newly allocated memory.
Modify update_leapsecond_table() to read the updated leapfile into the
existing lstab structure instead of the reallocation.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/lstab.c b/lstab.c
index 8e35504..357ed27 100644
--- a/lstab.c
+++ b/lstab.c
@@ -195,7 +195,6 @@ struct lstab *lstab_create(const char *filename)
int update_leapsecond_table(struct lstab *lstab)
{
- const char* leapfile;
struct stat statbuf;
int err;
@@ -212,14 +211,14 @@ int update_leapsecond_table(struct lstab *lstab)
return 0;
}
printf("updating leap seconds file\n");
- leapfile = lstab->leapfile;
- lstab_destroy(lstab);
- lstab = lstab_create(leapfile);
- if (!lstab) {
+ if (lstab_read(lstab, lstab->leapfile)) {
+ lstab->length = 0;
return -1;
}
+ lstab->lsfile_mtime = statbuf.st_mtim.tv_sec;
+
return 0;
}

View File

@ -1,28 +0,0 @@
commit 0b80e32829ca7430be851fc64c4812896ad97c88
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Jul 19 17:09:01 2021 +0200
Fix quoting in ptp4l man page.
In the groff syntax lines starting with a dot or quote are requests. A
line in the servo_offset_threshold description starts with a quote,
which breaks the output. Move a word to the beginning of the line to fix
it.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/ptp4l.8 b/ptp4l.8
index 7ca3474..a0779ef 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -788,8 +788,8 @@ 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.
+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 slave_event_monitor

29
linuxptp-nmeadelay.patch Normal file
View File

@ -0,0 +1,29 @@
commit 0404c1924254c9162222dd5000a140165d21250c
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 25 15:23:44 2024 +0100
ts2phc: Fix offset for NMEA delays over 0.5 seconds.
The current code of ts2phc assumes that the NMEA RMC message is received
within 0.5 seconds of the pulse the timestamp in the message is refering
to. However, with most receivers NMEA messages are referenced to the
previous pulse. This causes a 1-second error in the measured offset for
receivers with delays over 0.5 seconds.
Add a 0.5 second correction to map the whole interval between pulses to
the preceding pulse.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
index 3a4267d..274b70a 100644
--- a/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,
return -1;
}
rmc = tmv_add(rmc, duration_since_rmc);
+ rmc = tmv_add(rmc, nanoseconds_to_tmv(500000000));
utc_time = tmv_to_nanoseconds(rmc);
utc_time /= (int64_t) 1000000000;
*ts = tmv_to_timespec(rmc);

View File

@ -1,100 +0,0 @@
commit 25dcf01e340d85bcdbe7b3c24eac7fe1ce7ea0c2
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Mar 10 17:05:55 2021 +0100
Avoid unaligned pointers to packed members.
This fixes "taking address of packed member ... may result in an
unaligned pointer value [-Waddress-of-packed-member]" warnings from gcc.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index 7005636..f88df58 100644
--- a/clock.c
+++ b/clock.c
@@ -350,6 +350,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
struct time_status_np *tsn;
struct tlv_extra *extra;
struct PTPText *text;
+ uint16_t duration;
int datalen = 0;
extra = tlv_extra_alloc();
@@ -452,7 +453,8 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
break;
}
sen = (struct subscribe_events_np *)tlv->data;
- clock_get_subscription(c, req, sen->bitmask, &sen->duration);
+ clock_get_subscription(c, req, sen->bitmask, &duration);
+ memcpy(&sen->duration, &duration, sizeof(sen->duration));
datalen = sizeof(*sen);
break;
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
diff --git a/msg.c b/msg.c
index c4516ad..dcb397c 100644
--- a/msg.c
+++ b/msg.c
@@ -19,6 +19,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <malloc.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -36,8 +37,8 @@ int assume_two_step = 0;
struct message_storage {
unsigned char reserved[MSG_HEADROOM];
- struct ptp_message msg;
-} PACKED;
+ struct ptp_message msg __attribute__((aligned (8)));
+};
static TAILQ_HEAD(msg_pool, ptp_message) msg_pool = TAILQ_HEAD_INITIALIZER(msg_pool);
diff --git a/tlv.c b/tlv.c
index 879bb7e..98ef6e1 100644
--- a/tlv.c
+++ b/tlv.c
@@ -67,7 +67,7 @@ static void timestamp_net2host(struct Timestamp *t)
NTOHL(t->nanoseconds);
}
-static uint16_t flip16(uint16_t *p)
+static uint16_t flip16(void *p)
{
uint16_t v;
memcpy(&v, p, sizeof(v));
@@ -76,7 +76,7 @@ static uint16_t flip16(uint16_t *p)
return v;
}
-static int64_t host2net64_unaligned(int64_t *p)
+static int64_t host2net64_unaligned(void *p)
{
int64_t v;
memcpy(&v, p, sizeof(v));
@@ -85,7 +85,7 @@ static int64_t host2net64_unaligned(int64_t *p)
return v;
}
-static int64_t net2host64_unaligned(int64_t *p)
+static int64_t net2host64_unaligned(void *p)
{
int64_t v;
memcpy(&v, p, sizeof(v));
diff --git a/util.h b/util.h
index 41e33d4..739c8fd 100644
--- a/util.h
+++ b/util.h
@@ -57,7 +57,7 @@ const char *ts_str(enum timestamp_type ts);
*/
int addreq(enum transport_type type, struct address *a, struct address *b);
-static inline uint16_t align16(uint16_t *p)
+static inline uint16_t align16(void *p)
{
uint16_t v;
memcpy(&v, p, sizeof(v));

View File

@ -1,510 +0,0 @@
commit f32a8469a236728fb158ce997385b53f92b821cc
Author: Jacob Keller <jacob.e.keller@intel.com>
Date: Tue Nov 23 14:43:26 2021 -0800
phc2sys: move read_phc into clock_adj.c
The read_phc function implemented in phc2sys.c is used to perform clock
comparison between two arbitrary clocks using clock_gettime.
This support is used to allow phc2sys to work on any pair of clocks and
is implemented in a very similar manner as the kernel PTP_SYS_OFFSET
ioctls.
Make this function easier to re-use by moving it out of phc2sys.c and
into a more accessible location. clockadj.c seems like a reasonable
location as this file has many functions which deal with clockid_t
values, and this functionality is tangentially related to adjusting
clocks.
Moving this function will allow using it in the phc_ctl program in a
future change.
Notice that read_phc returned 0 on failure and 1 on success. This is
fairly non-standard, so lets update clockadj_compare to return 0 on
success and -1 on failure. Fix the call sites to check correctly and
report an error.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/clockadj.c b/clockadj.c
index b5c78cd..e8c5789 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -139,6 +139,37 @@ int clockadj_max_freq(clockid_t clkid)
return f;
}
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+ int64_t *offset, uint64_t *ts, int64_t *delay)
+{
+ struct timespec tdst1, tdst2, tsrc;
+ int i;
+ int64_t interval, best_interval = INT64_MAX;
+
+ /* Pick the quickest clkid reading. */
+ for (i = 0; i < readings; i++) {
+ if (clock_gettime(sysclk, &tdst1) ||
+ clock_gettime(clkid, &tsrc) ||
+ clock_gettime(sysclk, &tdst2)) {
+ pr_err("failed to read clock: %m");
+ return -1;
+ }
+
+ interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
+ tdst2.tv_nsec - tdst1.tv_nsec;
+
+ if (best_interval > interval) {
+ best_interval = interval;
+ *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
+ tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
+ *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
+ }
+ }
+ *delay = best_interval;
+
+ return 0;
+}
+
void sysclk_set_leap(int leap)
{
clockid_t clkid = CLOCK_REALTIME;
diff --git a/clockadj.h b/clockadj.h
index 43325c8..b63ae38 100644
--- a/clockadj.h
+++ b/clockadj.h
@@ -63,6 +63,24 @@ void clockadj_step(clockid_t clkid, int64_t step);
*/
int clockadj_max_freq(clockid_t clkid);
+/**
+ * Compare offset between two clocks
+ * @param clkid A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param sysclk A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param readings Number of readings to try
+ * @param offset On return, the nanoseconds offset between the clocks
+ * @param ts On return, the time of sysclk in nanoseconds that was used
+ * @param delay On return, the interval between two reads of sysclk
+ * @return Zero on success and non-zero on failure.
+ *
+ * Compare the offset between two clocks in a similar manner as the
+ * PTP_SYS_OFFSET ioctls. Performs multiple reads of sysclk with a read of
+ * clkid between in order to calculate the time difference of sysclk minus
+ * clkid.
+ */
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+ int64_t *offset, uint64_t *ts, int64_t *delay);
+
/**
* Set the system clock to insert/delete leap second at midnight.
* @param leap +1 to insert leap second, -1 to delete leap second,
diff --git a/phc2sys.c b/phc2sys.c
index a36cbe0..7a547fa 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -486,37 +486,6 @@ static void reconfigure(struct phc2sys_private *priv)
pr_info("selecting %s as the master clock", src->device);
}
-static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
- int64_t *offset, uint64_t *ts, int64_t *delay)
-{
- struct timespec tdst1, tdst2, tsrc;
- int i;
- int64_t interval, best_interval = INT64_MAX;
-
- /* Pick the quickest clkid reading. */
- for (i = 0; i < readings; i++) {
- if (clock_gettime(sysclk, &tdst1) ||
- clock_gettime(clkid, &tsrc) ||
- clock_gettime(sysclk, &tdst2)) {
- pr_err("failed to read clock: %m");
- return 0;
- }
-
- interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
- tdst2.tv_nsec - tdst1.tv_nsec;
-
- if (best_interval > interval) {
- best_interval = interval;
- *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
- tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
- *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
- }
- }
- *delay = best_interval;
-
- return 1;
-}
-
static int64_t get_sync_offset(struct phc2sys_private *priv, struct clock *dst)
{
int direction = priv->forced_sync_offset;
@@ -672,8 +641,10 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
/* If a PHC is available, use it to get the whole number
of seconds in the offset and PPS for the rest. */
if (src != CLOCK_INVALID) {
- if (!read_phc(src, clock->clkid, priv->phc_readings,
- &phc_offset, &phc_ts, &phc_delay))
+ if (clockadj_compare(src, clock->clkid,
+ priv->phc_readings,
+ &phc_offset, &phc_ts,
+ &phc_delay))
return -1;
/* Convert the time stamp to the PHC time. */
@@ -781,10 +752,11 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
ts += offset;
} else {
/* use phc */
- if (!read_phc(priv->master->clkid, clock->clkid,
- priv->phc_readings,
- &offset, &ts, &delay))
- continue;
+ if (clockadj_compare(priv->master->clkid,
+ clock->clkid,
+ priv->phc_readings,
+ &offset, &ts, &delay))
+ return -1;
}
update_clock(priv, clock, offset, ts, delay);
}
commit 96486bda9ac1613fb36feb84d76ababd8972bba6
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue May 17 12:31:45 2022 +0200
clockadj: Change clockadj_compare() to return errno.
Return -errno from the failed clock_gettime() to allow the callers to
check for specific errors.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clockadj.c b/clockadj.c
index e8c5789..957dc57 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -17,6 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <errno.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
@@ -152,7 +153,7 @@ int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
clock_gettime(clkid, &tsrc) ||
clock_gettime(sysclk, &tdst2)) {
pr_err("failed to read clock: %m");
- return -1;
+ return -errno;
}
interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
diff --git a/clockadj.h b/clockadj.h
index b63ae38..6db1d79 100644
--- a/clockadj.h
+++ b/clockadj.h
@@ -71,7 +71,7 @@ int clockadj_max_freq(clockid_t clkid);
* @param offset On return, the nanoseconds offset between the clocks
* @param ts On return, the time of sysclk in nanoseconds that was used
* @param delay On return, the interval between two reads of sysclk
- * @return Zero on success and non-zero on failure.
+ * @return Zero on success, or negative error code on failure.
*
* Compare the offset between two clocks in a similar manner as the
* PTP_SYS_OFFSET ioctls. Performs multiple reads of sysclk with a read of
commit a523e893a15001025379e3c2dedb231e99cc886f
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 24 11:55:35 2022 +0100
sysoff: Change sysoff_measure() to return errno.
Return -errno from failed ioctl instead of the SYSOFF_* enum from the
measurement functions to allow the callers to check for specific errors.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/sysoff.c b/sysoff.c
index 2743859..5d3b907 100644
--- a/sysoff.c
+++ b/sysoff.c
@@ -17,6 +17,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
@@ -38,11 +39,11 @@ static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
memset(&pso, 0, sizeof(pso));
if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) {
pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m");
- return SYSOFF_RUN_TIME_MISSING;
+ return -errno;
}
*result = pctns(&pso.sys_realtime) - pctns(&pso.device);
*ts = pctns(&pso.sys_realtime);
- return SYSOFF_PRECISE;
+ return 0;
}
static int64_t sysoff_estimate(struct ptp_clock_time *pct, int extended,
@@ -98,10 +99,10 @@ static int sysoff_extended(int fd, int n_samples,
pso.n_samples = n_samples;
if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) {
pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m");
- return SYSOFF_RUN_TIME_MISSING;
+ return -errno;
}
*result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
- return SYSOFF_EXTENDED;
+ return 0;
}
static int sysoff_basic(int fd, int n_samples,
@@ -112,10 +113,10 @@ static int sysoff_basic(int fd, int n_samples,
pso.n_samples = n_samples;
if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
perror("ioctl PTP_SYS_OFFSET");
- return SYSOFF_RUN_TIME_MISSING;
+ return -errno;
}
*result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
- return SYSOFF_BASIC;
+ return 0;
}
int sysoff_measure(int fd, int method, int n_samples,
@@ -130,7 +131,7 @@ int sysoff_measure(int fd, int method, int n_samples,
case SYSOFF_BASIC:
return sysoff_basic(fd, n_samples, result, ts, delay);
}
- return SYSOFF_RUN_TIME_MISSING;
+ return -EOPNOTSUPP;
}
int sysoff_probe(int fd, int n_samples)
diff --git a/sysoff.h b/sysoff.h
index e4de919..5480f8f 100644
--- a/sysoff.h
+++ b/sysoff.h
@@ -44,7 +44,7 @@ int sysoff_probe(int fd, int n_samples);
* @param result The estimated offset in nanoseconds.
* @param ts The system time corresponding to the 'result'.
* @param delay The delay in reading of the clock in nanoseconds.
- * @return One of the SYSOFF_ enumeration values.
+ * @return Zero on success, negative error code otherwise.
*/
int sysoff_measure(int fd, int method, int n_samples,
int64_t *result, uint64_t *ts, int64_t *delay);
commit 25b340eb1daad807d9485728f0917ec25a376e0c
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed May 18 10:21:29 2022 +0200
sysoff: Change log level of ioctl error messages.
Change the log level of ioctl error messages to the error level to make
them visible in default configuration, with the exception of EOPNOTSUPP
which is expected in probing and should stay at the debug level to avoid
confusing users.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/sysoff.c b/sysoff.c
index 5d3b907..a425275 100644
--- a/sysoff.c
+++ b/sysoff.c
@@ -28,6 +28,14 @@
#define NS_PER_SEC 1000000000LL
+static void print_ioctl_error(const char *name)
+{
+ if (errno == EOPNOTSUPP)
+ pr_debug("ioctl %s: %s", name, strerror(errno));
+ else
+ pr_err("ioctl %s: %s", name, strerror(errno));
+}
+
static int64_t pctns(struct ptp_clock_time *t)
{
return t->sec * NS_PER_SEC + t->nsec;
@@ -38,7 +46,7 @@ static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
struct ptp_sys_offset_precise pso;
memset(&pso, 0, sizeof(pso));
if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) {
- pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m");
+ print_ioctl_error("PTP_SYS_OFFSET_PRECISE");
return -errno;
}
*result = pctns(&pso.sys_realtime) - pctns(&pso.device);
@@ -98,7 +106,7 @@ static int sysoff_extended(int fd, int n_samples,
memset(&pso, 0, sizeof(pso));
pso.n_samples = n_samples;
if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) {
- pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m");
+ print_ioctl_error("PTP_SYS_OFFSET_EXTENDED");
return -errno;
}
*result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
@@ -112,7 +120,7 @@ static int sysoff_basic(int fd, int n_samples,
memset(&pso, 0, sizeof(pso));
pso.n_samples = n_samples;
if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
- perror("ioctl PTP_SYS_OFFSET");
+ print_ioctl_error("PTP_SYS_OFFSET");
return -errno;
}
*result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
commit 755cf11ad6e5d02e11519b6e2644ee0f71da91ea
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Mar 24 12:41:49 2022 +0100
sysoff: Retry on EBUSY when probing supported ioctls.
Handle EBUSY when probing support for a PTP_SYS_OFFSET ioctl. Try each
ioctl up to three times before giving up on it to make the detection
more reliable.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/sysoff.c b/sysoff.c
index a425275..fc1f7ca 100644
--- a/sysoff.c
+++ b/sysoff.c
@@ -145,8 +145,8 @@ int sysoff_measure(int fd, int method, int n_samples,
int sysoff_probe(int fd, int n_samples)
{
int64_t junk, delay;
+ int i, j, err;
uint64_t ts;
- int i;
if (n_samples > PTP_MAX_SAMPLES) {
fprintf(stderr, "warning: %d exceeds kernel max readings %d\n",
@@ -156,9 +156,15 @@ int sysoff_probe(int fd, int n_samples)
}
for (i = 0; i < SYSOFF_LAST; i++) {
- if (sysoff_measure(fd, i, n_samples, &junk, &ts, &delay) < 0)
- continue;
- return i;
+ for (j = 0; j < 3; j++) {
+ err = sysoff_measure(fd, i, n_samples, &junk, &ts,
+ &delay);
+ if (err == -EBUSY)
+ continue;
+ if (err)
+ break;
+ return i;
+ }
}
return SYSOFF_RUN_TIME_MISSING;
commit d1e8ea2405a42b42bcaf2166717fe0da6e9871ae
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Mar 8 12:18:31 2022 +0100
phc2sys: Don't exit when reading of PHC fails with EBUSY.
Reading of the PHC can occasionally fail with some drivers, e.g. the ice
driver returns EBUSY when it fails to get a lock. Continue in the loop
instead of exiting on the error.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/phc2sys.c b/phc2sys.c
index 7a547fa..b4e2e87 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -623,6 +623,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts;
clockid_t src = priv->master->clkid;
+ int err;
priv->master->source_label = "pps";
@@ -641,10 +642,13 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
/* If a PHC is available, use it to get the whole number
of seconds in the offset and PPS for the rest. */
if (src != CLOCK_INVALID) {
- if (clockadj_compare(src, clock->clkid,
- priv->phc_readings,
- &phc_offset, &phc_ts,
- &phc_delay))
+ err = clockadj_compare(src, clock->clkid,
+ priv->phc_readings,
+ &phc_offset, &phc_ts,
+ &phc_delay);
+ if (err == -EBUSY)
+ continue;
+ if (err)
return -1;
/* Convert the time stamp to the PHC time. */
@@ -692,6 +696,7 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
struct clock *clock;
uint64_t ts;
int64_t offset, delay;
+ int err;
interval.tv_sec = priv->phc_interval;
interval.tv_nsec = (priv->phc_interval - interval.tv_sec) * 1e9;
@@ -735,29 +740,32 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
if (clock->clkid == CLOCK_REALTIME &&
priv->master->sysoff_method >= 0) {
/* use sysoff */
- if (sysoff_measure(CLOCKID_TO_FD(priv->master->clkid),
- priv->master->sysoff_method,
- priv->phc_readings,
- &offset, &ts, &delay) < 0)
- return -1;
+ err = sysoff_measure(CLOCKID_TO_FD(priv->master->clkid),
+ priv->master->sysoff_method,
+ priv->phc_readings,
+ &offset, &ts, &delay);
} else if (priv->master->clkid == CLOCK_REALTIME &&
clock->sysoff_method >= 0) {
/* use reversed sysoff */
- if (sysoff_measure(CLOCKID_TO_FD(clock->clkid),
- clock->sysoff_method,
- priv->phc_readings,
- &offset, &ts, &delay) < 0)
- return -1;
- offset = -offset;
- ts += offset;
+ err = sysoff_measure(CLOCKID_TO_FD(clock->clkid),
+ clock->sysoff_method,
+ priv->phc_readings,
+ &offset, &ts, &delay);
+ if (!err) {
+ offset = -offset;
+ ts += offset;
+ }
} else {
/* use phc */
- if (clockadj_compare(priv->master->clkid,
- clock->clkid,
- priv->phc_readings,
- &offset, &ts, &delay))
- return -1;
+ err = clockadj_compare(priv->master->clkid,
+ clock->clkid,
+ priv->phc_readings,
+ &offset, &ts, &delay);
}
+ if (err == -EBUSY)
+ continue;
+ if (err)
+ return -1;
update_clock(priv, clock, offset, ts, delay);
}
}

60
linuxptp-ptpver.patch Normal file
View File

@ -0,0 +1,60 @@
commit 6e480c9572925a4ea8aac45a10a306e0c4e509a9
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 11 11:33:54 2024 +0100
Revert default PTP version to 2.0 for better compatibility.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/config.c b/config.c
index 398b420..d7775c0 100644
--- a/config.c
+++ b/config.c
@@ -319,7 +319,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_STR("productDescription", ";;"),
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", 1, 0, 1),
+ GLOB_ITEM_INT("ptp_minor_version", 0, 0, 1),
GLOB_ITEM_STR("refclock_sock_address", "/var/run/refclock.ptp.sock"),
GLOB_ITEM_STR("revisionData", ";;"),
GLOB_ITEM_INT("sanity_freq_limit", 200000000, 0, INT_MAX),
diff --git a/configs/default.cfg b/configs/default.cfg
index 0c7661c..8f94c16 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -46,7 +46,7 @@ power_profile.2011.networkTimeInaccuracy -1
power_profile.2017.totalTimeInaccuracy -1
power_profile.grandmasterID 0
power_profile.version none
-ptp_minor_version 1
+ptp_minor_version 0
#
# Run time options
#
diff --git a/msg.h b/msg.h
index 9c80f45..786ddc7 100644
--- a/msg.h
+++ b/msg.h
@@ -32,7 +32,7 @@
/* Version definition for IEEE 1588-2019 */
#define PTP_MAJOR_VERSION 2
-#define PTP_MINOR_VERSION 1
+#define PTP_MINOR_VERSION 0
#define PTP_VERSION (PTP_MINOR_VERSION << 4 | PTP_MAJOR_VERSION)
#define MAJOR_VERSION_MASK 0x0f
diff --git a/ptp4l.8 b/ptp4l.8
index 4cb9adb..c59b0b4 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -813,7 +813,7 @@ The default is 128.
.TP
.B ptp_minor_version
This option sets the minorVersionPTP in the common PTP message header.
-The default is 1.
+The default (specific to the installed linuxptp package) is 0.
.TP
.B refclock_sock_address

View File

@ -1,84 +0,0 @@
commit 2db8da6d1e3db074c01516c74899d42089039bc8
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Apr 26 13:45:41 2023 +0200
Clear pending errors on sockets.
When the netlink socket of a port (used for receiving link up/down
events) had an error (e.g. ENOBUFS due to the kernel sending too many
messages), ptp4l switched the port to the faulty state, but it kept
getting POLLERR on the socket and logged "port 1: unexpected socket
error" in an infinite loop.
Unlike the PTP event and general sockets, the netlink sockets cannot be
closed in the faulty state as they are needed to receive the link up event.
Instead, receive and clear the error on all descriptors getting POLLERR
with getsockopt(SO_ERROR). Include the error in the log message together
with the descriptor index to make it easier to debug issues like this in
future.
(Rebased to 3.1.1)
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index 469aab6..2821fc4 100644
--- a/clock.c
+++ b/clock.c
@@ -1611,8 +1611,10 @@ int clock_poll(struct clock *c)
if (cur[i].revents & (POLLIN|POLLPRI|POLLERR)) {
prior_state = port_state(p);
if (cur[i].revents & POLLERR) {
- pr_err("port %d: unexpected socket error",
- port_number(p));
+ int error = sk_get_error(cur[i].fd);
+ pr_err("port %d: error on fda[%d]: %s",
+ port_number(p), i,
+ strerror(error));
event = EV_FAULT_DETECTED;
} else {
event = port_event(p, i);
diff --git a/sk.c b/sk.c
index 3595649..47d8c3b 100644
--- a/sk.c
+++ b/sk.c
@@ -413,6 +413,20 @@ int sk_receive(int fd, void *buf, int buflen,
return cnt < 0 ? -errno : cnt;
}
+int sk_get_error(int fd)
+{
+ socklen_t len;
+ int error;
+
+ len = sizeof (error);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+ pr_err("getsockopt SO_ERROR failed: %m");
+ return -1;
+ }
+
+ return error;
+}
+
int sk_set_priority(int fd, int family, uint8_t dscp)
{
int level, optname, tos;
diff --git a/sk.h b/sk.h
index 04d26ee..ba88e2f 100644
--- a/sk.h
+++ b/sk.h
@@ -109,6 +109,13 @@ int sk_interface_addr(const char *name, int family, struct address *addr);
int sk_receive(int fd, void *buf, int buflen,
struct address *addr, struct hw_timestamp *hwts, int flags);
+/**
+ * Get and clear a pending socket error.
+ * @param fd An open socket.
+ * @return The error.
+ */
+int sk_get_error(int fd);
+
/**
* Set DSCP value for socket.
* @param fd An open socket.

26
linuxptp-subscribe.patch Normal file
View File

@ -0,0 +1,26 @@
commit b421a4c66ce636adff150dd1aa8eafa981c2693d
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Jan 3 14:45:51 2024 +0100
pmc: Allow missing values in SUBSCRIBE_EVENTS_NP command.
Don't require all supported notifications to be specified in the command
for compatibility with older scripts.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/pmc_common.c b/pmc_common.c
index 62e34a6..b88cfc2 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -310,8 +310,8 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
onoff_port_state,
onoff_time_status,
onoff_parent_data_set);
- if (cnt != 4) {
- fprintf(stderr, "%s SET needs 4 values\n",
+ if (cnt < 2) {
+ fprintf(stderr, "%s SET needs at least 2 values\n",
idtab[index].name);
break;
}

View File

@ -1,614 +0,0 @@
Patches backported from the upstream repository.
commit acc045034dd0db9dd4c4aca4b26528f8fed2ae78
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 11 16:47:08 2021 +0100
port: Ignore non-management messages on UDS port.
Drop non-management messages on the UDS port early in the processing to
prevent them from changing the port or clock state.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/port.c b/port.c
index fa49663..3fd06b1 100644
--- a/port.c
+++ b/port.c
@@ -56,6 +56,7 @@ enum syfu_event {
};
static int port_is_ieee8021as(struct port *p);
+static int port_is_uds(struct port *p);
static void port_nrate_initialize(struct port *p);
static int announce_compare(struct ptp_message *m1, struct ptp_message *m2)
@@ -691,6 +692,9 @@ static int port_ignore(struct port *p, struct ptp_message *m)
{
struct ClockIdentity c1, c2;
+ if (port_is_uds(p) && msg_type(m) != MANAGEMENT) {
+ return 1;
+ }
if (incapable_ignore(p, m)) {
return 1;
}
@@ -771,6 +775,11 @@ static int port_is_ieee8021as(struct port *p)
return p->follow_up_info ? 1 : 0;
}
+static int port_is_uds(struct port *p)
+{
+ return transport_type(p->trp) == TRANS_UDS;
+}
+
static void port_management_send_error(struct port *p, struct port *ingress,
struct ptp_message *msg, int error_id)
{
commit 72ec806fa62a87cb7e5444e27fa6bdcbfe4e27ca
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 11 16:47:09 2021 +0100
clock: Don't allow COMMAND action on non-UDS port.
No COMMAND actions are currently supported, but check the port early in
clock_manage() before reaching port_manage().
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index a66d189..a6947bc 100644
--- a/clock.c
+++ b/clock.c
@@ -1423,6 +1423,11 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
return changed;
break;
case COMMAND:
+ if (p != c->uds_port) {
+ /* Sorry, only allowed on the UDS port. */
+ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
+ return changed;
+ }
break;
default:
return changed;
commit 2b45d80eadcb81c8bdf45baf98dabeebd912b1b0
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 11 16:47:10 2021 +0100
clock: Rename UDS variables to read-write.
In preparation for a new read-only UDS port, rename variables of the
current UDS port to make it clear it is read-write, as opposed to
read-only.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index a6947bc..d013b19 100644
--- a/clock.c
+++ b/clock.c
@@ -95,7 +95,7 @@ struct clock {
struct foreign_clock *best;
struct ClockIdentity best_id;
LIST_HEAD(ports_head, port) ports;
- struct port *uds_port;
+ struct port *uds_rw_port;
struct pollfd *pollfd;
int pollfd_valid;
int nports; /* does not include the UDS port */
@@ -129,7 +129,7 @@ struct clock {
struct clock_stats stats;
int stats_interval;
struct clockcheck *sanity_check;
- struct interface *udsif;
+ struct interface *uds_rw_if;
LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
struct monitor *slave_event_monitor;
};
@@ -245,7 +245,7 @@ void clock_send_notification(struct clock *c, struct ptp_message *msg,
{
unsigned int event_pos = event / 8;
uint8_t mask = 1 << (event % 8);
- struct port *uds = c->uds_port;
+ struct port *uds = c->uds_rw_port;
struct clock_subscriber *s;
LIST_FOREACH(s, &c->subscribers, list) {
@@ -267,13 +267,13 @@ void clock_destroy(struct clock *c)
{
struct port *p, *tmp;
- interface_destroy(c->udsif);
+ interface_destroy(c->uds_rw_if);
clock_flush_subscriptions(c);
LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
clock_remove_port(c, p);
}
monitor_destroy(c->slave_event_monitor);
- port_close(c->uds_port);
+ port_close(c->uds_rw_port);
free(c->pollfd);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
@@ -442,7 +442,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
datalen = sizeof(*gsn);
break;
case TLV_SUBSCRIBE_EVENTS_NP:
- if (p != c->uds_port) {
+ if (p != c->uds_rw_port) {
/* Only the UDS port allowed. */
break;
}
@@ -784,7 +784,7 @@ static int forwarding(struct clock *c, struct port *p)
default:
break;
}
- if (p == c->uds_port && ps != PS_FAULTY) {
+ if (p == c->uds_rw_port && ps != PS_FAULTY) {
return 1;
}
return 0;
@@ -1044,20 +1044,20 @@ struct clock *clock_create(enum clock_type type, struct config *config,
/* Configure the UDS. */
uds_ifname = config_get_string(config, NULL, "uds_address");
- c->udsif = interface_create(uds_ifname);
- if (config_set_section_int(config, interface_name(c->udsif),
+ c->uds_rw_if = interface_create(uds_ifname);
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
"announceReceiptTimeout", 0)) {
return NULL;
}
- if (config_set_section_int(config, interface_name(c->udsif),
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
"delay_mechanism", DM_AUTO)) {
return NULL;
}
- if (config_set_section_int(config, interface_name(c->udsif),
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
"network_transport", TRANS_UDS)) {
return NULL;
}
- if (config_set_section_int(config, interface_name(c->udsif),
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
"delay_filter_length", 1)) {
return NULL;
}
@@ -1180,14 +1180,15 @@ struct clock *clock_create(enum clock_type type, struct config *config,
}
/* Create the UDS interface. */
- c->uds_port = port_open(phc_device, phc_index, timestamping, 0, c->udsif, c);
- if (!c->uds_port) {
+ c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0,
+ c->uds_rw_if, c);
+ if (!c->uds_rw_port) {
pr_err("failed to open the UDS port");
return NULL;
}
clock_fda_changed(c);
- c->slave_event_monitor = monitor_create(config, c->uds_port);
+ c->slave_event_monitor = monitor_create(config, c->uds_rw_port);
if (!c->slave_event_monitor) {
pr_err("failed to create slave event monitor");
return NULL;
@@ -1206,7 +1207,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
LIST_FOREACH(p, &c->ports, list) {
port_dispatch(p, EV_INITIALIZE, 0);
}
- port_dispatch(c->uds_port, EV_INITIALIZE, 0);
+ port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
return c;
}
@@ -1314,7 +1315,7 @@ static void clock_check_pollfd(struct clock *c)
clock_fill_pollfd(dest, p);
dest += N_CLOCK_PFD;
}
- clock_fill_pollfd(dest, c->uds_port);
+ clock_fill_pollfd(dest, c->uds_rw_port);
c->pollfd_valid = 1;
}
@@ -1331,7 +1332,7 @@ static int clock_do_forward_mgmt(struct clock *c,
return 0;
/* Don't forward any requests to the UDS port. */
- if (out == c->uds_port) {
+ if (out == c->uds_rw_port) {
switch (management_action(msg)) {
case GET:
case SET:
@@ -1362,7 +1363,7 @@ static void clock_forward_mgmt_msg(struct clock *c, struct port *p, struct ptp_m
pr_err("port %d: management forward failed",
port_number(piter));
}
- if (clock_do_forward_mgmt(c, p, c->uds_port, msg, &msg_ready))
+ if (clock_do_forward_mgmt(c, p, c->uds_rw_port, msg, &msg_ready))
pr_err("uds port: management forward failed");
if (msg_ready) {
msg_post_recv(msg, pdulen);
@@ -1414,7 +1415,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
clock_management_send_error(p, msg, TLV_WRONG_LENGTH);
return changed;
}
- if (p != c->uds_port) {
+ if (p != c->uds_rw_port) {
/* Sorry, only allowed on the UDS port. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return changed;
@@ -1423,7 +1424,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
return changed;
break;
case COMMAND:
- if (p != c->uds_port) {
+ if (p != c->uds_rw_port) {
/* Sorry, only allowed on the UDS port. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return changed;
@@ -1435,7 +1436,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
switch (mgt->id) {
case TLV_PORT_PROPERTIES_NP:
- if (p != c->uds_port) {
+ if (p != c->uds_rw_port) {
/* Only the UDS port allowed. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return 0;
@@ -1500,7 +1501,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
void clock_notify_event(struct clock *c, enum notification event)
{
- struct port *uds = c->uds_port;
+ struct port *uds = c->uds_rw_port;
struct PortIdentity pid = port_identity(uds);
struct ptp_message *msg;
int id;
@@ -1604,7 +1605,7 @@ int clock_poll(struct clock *c)
/* Check the UDS port. */
for (i = 0; i < N_POLLFD; i++) {
if (cur[i].revents & (POLLIN|POLLPRI)) {
- event = port_event(c->uds_port, i);
+ event = port_event(c->uds_rw_port, i);
if (EV_STATE_DECISION_EVENT == event) {
c->sde = 1;
}
commit 1f74a16502b55ce8eaed3d7488542e5469ac8263
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 11 16:47:11 2021 +0100
clock: Add read-only UDS port for monitoring.
Add a second UDS port to allow untrusted applications to monitor ptp4l.
On this "read-only" UDS port disable non-GET actions and forwarding.
The path can be configured with the uds_ro_address option (default is
/var/run/ptp4lro).
Forwarding is disabled to limit the access to the local ptp4l instance.
Subscriptions are not enabled to prevent the applications from making a
large number of subscriptions or interfere with applications that have
access to the read-write UDS port.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index d013b19..8592d29 100644
--- a/clock.c
+++ b/clock.c
@@ -96,9 +96,10 @@ struct clock {
struct ClockIdentity best_id;
LIST_HEAD(ports_head, port) ports;
struct port *uds_rw_port;
+ struct port *uds_ro_port;
struct pollfd *pollfd;
int pollfd_valid;
- int nports; /* does not include the UDS port */
+ int nports; /* does not include the two UDS ports */
int last_port_number;
int sde;
int free_running;
@@ -130,6 +131,7 @@ struct clock {
int stats_interval;
struct clockcheck *sanity_check;
struct interface *uds_rw_if;
+ struct interface *uds_ro_if;
LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
struct monitor *slave_event_monitor;
};
@@ -268,12 +270,14 @@ void clock_destroy(struct clock *c)
struct port *p, *tmp;
interface_destroy(c->uds_rw_if);
+ interface_destroy(c->uds_ro_if);
clock_flush_subscriptions(c);
LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
clock_remove_port(c, p);
}
monitor_destroy(c->slave_event_monitor);
port_close(c->uds_rw_port);
+ port_close(c->uds_ro_port);
free(c->pollfd);
if (c->clkid != CLOCK_REALTIME) {
phc_close(c->clkid);
@@ -443,7 +447,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
break;
case TLV_SUBSCRIBE_EVENTS_NP:
if (p != c->uds_rw_port) {
- /* Only the UDS port allowed. */
+ /* Only the UDS-RW port allowed. */
break;
}
sen = (struct subscribe_events_np *)tlv->data;
@@ -774,6 +778,10 @@ static int clock_utc_correct(struct clock *c, tmv_t ingress)
static int forwarding(struct clock *c, struct port *p)
{
enum port_state ps = port_state(p);
+
+ if (p == c->uds_ro_port)
+ return 0;
+
switch (ps) {
case PS_MASTER:
case PS_GRAND_MASTER:
@@ -818,7 +826,7 @@ static int clock_add_port(struct clock *c, const char *phc_device,
{
struct port *p, *piter, *lastp = NULL;
- if (clock_resize_pollfd(c, c->nports + 1)) {
+ if (clock_resize_pollfd(c, c->nports + 2)) {
return -1;
}
p = port_open(phc_device, phc_index, timestamping,
@@ -1043,6 +1051,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
}
/* Configure the UDS. */
+
uds_ifname = config_get_string(config, NULL, "uds_address");
c->uds_rw_if = interface_create(uds_ifname);
if (config_set_section_int(config, interface_name(c->uds_rw_if),
@@ -1062,6 +1071,25 @@ struct clock *clock_create(enum clock_type type, struct config *config,
return NULL;
}
+ uds_ifname = config_get_string(config, NULL, "uds_ro_address");
+ c->uds_ro_if = interface_create(uds_ifname);
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
+ "announceReceiptTimeout", 0)) {
+ return NULL;
+ }
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
+ "delay_mechanism", DM_AUTO)) {
+ return NULL;
+ }
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
+ "network_transport", TRANS_UDS)) {
+ return NULL;
+ }
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
+ "delay_filter_length", 1)) {
+ return NULL;
+ }
+
c->config = config;
c->free_running = config_get_int(config, NULL, "free_running");
c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval");
@@ -1179,11 +1207,18 @@ struct clock *clock_create(enum clock_type type, struct config *config,
return NULL;
}
- /* Create the UDS interface. */
+ /* Create the UDS interfaces. */
+
c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0,
c->uds_rw_if, c);
if (!c->uds_rw_port) {
- pr_err("failed to open the UDS port");
+ pr_err("failed to open the UDS-RW port");
+ return NULL;
+ }
+ c->uds_ro_port = port_open(phc_device, phc_index, timestamping, 0,
+ c->uds_ro_if, c);
+ if (!c->uds_ro_port) {
+ pr_err("failed to open the UDS-RO port");
return NULL;
}
clock_fda_changed(c);
@@ -1208,6 +1243,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
port_dispatch(p, EV_INITIALIZE, 0);
}
port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
+ port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0);
return c;
}
@@ -1278,9 +1314,9 @@ static int clock_resize_pollfd(struct clock *c, int new_nports)
{
struct pollfd *new_pollfd;
- /* Need to allocate one whole extra block of fds for UDS. */
+ /* Need to allocate two whole extra blocks of fds for UDS ports. */
new_pollfd = realloc(c->pollfd,
- (new_nports + 1) * N_CLOCK_PFD *
+ (new_nports + 2) * N_CLOCK_PFD *
sizeof(struct pollfd));
if (!new_pollfd) {
return -1;
@@ -1316,6 +1352,8 @@ static void clock_check_pollfd(struct clock *c)
dest += N_CLOCK_PFD;
}
clock_fill_pollfd(dest, c->uds_rw_port);
+ dest += N_CLOCK_PFD;
+ clock_fill_pollfd(dest, c->uds_ro_port);
c->pollfd_valid = 1;
}
@@ -1331,7 +1369,8 @@ static int clock_do_forward_mgmt(struct clock *c,
if (in == out || !forwarding(c, out))
return 0;
- /* Don't forward any requests to the UDS port. */
+ /* Don't forward any requests to the UDS-RW port
+ (the UDS-RO port doesn't allow any forwarding). */
if (out == c->uds_rw_port) {
switch (management_action(msg)) {
case GET:
@@ -1416,7 +1455,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
return changed;
}
if (p != c->uds_rw_port) {
- /* Sorry, only allowed on the UDS port. */
+ /* Sorry, only allowed on the UDS-RW port. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return changed;
}
@@ -1425,7 +1464,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
break;
case COMMAND:
if (p != c->uds_rw_port) {
- /* Sorry, only allowed on the UDS port. */
+ /* Sorry, only allowed on the UDS-RW port. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return changed;
}
@@ -1437,7 +1476,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
switch (mgt->id) {
case TLV_PORT_PROPERTIES_NP:
if (p != c->uds_rw_port) {
- /* Only the UDS port allowed. */
+ /* Only the UDS-RW port allowed. */
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
return 0;
}
@@ -1548,7 +1587,7 @@ int clock_poll(struct clock *c)
struct port *p;
clock_check_pollfd(c);
- cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1);
+ cnt = poll(c->pollfd, (c->nports + 2) * N_CLOCK_PFD, -1);
if (cnt < 0) {
if (EINTR == errno) {
return 0;
@@ -1602,7 +1641,7 @@ int clock_poll(struct clock *c)
cur += N_CLOCK_PFD;
}
- /* Check the UDS port. */
+ /* Check the UDS ports. */
for (i = 0; i < N_POLLFD; i++) {
if (cur[i].revents & (POLLIN|POLLPRI)) {
event = port_event(c->uds_rw_port, i);
@@ -1611,6 +1650,13 @@ int clock_poll(struct clock *c)
}
}
}
+ cur += N_CLOCK_PFD;
+ for (i = 0; i < N_POLLFD; i++) {
+ if (cur[i].revents & (POLLIN|POLLPRI)) {
+ event = port_event(c->uds_ro_port, i);
+ /* sde is not expected on the UDS-RO port */
+ }
+ }
if (c->sde) {
handle_state_decision_event(c);
diff --git a/config.c b/config.c
index d237de9..96a5351 100644
--- a/config.c
+++ b/config.c
@@ -323,6 +323,7 @@ struct config_item config_tab[] = {
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
+ GLOB_ITEM_STR("uds_ro_address", "/var/run/ptp4lro"),
PORT_ITEM_INT("unicast_listen", 0, 0, 1),
PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX),
PORT_ITEM_INT("unicast_req_duration", 3600, 10, INT_MAX),
diff --git a/configs/default.cfg b/configs/default.cfg
index 8c19129..d5bab7d 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -90,6 +90,7 @@ p2p_dst_mac 01:80:C2:00:00:0E
udp_ttl 1
udp6_scope 0x0E
uds_address /var/run/ptp4l
+uds_ro_address /var/run/ptp4lro
#
# Default interface options
#
diff --git a/ptp4l.8 b/ptp4l.8
index b179b81..f9bd228 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -615,6 +615,12 @@ is only relevant with IPv6 transport. See RFC 4291. The default is
Specifies the address of the UNIX domain socket for receiving local
management messages. The default is /var/run/ptp4l.
.TP
+.B uds_ro_address
+Specifies the address of the second UNIX domain socket for receiving local
+management messages, which is restricted to GET actions and does not forward
+messages to other ports. Access to this socket can be given to untrusted
+applications for monitoring purposes. The default is /var/run/ptp4lro.
+.TP
.B dscp_event
Defines the Differentiated Services Codepoint (DSCP) to be used for PTP
event messages. Must be a value between 0 and 63. There are several media
commit d4c5343237588d265c605f3772337bc88cabe787
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Feb 11 16:47:12 2021 +0100
timemaster: Set uds_ro_address for ptp4l instances.
This prevents conflicts on the new UDS-RO port.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/timemaster.c b/timemaster.c
index 00db59f..02408d6 100644
--- a/timemaster.c
+++ b/timemaster.c
@@ -712,7 +712,7 @@ static int add_ptp_source(struct ptp_domain *source,
char **ntp_config, struct script *script)
{
struct config_file *config_file;
- char **command, *uds_path, **interfaces, *message_tag;
+ char **command, *uds_path, *uds_path2, **interfaces, *message_tag;
char ts_interface[IF_NAMESIZE];
int i, j, num_interfaces, *phc, *phcs, hw_ts, sw_ts;
struct sk_ts_info ts_info;
@@ -809,6 +809,8 @@ static int add_ptp_source(struct ptp_domain *source,
uds_path = string_newf("%s/ptp4l.%d.socket",
config->rundir, *shm_segment);
+ uds_path2 = string_newf("%s/ptp4lro.%d.socket",
+ config->rundir, *shm_segment);
message_tag = string_newf("[%d", source->domain);
for (j = 0; interfaces[j]; j++)
@@ -832,8 +834,10 @@ static int add_ptp_source(struct ptp_domain *source,
"slaveOnly 1\n"
"domainNumber %d\n"
"uds_address %s\n"
+ "uds_ro_address %s\n"
"message_tag %s\n",
- source->domain, uds_path, message_tag);
+ source->domain, uds_path, uds_path2,
+ message_tag);
if (phcs[i] >= 0) {
/* HW time stamping */
@@ -868,6 +872,7 @@ static int add_ptp_source(struct ptp_domain *source,
free(message_tag);
free(uds_path);
+ free(uds_path2);
free(interfaces);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,451 +0,0 @@
commit afd709924edcea26fec24a6253d1b85fc94c88e6
Author: Hangbin Liu <liuhangbin@gmail.com>
Date: Wed May 25 14:46:14 2022 +0800
ptp4l: init iface->ts_label when interface created
It's redundant to ensure tslabel if we could get ts_info directly from
the interface. By init iface->ts_label when interface created, there is
no need to take care of ts_label on other places.
It will also make the later vlan over bonding support patch more clear
after removing function interface_ensure_tslabel().
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
diff --git a/clock.c b/clock.c
index 7ffbd6a..d4f273f 100644
--- a/clock.c
+++ b/clock.c
@@ -1006,9 +1006,8 @@ struct clock *clock_create(enum clock_type type, struct config *config,
required_modes = clock_required_modes(c);
STAILQ_FOREACH(iface, &config->interfaces, list) {
memset(ts_label, 0, sizeof(ts_label));
- rtnl_get_ts_device(interface_name(iface), ts_label);
- interface_set_label(iface, ts_label);
- interface_ensure_tslabel(iface);
+ if (!rtnl_get_ts_device(interface_name(iface), ts_label))
+ interface_set_label(iface, ts_label);
interface_get_tsinfo(iface);
if (interface_tsinfo_valid(iface) &&
!interface_tsmodes_supported(iface, required_modes)) {
diff --git a/interface.c b/interface.c
index 445a270..6c2630c 100644
--- a/interface.c
+++ b/interface.c
@@ -24,6 +24,7 @@ struct interface *interface_create(const char *name)
return NULL;
}
strncpy(iface->name, name, MAX_IFNAME_SIZE);
+ strncpy(iface->ts_label, name, MAX_IFNAME_SIZE);
iface->vclock = -1;
return iface;
@@ -34,13 +35,6 @@ void interface_destroy(struct interface *iface)
free(iface);
}
-void interface_ensure_tslabel(struct interface *iface)
-{
- if (!iface->ts_label[0]) {
- memcpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE);
- }
-}
-
int interface_get_tsinfo(struct interface *iface)
{
return sk_get_ts_info(iface->ts_label, &iface->ts_info);
diff --git a/interface.h b/interface.h
index 752f4f1..5fc7836 100644
--- a/interface.h
+++ b/interface.h
@@ -33,12 +33,6 @@ struct interface *interface_create(const char *name);
*/
void interface_destroy(struct interface *iface);
-/**
- * Ensures that an interface has a proper time stamping label.
- * @param iface The interface of interest.
- */
-void interface_ensure_tslabel(struct interface *iface);
-
/**
* Populate the time stamping information of a given interface.
* @param iface The interface of interest.
diff --git a/nsm.c b/nsm.c
index 5aa925b..8d4a362 100644
--- a/nsm.c
+++ b/nsm.c
@@ -274,9 +274,8 @@ static int nsm_open(struct nsm *nsm, struct config *cfg)
STAILQ_FOREACH(iface, &cfg->interfaces, list) {
ifname = interface_name(iface);
memset(ts_label, 0, sizeof(ts_label));
- rtnl_get_ts_device(ifname, ts_label);
- interface_set_label(iface, ts_label);
- interface_ensure_tslabel(iface);
+ if (!rtnl_get_ts_device(ifname, ts_label))
+ interface_set_label(iface, ts_label);
count++;
}
if (count != 1) {
diff --git a/pmc_common.c b/pmc_common.c
index 756edf5..ee2ece6 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -405,7 +405,6 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type,
pr_err("failed to create interface");
goto failed;
}
- interface_ensure_tslabel(pmc->iface);
if (transport_open(pmc->transport, pmc->iface,
&pmc->fdarray, TS_SOFTWARE)) {
commit 6aab466eb0563c1025c78ab496b22a8833b02d20
Author: Vincent Cheng <vincent.cheng.xh@renesas.com>
Date: Fri Jan 8 10:21:14 2021 -0500
port: Fix link down/up to continue using phc_index set from command line -p option.
In the scenario where a port link goes down and up, current code checks
the port's phc_index against the interface's phc_index and if they are
different will set the port phc_index to the interface phc_index.
If the phc_index was initially set by the command line -p option, then we
end up using the wrong phc_index.
Fix is to skip updating the port phc_index with the interface phc_index
when port link is back up if it was initialy set from the command line.
Signed-off-by: Vincent Cheng <vincent.cheng.xh@renesas.com>
diff --git a/port.c b/port.c
index 70b6e60..d22f30f 100644
--- a/port.c
+++ b/port.c
@@ -2601,6 +2601,11 @@ void port_link_status(void *ctx, int linkup, int ts_index)
"timestamping mode, set link status down by force.",
interface_label(p->iface));
p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
+ } else if (p->phc_from_cmdline) {
+ pr_warning("port %d: taking /dev/ptp%d from the "
+ "command line, not the attached ptp%d",
+ portnum(p), p->phc_index,
+ interface_phc_index(p->iface));
} else if (p->phc_index != interface_phc_index(p->iface)) {
p->phc_index = interface_phc_index(p->iface);
@@ -3107,6 +3112,7 @@ struct port *port_open(const char *phc_device,
"not the attached ptp%d", number, phc_device,
interface_phc_index(interface));
p->phc_index = phc_index;
+ p->phc_from_cmdline = 1;
} else {
pr_err("port %d: PHC device mismatch", number);
pr_err("port %d: /dev/ptp%d requested, ptp%d attached",
diff --git a/port_private.h b/port_private.h
index fcabaa6..6e40e15 100644
--- a/port_private.h
+++ b/port_private.h
@@ -69,6 +69,7 @@ struct port {
struct fdarray fda;
int fault_fd;
int phc_index;
+ int phc_from_cmdline;
void (*dispatch)(struct port *p, enum fsm_event event, int mdiff);
enum fsm_event (*event)(struct port *p, int fd_index);
commit 45f20e824fdfb8748d73495ccc7578dc70866282
Author: Hangbin Liu <liuhangbin@gmail.com>
Date: Wed May 25 14:46:15 2022 +0800
port: refactor port_link_status
Split port_change_phc() logic form port_link_status() to improve the
readability of the code
(Rebased to 3.1.1)
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
diff --git a/port.c b/port.c
index d22f30f..031b212 100644
--- a/port.c
+++ b/port.c
@@ -2563,10 +2563,43 @@ static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff)
}
}
+static void port_change_phc(struct port *p)
+{
+ int required_modes;
+
+ /* Only switch a non-vclock PHC with HW time stamping. */
+ if (!interface_tsinfo_valid(p->iface) ||
+ interface_get_vclock(p->iface) >= 0 ||
+ interface_phc_index(p->iface) < 0)
+ return;
+
+ required_modes = clock_required_modes(p->clock);
+ if (!interface_tsmodes_supported(p->iface, required_modes)) {
+ pr_err("interface '%s' does not support requested "
+ "timestamping mode, set link status down by force.",
+ interface_label(p->iface));
+ p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
+ } else if (p->phc_from_cmdline) {
+ pr_warning("port %d: taking /dev/ptp%d from the "
+ "command line, not the attached ptp%d",
+ portnum(p), p->phc_index,
+ interface_phc_index(p->iface));
+ } else if (p->phc_index != interface_phc_index(p->iface)) {
+ p->phc_index = interface_phc_index(p->iface);
+
+ if (clock_switch_phc(p->clock, p->phc_index)) {
+ p->last_fault_type = FT_SWITCH_PHC;
+ port_dispatch(p, EV_FAULT_DETECTED, 0);
+ return;
+ }
+ clock_sync_interval(p->clock, p->log_sync_interval);
+ }
+}
+
void port_link_status(void *ctx, int linkup, int ts_index)
{
char ts_label[MAX_IFNAME_SIZE + 1] = {0};
- int link_state, required_modes;
+ int link_state;
const char *old_ts_label;
struct port *p = ctx;
@@ -2590,33 +2623,7 @@ void port_link_status(void *ctx, int linkup, int ts_index)
if (p->link_status & LINK_UP &&
(p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) {
interface_get_tsinfo(p->iface);
-
- /* Only switch a non-vclock PHC with HW time stamping. */
- if (interface_tsinfo_valid(p->iface) &&
- interface_get_vclock(p->iface) < 0 &&
- interface_phc_index(p->iface) >= 0) {
- required_modes = clock_required_modes(p->clock);
- if (!interface_tsmodes_supported(p->iface, required_modes)) {
- pr_err("interface '%s' does not support requested "
- "timestamping mode, set link status down by force.",
- interface_label(p->iface));
- p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
- } else if (p->phc_from_cmdline) {
- pr_warning("port %d: taking /dev/ptp%d from the "
- "command line, not the attached ptp%d",
- portnum(p), p->phc_index,
- interface_phc_index(p->iface));
- } else if (p->phc_index != interface_phc_index(p->iface)) {
- p->phc_index = interface_phc_index(p->iface);
-
- if (clock_switch_phc(p->clock, p->phc_index)) {
- p->last_fault_type = FT_SWITCH_PHC;
- port_dispatch(p, EV_FAULT_DETECTED, 0);
- return;
- }
- clock_sync_interval(p->clock, p->log_sync_interval);
- }
- }
+ port_change_phc(p);
}
/*
commit 878c2eac77cc7abd1d86620a82ae9046545439ea
Author: Hangbin Liu <liuhangbin@gmail.com>
Date: Wed May 25 14:46:16 2022 +0800
ptp4l: add VLAN over bond support
Latest Linux kernel has supported getting active port's PHC from bond
directly. This would help topology like VLAN over bond to get PHC natively,
as VLAN also albe to get downlink's PHC.
To achieve this, the new hwtstamp flag is needed when passing hwtstamp_config
to kernel. Let's supply the flag first, and fall back without flag if user
run on old kernel.
We also need to update the PHC index in port_link_status() when there is
a RTNL event. The PHC info will be update in later port_change_phc().
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
diff --git a/clock.c b/clock.c
index d4f273f..f3df220 100644
--- a/clock.c
+++ b/clock.c
@@ -1758,6 +1758,9 @@ int clock_switch_phc(struct clock *c, int phc_index)
c->clkid = clkid;
c->servo = servo;
c->servo_state = SERVO_UNLOCKED;
+
+ pr_info("Switched to /dev/ptp%d as PTP clock", phc_index);
+
return 0;
}
diff --git a/missing.h b/missing.h
index c5194f4..5f684dd 100644
--- a/missing.h
+++ b/missing.h
@@ -73,6 +73,12 @@ struct so_timestamping {
};
#endif
+#ifndef HWTSTAMP_FLAG_BONDED_PHC_INDEX
+enum {
+ HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0),
+};
+#endif
+
#ifdef PTP_EXTTS_REQUEST2
#define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m"
#else
diff --git a/port.c b/port.c
index 031b212..ae9c4d3 100644
--- a/port.c
+++ b/port.c
@@ -2619,12 +2619,18 @@ void port_link_status(void *ctx, int linkup, int ts_index)
pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label);
}
+ /* phc index may changed while ts_label keeps the same after failover.
+ * e.g. vlan over bond. Since the lower link changed, we still set
+ * the TS_LABEL_CHANGED flag.
+ */
+ interface_get_tsinfo(p->iface);
+ if (p->phc_index != interface_phc_index(p->iface))
+ p->link_status |= TS_LABEL_CHANGED;
+
/* Both link down/up and change ts_label may change phc index. */
if (p->link_status & LINK_UP &&
- (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) {
- interface_get_tsinfo(p->iface);
+ (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED))
port_change_phc(p);
- }
/*
* A port going down can affect the BMCA result.
diff --git a/sk.c b/sk.c
index b55d6b5..80075be 100644
--- a/sk.c
+++ b/sk.c
@@ -66,6 +66,11 @@ static int hwts_init(int fd, const char *device, int rx_filter,
init_ifreq(&ifreq, &cfg, device);
+ cfg.flags = HWTSTAMP_FLAG_BONDED_PHC_INDEX;
+ /* Fall back without flag if user run new build on old kernel */
+ if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) == -EINVAL)
+ init_ifreq(&ifreq, &cfg, device);
+
switch (sk_hwts_filter_mode) {
case HWTS_FILTER_CHECK:
err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
commit 98edb4d72b3d1d4e988f810b9a9cb1078212e5dc
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Nov 22 17:07:16 2022 +0100
port: Avoid faults with vclocks and PHC from command line.
After commit afeabf3c90ed ("ptp4l: add VLAN over bond support") the
TS_LABEL_CHANGED flag was set on link status changes when the used
PHC index was different from the PHC index of the interface.
This caused the port to be constantly switching to the faulty state when
using vclocks, or a different PHC device was forced with the -p option,
where it is expected the used PHC doesn't match the interface's PHC.
Rework port_link_status() and port_change_phc() to avoid setting the
flag and switch the clock only in the cases where it is expected.
Fixes: afeabf3c90ed ("ptp4l: add VLAN over bond support")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/port.c b/port.c
index ae9c4d3..96e097a 100644
--- a/port.c
+++ b/port.c
@@ -2567,10 +2567,13 @@ static void port_change_phc(struct port *p)
{
int required_modes;
- /* Only switch a non-vclock PHC with HW time stamping. */
- if (!interface_tsinfo_valid(p->iface) ||
+ /* Try to switch only if the interface is up, it has HW time stamping
+ using a non-vclock PHC, and the PHC actually changed. */
+ if (!(p->link_status & LINK_UP) ||
+ !interface_tsinfo_valid(p->iface) ||
interface_get_vclock(p->iface) >= 0 ||
- interface_phc_index(p->iface) < 0)
+ interface_phc_index(p->iface) < 0 ||
+ p->phc_index == interface_phc_index(p->iface))
return;
required_modes = clock_required_modes(p->clock);
@@ -2584,7 +2587,7 @@ static void port_change_phc(struct port *p)
"command line, not the attached ptp%d",
portnum(p), p->phc_index,
interface_phc_index(p->iface));
- } else if (p->phc_index != interface_phc_index(p->iface)) {
+ } else {
p->phc_index = interface_phc_index(p->iface);
if (clock_switch_phc(p->clock, p->phc_index)) {
@@ -2619,18 +2622,12 @@ void port_link_status(void *ctx, int linkup, int ts_index)
pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label);
}
- /* phc index may changed while ts_label keeps the same after failover.
- * e.g. vlan over bond. Since the lower link changed, we still set
- * the TS_LABEL_CHANGED flag.
- */
+ /* The PHC index may change even with the same ts_label, e.g. after
+ failover with VLAN over bond. */
interface_get_tsinfo(p->iface);
- if (p->phc_index != interface_phc_index(p->iface))
- p->link_status |= TS_LABEL_CHANGED;
- /* Both link down/up and change ts_label may change phc index. */
- if (p->link_status & LINK_UP &&
- (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED))
- port_change_phc(p);
+ /* Switch the clock if needed */
+ port_change_phc(p);
/*
* A port going down can affect the BMCA result.
commit 8cf63218e4cc33d63bb783bf322d4a0d2f4be73e
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Mar 15 11:24:16 2023 +0100
port: Don't switch to PHC with SW timestamping.
When ptp4l was configured to use SW timestamping, but the interface
supported also HW timestamping, ptp4l detected a change of the PHC on
start, switched to it from the system clock, and tried to control the
PHC using SW timestamps.
Don't switch the PHC if the current PHC index is -1, which is expected
with SW timestamping and in the free-running mode.
Fixes: afeabf3c90ed ("ptp4l: add VLAN over bond support")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/port.c b/port.c
index 96e097a..32ee83b 100644
--- a/port.c
+++ b/port.c
@@ -2570,6 +2570,7 @@ static void port_change_phc(struct port *p)
/* Try to switch only if the interface is up, it has HW time stamping
using a non-vclock PHC, and the PHC actually changed. */
if (!(p->link_status & LINK_UP) ||
+ p->phc_index < 0 ||
!interface_tsinfo_valid(p->iface) ||
interface_get_vclock(p->iface) >= 0 ||
interface_phc_index(p->iface) < 0 ||

View File

@ -1,37 +0,0 @@
commit 9633ab52460f58c92c6daa35e9d24e4ce9c5ab1c
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Feb 23 11:01:43 2021 +0100
sk: Don't return error for zero-length messages.
The recvmsg() call can return zero for a zero-length UDP message, which
should be handled as a bad message and not a fault of the port. This was
addressed in commit 6b61ba29c78e ("Avoid fault when receiving zero
length packets"), but later regressed in commit a6e0b83bd503
("sk: Convey transmit path errors to the caller.").
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Fixes: a6e0b83bd503 ("sk: Convey transmit path errors to the caller.")
diff --git a/sk.c b/sk.c
index c9ef4d2..8be0708 100644
--- a/sk.c
+++ b/sk.c
@@ -391,7 +391,7 @@ int sk_receive(int fd, void *buf, int buflen,
if (!ts) {
memset(&hwts->ts, 0, sizeof(hwts->ts));
- return cnt < 1 ? -errno : cnt;
+ return cnt < 0 ? -errno : cnt;
}
switch (hwts->type) {
@@ -407,7 +407,7 @@ int sk_receive(int fd, void *buf, int buflen,
hwts->ts = timespec_to_tmv(ts[1]);
break;
}
- return cnt < 1 ? -errno : cnt;
+ return cnt < 0 ? -errno : cnt;
}
int sk_set_priority(int fd, int family, uint8_t dscp)

View File

@ -1,10 +1,10 @@
%global _hardened_build 1
%global testsuite_ver c66922
%global clknetsim_ver c63e22
%global testsuite_ver bf8ead
%global clknetsim_ver 5d1dc0
Name: linuxptp
Version: 3.1.1
Release: 8%{?dist}
Version: 4.2
Release: 2%{?dist}
Summary: PTP implementation for Linux
License: GPLv2+
@ -21,40 +21,20 @@ Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver
# simulator for test suite
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
# don't repeat some log messages in multi-port configuration
Patch1: linuxptp-logmsgs.patch
# add option to set clockClass threshold
Patch2: linuxptp-classthreshold.patch
# increase default TX timestamp timeout to 10 ms
Patch3: linuxptp-deftxtout.patch
# allow old syntax of SET SUBSCRIBE_EVENTS_NP command
Patch1: linuxptp-subscribe.patch
# disable warning messages about deprecated options
Patch2: linuxptp-deprecated.patch
# revert default PTP version to 2.0 for better compatibility
Patch3: linuxptp-ptpver.patch
# limit unicast message rate per address and grant duration
Patch4: linuxptp-ucastrate.patch
# add read-only UDS port
Patch5: linuxptp-udsro.patch
# fix quoting in ptp4l man page
Patch7: linuxptp-manfix.patch
# close lstab file after use
Patch8: linuxptp-fclose.patch
# fix handling of zero-length messages
Patch9: linuxptp-zerolength.patch
# avoid unaligned pointers to packed members
Patch10: linuxptp-packalign.patch
# make sanity clock check more reliable
Patch11: linuxptp-clockcheck.patch
# add support for virtual clocks
# fix ts2phc to handle large NMEA delay
Patch5: linuxptp-nmeadelay.patch
# fix loading and reloading of leapfile
Patch6: linuxptp-lstab.patch
# check for EL-specific kernels with vclock support
Patch12: linuxptp-vclock.patch
# handle PHC read failing with EBUSY in phc2sys
Patch13: linuxptp-phcerr.patch
# add support for VLAN over bond
Patch14: linuxptp-vlanbond.patch
# handle EINTR when waiting for transmit timestamp
Patch15: linuxptp-eintr.patch
# check for unexpected changes in frequency offset
Patch16: linuxptp-freqcheck.patch
# don't re-arm fault clearing timer on unrelated netlink events
Patch17: linuxptp-faultrearm.patch
# clear pending errors on sockets
Patch18: linuxptp-soerror.patch
BuildRequires: gcc gcc-c++ make systemd
@ -69,23 +49,7 @@ Supporting legacy APIs and other platforms is not a goal.
%prep
%setup -q -a 10 -a 11 -n %{name}-%{!?gitfullver:%{version}}%{?gitfullver}
%patch1 -p1 -b .logmsgs
%patch2 -p1 -b .classthreshold
%patch3 -p1 -b .deftxtout
%patch4 -p1 -b .ucastrate
%patch5 -p1 -b .udsro
%patch7 -p1 -b .manfix
%patch8 -p1 -b .fclose
%patch9 -p1 -b .zerolength
%patch10 -p1 -b .packalign
%patch11 -p1 -b .clockcheck
%patch12 -p1 -b .vclock
%patch13 -p1 -b .phcerr
%patch14 -p1 -b .vlanbond
%patch15 -p1 -b .eintr
%patch16 -p1 -b .freqcheck
%patch17 -p1 -b .faultrearm
%patch18 -p1 -b .soerror
%autopatch -p1
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
@ -144,10 +108,21 @@ PATH=..:$PATH ./run
%{_sbindir}/ptp4l
%{_sbindir}/timemaster
%{_sbindir}/ts2phc
%{_sbindir}/tz2alt
%{_mandir}/man5/*.5*
%{_mandir}/man8/*.8*
%changelog
* Thu Feb 22 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-2
- fix loading and reloading of leapfile
* Tue Jan 30 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
- update to 4.2 (RHEL-2026 RHEL-2342 RHEL-12182 RHEL-15929)
- fix ts2phc to handle large NMEA delay (RHEL-23208)
* Wed May 03 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-9
- clear pending errors on sockets (#2192559)
* Mon Mar 20 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-8
- don't switch from system clock to PHC with SW timestamping (#2179041)

View File

@ -1,3 +1,3 @@
SHA512 (linuxptp-3.1.1.tgz) = c3c40987fe68480a8473097ebc3c506fb4f8f3b6456bbe637b2b3cb0b3e0182f1513b511fdc04b3607d5f7d8bd1bd22502bb86eb13f9fa4fa63a3331846b33ec
SHA512 (linuxptp-testsuite-c66922.tar.gz) = 1cf30348bb72768e4de59c363f57b56257b01e5306e27b3d243418572ebfbf324c4cc9cb4f74cac04f8408223b501105aeec70a509cf76ae8e0945a01bc70dd6
SHA512 (clknetsim-c63e22.tar.gz) = 000b15b7877c32da06ea93d46dfc41bee51e13e7c3d9b64cfd660527f7ffdfefc5a3f49cc621512cd9f1bc28312113892630b2b6d06a2f3ee41cb4cb859219cd
SHA512 (linuxptp-4.2.tgz) = 479e512efd0573602379a9e1d8ef5c0ec9e033944cee5aed11c68cea5e8a3f7d4b6f2d11f6d6d4718282010da52c2c8629d675d9b388cc0c3d574845a913cdbb
SHA512 (linuxptp-testsuite-bf8ead.tar.gz) = 6a6d190e8ef43cdb91304f9dc69fd4bc71590b2178c10a8305ddc2660fdc0963a00721db46b951afb0aaf73b268ce2927bca6551010477b6e59ce64aeec22bc6
SHA512 (clknetsim-5d1dc0.tar.gz) = 76889da425dc9d63ba78811661d78ffa922a63c4f83aeb809fef02c866f64a97b09dd4b0906ccfd1e20cee5091d8b886aadfce54cd338d3bf597b0e976a78927