import linuxptp-3.1.1-1.el8
This commit is contained in:
parent
9cd3db172c
commit
e1c6ec378f
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
SOURCES/clknetsim-8b4842.tar.gz
|
SOURCES/clknetsim-ce3c4a.tar.gz
|
||||||
SOURCES/linuxptp-2.0.tgz
|
SOURCES/linuxptp-3.1.1.tgz
|
||||||
SOURCES/linuxptp-testsuite-a7f6e1.tar.gz
|
SOURCES/linuxptp-testsuite-c66922.tar.gz
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
b674017c26433870107fb18e160c7d88d7d2eb86 SOURCES/clknetsim-8b4842.tar.gz
|
338f0be03fd391857adc47306a091952d30d6b89 SOURCES/clknetsim-ce3c4a.tar.gz
|
||||||
592ca42c6146a79c1fcabed7c19fa7af4803d4f6 SOURCES/linuxptp-2.0.tgz
|
f905eabc6fd0f03c6a353f9c4ba188a3bd1b774c SOURCES/linuxptp-3.1.1.tgz
|
||||||
2b8edc55e4967660a0c4a3892c817c0e8f55c3bc SOURCES/linuxptp-testsuite-a7f6e1.tar.gz
|
73af42ccc7911c1c2d08fe313cb67329229a5a4b SOURCES/linuxptp-testsuite-c66922.tar.gz
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
diff -up linuxptp-2.0/util.c.addreq linuxptp-2.0/util.c
|
|
||||||
--- linuxptp-2.0/util.c.addreq 2019-03-25 11:43:55.878146767 +0100
|
|
||||||
+++ linuxptp-2.0/util.c 2019-03-25 11:44:38.215244483 +0100
|
|
||||||
@@ -78,7 +78,7 @@ int addreq(enum transport_type type, str
|
|
||||||
case TRANS_UDP_IPV4:
|
|
||||||
bufa = &a->sin.sin_addr;
|
|
||||||
bufb = &b->sin.sin_addr;
|
|
||||||
- len = sizeof(a->sin);
|
|
||||||
+ len = sizeof(a->sin.sin_addr);
|
|
||||||
break;
|
|
||||||
case TRANS_IEEE_802_3:
|
|
||||||
bufa = &a->sll.sll_addr;
|
|
138
SOURCES/linuxptp-classthreshold.patch
Normal file
138
SOURCES/linuxptp-classthreshold.patch
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
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.
|
82
SOURCES/linuxptp-deftxtout.patch
Normal file
82
SOURCES/linuxptp-deftxtout.patch
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
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
|
22
SOURCES/linuxptp-fclose.patch
Normal file
22
SOURCES/linuxptp-fclose.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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;
|
@ -1,51 +0,0 @@
|
|||||||
commit d663a483c40939bad58301c256d86da1f3da6cc0
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Tue Nov 13 13:16:08 2018 +0100
|
|
||||||
|
|
||||||
Fix building with new kernel headers.
|
|
||||||
|
|
||||||
net_tstamp.h in recent kernel versions requires time.h for clockid_t.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/clock.c b/clock.c
|
|
||||||
index 9c493c3..8533b39 100644
|
|
||||||
--- a/clock.c
|
|
||||||
+++ b/clock.c
|
|
||||||
@@ -17,11 +17,11 @@
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
#include <errno.h>
|
|
||||||
+#include <time.h>
|
|
||||||
#include <linux/net_tstamp.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
-#include <time.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
|
|
||||||
#include "address.h"
|
|
||||||
diff --git a/sk.c b/sk.c
|
|
||||||
index e2b1f28..30162eb 100644
|
|
||||||
--- a/sk.c
|
|
||||||
+++ b/sk.c
|
|
||||||
@@ -18,6 +18,7 @@
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
#include <errno.h>
|
|
||||||
+#include <time.h>
|
|
||||||
#include <linux/net_tstamp.h>
|
|
||||||
#include <linux/sockios.h>
|
|
||||||
#include <linux/ethtool.h>
|
|
||||||
diff --git a/timemaster.c b/timemaster.c
|
|
||||||
index 058678f..00db59f 100644
|
|
||||||
--- a/timemaster.c
|
|
||||||
+++ b/timemaster.c
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
#include <errno.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <limits.h>
|
|
||||||
+#include <time.h>
|
|
||||||
#include <linux/net_tstamp.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <signal.h>
|
|
@ -1,228 +0,0 @@
|
|||||||
commit 399907db7f9dc3f57c3f9831b3b4da705a2c51a3
|
|
||||||
Author: Erez Geva <erezgeva2@gmail.com>
|
|
||||||
Date: Tue Aug 28 22:05:28 2018 +0200
|
|
||||||
|
|
||||||
config: Add hardware time stamp filter setting mode
|
|
||||||
|
|
||||||
Add global option for the hardware time stamp setting.
|
|
||||||
The function could:
|
|
||||||
Normally set the filters as the PTP daemon require.
|
|
||||||
Check that the filters are proper but do not change them.
|
|
||||||
Full, set the RX filter to all and the TX filter as the PTP daemon require.
|
|
||||||
|
|
||||||
[ RC: added missing extern keyword and fixed indentation. ]
|
|
||||||
|
|
||||||
Signed-off-by: Erez Geva <erez.geva.ext@siemens.com>
|
|
||||||
Signed-off-by: Erez Geva <ErezGeva2@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/config.c b/config.c
|
|
||||||
index 7914ba4..3530ce6 100644
|
|
||||||
--- a/config.c
|
|
||||||
+++ b/config.c
|
|
||||||
@@ -164,6 +164,13 @@ static struct config_enum delay_mech_enu[] = {
|
|
||||||
{ NULL, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
+static struct config_enum hwts_filter_enu[] = {
|
|
||||||
+ { "normal", HWTS_FILTER_NORMAL },
|
|
||||||
+ { "check", HWTS_FILTER_CHECK },
|
|
||||||
+ { "full", HWTS_FILTER_FULL },
|
|
||||||
+ { NULL, 0 },
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static struct config_enum nw_trans_enu[] = {
|
|
||||||
{ "L2", TRANS_IEEE_802_3 },
|
|
||||||
{ "UDPv4", TRANS_UDP_IPV4 },
|
|
||||||
@@ -215,6 +222,7 @@ struct config_item config_tab[] = {
|
|
||||||
GLOB_ITEM_INT("G.8275.defaultDS.localPriority", 128, 1, UINT8_MAX),
|
|
||||||
PORT_ITEM_INT("G.8275.portDS.localPriority", 128, 1, UINT8_MAX),
|
|
||||||
GLOB_ITEM_INT("gmCapable", 1, 0, 1),
|
|
||||||
+ GLOB_ITEM_ENU("hwts_filter", HWTS_FILTER_NORMAL, hwts_filter_enu),
|
|
||||||
PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
|
|
||||||
PORT_ITEM_INT("ignore_transport_specific", 0, 0, 1),
|
|
||||||
PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX),
|
|
||||||
diff --git a/ptp4l.8 b/ptp4l.8
|
|
||||||
index 10c5c2f..39bf36e 100644
|
|
||||||
--- a/ptp4l.8
|
|
||||||
+++ b/ptp4l.8
|
|
||||||
@@ -661,6 +661,15 @@ The time source is a single byte code that gives an idea of the kind
|
|
||||||
of local clock in use. The value is purely informational, having no
|
|
||||||
effect on the outcome of the Best Master Clock algorithm, and is
|
|
||||||
advertised when the clock becomes grand master.
|
|
||||||
+.TP
|
|
||||||
+.B hwts_filter
|
|
||||||
+Select the hardware time stamp filter setting mode.
|
|
||||||
+Possible values are normal, check, full.
|
|
||||||
+Normal mode set the filters as needed.
|
|
||||||
+Check mode only check but do not set.
|
|
||||||
+Full mode set the receive filter to mark all packets with hardware time stamp,
|
|
||||||
+ so all applications can get them.
|
|
||||||
+The default is normal.
|
|
||||||
|
|
||||||
.SH UNICAST DISCOVERY OPTIONS
|
|
||||||
|
|
||||||
diff --git a/ptp4l.c b/ptp4l.c
|
|
||||||
index 9ef8169..3a9f084 100644
|
|
||||||
--- a/ptp4l.c
|
|
||||||
+++ b/ptp4l.c
|
|
||||||
@@ -191,6 +191,7 @@ int main(int argc, char *argv[])
|
|
||||||
assume_two_step = config_get_int(cfg, NULL, "assume_two_step");
|
|
||||||
sk_check_fupsync = config_get_int(cfg, NULL, "check_fup_sync");
|
|
||||||
sk_tx_timeout = config_get_int(cfg, NULL, "tx_timestamp_timeout");
|
|
||||||
+ sk_hwts_filter_mode = config_get_int(cfg, NULL, "hwts_filter");
|
|
||||||
|
|
||||||
if (config_get_int(cfg, NULL, "clock_servo") == CLOCK_SERVO_NTPSHM) {
|
|
||||||
config_set_int(cfg, "kernel_leap", 0);
|
|
||||||
diff --git a/sk.c b/sk.c
|
|
||||||
index f18b2bf..43f1800 100644
|
|
||||||
--- a/sk.c
|
|
||||||
+++ b/sk.c
|
|
||||||
@@ -40,39 +40,76 @@
|
|
||||||
|
|
||||||
int sk_tx_timeout = 1;
|
|
||||||
int sk_check_fupsync;
|
|
||||||
+enum hwts_filter_mode sk_hwts_filter_mode = HWTS_FILTER_NORMAL;
|
|
||||||
|
|
||||||
/* private methods */
|
|
||||||
|
|
||||||
-static int hwts_init(int fd, const char *device, int rx_filter, int tx_type)
|
|
||||||
+static void init_ifreq(struct ifreq *ifreq, struct hwtstamp_config *cfg,
|
|
||||||
+ const char *device)
|
|
||||||
{
|
|
||||||
- struct ifreq ifreq;
|
|
||||||
- struct hwtstamp_config cfg, req;
|
|
||||||
- int err;
|
|
||||||
+ memset(ifreq, 0, sizeof(*ifreq));
|
|
||||||
+ memset(cfg, 0, sizeof(*cfg));
|
|
||||||
|
|
||||||
- memset(&ifreq, 0, sizeof(ifreq));
|
|
||||||
- memset(&cfg, 0, sizeof(cfg));
|
|
||||||
+ strncpy(ifreq->ifr_name, device, sizeof(ifreq->ifr_name) - 1);
|
|
||||||
|
|
||||||
- strncpy(ifreq.ifr_name, device, sizeof(ifreq.ifr_name) - 1);
|
|
||||||
+ ifreq->ifr_data = (void *) cfg;
|
|
||||||
+}
|
|
||||||
|
|
||||||
- ifreq.ifr_data = (void *) &cfg;
|
|
||||||
- cfg.tx_type = tx_type;
|
|
||||||
- cfg.rx_filter = rx_filter;
|
|
||||||
- req = cfg;
|
|
||||||
- err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
|
|
||||||
- if (err < 0)
|
|
||||||
- return err;
|
|
||||||
+static int hwts_init(int fd, const char *device, int rx_filter,
|
|
||||||
+ int rx_filter2, int tx_type)
|
|
||||||
+{
|
|
||||||
+ struct ifreq ifreq;
|
|
||||||
+ struct hwtstamp_config cfg;
|
|
||||||
+ int err;
|
|
||||||
|
|
||||||
- if (memcmp(&cfg, &req, sizeof(cfg))) {
|
|
||||||
+ init_ifreq(&ifreq, &cfg, device);
|
|
||||||
|
|
||||||
- pr_debug("driver changed our HWTSTAMP options");
|
|
||||||
- pr_debug("tx_type %d not %d", cfg.tx_type, req.tx_type);
|
|
||||||
- pr_debug("rx_filter %d not %d", cfg.rx_filter, req.rx_filter);
|
|
||||||
+ switch (sk_hwts_filter_mode) {
|
|
||||||
+ case HWTS_FILTER_CHECK:
|
|
||||||
+ err = ioctl(fd, SIOCGHWTSTAMP, &ifreq);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ pr_err("ioctl SIOCGHWTSTAMP failed: %m");
|
|
||||||
+ return err;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case HWTS_FILTER_FULL:
|
|
||||||
+ cfg.tx_type = tx_type;
|
|
||||||
+ cfg.rx_filter = HWTSTAMP_FILTER_ALL;
|
|
||||||
+ err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ pr_err("ioctl SIOCSHWTSTAMP failed: %m");
|
|
||||||
+ return err;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case HWTS_FILTER_NORMAL:
|
|
||||||
+ cfg.tx_type = tx_type;
|
|
||||||
+ cfg.rx_filter = rx_filter;
|
|
||||||
+ err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ pr_info("driver rejected most general HWTSTAMP filter");
|
|
||||||
|
|
||||||
- if (cfg.tx_type != req.tx_type ||
|
|
||||||
- (cfg.rx_filter != HWTSTAMP_FILTER_ALL &&
|
|
||||||
- cfg.rx_filter != HWTSTAMP_FILTER_PTP_V2_EVENT)) {
|
|
||||||
- return -1;
|
|
||||||
+ init_ifreq(&ifreq, &cfg, device);
|
|
||||||
+ cfg.tx_type = tx_type;
|
|
||||||
+ cfg.rx_filter = rx_filter2;
|
|
||||||
+
|
|
||||||
+ err = ioctl(fd, SIOCSHWTSTAMP, &ifreq);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ pr_err("ioctl SIOCSHWTSTAMP failed: %m");
|
|
||||||
+ return err;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (cfg.tx_type != tx_type ||
|
|
||||||
+ (cfg.rx_filter != rx_filter &&
|
|
||||||
+ cfg.rx_filter != rx_filter2 &&
|
|
||||||
+ cfg.rx_filter != HWTSTAMP_FILTER_ALL)) {
|
|
||||||
+ pr_debug("tx_type %d not %d", cfg.tx_type, tx_type);
|
|
||||||
+ pr_debug("rx_filter %d not %d or %d", cfg.rx_filter, rx_filter,
|
|
||||||
+ rx_filter2);
|
|
||||||
+ pr_err("The current filter does not match the required");
|
|
||||||
+ return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -450,15 +487,9 @@ int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
|
|
||||||
case TRANS_UDS:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- err = hwts_init(fd, device, filter1, tx_type);
|
|
||||||
- if (err) {
|
|
||||||
- pr_info("driver rejected most general HWTSTAMP filter");
|
|
||||||
- err = hwts_init(fd, device, filter2, tx_type);
|
|
||||||
- if (err) {
|
|
||||||
- pr_err("ioctl SIOCSHWTSTAMP failed: %m");
|
|
||||||
- return err;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ err = hwts_init(fd, device, filter1, filter2, tx_type);
|
|
||||||
+ if (err)
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
|
|
||||||
diff --git a/sk.h b/sk.h
|
|
||||||
index d91d5d8..fd4d820 100644
|
|
||||||
--- a/sk.h
|
|
||||||
+++ b/sk.h
|
|
||||||
@@ -23,6 +23,16 @@
|
|
||||||
#include "address.h"
|
|
||||||
#include "transport.h"
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * Defines the available Hardware time-stamp setting modes.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+enum hwts_filter_mode {
|
|
||||||
+ HWTS_FILTER_NORMAL, /* set hardware filters in normal way */
|
|
||||||
+ HWTS_FILTER_CHECK, /* check filters but do not change them */
|
|
||||||
+ HWTS_FILTER_FULL, /* Use time-stamp on all received packets */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* Contains timestamping information returned by the GET_TS_INFO ioctl.
|
|
||||||
* @valid: set to non-zero when the info struct contains valid data.
|
|
||||||
@@ -131,4 +141,9 @@ extern int sk_tx_timeout;
|
|
||||||
*/
|
|
||||||
extern int sk_check_fupsync;
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * Hardware time-stamp setting mode
|
|
||||||
+ */
|
|
||||||
+extern enum hwts_filter_mode sk_hwts_filter_mode;
|
|
||||||
+
|
|
||||||
#endif
|
|
96
SOURCES/linuxptp-logmsgs.patch
Normal file
96
SOURCES/linuxptp-logmsgs.patch
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
28
SOURCES/linuxptp-manfix.patch
Normal file
28
SOURCES/linuxptp-manfix.patch
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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
|
@ -1,20 +0,0 @@
|
|||||||
commit 86723cfc6a7ac1d9b1bff5e90b7f4696d6460a0e
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Thu Mar 21 17:12:03 2019 +0100
|
|
||||||
|
|
||||||
pmc: Don't leak memory when msg_tlv_append() fails.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/pmc_common.c b/pmc_common.c
|
|
||||||
index 4a160f6..4d48e3a 100644
|
|
||||||
--- a/pmc_common.c
|
|
||||||
+++ b/pmc_common.c
|
|
||||||
@@ -546,6 +546,7 @@ int pmc_send_set_action(struct pmc *pmc, int id, void *data, int datasize)
|
|
||||||
}
|
|
||||||
extra = msg_tlv_append(msg, sizeof(*mgt) + datasize);
|
|
||||||
if (!extra) {
|
|
||||||
+ msg_put(msg);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
mgt = (struct management_tlv *) extra->tlv;
|
|
@ -1,486 +0,0 @@
|
|||||||
commit c0e49c708814ec783726fe92202371847703c5ed
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Mon Nov 12 17:27:58 2018 +0100
|
|
||||||
|
|
||||||
sysoff: Initialize data for ioctl(PTP_SYS_OFFSET).
|
|
||||||
|
|
||||||
This fixes valgrind errors.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/sysoff.c b/sysoff.c
|
|
||||||
index f7b6240..407a01c 100644
|
|
||||||
--- a/sysoff.c
|
|
||||||
+++ b/sysoff.c
|
|
||||||
@@ -18,6 +18,7 @@
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
+#include <string.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/ptp_clock.h>
|
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ int sysoff_measure(int fd, int n_samples,
|
|
||||||
int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
{
|
|
||||||
struct ptp_sys_offset pso;
|
|
||||||
+ memset(&pso, 0, sizeof(pso));
|
|
||||||
pso.n_samples = n_samples;
|
|
||||||
if (ioctl(fd, PTP_SYS_OFFSET, &pso)) {
|
|
||||||
perror("ioctl PTP_SYS_OFFSET");
|
|
||||||
|
|
||||||
commit 93baf34adb81046a5e1c3b9a3e685029f2046993
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Mon Nov 12 17:27:59 2018 +0100
|
|
||||||
|
|
||||||
sysoff: Extend API for different sysoff methods.
|
|
||||||
|
|
||||||
The kernel supports different PTP_SYS_OFFSET* ioctls. Use the sysoff
|
|
||||||
enum to allow selecting between them in sysoff_measure().
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/phc2sys.c b/phc2sys.c
|
|
||||||
index 15f8d75..2cd477a 100644
|
|
||||||
--- a/phc2sys.c
|
|
||||||
+++ b/phc2sys.c
|
|
||||||
@@ -74,7 +74,7 @@ struct clock {
|
|
||||||
LIST_ENTRY(clock) dst_list;
|
|
||||||
clockid_t clkid;
|
|
||||||
int phc_index;
|
|
||||||
- int sysoff_supported;
|
|
||||||
+ int sysoff_method;
|
|
||||||
int is_utc;
|
|
||||||
int dest_only;
|
|
||||||
int state;
|
|
||||||
@@ -255,9 +255,8 @@ static struct clock *clock_add(struct node *node, char *device)
|
|
||||||
c->servo = servo_add(node, c);
|
|
||||||
|
|
||||||
if (clkid != CLOCK_INVALID && clkid != CLOCK_REALTIME)
|
|
||||||
- c->sysoff_supported = (SYSOFF_SUPPORTED ==
|
|
||||||
- sysoff_probe(CLOCKID_TO_FD(clkid),
|
|
||||||
- node->phc_readings));
|
|
||||||
+ c->sysoff_method = sysoff_probe(CLOCKID_TO_FD(clkid),
|
|
||||||
+ node->phc_readings);
|
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&node->clocks, c, list);
|
|
||||||
return c;
|
|
||||||
@@ -784,11 +783,12 @@ static int do_loop(struct node *node, int subscriptions)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clock->clkid == CLOCK_REALTIME &&
|
|
||||||
- node->master->sysoff_supported) {
|
|
||||||
+ node->master->sysoff_method >= 0) {
|
|
||||||
/* use sysoff */
|
|
||||||
if (sysoff_measure(CLOCKID_TO_FD(node->master->clkid),
|
|
||||||
+ node->master->sysoff_method,
|
|
||||||
node->phc_readings,
|
|
||||||
- &offset, &ts, &delay))
|
|
||||||
+ &offset, &ts, &delay) < 0)
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
/* use phc */
|
|
||||||
diff --git a/phc_ctl.c b/phc_ctl.c
|
|
||||||
index 4a78a19..b9a9cf4 100644
|
|
||||||
--- a/phc_ctl.c
|
|
||||||
+++ b/phc_ctl.c
|
|
||||||
@@ -367,10 +367,12 @@ static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
|
|
||||||
struct timespec ts, rta, rtb;
|
|
||||||
int64_t sys_offset, delay = 0, offset;
|
|
||||||
uint64_t sys_ts;
|
|
||||||
+ int method;
|
|
||||||
|
|
||||||
- if (SYSOFF_SUPPORTED ==
|
|
||||||
- sysoff_measure(CLOCKID_TO_FD(clkid),
|
|
||||||
- 9, &sys_offset, &sys_ts, &delay)) {
|
|
||||||
+ method = sysoff_probe(CLOCKID_TO_FD(clkid), 9);
|
|
||||||
+
|
|
||||||
+ if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9,
|
|
||||||
+ &sys_offset, &sys_ts, &delay) >= 0) {
|
|
||||||
pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n",
|
|
||||||
sys_offset);
|
|
||||||
return 0;
|
|
||||||
diff --git a/sysoff.c b/sysoff.c
|
|
||||||
index 407a01c..f709a9b 100644
|
|
||||||
--- a/sysoff.c
|
|
||||||
+++ b/sysoff.c
|
|
||||||
@@ -73,8 +73,8 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
|
|
||||||
return samples[0].offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int sysoff_measure(int fd, int n_samples,
|
|
||||||
- int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
+static int sysoff_basic(int fd, int n_samples,
|
|
||||||
+ int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
{
|
|
||||||
struct ptp_sys_offset pso;
|
|
||||||
memset(&pso, 0, sizeof(pso));
|
|
||||||
@@ -84,13 +84,24 @@ int sysoff_measure(int fd, int n_samples,
|
|
||||||
return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
}
|
|
||||||
*result = sysoff_estimate(pso.ts, n_samples, ts, delay);
|
|
||||||
- return SYSOFF_SUPPORTED;
|
|
||||||
+ return SYSOFF_BASIC;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int sysoff_measure(int fd, int method, int n_samples,
|
|
||||||
+ int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
+{
|
|
||||||
+ switch (method) {
|
|
||||||
+ case SYSOFF_BASIC:
|
|
||||||
+ return sysoff_basic(fd, n_samples, result, ts, delay);
|
|
||||||
+ }
|
|
||||||
+ return SYSOFF_COMPILE_TIME_MISSING;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sysoff_probe(int fd, int n_samples)
|
|
||||||
{
|
|
||||||
int64_t junk, delay;
|
|
||||||
uint64_t ts;
|
|
||||||
+ int i;
|
|
||||||
|
|
||||||
if (n_samples > PTP_MAX_SAMPLES) {
|
|
||||||
fprintf(stderr, "warning: %d exceeds kernel max readings %d\n",
|
|
||||||
@@ -99,7 +110,13 @@ int sysoff_probe(int fd, int n_samples)
|
|
||||||
return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return sysoff_measure(fd, n_samples, &junk, &ts, &delay);
|
|
||||||
+ for (i = 0; i < SYSOFF_LAST; i++) {
|
|
||||||
+ if (sysoff_measure(fd, i, n_samples, &junk, &ts, &delay) < 0)
|
|
||||||
+ continue;
|
|
||||||
+ return i;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !PTP_SYS_OFFSET */
|
|
||||||
diff --git a/sysoff.h b/sysoff.h
|
|
||||||
index cb70265..02ecdfa 100644
|
|
||||||
--- a/sysoff.h
|
|
||||||
+++ b/sysoff.h
|
|
||||||
@@ -21,13 +21,14 @@
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
- SYSOFF_SUPPORTED,
|
|
||||||
- SYSOFF_COMPILE_TIME_MISSING,
|
|
||||||
- SYSOFF_RUN_TIME_MISSING,
|
|
||||||
+ SYSOFF_COMPILE_TIME_MISSING = -2,
|
|
||||||
+ SYSOFF_RUN_TIME_MISSING = -1,
|
|
||||||
+ SYSOFF_BASIC,
|
|
||||||
+ SYSOFF_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
- * Check to see if the PTP_SYS_OFFSET ioctl is supported.
|
|
||||||
+ * Check to see if a PTP_SYS_OFFSET ioctl is supported.
|
|
||||||
* @param fd An open file descriptor to a PHC device.
|
|
||||||
* @return One of the SYSOFF_ enumeration values.
|
|
||||||
*/
|
|
||||||
@@ -36,11 +37,12 @@ int sysoff_probe(int fd, int n_samples);
|
|
||||||
/**
|
|
||||||
* Measure the offset between a PHC and the system time.
|
|
||||||
* @param fd An open file descriptor to a PHC device.
|
|
||||||
+ * @param method A non-negative SYSOFF_ value returned by sysoff_probe().
|
|
||||||
* @param n_samples The number of consecutive readings to make.
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
-int sysoff_measure(int fd, int n_samples,
|
|
||||||
+int sysoff_measure(int fd, int method, int n_samples,
|
|
||||||
int64_t *result, uint64_t *ts, int64_t *delay);
|
|
||||||
|
|
||||||
commit 192b8e315c4585489d7aa7f59683035998805e40
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Mon Nov 12 17:28:00 2018 +0100
|
|
||||||
|
|
||||||
sysoff: Add support for PTP_SYS_OFFSET_PRECISE ioctl.
|
|
||||||
|
|
||||||
This ioctl uses cross timestamping for a more accurate measurement of
|
|
||||||
the offset. It is supported on some onboard Intel NICs using the e1000e
|
|
||||||
driver and a virtual PHC with the ptp_kvm driver.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/sysoff.c b/sysoff.c
|
|
||||||
index f709a9b..9f65d95 100644
|
|
||||||
--- a/sysoff.c
|
|
||||||
+++ b/sysoff.c
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/ptp_clock.h>
|
|
||||||
|
|
||||||
+#include "print.h"
|
|
||||||
#include "sysoff.h"
|
|
||||||
|
|
||||||
#define NS_PER_SEC 1000000000LL
|
|
||||||
@@ -39,6 +40,23 @@ static struct {
|
|
||||||
uint64_t timestamp;
|
|
||||||
} samples[PTP_MAX_SAMPLES];
|
|
||||||
|
|
||||||
+static int sysoff_precise(int fd, int64_t *result, uint64_t *ts)
|
|
||||||
+{
|
|
||||||
+#ifdef PTP_SYS_OFFSET_PRECISE
|
|
||||||
+ 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");
|
|
||||||
+ return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
+ }
|
|
||||||
+ *result = pctns(&pso.sys_realtime) - pctns(&pso.device);
|
|
||||||
+ *ts = pctns(&pso.sys_realtime);
|
|
||||||
+ return SYSOFF_PRECISE;
|
|
||||||
+#else
|
|
||||||
+ return SYSOFF_COMPILE_TIME_MISSING;
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_t ts)
|
|
||||||
{
|
|
||||||
int i = length - 1;
|
|
||||||
@@ -91,6 +109,9 @@ int sysoff_measure(int fd, int method, int n_samples,
|
|
||||||
int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
{
|
|
||||||
switch (method) {
|
|
||||||
+ case SYSOFF_PRECISE:
|
|
||||||
+ *delay = 0;
|
|
||||||
+ return sysoff_precise(fd, result, ts);
|
|
||||||
case SYSOFF_BASIC:
|
|
||||||
return sysoff_basic(fd, n_samples, result, ts, delay);
|
|
||||||
}
|
|
||||||
diff --git a/sysoff.h b/sysoff.h
|
|
||||||
index 02ecdfa..37f7353 100644
|
|
||||||
--- a/sysoff.h
|
|
||||||
+++ b/sysoff.h
|
|
||||||
@@ -23,6 +23,7 @@
|
|
||||||
enum {
|
|
||||||
SYSOFF_COMPILE_TIME_MISSING = -2,
|
|
||||||
SYSOFF_RUN_TIME_MISSING = -1,
|
|
||||||
+ SYSOFF_PRECISE,
|
|
||||||
SYSOFF_BASIC,
|
|
||||||
SYSOFF_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
commit 68a9011c9d7d859920da339ba59c14dc1d617a45
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Mon Nov 12 17:28:01 2018 +0100
|
|
||||||
|
|
||||||
sysoff: Add support for PTP_SYS_OFFSET_EXTENDED ioctl.
|
|
||||||
|
|
||||||
This is a more accurate variant of the the PTP_SYS_OFFSET ioctl, which
|
|
||||||
will probably be supported in future kernel versions.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/sysoff.c b/sysoff.c
|
|
||||||
index 9f65d95..b993ee9 100644
|
|
||||||
--- a/sysoff.c
|
|
||||||
+++ b/sysoff.c
|
|
||||||
@@ -71,17 +71,23 @@ static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_
|
|
||||||
samples[i+1].timestamp = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
|
|
||||||
- uint64_t *ts, int64_t *delay)
|
|
||||||
+static int64_t sysoff_estimate(struct ptp_clock_time *pct, int extended,
|
|
||||||
+ int n_samples, uint64_t *ts, int64_t *delay)
|
|
||||||
{
|
|
||||||
int64_t t1, t2, tp;
|
|
||||||
int64_t interval, offset;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_samples; i++) {
|
|
||||||
- t1 = pctns(&pct[2*i]);
|
|
||||||
- tp = pctns(&pct[2*i+1]);
|
|
||||||
- t2 = pctns(&pct[2*i+2]);
|
|
||||||
+ if (extended) {
|
|
||||||
+ t1 = pctns(&pct[3*i]);
|
|
||||||
+ tp = pctns(&pct[3*i+1]);
|
|
||||||
+ t2 = pctns(&pct[3*i+2]);
|
|
||||||
+ } else {
|
|
||||||
+ t1 = pctns(&pct[2*i]);
|
|
||||||
+ tp = pctns(&pct[2*i+1]);
|
|
||||||
+ t2 = pctns(&pct[2*i+2]);
|
|
||||||
+ }
|
|
||||||
interval = t2 - t1;
|
|
||||||
offset = (t2 + t1) / 2 - tp;
|
|
||||||
insertion_sort(i, interval, offset, (t2 + t1) / 2);
|
|
||||||
@@ -91,6 +97,24 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples,
|
|
||||||
return samples[0].offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int sysoff_extended(int fd, int n_samples,
|
|
||||||
+ int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
+{
|
|
||||||
+#ifdef PTP_SYS_OFFSET_EXTENDED
|
|
||||||
+ struct ptp_sys_offset_extended pso;
|
|
||||||
+ 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");
|
|
||||||
+ return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
+ }
|
|
||||||
+ *result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay);
|
|
||||||
+ return SYSOFF_EXTENDED;
|
|
||||||
+#else
|
|
||||||
+ return SYSOFF_COMPILE_TIME_MISSING;
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int sysoff_basic(int fd, int n_samples,
|
|
||||||
int64_t *result, uint64_t *ts, int64_t *delay)
|
|
||||||
{
|
|
||||||
@@ -101,7 +125,7 @@ static int sysoff_basic(int fd, int n_samples,
|
|
||||||
perror("ioctl PTP_SYS_OFFSET");
|
|
||||||
return SYSOFF_RUN_TIME_MISSING;
|
|
||||||
}
|
|
||||||
- *result = sysoff_estimate(pso.ts, n_samples, ts, delay);
|
|
||||||
+ *result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay);
|
|
||||||
return SYSOFF_BASIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -112,6 +136,8 @@ int sysoff_measure(int fd, int method, int n_samples,
|
|
||||||
case SYSOFF_PRECISE:
|
|
||||||
*delay = 0;
|
|
||||||
return sysoff_precise(fd, result, ts);
|
|
||||||
+ case SYSOFF_EXTENDED:
|
|
||||||
+ return sysoff_extended(fd, n_samples, result, ts, delay);
|
|
||||||
case SYSOFF_BASIC:
|
|
||||||
return sysoff_basic(fd, n_samples, result, ts, delay);
|
|
||||||
}
|
|
||||||
diff --git a/sysoff.h b/sysoff.h
|
|
||||||
index 37f7353..79d2290 100644
|
|
||||||
--- a/sysoff.h
|
|
||||||
+++ b/sysoff.h
|
|
||||||
@@ -24,6 +24,7 @@ enum {
|
|
||||||
SYSOFF_COMPILE_TIME_MISSING = -2,
|
|
||||||
SYSOFF_RUN_TIME_MISSING = -1,
|
|
||||||
SYSOFF_PRECISE,
|
|
||||||
+ SYSOFF_EXTENDED,
|
|
||||||
SYSOFF_BASIC,
|
|
||||||
SYSOFF_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
commit 8142da41b61fb5b9ee4ad8f5ab56adb0447cd37b
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Mon Nov 12 17:28:02 2018 +0100
|
|
||||||
|
|
||||||
phc2sys: Use reversed sysoff when synchronizing to system clock.
|
|
||||||
|
|
||||||
If synchronizing a PHC to the system clock, use one of the
|
|
||||||
PTP_SYS_OFFSET ioctls (if supported) to measure the offset between the
|
|
||||||
two clocks. Negate the offset and switch the timestamp before passing
|
|
||||||
them to the servo.
|
|
||||||
|
|
||||||
This makes the synchronization between PHC and system clock symmetric.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/phc2sys.c b/phc2sys.c
|
|
||||||
index 2cd477a..b8f1ea0 100644
|
|
||||||
--- a/phc2sys.c
|
|
||||||
+++ b/phc2sys.c
|
|
||||||
@@ -790,6 +790,16 @@ static int do_loop(struct node *node, int subscriptions)
|
|
||||||
node->phc_readings,
|
|
||||||
&offset, &ts, &delay) < 0)
|
|
||||||
return -1;
|
|
||||||
+ } else if (node->master->clkid == CLOCK_REALTIME &&
|
|
||||||
+ clock->sysoff_method >= 0) {
|
|
||||||
+ /* use reversed sysoff */
|
|
||||||
+ if (sysoff_measure(CLOCKID_TO_FD(clock->clkid),
|
|
||||||
+ clock->sysoff_method,
|
|
||||||
+ node->phc_readings,
|
|
||||||
+ &offset, &ts, &delay) < 0)
|
|
||||||
+ return -1;
|
|
||||||
+ ts += offset;
|
|
||||||
+ offset = -offset;
|
|
||||||
} else {
|
|
||||||
/* use phc */
|
|
||||||
if (!read_phc(node->master->clkid, clock->clkid,
|
|
||||||
commit e0580929f451e685d92cd10d80b76f39e9b09a97
|
|
||||||
Author: Richard Cochran <richardcochran@gmail.com>
|
|
||||||
Date: Tue Dec 24 11:09:34 2019 -0800
|
|
||||||
|
|
||||||
phc2sys: Fix frequency estimation when synchronizing a PHC to the system clock.
|
|
||||||
|
|
||||||
When synchronizing a PHC to the Linux system clock (CLOCK_REALTIME),
|
|
||||||
the phc2sys uses the sysoff method, reversing the master and slave
|
|
||||||
roles.
|
|
||||||
|
|
||||||
The offset between a master clock and a slave clock is given by
|
|
||||||
|
|
||||||
offset = slave_ts - master_ts,
|
|
||||||
|
|
||||||
and the call to sysoff_measure() provides the 'offset' and 'slave_ts'
|
|
||||||
values. The needed local time stamp on the 'master' is given by
|
|
||||||
|
|
||||||
master_ts = slave_ts - offset,
|
|
||||||
|
|
||||||
but the code calcuates
|
|
||||||
|
|
||||||
master_ts = slave_ts + offset.
|
|
||||||
|
|
||||||
When passed to the servo, the local time stamp is used to estimate the
|
|
||||||
frequency offset between the two clocks before starting the main
|
|
||||||
synchronization loop. The effect of the bug may be seen with a simple
|
|
||||||
test. Here is a sample output with the existing code.
|
|
||||||
|
|
||||||
$ sudo testptp -d /dev/ptp1 -f 62400000
|
|
||||||
frequency adjustment okay
|
|
||||||
$ sudo ./phc2sys -m -q -c eth6 -s CLOCK_REALTIME -O0
|
|
||||||
phc2sys[90221.239]: eth6 sys offset 191001318 s0 freq -62400000 delay 5547
|
|
||||||
phc2sys[90222.239]: eth6 sys offset 253380897 s1 freq +8265884 delay 5507
|
|
||||||
phc2sys[90223.239]: eth6 sys offset -8301685 s2 freq -35801 delay 5487
|
|
||||||
phc2sys[90224.239]: eth6 sys offset -8297136 s2 freq -2521757 delay 5531
|
|
||||||
phc2sys[90225.239]: eth6 sys offset -5806117 s2 freq -2519879 delay 5542
|
|
||||||
phc2sys[90226.239]: eth6 sys offset -3317009 s2 freq -1772606 delay 5495
|
|
||||||
phc2sys[90227.240]: eth6 sys offset -1575231 s2 freq -1025931 delay 5505
|
|
||||||
phc2sys[90228.240]: eth6 sys offset -580249 s2 freq -503518 delay 5524
|
|
||||||
phc2sys[90229.240]: eth6 sys offset -107770 s2 freq -205114 delay 5519
|
|
||||||
phc2sys[90230.240]: eth6 sys offset 66298 s2 freq -63377 delay 5490
|
|
||||||
phc2sys[90230.881]: eth6 sys offset 86942 s2 freq -22844 delay 5495
|
|
||||||
|
|
||||||
And this is the output with the bug fix in place.
|
|
||||||
|
|
||||||
$ sudo testptp -d /dev/ptp1 -f 62400000
|
|
||||||
frequency adjustment okay
|
|
||||||
$ sudo ./phc2sys -m -q -c eth6 -s CLOCK_REALTIME -O0
|
|
||||||
phc2sys[90365.624]: eth6 sys offset 311912675 s0 freq -62400000 delay 5490
|
|
||||||
phc2sys[90366.624]: eth6 sys offset 374292766 s1 freq -31098 delay 5642
|
|
||||||
phc2sys[90367.624]: eth6 sys offset -3825 s2 freq -34923 delay 5617
|
|
||||||
phc2sys[90368.625]: eth6 sys offset 6 s2 freq -32240 delay 5564
|
|
||||||
phc2sys[90369.625]: eth6 sys offset 1241 s2 freq -31003 delay 5605
|
|
||||||
phc2sys[90370.625]: eth6 sys offset 1131 s2 freq -30741 delay 5600
|
|
||||||
phc2sys[90371.625]: eth6 sys offset 801 s2 freq -30732 delay 5621
|
|
||||||
phc2sys[90372.625]: eth6 sys offset 458 s2 freq -30834 delay 5640
|
|
||||||
phc2sys[90373.626]: eth6 sys offset 186 s2 freq -30969 delay 5598
|
|
||||||
phc2sys[90374.626]: eth6 sys offset 134 s2 freq -30965 delay 5599
|
|
||||||
phc2sys[90375.626]: eth6 sys offset 43 s2 freq -31016 delay 5595
|
|
||||||
phc2sys[90375.681]: eth6 sys offset -32 s2 freq -31078 delay 5541
|
|
||||||
|
|
||||||
This patch fixes the issue by correcting the calculation of the local
|
|
||||||
time stamp value.
|
|
||||||
|
|
||||||
Fixes: 8142da41b61f ("phc2sys: Use reversed sysoff when synchronizing to system clock.")
|
|
||||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
|
||||||
Reported-by: Cliff Spradlin <cspradlin@google.com>
|
|
||||||
Tested-by: Vladimir Oltean <olteanv@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/phc2sys.c b/phc2sys.c
|
|
||||||
index 28c657a..c0b7b3d 100644
|
|
||||||
--- a/phc2sys.c
|
|
||||||
+++ b/phc2sys.c
|
|
||||||
@@ -770,8 +770,8 @@ static int do_loop(struct node *node, int subscriptions)
|
|
||||||
node->phc_readings,
|
|
||||||
&offset, &ts, &delay) < 0)
|
|
||||||
return -1;
|
|
||||||
- ts += offset;
|
|
||||||
offset = -offset;
|
|
||||||
+ ts += offset;
|
|
||||||
} else {
|
|
||||||
/* use phc */
|
|
||||||
if (!read_phc(node->master->clkid, clock->clkid,
|
|
@ -1,437 +0,0 @@
|
|||||||
commit 9c4d9ce0347ec35b2ff2babfc9ed9f8e6e51ac91
|
|
||||||
Author: Hangbin Liu <liuhangbin@gmail.com>
|
|
||||||
Date: Fri Mar 22 15:02:46 2019 +0800
|
|
||||||
|
|
||||||
rtnl: add team activebackup support
|
|
||||||
|
|
||||||
This patch add team interface activebackup mode support. As linux team use
|
|
||||||
genl netlink message, when we get a rtnl link change notify, we have to setup
|
|
||||||
a new genl socket and request the current active port.
|
|
||||||
|
|
||||||
v2: check nlmsg_len before copy rta_data
|
|
||||||
v3: a) Do not make rtnl_buf global as it may be freed by calling rtnl_close()
|
|
||||||
while we are using it in rtnl_link_status()
|
|
||||||
b) Reorder declarations of variables as reversed Christmas tree for
|
|
||||||
function rtnl_link_status()
|
|
||||||
c) remove rtnl_len
|
|
||||||
v4: Remove the first !rtnl_buf check in rtnl_link_status as it's alway true
|
|
||||||
v5: a) Re-order {nl, rtnl}_open and add function nl_close()
|
|
||||||
b) revert the v3_{a,c}, v4 changes, use nl_close to close genl fd
|
|
||||||
c) do not use len in get_team_active_iface() as it may mislead reader
|
|
||||||
v6: Return index at the end to fix fd leak in get_team_active_iface()
|
|
||||||
|
|
||||||
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/missing.h b/missing.h
|
|
||||||
index 2f7adb9..8f92079 100644
|
|
||||||
--- a/missing.h
|
|
||||||
+++ b/missing.h
|
|
||||||
@@ -118,6 +118,22 @@ enum {
|
|
||||||
#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
|
|
||||||
#endif /*IFLA_BOND_MAX*/
|
|
||||||
|
|
||||||
+#ifndef NLA_TYPE_MAX
|
|
||||||
+enum {
|
|
||||||
+ NLA_UNSPEC,
|
|
||||||
+ NLA_U8,
|
|
||||||
+ NLA_U16,
|
|
||||||
+ NLA_U32,
|
|
||||||
+ NLA_U64,
|
|
||||||
+ NLA_STRING,
|
|
||||||
+ NLA_FLAG,
|
|
||||||
+ NLA_MSECS,
|
|
||||||
+ NLA_NESTED,
|
|
||||||
+ __NLA_TYPE_MAX,
|
|
||||||
+};
|
|
||||||
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
|
|
||||||
+#endif /*NLA_TYPE_MAX*/
|
|
||||||
+
|
|
||||||
#ifdef __UCLIBC__
|
|
||||||
|
|
||||||
#if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && \
|
|
||||||
diff --git a/phc2sys.8 b/phc2sys.8
|
|
||||||
index 45cb0e3..b3a3de3 100644
|
|
||||||
--- a/phc2sys.8
|
|
||||||
+++ b/phc2sys.8
|
|
||||||
@@ -108,9 +108,9 @@ together with the
|
|
||||||
option, the master clock is used only to correct the offset by whole number of
|
|
||||||
seconds, which cannot be fixed with PPS alone. Not compatible with the
|
|
||||||
.B \-a
|
|
||||||
-option. This option does not support bonded interface (e.g. bond0). If
|
|
||||||
+option. This option does not support bonded interface (e.g. bond0, team0). If
|
|
||||||
.B ptp4l
|
|
||||||
-has a port on an active-backup bond interface, the
|
|
||||||
+has a port on an active-backup bond or team interface, the
|
|
||||||
.B \-a
|
|
||||||
option can be used to track the active interface.
|
|
||||||
.TP
|
|
||||||
diff --git a/rtnl.c b/rtnl.c
|
|
||||||
index f9a572b..59ed0ec 100644
|
|
||||||
--- a/rtnl.c
|
|
||||||
+++ b/rtnl.c
|
|
||||||
@@ -20,6 +20,8 @@
|
|
||||||
#include <sys/socket.h> /* Must come before linux/netlink.h on some systems. */
|
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
+#include <linux/genetlink.h>
|
|
||||||
+#include <linux/if_team.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
@@ -30,8 +32,39 @@
|
|
||||||
#include "print.h"
|
|
||||||
#include "rtnl.h"
|
|
||||||
|
|
||||||
+#define BUF_SIZE 4096
|
|
||||||
+#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
|
|
||||||
+
|
|
||||||
static int rtnl_len;
|
|
||||||
static char *rtnl_buf;
|
|
||||||
+static int get_team_active_iface(int master_index);
|
|
||||||
+
|
|
||||||
+static int nl_close(int fd)
|
|
||||||
+{
|
|
||||||
+ return close(fd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int nl_open(int family)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ struct sockaddr_nl sa;
|
|
||||||
+
|
|
||||||
+ memset(&sa, 0, sizeof(sa));
|
|
||||||
+ sa.nl_family = AF_NETLINK;
|
|
||||||
+ sa.nl_groups = RTNLGRP_LINK;
|
|
||||||
+
|
|
||||||
+ fd = socket(AF_NETLINK, SOCK_RAW, family);
|
|
||||||
+ if (fd < 0) {
|
|
||||||
+ pr_err("failed to open netlink socket: %m");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) {
|
|
||||||
+ pr_err("failed to bind netlink socket: %m");
|
|
||||||
+ close(fd);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return fd;
|
|
||||||
+}
|
|
||||||
|
|
||||||
int rtnl_close(int fd)
|
|
||||||
{
|
|
||||||
@@ -40,7 +73,12 @@ int rtnl_close(int fd)
|
|
||||||
rtnl_buf = NULL;
|
|
||||||
rtnl_len = 0;
|
|
||||||
}
|
|
||||||
- return close(fd);
|
|
||||||
+ return nl_close(fd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int rtnl_open(void)
|
|
||||||
+{
|
|
||||||
+ return nl_open(NETLINK_ROUTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rtnl_get_ts_device_callback(void *ctx, int linkup, int ts_index)
|
|
||||||
@@ -116,14 +154,24 @@ int rtnl_link_query(int fd, char *device)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline __u32 rta_getattr_u32(const struct rtattr *rta)
|
|
||||||
+static inline __u8 rta_getattr_u8(struct rtattr *rta)
|
|
||||||
+{
|
|
||||||
+ return *(__u8 *)RTA_DATA(rta);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline __u16 rta_getattr_u16(struct rtattr *rta)
|
|
||||||
+{
|
|
||||||
+ return *(__u16 *)RTA_DATA(rta);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline __u32 rta_getattr_u32(struct rtattr *rta)
|
|
||||||
{
|
|
||||||
return *(__u32 *)RTA_DATA(rta);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline const char *rta_getattr_str(const struct rtattr *rta)
|
|
||||||
+static inline char *rta_getattr_str(struct rtattr *rta)
|
|
||||||
{
|
|
||||||
- return (const char *)RTA_DATA(rta);
|
|
||||||
+ return (char *)RTA_DATA(rta);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
|
||||||
@@ -150,12 +198,12 @@ static inline int rtnl_nested_rtattr_parse(struct rtattr *tb[], int max, struct
|
|
||||||
return rtnl_rtattr_parse(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
||||||
+static int rtnl_linkinfo_parse(int master_index, struct rtattr *rta)
|
|
||||||
{
|
|
||||||
- int index = -1;
|
|
||||||
- const char *kind;
|
|
||||||
struct rtattr *linkinfo[IFLA_INFO_MAX];
|
|
||||||
struct rtattr *bond[IFLA_BOND_MAX];
|
|
||||||
+ int index = -1;
|
|
||||||
+ char *kind;
|
|
||||||
|
|
||||||
if (rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta) < 0)
|
|
||||||
return -1;
|
|
||||||
@@ -172,6 +220,8 @@ static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
||||||
if (bond[IFLA_BOND_ACTIVE_SLAVE]) {
|
|
||||||
index = rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]);
|
|
||||||
}
|
|
||||||
+ } else if (kind && !strncmp(kind, "team", 4)) {
|
|
||||||
+ index = get_team_active_iface(master_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
@@ -179,18 +229,18 @@ static int rtnl_linkinfo_parse(struct rtattr *rta)
|
|
||||||
|
|
||||||
int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
||||||
{
|
|
||||||
+ struct rtattr *tb[IFLA_MAX+1];
|
|
||||||
+ struct ifinfomsg *info = NULL;
|
|
||||||
int index, len, link_up;
|
|
||||||
- int slave_index = -1;
|
|
||||||
- struct iovec iov;
|
|
||||||
struct sockaddr_nl sa;
|
|
||||||
- struct msghdr msg;
|
|
||||||
+ int slave_index = -1;
|
|
||||||
struct nlmsghdr *nh;
|
|
||||||
- struct ifinfomsg *info = NULL;
|
|
||||||
- struct rtattr *tb[IFLA_MAX+1];
|
|
||||||
+ struct msghdr msg;
|
|
||||||
+ struct iovec iov;
|
|
||||||
|
|
||||||
index = if_nametoindex(device);
|
|
||||||
if (!rtnl_buf) {
|
|
||||||
- rtnl_len = 4096;
|
|
||||||
+ rtnl_len = BUF_SIZE;
|
|
||||||
rtnl_buf = malloc(rtnl_len);
|
|
||||||
if (!rtnl_buf) {
|
|
||||||
pr_err("rtnl: low memory");
|
|
||||||
@@ -246,7 +296,7 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
||||||
IFLA_PAYLOAD(nh));
|
|
||||||
|
|
||||||
if (tb[IFLA_LINKINFO])
|
|
||||||
- slave_index = rtnl_linkinfo_parse(tb[IFLA_LINKINFO]);
|
|
||||||
+ slave_index = rtnl_linkinfo_parse(index, tb[IFLA_LINKINFO]);
|
|
||||||
|
|
||||||
if (cb)
|
|
||||||
cb(ctx, link_up, slave_index);
|
|
||||||
@@ -255,24 +305,163 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int rtnl_open(void)
|
|
||||||
+static int genl_send_msg(int fd, int family_id, int genl_cmd, int genl_version,
|
|
||||||
+ int rta_type, void *rta_data, int rta_len)
|
|
||||||
{
|
|
||||||
- int fd;
|
|
||||||
- struct sockaddr_nl sa;
|
|
||||||
+ struct sockaddr_nl daddr;
|
|
||||||
+ struct genlmsghdr *gnlh;
|
|
||||||
+ struct nlmsghdr *nlh;
|
|
||||||
+ struct rtattr *attr;
|
|
||||||
+ char msg[BUF_SIZE];
|
|
||||||
|
|
||||||
- memset(&sa, 0, sizeof(sa));
|
|
||||||
- sa.nl_family = AF_NETLINK;
|
|
||||||
- sa.nl_groups = RTNLGRP_LINK;
|
|
||||||
+ memset(&daddr, 0, sizeof(daddr));
|
|
||||||
+ daddr.nl_family = AF_NETLINK;
|
|
||||||
|
|
||||||
- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
||||||
- if (fd < 0) {
|
|
||||||
- pr_err("failed to open netlink socket: %m");
|
|
||||||
+ memset(&msg, 0, sizeof(msg));
|
|
||||||
+ nlh = (struct nlmsghdr *) msg;
|
|
||||||
+ nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
|
|
||||||
+ nlh->nlmsg_type = family_id;
|
|
||||||
+ nlh->nlmsg_flags = NLM_F_REQUEST;
|
|
||||||
+
|
|
||||||
+ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh);
|
|
||||||
+ gnlh->cmd = genl_cmd;
|
|
||||||
+ gnlh->version = genl_version;
|
|
||||||
+
|
|
||||||
+ if (rta_data && rta_len > 0) {
|
|
||||||
+ attr = (struct rtattr *) GENLMSG_DATA(msg);
|
|
||||||
+ attr->rta_type = rta_type;
|
|
||||||
+ attr->rta_len = RTA_LENGTH(rta_len);
|
|
||||||
+ nlh->nlmsg_len += NLMSG_ALIGN(attr->rta_len);
|
|
||||||
+ if (nlh->nlmsg_len < sizeof(msg))
|
|
||||||
+ memcpy(RTA_DATA(attr), rta_data, rta_len);
|
|
||||||
+ else
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return sendto(fd, &msg, nlh->nlmsg_len, 0,
|
|
||||||
+ (struct sockaddr *)&daddr, sizeof(daddr));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int genl_get_family_id(int fd, void *family_name)
|
|
||||||
+{
|
|
||||||
+ struct rtattr *tb[CTRL_ATTR_MAX+1];
|
|
||||||
+ struct nlmsghdr *nlh;
|
|
||||||
+ struct rtattr *attr;
|
|
||||||
+ char msg[BUF_SIZE];
|
|
||||||
+ int len, gf_id;
|
|
||||||
+
|
|
||||||
+ len = genl_send_msg(fd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1,
|
|
||||||
+ CTRL_ATTR_FAMILY_NAME, family_name,
|
|
||||||
+ strlen(family_name) + 1);
|
|
||||||
+ if (len < 0)
|
|
||||||
+ return len;
|
|
||||||
+
|
|
||||||
+ len = recv(fd, &msg, sizeof(msg), 0);
|
|
||||||
+ if (len < 0)
|
|
||||||
+ return len;
|
|
||||||
+
|
|
||||||
+ nlh = (struct nlmsghdr *) msg;
|
|
||||||
+ if (nlh->nlmsg_type == NLMSG_ERROR || !NLMSG_OK(nlh, len))
|
|
||||||
return -1;
|
|
||||||
+
|
|
||||||
+ attr = (struct rtattr *) GENLMSG_DATA(msg);
|
|
||||||
+ rtnl_rtattr_parse(tb, CTRL_ATTR_MAX, attr, NLMSG_PAYLOAD(nlh, GENL_HDRLEN));
|
|
||||||
+
|
|
||||||
+ if (tb[CTRL_ATTR_FAMILY_ID])
|
|
||||||
+ gf_id = rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
|
|
||||||
+ else
|
|
||||||
+ gf_id = -1;
|
|
||||||
+
|
|
||||||
+ return gf_id;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int parase_team_list_option(struct rtattr *attr)
|
|
||||||
+{
|
|
||||||
+ struct rtattr *tb[TEAM_ATTR_OPTION_MAX+1];
|
|
||||||
+ int len = RTA_PAYLOAD(attr);
|
|
||||||
+ const char *optname = "";
|
|
||||||
+ const char *mode = "";
|
|
||||||
+ int active_index = -1;
|
|
||||||
+
|
|
||||||
+ for (attr = RTA_DATA(attr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
|
|
||||||
+ rtnl_nested_rtattr_parse(tb, TEAM_ATTR_OPTION_MAX, attr);
|
|
||||||
+
|
|
||||||
+ if (tb[TEAM_ATTR_OPTION_NAME])
|
|
||||||
+ optname = rta_getattr_str(tb[TEAM_ATTR_OPTION_NAME]);
|
|
||||||
+
|
|
||||||
+ if (!strcmp(optname, "mode") && tb[TEAM_ATTR_OPTION_TYPE] &&
|
|
||||||
+ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_STRING)
|
|
||||||
+ mode = rta_getattr_str(tb[TEAM_ATTR_OPTION_DATA]);
|
|
||||||
+
|
|
||||||
+ if (!strcmp(optname, "activeport") && tb[TEAM_ATTR_OPTION_TYPE] &&
|
|
||||||
+ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_U32)
|
|
||||||
+ active_index = rta_getattr_u32(tb[TEAM_ATTR_OPTION_DATA]);
|
|
||||||
}
|
|
||||||
- if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) {
|
|
||||||
- pr_err("failed to bind netlink socket: %m");
|
|
||||||
- close(fd);
|
|
||||||
+
|
|
||||||
+ if (strcmp(mode, "activebackup")) {
|
|
||||||
+ pr_err("team supported only in activebackup mode");
|
|
||||||
return -1;
|
|
||||||
+ } else {
|
|
||||||
+ return active_index;
|
|
||||||
}
|
|
||||||
- return fd;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int get_team_active_iface(int master_index)
|
|
||||||
+{
|
|
||||||
+ struct rtattr *tb[TEAM_ATTR_MAX+1];
|
|
||||||
+ struct genlmsghdr *gnlh;
|
|
||||||
+ struct nlmsghdr *nlh;
|
|
||||||
+ char msg[BUF_SIZE];
|
|
||||||
+ int fd, gf_id, len;
|
|
||||||
+ int index = -1;
|
|
||||||
+
|
|
||||||
+ fd = nl_open(NETLINK_GENERIC);
|
|
||||||
+ if (fd < 0)
|
|
||||||
+ return fd;
|
|
||||||
+
|
|
||||||
+ gf_id = genl_get_family_id(fd, TEAM_GENL_NAME);
|
|
||||||
+ if (gf_id < 0) {
|
|
||||||
+ pr_err("get genl family failed");
|
|
||||||
+ goto no_info;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ len = genl_send_msg(fd, gf_id, TEAM_CMD_OPTIONS_GET,
|
|
||||||
+ TEAM_GENL_VERSION, TEAM_ATTR_TEAM_IFINDEX,
|
|
||||||
+ &master_index, sizeof(master_index));
|
|
||||||
+ if (len < 0) {
|
|
||||||
+ pr_err("send team info request failed: %m");
|
|
||||||
+ goto no_info;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ len = recv(fd, msg, sizeof(msg), 0);
|
|
||||||
+ if (len < 0) {
|
|
||||||
+ pr_err("recv team info failed: %m");
|
|
||||||
+ goto no_info;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ nlh = (struct nlmsghdr *) msg;
|
|
||||||
+ for ( ; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) {
|
|
||||||
+ if (nlh->nlmsg_type != gf_id)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh);
|
|
||||||
+ if (gnlh->cmd != TEAM_CMD_OPTIONS_GET)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ rtnl_rtattr_parse(tb, TEAM_ATTR_MAX, (struct rtattr *)GENLMSG_DATA(msg),
|
|
||||||
+ NLMSG_PAYLOAD(nlh, GENL_HDRLEN));
|
|
||||||
+
|
|
||||||
+ if (tb[TEAM_ATTR_TEAM_IFINDEX] &&
|
|
||||||
+ master_index != rta_getattr_u32(tb[TEAM_ATTR_TEAM_IFINDEX]))
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ if (tb[TEAM_ATTR_LIST_OPTION]) {
|
|
||||||
+ index = parase_team_list_option(tb[TEAM_ATTR_LIST_OPTION]);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+no_info:
|
|
||||||
+ nl_close(fd);
|
|
||||||
+ return index;
|
|
||||||
}
|
|
||||||
commit 51d76bdfb7423947dbb3e250c86d83f9edb0a15b
|
|
||||||
Author: Hangbin Liu <liuhangbin@gmail.com>
|
|
||||||
Date: Wed Mar 20 14:44:13 2019 +0800
|
|
||||||
|
|
||||||
port: should check the new phc_index before switching
|
|
||||||
|
|
||||||
In logic, when we want to switch phc, we should check if the new phc
|
|
||||||
index is valid instead of checking the previous one.
|
|
||||||
|
|
||||||
In reality, if we use linux team interface with activebackup mode. As
|
|
||||||
teamd is a userspace tool, it sets the new slave as active port after
|
|
||||||
receiving link change message. If we set current active port down and
|
|
||||||
another slave up. There is a race that we receive the new slave's link
|
|
||||||
up message while active port(ts_index) is still the old one. This means
|
|
||||||
we may use a link down interface as ts_index and get phc_index with -1.
|
|
||||||
|
|
||||||
If we update the p->phc_index to -1, there will be no possibility to
|
|
||||||
change it back to other value as we swith phc only when p->phc_index >= 0.
|
|
||||||
|
|
||||||
With this fix, we will not switch phc_index until receiving the real
|
|
||||||
active port(p->iface->ts_info.phc_index >= 0) update message.
|
|
||||||
|
|
||||||
Reported-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Fixes: 536a71031d5c ("ptp4l: use ts label to get ts info")
|
|
||||||
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
|
|
||||||
|
|
||||||
diff --git a/port.c b/port.c
|
|
||||||
index 9264211..facebd2 100644
|
|
||||||
--- a/port.c
|
|
||||||
+++ b/port.c
|
|
||||||
@@ -2442,7 +2442,7 @@ void port_link_status(void *ctx, int linkup, int ts_index)
|
|
||||||
sk_get_ts_info(p->iface->ts_label, &p->iface->ts_info);
|
|
||||||
|
|
||||||
/* Only switch phc with HW time stamping mode */
|
|
||||||
- if (p->phc_index >= 0 && p->iface->ts_info.valid) {
|
|
||||||
+ if (p->iface->ts_info.valid && p->iface->ts_info.phc_index >= 0) {
|
|
||||||
required_modes = clock_required_modes(p->clock);
|
|
||||||
if ((p->iface->ts_info.so_timestamping & required_modes) != required_modes) {
|
|
||||||
pr_err("interface '%s' does not support requested "
|
|
@ -1,24 +0,0 @@
|
|||||||
commit 241d8a064efa535029e28b87a8995add3cca8c0c
|
|
||||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
Date: Tue Sep 25 18:16:19 2018 +0200
|
|
||||||
|
|
||||||
unicast: Process timeouts equal to current time.
|
|
||||||
|
|
||||||
Don't postpone processing of a timeout if it is equal to the current
|
|
||||||
time. This prevents an infinite loop with a simulated clock.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/unicast_service.c b/unicast_service.c
|
|
||||||
index ad0e06a..9c9b95b 100644
|
|
||||||
--- a/unicast_service.c
|
|
||||||
+++ b/unicast_service.c
|
|
||||||
@@ -502,7 +502,7 @@ int unicast_service_timer(struct port *p)
|
|
||||||
pr_debug("peek i={2^%d} tmo={%ld,%ld}", interval->log_period,
|
|
||||||
interval->tmo.tv_sec, interval->tmo.tv_nsec);
|
|
||||||
|
|
||||||
- if (timespec_compare(&now, &interval->tmo) >= 0) {
|
|
||||||
+ if (timespec_compare(&now, &interval->tmo) > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
interval = pqueue_extract(p->unicast_service->queue);
|
|
614
SOURCES/linuxptp-udsro.patch
Normal file
614
SOURCES/linuxptp-udsro.patch
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|
@ -1,46 +1,37 @@
|
|||||||
commit 6b61ba29c78e26109426429c6d6b354f6e4443cd
|
commit 9633ab52460f58c92c6daa35e9d24e4ce9c5ab1c
|
||||||
Author: David Mirabito via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net>
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
Date: Tue Mar 19 13:42:48 2019 +1100
|
Date: Tue Feb 23 11:01:43 2021 +0100
|
||||||
|
|
||||||
Avoid fault when receiving zero length packets
|
sk: Don't return error for zero-length messages.
|
||||||
|
|
||||||
The manpage for recvmsg says -1 will be returned on error, Zero indicates an
|
The recvmsg() call can return zero for a zero-length UDP message, which
|
||||||
"orderly shutdown", presumably only in case of stream sockets.
|
should be handled as a bad message and not a fault of the port. This was
|
||||||
Further, UNIX Network Programming, Vol 1 says ".. a return value of 0 from
|
addressed in commit 6b61ba29c78e ("Avoid fault when receiving zero
|
||||||
recvfrom is acceptable for a datagram protocol"
|
length packets"), but later regressed in commit a6e0b83bd503
|
||||||
|
("sk: Convey transmit path errors to the caller.").
|
||||||
|
|
||||||
Such packets have been observed in the wild, aimed at PTP's multicast
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||||
address and port, possibly related to malformed management queries.
|
Fixes: a6e0b83bd503 ("sk: Convey transmit path errors to the caller.")
|
||||||
|
|
||||||
Patch to properly check return from recvmesg and not trigger the fault
|
|
||||||
codepath. Instead, such packets are treated as "Bad Message" the same as
|
|
||||||
non-zero but still too-short UDP payloads.
|
|
||||||
|
|
||||||
Signed-off-by: David Mirabito <davidjm@arista.com>
|
|
||||||
|
|
||||||
diff --git a/port.c b/port.c
|
|
||||||
index ad9554f..9264211 100644
|
|
||||||
--- a/port.c
|
|
||||||
+++ b/port.c
|
|
||||||
@@ -2563,7 +2563,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index)
|
|
||||||
msg->hwts.type = p->timestamping;
|
|
||||||
|
|
||||||
cnt = transport_recv(p->trp, fd, msg);
|
|
||||||
- if (cnt <= 0) {
|
|
||||||
+ if (cnt < 0) {
|
|
||||||
pr_err("port %hu: recv message failed", portnum(p));
|
|
||||||
msg_put(msg);
|
|
||||||
return EV_FAULT_DETECTED;
|
|
||||||
diff --git a/sk.c b/sk.c
|
diff --git a/sk.c b/sk.c
|
||||||
index 30162eb..93ba77a 100644
|
index c9ef4d2..8be0708 100644
|
||||||
--- a/sk.c
|
--- a/sk.c
|
||||||
+++ b/sk.c
|
+++ b/sk.c
|
||||||
@@ -359,7 +359,7 @@ int sk_receive(int fd, void *buf, int buflen,
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
cnt = recvmsg(fd, &msg, flags);
|
switch (hwts->type) {
|
||||||
- if (cnt < 1)
|
@@ -407,7 +407,7 @@ int sk_receive(int fd, void *buf, int buflen,
|
||||||
+ if (cnt < 0)
|
hwts->ts = timespec_to_tmv(ts[1]);
|
||||||
pr_err("recvmsg%sfailed: %m",
|
break;
|
||||||
flags == MSG_ERRQUEUE ? " tx timestamp " : " ");
|
}
|
||||||
|
- return cnt < 1 ? -errno : cnt;
|
||||||
|
+ return cnt < 0 ? -errno : cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sk_set_priority(int fd, int family, uint8_t dscp)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
%global testsuite_ver a7f6e1
|
%global testsuite_ver c66922
|
||||||
%global clknetsim_ver 8b4842
|
%global clknetsim_ver ce3c4a
|
||||||
|
|
||||||
Name: linuxptp
|
Name: linuxptp
|
||||||
Version: 2.0
|
Version: 3.1.1
|
||||||
Release: 5%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: PTP implementation for Linux
|
Summary: PTP implementation for Linux
|
||||||
|
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
@ -21,22 +21,20 @@ Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver
|
|||||||
# simulator for test suite
|
# simulator for test suite
|
||||||
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
|
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
|
||||||
|
|
||||||
# fix building with new kernel headers
|
# don't repeat some log messages in multi-port configuration
|
||||||
Patch1: linuxptp-headers.patch
|
Patch1: linuxptp-logmsgs.patch
|
||||||
# fix timeout handling to work with simulated clock
|
# add option to set clockClass threshold
|
||||||
Patch2: linuxptp-timeout.patch
|
Patch2: linuxptp-classthreshold.patch
|
||||||
# add support for more accurate synchronization to phc2sys
|
# increase default TX timestamp timeout to 10 ms
|
||||||
Patch3: linuxptp-sysoff.patch
|
Patch3: linuxptp-deftxtout.patch
|
||||||
# limit unicast message rate per address and grant duration
|
# limit unicast message rate per address and grant duration
|
||||||
Patch4: linuxptp-ucastrate.patch
|
Patch4: linuxptp-ucastrate.patch
|
||||||
# add support for active-backup team interface
|
# add read-only UDS port
|
||||||
Patch5: linuxptp-team.patch
|
Patch5: linuxptp-udsro.patch
|
||||||
# fix comparing of unicast addresses
|
# fix quoting in ptp4l man page
|
||||||
Patch6: linuxptp-addreq.patch
|
Patch7: linuxptp-manfix.patch
|
||||||
# don't leak memory when allocation fails
|
# close lstab file after use
|
||||||
Patch7: linuxptp-msgput.patch
|
Patch8: linuxptp-fclose.patch
|
||||||
# add hwts_filter option to ptp4l
|
|
||||||
Patch8: linuxptp-hwtsfilter.patch
|
|
||||||
# fix handling of zero-length messages
|
# fix handling of zero-length messages
|
||||||
Patch9: linuxptp-zerolength.patch
|
Patch9: linuxptp-zerolength.patch
|
||||||
|
|
||||||
@ -54,14 +52,13 @@ Supporting legacy APIs and other platforms is not a goal.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -a 10 -a 11 -n %{name}-%{!?gitfullver:%{version}}%{?gitfullver}
|
%setup -q -a 10 -a 11 -n %{name}-%{!?gitfullver:%{version}}%{?gitfullver}
|
||||||
%patch1 -p1 -b .headers
|
%patch1 -p1 -b .logmsgs
|
||||||
%patch2 -p1 -b .timeout
|
%patch2 -p1 -b .classthreshold
|
||||||
%patch3 -p1 -b .sysoff
|
%patch3 -p1 -b .deftxtout
|
||||||
%patch4 -p1 -b .ucastrate
|
%patch4 -p1 -b .ucastrate
|
||||||
%patch5 -p1 -b .team
|
%patch5 -p1 -b .udsro
|
||||||
%patch6 -p1 -b .addreq
|
%patch7 -p1 -b .manfix
|
||||||
%patch7 -p1 -b .msgput
|
%patch8 -p1 -b .fclose
|
||||||
%patch8 -p1 -b .hwtsfilter
|
|
||||||
%patch9 -p1 -b .zerolength
|
%patch9 -p1 -b .zerolength
|
||||||
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
|
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
|
||||||
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
|
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
|
||||||
@ -86,6 +83,9 @@ echo 'OPTIONS="-a -r"' > $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/phc2sys
|
|||||||
echo '.so man8/ptp4l.8' > $RPM_BUILD_ROOT%{_mandir}/man5/ptp4l.conf.5
|
echo '.so man8/ptp4l.8' > $RPM_BUILD_ROOT%{_mandir}/man5/ptp4l.conf.5
|
||||||
echo '.so man8/timemaster.8' > $RPM_BUILD_ROOT%{_mandir}/man5/timemaster.conf.5
|
echo '.so man8/timemaster.8' > $RPM_BUILD_ROOT%{_mandir}/man5/timemaster.conf.5
|
||||||
|
|
||||||
|
# Remove patch backup files and non-linuxptp configuration
|
||||||
|
find configs -type f ! -name '*.cfg' -delete
|
||||||
|
|
||||||
%check
|
%check
|
||||||
cd testsuite
|
cd testsuite
|
||||||
# set random seed to get deterministic results
|
# set random seed to get deterministic results
|
||||||
@ -118,10 +118,21 @@ PATH=..:$PATH ./run
|
|||||||
%{_sbindir}/pmc
|
%{_sbindir}/pmc
|
||||||
%{_sbindir}/ptp4l
|
%{_sbindir}/ptp4l
|
||||||
%{_sbindir}/timemaster
|
%{_sbindir}/timemaster
|
||||||
|
%{_sbindir}/ts2phc
|
||||||
%{_mandir}/man5/*.5*
|
%{_mandir}/man5/*.5*
|
||||||
%{_mandir}/man8/*.8*
|
%{_mandir}/man8/*.8*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Jul 26 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-1
|
||||||
|
- update to 3.1.1 (#1895005 CVE-2021-3571)
|
||||||
|
- add read-only UDS port (#1929797)
|
||||||
|
- add option to set clockClass threshold (#1980386)
|
||||||
|
- don't repeat some log messages in multi-port configuration (#1980377)
|
||||||
|
- increase default TX timestamp timeout to 10 ms (#1977136)
|
||||||
|
|
||||||
|
* Thu Jun 24 2021 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5.el8_4.1
|
||||||
|
- validate length of forwarded messages (CVE-2021-3570)
|
||||||
|
|
||||||
* Mon Apr 27 2020 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5
|
* Mon Apr 27 2020 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5
|
||||||
- fix sample timestamps when synchronizing PHC to system clock (#1787376)
|
- fix sample timestamps when synchronizing PHC to system clock (#1787376)
|
||||||
- fix handling of zero-length messages (#1827275)
|
- fix handling of zero-length messages (#1827275)
|
||||||
|
Loading…
Reference in New Issue
Block a user