import linuxptp-2.0-4.el8
This commit is contained in:
parent
110f5c93f9
commit
1cb58b0988
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
SOURCES/clknetsim-42b693.tar.gz
|
||||
SOURCES/clknetsim-8b4842.tar.gz
|
||||
SOURCES/linuxptp-2.0.tgz
|
||||
SOURCES/linuxptp-testsuite-f6a640.tar.gz
|
||||
SOURCES/linuxptp-testsuite-a7f6e1.tar.gz
|
||||
|
@ -1,3 +1,3 @@
|
||||
fc8083f6f3e37bee538ac3a476dcf53eef26a943 SOURCES/clknetsim-42b693.tar.gz
|
||||
b674017c26433870107fb18e160c7d88d7d2eb86 SOURCES/clknetsim-8b4842.tar.gz
|
||||
592ca42c6146a79c1fcabed7c19fa7af4803d4f6 SOURCES/linuxptp-2.0.tgz
|
||||
2b9333d8aaa3113adedffc495f9eb527b68eb0ed SOURCES/linuxptp-testsuite-f6a640.tar.gz
|
||||
2b8edc55e4967660a0c4a3892c817c0e8f55c3bc SOURCES/linuxptp-testsuite-a7f6e1.tar.gz
|
||||
|
12
SOURCES/linuxptp-addreq.patch
Normal file
12
SOURCES/linuxptp-addreq.patch
Normal file
@ -0,0 +1,12 @@
|
||||
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;
|
51
SOURCES/linuxptp-headers.patch
Normal file
51
SOURCES/linuxptp-headers.patch
Normal file
@ -0,0 +1,51 @@
|
||||
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>
|
228
SOURCES/linuxptp-hwtsfilter.patch
Normal file
228
SOURCES/linuxptp-hwtsfilter.patch
Normal file
@ -0,0 +1,228 @@
|
||||
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
|
20
SOURCES/linuxptp-msgput.patch
Normal file
20
SOURCES/linuxptp-msgput.patch
Normal file
@ -0,0 +1,20 @@
|
||||
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;
|
403
SOURCES/linuxptp-sysoff.patch
Normal file
403
SOURCES/linuxptp-sysoff.patch
Normal file
@ -0,0 +1,403 @@
|
||||
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,
|
437
SOURCES/linuxptp-team.patch
Normal file
437
SOURCES/linuxptp-team.patch
Normal file
@ -0,0 +1,437 @@
|
||||
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 "
|
24
SOURCES/linuxptp-timeout.patch
Normal file
24
SOURCES/linuxptp-timeout.patch
Normal file
@ -0,0 +1,24 @@
|
||||
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);
|
45
SOURCES/linuxptp-ucastrate.patch
Normal file
45
SOURCES/linuxptp-ucastrate.patch
Normal file
@ -0,0 +1,45 @@
|
||||
commit a36602f1e65cd6bace6ed9405b0ce359de4a27d1
|
||||
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Thu Jan 3 15:23:54 2019 +0100
|
||||
|
||||
unicast: limit message rate and grant duration
|
||||
|
||||
Deny service requests with logInterMessagePeriod smaller than -7 (128
|
||||
packets per second) or larger than 16. This limits the network and CPU
|
||||
consumption per address and prevents undefined shifts in the calculation
|
||||
of the interval.
|
||||
|
||||
Also, limit the maximum grant duration to one hour.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
diff --git a/unicast_service.c b/unicast_service.c
|
||||
index 9c9b95b..c6c17c6 100644
|
||||
--- a/unicast_service.c
|
||||
+++ b/unicast_service.c
|
||||
@@ -31,6 +31,9 @@
|
||||
#include "unicast_service.h"
|
||||
#include "util.h"
|
||||
|
||||
+#define MIN_LOG_INTER_MESSAGE_PERIOD -7
|
||||
+#define MAX_LOG_INTER_MESSAGE_PERIOD 16
|
||||
+#define MAX_DURATION 3600
|
||||
#define QUEUE_LEN 16
|
||||
|
||||
struct unicast_client_address {
|
||||
@@ -289,6 +292,15 @@ int unicast_service_add(struct port *p, struct ptp_message *m,
|
||||
return SERVICE_DENIED;
|
||||
}
|
||||
|
||||
+ if (req->logInterMessagePeriod < MIN_LOG_INTER_MESSAGE_PERIOD ||
|
||||
+ req->logInterMessagePeriod > MAX_LOG_INTER_MESSAGE_PERIOD) {
|
||||
+ return SERVICE_DENIED;
|
||||
+ }
|
||||
+
|
||||
+ if (req->durationField > MAX_DURATION) {
|
||||
+ req->durationField = MAX_DURATION;
|
||||
+ }
|
||||
+
|
||||
LIST_FOREACH(itmp, &p->unicast_service->intervals, list) {
|
||||
/*
|
||||
* Remember the interval of interest.
|
@ -1,10 +1,10 @@
|
||||
%global _hardened_build 1
|
||||
%global testsuite_ver f6a640
|
||||
%global clknetsim_ver 42b693
|
||||
%global testsuite_ver a7f6e1
|
||||
%global clknetsim_ver 8b4842
|
||||
|
||||
Name: linuxptp
|
||||
Version: 2.0
|
||||
Release: 2%{?dist}
|
||||
Release: 4%{?dist}
|
||||
Summary: PTP implementation for Linux
|
||||
|
||||
Group: System Environment/Base
|
||||
@ -21,6 +21,24 @@ Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver
|
||||
# simulator for test suite
|
||||
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
|
||||
|
||||
# fix building with new kernel headers
|
||||
Patch1: linuxptp-headers.patch
|
||||
# fix timeout handling to work with simulated clock
|
||||
Patch2: linuxptp-timeout.patch
|
||||
# add support for more accurate synchronization to phc2sys
|
||||
Patch3: linuxptp-sysoff.patch
|
||||
# limit unicast message rate per address and grant duration
|
||||
Patch4: linuxptp-ucastrate.patch
|
||||
# add support for active-backup team interface
|
||||
Patch5: linuxptp-team.patch
|
||||
# fix comparing of unicast addresses
|
||||
Patch6: linuxptp-addreq.patch
|
||||
# don't leak memory when allocation fails
|
||||
Patch7: linuxptp-msgput.patch
|
||||
# add hwts_filter option to ptp4l
|
||||
Patch8: linuxptp-hwtsfilter.patch
|
||||
|
||||
BuildRequires: kernel-headers > 4.18.0-87
|
||||
BuildRequires: systemd
|
||||
|
||||
%{?systemd_requires}
|
||||
@ -34,6 +52,14 @@ Supporting legacy APIs and other platforms is not a goal.
|
||||
|
||||
%prep
|
||||
%setup -q -a 10 -a 11 -n %{name}-%{!?gitfullver:%{version}}%{?gitfullver}
|
||||
%patch1 -p1 -b .headers
|
||||
%patch2 -p1 -b .timeout
|
||||
%patch3 -p1 -b .sysoff
|
||||
%patch4 -p1 -b .ucastrate
|
||||
%patch5 -p1 -b .team
|
||||
%patch6 -p1 -b .addreq
|
||||
%patch7 -p1 -b .msgput
|
||||
%patch8 -p1 -b .hwtsfilter
|
||||
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
|
||||
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
|
||||
|
||||
@ -93,6 +119,19 @@ PATH=..:$PATH ./run
|
||||
%{_mandir}/man8/*.8*
|
||||
|
||||
%changelog
|
||||
* Thu May 16 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-4
|
||||
- rebuild with enabled gating (#1680888)
|
||||
|
||||
* Wed May 15 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-3
|
||||
- add support for active-backup team interface (#1685467)
|
||||
- add support for more accurate synchronization to phc2sys (#1677217)
|
||||
- add hwts_filter option to ptp4l (#1708554)
|
||||
- limit unicast message rate per address and grant duration (#1707395)
|
||||
- fix comparing of unicast addresses (#1707395)
|
||||
- fix building with new kernel headers (#1707395)
|
||||
- update testsuite (#1707395)
|
||||
- don't leak memory when allocation fails (#1707395)
|
||||
|
||||
* Tue Nov 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-2
|
||||
- start ptp4l, timemaster and phc2sys after network-online target (#1632282)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user