diff --git a/SOURCES/linuxptp-eintr.patch b/SOURCES/linuxptp-eintr.patch new file mode 100644 index 0000000..2ea76ad --- /dev/null +++ b/SOURCES/linuxptp-eintr.patch @@ -0,0 +1,30 @@ +commit c8de9f33e437fb15cff32c0028f651d7cb916a37 +Author: Miroslav Lichvar +Date: Tue Sep 13 13:44:10 2022 +0200 + + sk: Handle EINTR when waiting for transmit timestamp. + + If ptp4l received a signal in poll() waiting for a transmit timestamp, + multiple (possibly confusing) error messages are logged before exit. + + If poll() returns with EINTR, call it once again to get the timestamp + and avoid logging the errors. Don't call it in a loop to avoid getting + stuck in case the timestamp is lost and the signal is repeated before + the poll timeout can be reached. + + Signed-off-by: Miroslav Lichvar + +diff --git a/sk.c b/sk.c +index 80075be..d27abff 100644 +--- a/sk.c ++++ b/sk.c +@@ -354,6 +354,9 @@ int sk_receive(int fd, void *buf, int buflen, + if (flags == MSG_ERRQUEUE) { + struct pollfd pfd = { fd, sk_events, 0 }; + res = poll(&pfd, 1, sk_tx_timeout); ++ /* Retry once on EINTR to avoid logging errors before exit */ ++ if (res < 0 && errno == EINTR) ++ res = poll(&pfd, 1, sk_tx_timeout); + if (res < 1) { + pr_err(res ? "poll for tx timestamp failed: %m" : + "timed out while polling for tx timestamp"); diff --git a/SOURCES/linuxptp-freqcheck.patch b/SOURCES/linuxptp-freqcheck.patch new file mode 100644 index 0000000..28d1b93 --- /dev/null +++ b/SOURCES/linuxptp-freqcheck.patch @@ -0,0 +1,208 @@ +commit 513c7457865dba262a43e03fbe9178f4b08ba319 +Author: Miroslav Lichvar +Date: Mon Oct 24 15:25:30 2022 +0200 + + Drop support for old kernels returning zero frequency. + + Kernels before 3.10 had a bug in reading of the system clock frequency, + which was worked around by commit da347d7a36f2 ("ptp4l: Set clock + frequency on start"). + + Drop this workaround and support for the old kernels to make + clockadj_get_freq() useful. + + (Rebased to 3.1.1) + + Signed-off-by: Miroslav Lichvar + +diff --git a/clock.c b/clock.c +index f3df220..9079428 100644 +--- a/clock.c ++++ b/clock.c +@@ -1147,11 +1147,6 @@ struct clock *clock_create(enum clock_type type, struct config *config, + + if (c->clkid != CLOCK_INVALID) { + fadj = (int) clockadj_get_freq(c->clkid); +- /* Due to a bug in older kernels, the reading may silently fail +- and return 0. Set the frequency back to make sure fadj is +- the actual frequency of the clock. */ +- clockadj_set_freq(c->clkid, fadj); +- + /* Disable write phase mode if not implemented by driver */ + if (c->write_phase_mode && !phc_has_writephase(c->clkid)) { + pr_err("clock does not support write phase mode"); +@@ -1746,7 +1741,6 @@ int clock_switch_phc(struct clock *c, int phc_index) + return -1; + } + fadj = (int) clockadj_get_freq(clkid); +- clockadj_set_freq(clkid, fadj); + servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0); + if (!servo) { + pr_err("Switching PHC, failed to create clock servo"); +diff --git a/phc2sys.c b/phc2sys.c +index 5f6fbaa..af948eb 100644 +--- a/phc2sys.c ++++ b/phc2sys.c +@@ -147,9 +147,6 @@ static struct servo *servo_add(struct phc2sys_private *priv, + + clockadj_init(clock->clkid); + ppb = clockadj_get_freq(clock->clkid); +- /* The reading may silently fail and return 0, reset the frequency to +- make sure ppb is the actual frequency of the clock. */ +- clockadj_set_freq(clock->clkid, ppb); + if (clock->clkid == CLOCK_REALTIME) { + sysclk_set_leap(0); + max_ppb = sysclk_max_freq(); +diff --git a/ts2phc_slave.c b/ts2phc_slave.c +index 749efe5..5541d91 100644 +--- a/ts2phc_slave.c ++++ b/ts2phc_slave.c +@@ -183,10 +183,6 @@ static struct ts2phc_slave *ts2phc_slave_create(struct config *cfg, const char * + pr_debug("PHC slave %s has ptp index %d", device, junk); + + fadj = (int) clockadj_get_freq(slave->clk); +- /* Due to a bug in older kernels, the reading may silently fail +- and return 0. Set the frequency back to make sure fadj is +- the actual frequency of the clock. */ +- clockadj_set_freq(slave->clk, fadj); + + max_adj = phc_max_adj(slave->clk); + + +commit 80d6875b0072c7ea636a5631e590fa72d169c351 +Author: Miroslav Lichvar +Date: Mon Oct 24 15:25:31 2022 +0200 + + Don't accept errors in clockadj_get_freq(). + + Exit if an error is returned from the clock_adjtime() call in + clockadj_get_freq(). No recoverable errors are expected. + + Signed-off-by: Miroslav Lichvar + +diff --git a/clockadj.c b/clockadj.c +index 957dc57..4c920b9 100644 +--- a/clockadj.c ++++ b/clockadj.c +@@ -19,6 +19,7 @@ + + #include + #include ++#include + #include + #include + +@@ -72,6 +73,7 @@ double clockadj_get_freq(clockid_t clkid) + memset(&tx, 0, sizeof(tx)); + if (clock_adjtime(clkid, &tx) < 0) { + pr_err("failed to read out the clock frequency adjustment: %m"); ++ exit(1); + } else { + f = tx.freq / 65.536; + if (clkid == CLOCK_REALTIME && realtime_nominal_tick && tx.tick) + +commit 211cbfe810ef4082d1af8e9b50f65d4f6fd7246a +Author: Miroslav Lichvar +Date: Mon Oct 24 15:25:32 2022 +0200 + + Extend clockcheck to check for changes in frequency. + + Before setting the new frequency offset on a clock update, compare the + current frequency returned by the kernel with the value saved from the + previous update. Print a warning message if the difference is larger + than 1 ppb, allowing for rounding errors in conversion to and from + double. The kernel caches the value set by clock_adjtime() in shifted + ppm, it doesn't request it from the driver, which can have a lower + resulution. + + This should detect misconfigurations where multiple processes are trying + to control the clock (e.g. another ptp4l/phc2sys instance or an NTP + client), even when they don't step the clock. + + Signed-off-by: Miroslav Lichvar + +diff --git a/clock.c b/clock.c +index 9079428..eea7983 100644 +--- a/clock.c ++++ b/clock.c +@@ -1760,6 +1760,9 @@ int clock_switch_phc(struct clock *c, int phc_index) + + static void clock_synchronize_locked(struct clock *c, double adj) + { ++ if (c->sanity_check) { ++ clockcheck_freq(c->sanity_check, clockadj_get_freq(c->clkid)); ++ } + clockadj_set_freq(c->clkid, -adj); + if (c->clkid == CLOCK_REALTIME) { + sysclk_set_sync(); +diff --git a/clockcheck.c b/clockcheck.c +index f0141be..b5a69cc 100644 +--- a/clockcheck.c ++++ b/clockcheck.c +@@ -123,6 +123,16 @@ void clockcheck_set_freq(struct clockcheck *cc, int freq) + cc->freq_known = 1; + } + ++int clockcheck_freq(struct clockcheck *cc, int freq) ++{ ++ /* Allow difference of 1 ppb due to conversion to/from double */ ++ if (cc->freq_known && abs(cc->current_freq - freq) > 1) { ++ pr_warning("clockcheck: clock frequency changed unexpectedly!"); ++ return 1; ++ } ++ return 0; ++} ++ + void clockcheck_step(struct clockcheck *cc, int64_t step) + { + if (cc->last_ts) +diff --git a/clockcheck.h b/clockcheck.h +index 1ff86eb..4b09b98 100644 +--- a/clockcheck.h ++++ b/clockcheck.h +@@ -54,6 +54,14 @@ int clockcheck_sample(struct clockcheck *cc, uint64_t ts); + */ + void clockcheck_set_freq(struct clockcheck *cc, int freq); + ++/** ++ * Check whether the frequency correction did not change unexpectedly. ++ * @param cc Pointer to a clock check obtained via @ref clockcheck_create(). ++ * @param freq Current reading of the frequency correction in ppb. ++ * @return Zero if the frequency did not change, non-zero otherwise. ++ */ ++int clockcheck_freq(struct clockcheck *cc, int freq); ++ + /** + * Inform clock check that the clock was stepped. + * @param cc Pointer to a clock check obtained via @ref clockcheck_create(). +diff --git a/phc2sys.c b/phc2sys.c +index af948eb..4daa1bf 100644 +--- a/phc2sys.c ++++ b/phc2sys.c +@@ -566,6 +566,9 @@ static void update_clock(struct phc2sys_private *priv, struct clock *clock, + /* Fall through. */ + case SERVO_LOCKED: + case SERVO_LOCKED_STABLE: ++ if (clock->sanity_check) ++ clockcheck_freq(clock->sanity_check, ++ clockadj_get_freq(clock->clkid)); + clockadj_set_freq(clock->clkid, -ppb); + if (clock->clkid == CLOCK_REALTIME) + sysclk_set_sync(); +diff --git a/ptp4l.8 b/ptp4l.8 +index 4917240..f760e2b 100644 +--- a/ptp4l.8 ++++ b/ptp4l.8 +@@ -605,8 +605,10 @@ This option used to be called + The maximum allowed frequency offset between uncorrected clock and the system + monotonic clock in parts per billion (ppb). This is used as a sanity check of + the synchronized clock. When a larger offset is measured, a warning message +-will be printed and the servo will be reset. When set to 0, the sanity check is +-disabled. The default is 200000000 (20%). ++will be printed and the servo will be reset. If the frequency correction set by ++ptp4l changes unexpectedly between updates of the clock (e.g. due to another ++process trying to control the clock), a warning message will be printed. When ++set to 0, the sanity check is disabled. The default is 200000000 (20%). + .TP + .B initial_delay + The initial path delay of the clock in nanoseconds used for synchronization of diff --git a/SOURCES/linuxptp-vlanbond.patch b/SOURCES/linuxptp-vlanbond.patch new file mode 100644 index 0000000..d4ae8c5 --- /dev/null +++ b/SOURCES/linuxptp-vlanbond.patch @@ -0,0 +1,451 @@ +commit afd709924edcea26fec24a6253d1b85fc94c88e6 +Author: Hangbin Liu +Date: Wed May 25 14:46:14 2022 +0800 + + ptp4l: init iface->ts_label when interface created + + It's redundant to ensure tslabel if we could get ts_info directly from + the interface. By init iface->ts_label when interface created, there is + no need to take care of ts_label on other places. + + It will also make the later vlan over bonding support patch more clear + after removing function interface_ensure_tslabel(). + + Signed-off-by: Hangbin Liu + +diff --git a/clock.c b/clock.c +index 7ffbd6a..d4f273f 100644 +--- a/clock.c ++++ b/clock.c +@@ -1006,9 +1006,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, + required_modes = clock_required_modes(c); + STAILQ_FOREACH(iface, &config->interfaces, list) { + memset(ts_label, 0, sizeof(ts_label)); +- rtnl_get_ts_device(interface_name(iface), ts_label); +- interface_set_label(iface, ts_label); +- interface_ensure_tslabel(iface); ++ if (!rtnl_get_ts_device(interface_name(iface), ts_label)) ++ interface_set_label(iface, ts_label); + interface_get_tsinfo(iface); + if (interface_tsinfo_valid(iface) && + !interface_tsmodes_supported(iface, required_modes)) { +diff --git a/interface.c b/interface.c +index 445a270..6c2630c 100644 +--- a/interface.c ++++ b/interface.c +@@ -24,6 +24,7 @@ struct interface *interface_create(const char *name) + return NULL; + } + strncpy(iface->name, name, MAX_IFNAME_SIZE); ++ strncpy(iface->ts_label, name, MAX_IFNAME_SIZE); + iface->vclock = -1; + + return iface; +@@ -34,13 +35,6 @@ void interface_destroy(struct interface *iface) + free(iface); + } + +-void interface_ensure_tslabel(struct interface *iface) +-{ +- if (!iface->ts_label[0]) { +- memcpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE); +- } +-} +- + int interface_get_tsinfo(struct interface *iface) + { + return sk_get_ts_info(iface->ts_label, &iface->ts_info); +diff --git a/interface.h b/interface.h +index 752f4f1..5fc7836 100644 +--- a/interface.h ++++ b/interface.h +@@ -33,12 +33,6 @@ struct interface *interface_create(const char *name); + */ + void interface_destroy(struct interface *iface); + +-/** +- * Ensures that an interface has a proper time stamping label. +- * @param iface The interface of interest. +- */ +-void interface_ensure_tslabel(struct interface *iface); +- + /** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. +diff --git a/nsm.c b/nsm.c +index 5aa925b..8d4a362 100644 +--- a/nsm.c ++++ b/nsm.c +@@ -274,9 +274,8 @@ static int nsm_open(struct nsm *nsm, struct config *cfg) + STAILQ_FOREACH(iface, &cfg->interfaces, list) { + ifname = interface_name(iface); + memset(ts_label, 0, sizeof(ts_label)); +- rtnl_get_ts_device(ifname, ts_label); +- interface_set_label(iface, ts_label); +- interface_ensure_tslabel(iface); ++ if (!rtnl_get_ts_device(ifname, ts_label)) ++ interface_set_label(iface, ts_label); + count++; + } + if (count != 1) { +diff --git a/pmc_common.c b/pmc_common.c +index 756edf5..ee2ece6 100644 +--- a/pmc_common.c ++++ b/pmc_common.c +@@ -405,7 +405,6 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type, + pr_err("failed to create interface"); + goto failed; + } +- interface_ensure_tslabel(pmc->iface); + + if (transport_open(pmc->transport, pmc->iface, + &pmc->fdarray, TS_SOFTWARE)) { + +commit 6aab466eb0563c1025c78ab496b22a8833b02d20 +Author: Vincent Cheng +Date: Fri Jan 8 10:21:14 2021 -0500 + + port: Fix link down/up to continue using phc_index set from command line -p option. + + In the scenario where a port link goes down and up, current code checks + the port's phc_index against the interface's phc_index and if they are + different will set the port phc_index to the interface phc_index. + + If the phc_index was initially set by the command line -p option, then we + end up using the wrong phc_index. + + Fix is to skip updating the port phc_index with the interface phc_index + when port link is back up if it was initialy set from the command line. + + Signed-off-by: Vincent Cheng + +diff --git a/port.c b/port.c +index 70b6e60..d22f30f 100644 +--- a/port.c ++++ b/port.c +@@ -2601,6 +2601,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) + "timestamping mode, set link status down by force.", + interface_label(p->iface)); + p->link_status = LINK_DOWN | LINK_STATE_CHANGED; ++ } else if (p->phc_from_cmdline) { ++ pr_warning("port %d: taking /dev/ptp%d from the " ++ "command line, not the attached ptp%d", ++ portnum(p), p->phc_index, ++ interface_phc_index(p->iface)); + } else if (p->phc_index != interface_phc_index(p->iface)) { + p->phc_index = interface_phc_index(p->iface); + +@@ -3107,6 +3112,7 @@ struct port *port_open(const char *phc_device, + "not the attached ptp%d", number, phc_device, + interface_phc_index(interface)); + p->phc_index = phc_index; ++ p->phc_from_cmdline = 1; + } else { + pr_err("port %d: PHC device mismatch", number); + pr_err("port %d: /dev/ptp%d requested, ptp%d attached", +diff --git a/port_private.h b/port_private.h +index fcabaa6..6e40e15 100644 +--- a/port_private.h ++++ b/port_private.h +@@ -69,6 +69,7 @@ struct port { + struct fdarray fda; + int fault_fd; + int phc_index; ++ int phc_from_cmdline; + + void (*dispatch)(struct port *p, enum fsm_event event, int mdiff); + enum fsm_event (*event)(struct port *p, int fd_index); + +commit 45f20e824fdfb8748d73495ccc7578dc70866282 +Author: Hangbin Liu +Date: Wed May 25 14:46:15 2022 +0800 + + port: refactor port_link_status + + Split port_change_phc() logic form port_link_status() to improve the + readability of the code + + (Rebased to 3.1.1) + + Signed-off-by: Hangbin Liu + +diff --git a/port.c b/port.c +index d22f30f..031b212 100644 +--- a/port.c ++++ b/port.c +@@ -2563,10 +2563,43 @@ static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff) + } + } + ++static void port_change_phc(struct port *p) ++{ ++ int required_modes; ++ ++ /* Only switch a non-vclock PHC with HW time stamping. */ ++ if (!interface_tsinfo_valid(p->iface) || ++ interface_get_vclock(p->iface) >= 0 || ++ interface_phc_index(p->iface) < 0) ++ return; ++ ++ required_modes = clock_required_modes(p->clock); ++ if (!interface_tsmodes_supported(p->iface, required_modes)) { ++ pr_err("interface '%s' does not support requested " ++ "timestamping mode, set link status down by force.", ++ interface_label(p->iface)); ++ p->link_status = LINK_DOWN | LINK_STATE_CHANGED; ++ } else if (p->phc_from_cmdline) { ++ pr_warning("port %d: taking /dev/ptp%d from the " ++ "command line, not the attached ptp%d", ++ portnum(p), p->phc_index, ++ interface_phc_index(p->iface)); ++ } else if (p->phc_index != interface_phc_index(p->iface)) { ++ p->phc_index = interface_phc_index(p->iface); ++ ++ if (clock_switch_phc(p->clock, p->phc_index)) { ++ p->last_fault_type = FT_SWITCH_PHC; ++ port_dispatch(p, EV_FAULT_DETECTED, 0); ++ return; ++ } ++ clock_sync_interval(p->clock, p->log_sync_interval); ++ } ++} ++ + void port_link_status(void *ctx, int linkup, int ts_index) + { + char ts_label[MAX_IFNAME_SIZE + 1] = {0}; +- int link_state, required_modes; ++ int link_state; + const char *old_ts_label; + struct port *p = ctx; + +@@ -2590,33 +2623,7 @@ void port_link_status(void *ctx, int linkup, int ts_index) + if (p->link_status & LINK_UP && + (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) { + interface_get_tsinfo(p->iface); +- +- /* Only switch a non-vclock PHC with HW time stamping. */ +- if (interface_tsinfo_valid(p->iface) && +- interface_get_vclock(p->iface) < 0 && +- interface_phc_index(p->iface) >= 0) { +- required_modes = clock_required_modes(p->clock); +- if (!interface_tsmodes_supported(p->iface, required_modes)) { +- pr_err("interface '%s' does not support requested " +- "timestamping mode, set link status down by force.", +- interface_label(p->iface)); +- p->link_status = LINK_DOWN | LINK_STATE_CHANGED; +- } else if (p->phc_from_cmdline) { +- pr_warning("port %d: taking /dev/ptp%d from the " +- "command line, not the attached ptp%d", +- portnum(p), p->phc_index, +- interface_phc_index(p->iface)); +- } else if (p->phc_index != interface_phc_index(p->iface)) { +- p->phc_index = interface_phc_index(p->iface); +- +- if (clock_switch_phc(p->clock, p->phc_index)) { +- p->last_fault_type = FT_SWITCH_PHC; +- port_dispatch(p, EV_FAULT_DETECTED, 0); +- return; +- } +- clock_sync_interval(p->clock, p->log_sync_interval); +- } +- } ++ port_change_phc(p); + } + + /* + +commit 878c2eac77cc7abd1d86620a82ae9046545439ea +Author: Hangbin Liu +Date: Wed May 25 14:46:16 2022 +0800 + + ptp4l: add VLAN over bond support + + Latest Linux kernel has supported getting active port's PHC from bond + directly. This would help topology like VLAN over bond to get PHC natively, + as VLAN also albe to get downlink's PHC. + + To achieve this, the new hwtstamp flag is needed when passing hwtstamp_config + to kernel. Let's supply the flag first, and fall back without flag if user + run on old kernel. + + We also need to update the PHC index in port_link_status() when there is + a RTNL event. The PHC info will be update in later port_change_phc(). + + Signed-off-by: Hangbin Liu + +diff --git a/clock.c b/clock.c +index d4f273f..f3df220 100644 +--- a/clock.c ++++ b/clock.c +@@ -1758,6 +1758,9 @@ int clock_switch_phc(struct clock *c, int phc_index) + c->clkid = clkid; + c->servo = servo; + c->servo_state = SERVO_UNLOCKED; ++ ++ pr_info("Switched to /dev/ptp%d as PTP clock", phc_index); ++ + return 0; + } + +diff --git a/missing.h b/missing.h +index c5194f4..5f684dd 100644 +--- a/missing.h ++++ b/missing.h +@@ -73,6 +73,12 @@ struct so_timestamping { + }; + #endif + ++#ifndef HWTSTAMP_FLAG_BONDED_PHC_INDEX ++enum { ++ HWTSTAMP_FLAG_BONDED_PHC_INDEX = (1<<0), ++}; ++#endif ++ + #ifdef PTP_EXTTS_REQUEST2 + #define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m" + #else +diff --git a/port.c b/port.c +index 031b212..ae9c4d3 100644 +--- a/port.c ++++ b/port.c +@@ -2619,12 +2619,18 @@ void port_link_status(void *ctx, int linkup, int ts_index) + pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label); + } + ++ /* phc index may changed while ts_label keeps the same after failover. ++ * e.g. vlan over bond. Since the lower link changed, we still set ++ * the TS_LABEL_CHANGED flag. ++ */ ++ interface_get_tsinfo(p->iface); ++ if (p->phc_index != interface_phc_index(p->iface)) ++ p->link_status |= TS_LABEL_CHANGED; ++ + /* Both link down/up and change ts_label may change phc index. */ + if (p->link_status & LINK_UP && +- (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) { +- interface_get_tsinfo(p->iface); ++ (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) + port_change_phc(p); +- } + + /* + * A port going down can affect the BMCA result. +diff --git a/sk.c b/sk.c +index b55d6b5..80075be 100644 +--- a/sk.c ++++ b/sk.c +@@ -66,6 +66,11 @@ static int hwts_init(int fd, const char *device, int rx_filter, + + init_ifreq(&ifreq, &cfg, device); + ++ cfg.flags = HWTSTAMP_FLAG_BONDED_PHC_INDEX; ++ /* Fall back without flag if user run new build on old kernel */ ++ if (ioctl(fd, SIOCGHWTSTAMP, &ifreq) == -EINVAL) ++ init_ifreq(&ifreq, &cfg, device); ++ + switch (sk_hwts_filter_mode) { + case HWTS_FILTER_CHECK: + err = ioctl(fd, SIOCGHWTSTAMP, &ifreq); + +commit 98edb4d72b3d1d4e988f810b9a9cb1078212e5dc +Author: Miroslav Lichvar +Date: Tue Nov 22 17:07:16 2022 +0100 + + port: Avoid faults with vclocks and PHC from command line. + + After commit afeabf3c90ed ("ptp4l: add VLAN over bond support") the + TS_LABEL_CHANGED flag was set on link status changes when the used + PHC index was different from the PHC index of the interface. + + This caused the port to be constantly switching to the faulty state when + using vclocks, or a different PHC device was forced with the -p option, + where it is expected the used PHC doesn't match the interface's PHC. + + Rework port_link_status() and port_change_phc() to avoid setting the + flag and switch the clock only in the cases where it is expected. + + Fixes: afeabf3c90ed ("ptp4l: add VLAN over bond support") + Signed-off-by: Miroslav Lichvar + +diff --git a/port.c b/port.c +index ae9c4d3..96e097a 100644 +--- a/port.c ++++ b/port.c +@@ -2567,10 +2567,13 @@ static void port_change_phc(struct port *p) + { + int required_modes; + +- /* Only switch a non-vclock PHC with HW time stamping. */ +- if (!interface_tsinfo_valid(p->iface) || ++ /* Try to switch only if the interface is up, it has HW time stamping ++ using a non-vclock PHC, and the PHC actually changed. */ ++ if (!(p->link_status & LINK_UP) || ++ !interface_tsinfo_valid(p->iface) || + interface_get_vclock(p->iface) >= 0 || +- interface_phc_index(p->iface) < 0) ++ interface_phc_index(p->iface) < 0 || ++ p->phc_index == interface_phc_index(p->iface)) + return; + + required_modes = clock_required_modes(p->clock); +@@ -2584,7 +2587,7 @@ static void port_change_phc(struct port *p) + "command line, not the attached ptp%d", + portnum(p), p->phc_index, + interface_phc_index(p->iface)); +- } else if (p->phc_index != interface_phc_index(p->iface)) { ++ } else { + p->phc_index = interface_phc_index(p->iface); + + if (clock_switch_phc(p->clock, p->phc_index)) { +@@ -2619,18 +2622,12 @@ void port_link_status(void *ctx, int linkup, int ts_index) + pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label); + } + +- /* phc index may changed while ts_label keeps the same after failover. +- * e.g. vlan over bond. Since the lower link changed, we still set +- * the TS_LABEL_CHANGED flag. +- */ ++ /* The PHC index may change even with the same ts_label, e.g. after ++ failover with VLAN over bond. */ + interface_get_tsinfo(p->iface); +- if (p->phc_index != interface_phc_index(p->iface)) +- p->link_status |= TS_LABEL_CHANGED; + +- /* Both link down/up and change ts_label may change phc index. */ +- if (p->link_status & LINK_UP && +- (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) +- port_change_phc(p); ++ /* Switch the clock if needed */ ++ port_change_phc(p); + + /* + * A port going down can affect the BMCA result. +commit 730a775fec159f012f3e0f65bb059465e9f7b49b +Author: Miroslav Lichvar +Date: Wed Mar 15 11:24:16 2023 +0100 + + port: Don't switch to PHC with SW timestamping. + + When ptp4l was configured to use SW timestamping, but the interface + supported also HW timestamping, ptp4l detected a change of the PHC on + start, switched to it from the system clock, and tried to control the + PHC using SW timestamps. + + Don't switch the PHC if the current PHC index is -1, which is expected + with SW timestamping and in the free-running mode. + + Fixes: afeabf3c90ed ("ptp4l: add VLAN over bond support") + Signed-off-by: Miroslav Lichvar + +diff --git a/port.c b/port.c +index 96e097a..32ee83b 100644 +--- a/port.c ++++ b/port.c +@@ -2570,6 +2570,7 @@ static void port_change_phc(struct port *p) + /* Try to switch only if the interface is up, it has HW time stamping + using a non-vclock PHC, and the PHC actually changed. */ + if (!(p->link_status & LINK_UP) || ++ p->phc_index < 0 || + !interface_tsinfo_valid(p->iface) || + interface_get_vclock(p->iface) >= 0 || + interface_phc_index(p->iface) < 0 || diff --git a/SPECS/linuxptp.spec b/SPECS/linuxptp.spec index 54b60a9..dfc1e43 100644 --- a/SPECS/linuxptp.spec +++ b/SPECS/linuxptp.spec @@ -4,7 +4,7 @@ Name: linuxptp Version: 3.1.1 -Release: 5%{?dist} +Release: 6%{?dist}.1 Summary: PTP implementation for Linux License: GPLv2+ @@ -45,6 +45,12 @@ Patch11: linuxptp-clockcheck.patch Patch12: linuxptp-vclock.patch # handle PHC read failing with EBUSY in phc2sys Patch13: linuxptp-phcerr.patch +# add support for VLAN over bond +Patch14: linuxptp-vlanbond.patch +# handle EINTR when waiting for transmit timestamp +Patch15: linuxptp-eintr.patch +# check for unexpected changes in frequency offset +Patch16: linuxptp-freqcheck.patch BuildRequires: gcc gcc-c++ make systemd @@ -71,6 +77,9 @@ Supporting legacy APIs and other platforms is not a goal. %patch11 -p1 -b .clockcheck %patch12 -p1 -b .vclock %patch13 -p1 -b .phcerr +%patch14 -p1 -b .vlanbond +%patch15 -p1 -b .eintr +%patch16 -p1 -b .freqcheck mv linuxptp-testsuite-%{testsuite_ver}* testsuite mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim @@ -133,6 +142,14 @@ PATH=..:$PATH ./run %{_mandir}/man8/*.8* %changelog +* Mon Mar 20 2023 Miroslav Lichvar 3.1.1-6.el9_2.1 +- don't switch from system clock to PHC with SW timestamping (#2178233) + +* Thu Jan 05 2023 Miroslav Lichvar 3.1.1-6 +- add support for VLAN over bond (#2120521) +- handle EINTR when waiting for transmit timestamp (#2128786) +- check for unexpected changes in frequency offset (#2150815) + * Thu Jul 28 2022 Miroslav Lichvar 3.1.1-5 - disable PHC switch with vclocks (#2066452)