Compare commits

...

1 Commits
c8 ... c10

Author SHA1 Message Date
50fcbd788a import OL linuxptp-4.4-5.el10_1 2025-12-22 07:19:20 +00:00
29 changed files with 2156 additions and 513 deletions

6
.gitignore vendored
View File

@ -1,3 +1,3 @@
SOURCES/clknetsim-5d1dc0.tar.gz
SOURCES/linuxptp-4.2.tgz
SOURCES/linuxptp-testsuite-bf8ead.tar.gz
clknetsim-64df92.tar.gz
linuxptp-4.4.tgz
linuxptp-testsuite-d27dbd.tar.gz

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +0,0 @@
[Unit]
Description=Synchronize system clock or PTP hardware clock (PHC)
After=ntpdate.service ptp4l.service
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/phc2sys
ExecStart=/usr/sbin/phc2sys $OPTIONS
[Install]
WantedBy=multi-user.target

View File

@ -1,12 +0,0 @@
[Unit]
Description=Precision Time Protocol (PTP) service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/ptp4l
ExecStart=/usr/sbin/ptp4l $OPTIONS
[Install]
WantedBy=multi-user.target

View File

@ -1,12 +0,0 @@
[Unit]
Description=Synchronize system clock to NTP and PTP time sources
After=chronyd.service ntpd.service ntpdate.service sntp.service network-online.target
Conflicts=chronyd.service ntpd.service phc2sys.service ptp4l.service
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/sbin/timemaster -f /etc/timemaster.conf
[Install]
WantedBy=multi-user.target

View File

@ -1,255 +0,0 @@
%global _hardened_build 1
%global testsuite_ver bf8ead
%global clknetsim_ver 5d1dc0
Name: linuxptp
Version: 4.2
Release: 1%{?dist}
Summary: PTP implementation for Linux
Group: System Environment/Base
License: GPLv2+
URL: http://linuxptp.sourceforge.net/
Source0: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tgz
Source1: phc2sys.service
Source2: ptp4l.service
Source3: timemaster.service
Source4: timemaster.conf
# external test suite
Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver}/linuxptp-testsuite-%{testsuite_ver}.tar.gz
# simulator for test suite
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
# allow old syntax of SET SUBSCRIBE_EVENTS_NP command
Patch1: linuxptp-subscribe.patch
# disable warning messages about deprecated options
Patch2: linuxptp-deprecated.patch
# revert default PTP version to 2.0 for better compatibility
Patch3: linuxptp-ptpver.patch
# limit unicast message rate per address and grant duration
Patch4: linuxptp-ucastrate.patch
# fix ts2phc to handle large NMEA delay
Patch5: linuxptp-nmeadelay.patch
# fix loading and reloading of leapfile
Patch6: linuxptp-lstab.patch
BuildRequires: kernel-headers > 4.18.0-87
BuildRequires: systemd
%{?systemd_requires}
%description
This software is an implementation of the Precision Time Protocol (PTP)
according to IEEE standard 1588 for Linux. The dual design goals are to provide
a robust implementation of the standard and to use the most relevant and modern
Application Programming Interfaces (API) offered by the Linux kernel.
Supporting legacy APIs and other platforms is not a goal.
%prep
%setup -q -a 10 -a 11 -n %{name}-%{!?gitfullver:%{version}}%{?gitfullver}
%autopatch -p1
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
%build
make %{?_smp_mflags} \
EXTRA_CFLAGS="$RPM_OPT_FLAGS" \
EXTRA_LDFLAGS="$RPM_LD_FLAGS"
%install
%makeinstall
mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/sysconfig,%{_unitdir},%{_mandir}/man5}
install -m 644 -p configs/default.cfg $RPM_BUILD_ROOT%{_sysconfdir}/ptp4l.conf
install -m 644 -p %{SOURCE1} %{SOURCE2} %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir}
install -m 644 -p %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}
echo 'OPTIONS="-f /etc/ptp4l.conf -i eth0"' > \
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ptp4l
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/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
cd testsuite
# set random seed to get deterministic results
export CLKNETSIM_RANDOM_SEED=26743
make %{?_smp_mflags} -C clknetsim
PATH=..:$PATH ./run
%post
%systemd_post phc2sys.service ptp4l.service timemaster.service
%preun
%systemd_preun phc2sys.service ptp4l.service timemaster.service
%postun
%systemd_postun_with_restart phc2sys.service ptp4l.service timemaster.service
%files
%doc COPYING README.org configs
%config(noreplace) %{_sysconfdir}/ptp4l.conf
%config(noreplace) %{_sysconfdir}/sysconfig/phc2sys
%config(noreplace) %{_sysconfdir}/sysconfig/ptp4l
%config(noreplace) %{_sysconfdir}/timemaster.conf
%{_unitdir}/phc2sys.service
%{_unitdir}/ptp4l.service
%{_unitdir}/timemaster.service
%{_sbindir}/hwstamp_ctl
%{_sbindir}/nsm
%{_sbindir}/phc2sys
%{_sbindir}/phc_ctl
%{_sbindir}/pmc
%{_sbindir}/ptp4l
%{_sbindir}/timemaster
%{_sbindir}/ts2phc
%{_sbindir}/tz2alt
%{_mandir}/man5/*.5*
%{_mandir}/man8/*.8*
%changelog
* Thu Feb 22 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
- update to 4.2 (RHEL-21326 RHEL-21328 RHEL-21329)
- fix ts2phc to handle large NMEA delay (RHEL-23278)
- fix loading and reloading of leapfile
* Wed May 03 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-6
- clear pending errors on sockets (#2192560)
* Wed Apr 12 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-5
- handle EINTR when waiting for transmit timestamp (#2123224)
* Mon Mar 20 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-4
- don't re-arm fault clearing timer on unrelated netlink events (#2174900)
* Wed Jun 29 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-3
- handle PHC read failing with EBUSY in phc2sys (#2079129)
* Mon Nov 01 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-2
- make sanity clock check more reliable (#2007281)
* 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
- fix sample timestamps when synchronizing PHC to system clock (#1787376)
- fix handling of zero-length messages (#1827275)
* 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)
* Mon Aug 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-1
- update to 2.0 (#1614300)
* Mon Apr 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-1
- update to 1.9.2
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-7.20180101git303b08
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Tue Jan 30 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.8-6.20180101git303b08
- use macro for systemd scriptlet dependencies
* Thu Jan 11 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.8-5.20180101git303b08
- update to 20180101git303b08
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Nov 07 2016 Miroslav Lichvar <mlichvar@redhat.com> 1.8-1
- update to 1.8
* Fri Jul 22 2016 Miroslav Lichvar <mlichvar@redhat.com> 1.7-1
- update to 1.7
- add delay option to default timemaster.conf
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Tue Sep 22 2015 Miroslav Lichvar <mlichvar@redhat.com> 1.6-1
- update to 1.6
- set random seed in testing to get deterministic results
- remove trailing whitespace in default timemaster.conf
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Mon Jan 05 2015 Miroslav Lichvar <mlichvar@redhat.com> 1.5-1
- update to 1.5
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Fri Feb 21 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.4-1
- update to 1.4
- replace hardening build flags with _hardened_build
- include test suite
* Fri Aug 02 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.3-1
- update to 1.3
* Tue Jul 30 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-3.20130730git7789f0
- update to 20130730git7789f0
* Fri Jul 19 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-2.20130719git46db40
- update to 20130719git46db40
- drop old systemd scriptlets
- add man page link for ptp4l.conf
* Mon Apr 22 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-1
- update to 1.2
* Mon Feb 18 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.1-1
- update to 1.1
- log phc2sys output
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Thu Dec 13 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.0-1
- update to 1.0
* Fri Nov 09 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.3.20121109git4e8107
- update to 20121109git4e8107
- install unchanged default.cfg as ptp4l.conf
- drop conflicts from phc2sys service
* Fri Sep 21 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.2.20120920git6ce135
- fix issues found in package review (#859193)
* Thu Sep 20 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.1.20120920git6ce135
- initial release

275
linuxptp-externalgm.patch Normal file
View File

@ -0,0 +1,275 @@
commit 120e46985e5176bc908866b76ef5be6c9abf00be
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 16 15:04:04 2025 +0100
clock: Add variables for external grandmaster.
When ptp4l is configured to run as the server part of a bridge between
different domains, or a boundary clock split into multiple instances
(using one or two clocks), it announces its own clock identity as
grandmasterIdentity and stepsRemoved of 0. The clients of the server
don't see the true identity and distance, which can impact the result of
BMCA if there are multiple bridges/paths to the grandmaster. In the
worst case it could cause synchronization loops.
Add new variables to the clock that will override the grandmaster
identity and stepsRemoved values included in announce messages to make
it possible to pass them from the source domain as if the bridge/BC was
a single PTP instance. The variables will be used only when in the
grandmaster state and when not zero.
Runtime configuration over the UDS port will follow.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index 863e9d8..fb33ac0 100644
--- a/clock.c
+++ b/clock.c
@@ -148,6 +148,8 @@ struct clock {
int step_window_counter;
int step_window;
struct time_zone tz[MAX_TIME_ZONES];
+ struct ClockIdentity ext_gm_identity;
+ int ext_gm_steps_removed;
};
struct clock the_clock;
@@ -830,13 +832,22 @@ static int clock_compare_pds(struct parentDS *pds1, struct parentDS *pds2)
static void clock_update_grandmaster(struct clock *c)
{
struct parentDS *pds = &c->dad.pds, old_pds = *pds;
+ struct ClockIdentity gm_identity, nul_identity;
+
+ memset(&nul_identity, 0, sizeof(nul_identity));
memset(&c->cur, 0, sizeof(c->cur));
memset(c->ptl, 0, sizeof(c->ptl));
+ if (!cid_eq(&nul_identity, &c->ext_gm_identity))
+ gm_identity = c->ext_gm_identity;
+ else
+ gm_identity = c->dds.clockIdentity;
+
+ c->cur.stepsRemoved = c->ext_gm_steps_removed;
pds->parentPortIdentity.clockIdentity = c->dds.clockIdentity;
/* Follow IEEE 1588 Table 30: Updates for state decision code M1 and M2 */
pds->parentPortIdentity.portNumber = 0;
- pds->grandmasterIdentity = c->dds.clockIdentity;
+ pds->grandmasterIdentity = gm_identity;
pds->grandmasterClockQuality = c->dds.clockQuality;
pds->grandmasterPriority1 = c->dds.priority1;
pds->grandmasterPriority2 = c->dds.priority2;
commit dfd52bff9d1b25b291aae6343154b38fb8fede4e
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 16 15:04:05 2025 +0100
Add management message for external grandmaster properties.
Add EXTERNAL_GRANDMASTER_PROPERTIES_NP management message to get and set
the new external grandmasterIdentity and stepsRemoved variables of the
clock. Together with the GRANDMASTER_SETTINGS_NP message all
grandmaster-specific values in announce messages can be now set.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/clock.c b/clock.c
index fb33ac0..7c30066 100644
--- a/clock.c
+++ b/clock.c
@@ -422,6 +422,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
struct ptp_message *req,
struct ptp_message *rsp, int id)
{
+ struct external_grandmaster_properties_np *egpn;
struct alternate_time_offset_properties *atop;
struct alternate_time_offset_name *aton;
struct grandmaster_settings_np *gsn;
@@ -582,6 +583,12 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
mtd->val = c->local_sync_uncertain;
datalen = sizeof(*mtd);
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ egpn = (struct external_grandmaster_properties_np *) tlv->data;
+ egpn->gmIdentity = c->ext_gm_identity;
+ egpn->stepsRemoved = c->ext_gm_steps_removed;
+ datalen = sizeof(*egpn);
+ break;
default:
/* The caller should *not* respond to this message. */
tlv_extra_recycle(extra);
@@ -620,6 +627,7 @@ static int clock_management_get_response(struct clock *c, struct port *p,
static int clock_management_set(struct clock *c, struct port *p,
int id, struct ptp_message *req, int *changed)
{
+ struct external_grandmaster_properties_np *egpn;
struct alternate_time_offset_properties *atop;
struct alternate_time_offset_name *aton;
struct grandmaster_settings_np *gsn;
@@ -710,6 +718,13 @@ static int clock_management_set(struct clock *c, struct port *p,
break;
}
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ egpn = (struct external_grandmaster_properties_np *) tlv->data;
+ c->ext_gm_identity = egpn->gmIdentity;
+ c->ext_gm_steps_removed = egpn->stepsRemoved;
+ *changed = 1;
+ respond = 1;
+ break;
}
if (respond && !clock_management_get_response(c, p, id, req))
pr_err("failed to send management set response");
diff --git a/pmc.c b/pmc.c
index 0b61da4..6a6a94e 100644
--- a/pmc.c
+++ b/pmc.c
@@ -158,6 +158,7 @@ static void pmc_show_signaling(struct ptp_message *msg, FILE *fp)
static void pmc_show(struct ptp_message *msg, FILE *fp)
{
+ struct external_grandmaster_properties_np *egpn;
struct alternate_time_offset_properties *atop;
struct alternate_time_offset_name *aton;
struct ieee_c37_238_settings_np *pwr;
@@ -475,6 +476,14 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
fprintf(fp, "SYNCHRONIZATION_UNCERTAIN_NP "
IFMT "uncertain %hhu", mtd->val);
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ egpn = (struct external_grandmaster_properties_np *) mgt->data;
+ fprintf(fp, "EXTERNAL_GRANDMASTER_PROPERTIES_NP "
+ IFMT "gmIdentity %s"
+ IFMT "stepsRemoved %hu",
+ cid2str(&egpn->gmIdentity),
+ egpn->stepsRemoved);
+ break;
case MID_PORT_DATA_SET:
p = (struct portDS *) mgt->data;
if (p->portState > PS_SLAVE) {
diff --git a/pmc_common.c b/pmc_common.c
index 7c77a10..b55e7ec 100644
--- a/pmc_common.c
+++ b/pmc_common.c
@@ -132,6 +132,7 @@ struct management_id idtab[] = {
{ "GRANDMASTER_SETTINGS_NP", MID_GRANDMASTER_SETTINGS_NP, do_set_action },
{ "SUBSCRIBE_EVENTS_NP", MID_SUBSCRIBE_EVENTS_NP, do_set_action },
{ "SYNCHRONIZATION_UNCERTAIN_NP", MID_SYNCHRONIZATION_UNCERTAIN_NP, do_set_action },
+ { "EXTERNAL_GRANDMASTER_PROPERTIES_NP", MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP, do_set_action },
/* Port management ID values */
{ "NULL_MANAGEMENT", MID_NULL_MANAGEMENT, null_management },
{ "CLOCK_DESCRIPTION", MID_CLOCK_DESCRIPTION, do_get_action },
@@ -172,6 +173,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
{
int cnt, code = idtab[index].code, freq_traceable, leap_59, leap_61,
ptp_timescale, time_traceable, utc_off_valid;
+ struct external_grandmaster_properties_np egpn;
struct alternate_time_offset_properties atop;
struct ieee_c37_238_settings_np pwr;
struct grandmaster_settings_np gsn;
@@ -183,6 +185,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
char onoff_parent_data_set[4] = "off";
char onoff_cmlds[4] = "off";
char display_name[11] = {0};
+ char identity[19];
uint64_t jump;
uint8_t key;
int enable;
@@ -400,6 +403,19 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
IEEE_C37_238_VERSION_2017);
}
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ cnt = sscanf(str, " %*s %*s "
+ "gmIdentity %18s "
+ "stepsRemoved %hu ",
+ identity,
+ &egpn.stepsRemoved);
+ if (cnt != 2 || str2cid(identity, &egpn.gmIdentity)) {
+ fprintf(stderr, "%s SET needs 2 values\n",
+ idtab[index].name);
+ break;
+ }
+ pmc_send_set_action(pmc, code, &egpn, sizeof(egpn));
+ break;
}
}
@@ -704,6 +720,9 @@ static int pmc_tlv_datalen(struct pmc *pmc, int id)
case MID_POWER_PROFILE_SETTINGS_NP:
len += sizeof(struct ieee_c37_238_settings_np);
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ len += sizeof(struct external_grandmaster_properties_np);
+ break;
case MID_LOG_ANNOUNCE_INTERVAL:
case MID_ANNOUNCE_RECEIPT_TIMEOUT:
case MID_LOG_SYNC_INTERVAL:
diff --git a/tlv.c b/tlv.c
index b22277c..0639a71 100644
--- a/tlv.c
+++ b/tlv.c
@@ -164,6 +164,7 @@ static void alttime_offset_pre_send(struct tlv_extra *extra)
static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
struct tlv_extra *extra)
{
+ struct external_grandmaster_properties_np *egpn;
struct alternate_time_offset_properties *atop;
struct alternate_time_offset_name *aton;
struct ieee_c37_238_settings_np *pwr;
@@ -490,6 +491,12 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
NTOHL(cmlds->scaledNeighborRateRatio);
NTOHL(cmlds->as_capable);
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ if (data_len != sizeof(struct external_grandmaster_properties_np))
+ goto bad_length;
+ egpn = (struct external_grandmaster_properties_np *) m->data;
+ NTOHS(egpn->stepsRemoved);
+ break;
case MID_SAVE_IN_NON_VOLATILE_STORAGE:
case MID_RESET_NON_VOLATILE_STORAGE:
case MID_INITIALIZE:
@@ -513,6 +520,7 @@ bad_length:
static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
{
+ struct external_grandmaster_properties_np *egpn;
struct alternate_time_offset_properties *atop;
struct ieee_c37_238_settings_np *pwr;
struct unicast_master_table_np *umtn;
@@ -688,6 +696,10 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
HTONL(cmlds->scaledNeighborRateRatio);
HTONL(cmlds->as_capable);
break;
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
+ egpn = (struct external_grandmaster_properties_np *)m->data;
+ HTONS(egpn->stepsRemoved);
+ break;
}
}
diff --git a/tlv.h b/tlv.h
index 1b464f3..f0c47ce 100644
--- a/tlv.h
+++ b/tlv.h
@@ -100,6 +100,7 @@ enum management_action {
#define MID_GRANDMASTER_SETTINGS_NP 0xC001
#define MID_SUBSCRIBE_EVENTS_NP 0xC003
#define MID_SYNCHRONIZATION_UNCERTAIN_NP 0xC006
+#define MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP 0xC00D
/* Port management ID values */
#define MID_NULL_MANAGEMENT 0x0000
@@ -489,6 +490,11 @@ struct msg_interface_rate_tlv {
UInteger16 numberOfBitsAfterTimestamp;
} PACKED;
+struct external_grandmaster_properties_np {
+ struct ClockIdentity gmIdentity;
+ UInteger16 stepsRemoved;
+} PACKED;
+
/**
* Allocates a new tlv_extra structure.
* @return Pointer to a new structure on success or NULL otherwise.

149
linuxptp-externalpps.patch Normal file
View File

@ -0,0 +1,149 @@
commit f20e568cb2bf3b0ea6105e5624409f02fb9aa2bc
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 9 15:46:05 2025 +0100
ts2phc: Add option for external reference in automatic mode.
ts2phc running in the automatic mode assumes that the PPS source is one
of the PHCs used by ptp4l. That doesn't always have to be the case. Add
"external_pps" option to use the non-automatic-mode reading of the
source timestamp and don't mark sink clocks as targets if they are
synchronized by ptp4l.
The use case is holdover with an externally controlled stabilized clock.
The clock is synchronized by an external process to the PHC when it's
synchronized by ptp4l and the PHC is synchronized to the external clock
by ts2phc when not synchronized by ptp4l. Multiple PHCs can be connected
to the external clock to make a JBOD boundary clock.
Don't require the PHC that is synchronized by ptp4l to be receiving the
PPS signal (providing timestamps) to make it possible to switch the PPS
direction to synchronize the external clock if there is only one
usable channel.
(This is a RHEL-specific downstream patch using "ts2phc.rh_external_pps"
name for the option to make it clear it's considered experimental.)
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/config.c b/config.c
index cbff976..fedc3a0 100644
--- a/config.c
+++ b/config.c
@@ -368,6 +368,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_ENU("time_stamping", TS_HARDWARE, timestamping_enu),
PORT_ITEM_INT("transportSpecific", 0, 0, 0x0F),
PORT_ITEM_INT("ts2phc.channel", 0, 0, INT_MAX),
+ GLOB_ITEM_INT("ts2phc.rh_external_pps", 0, 0, 1),
PORT_ITEM_INT("ts2phc.extts_correction", 0, INT_MIN, INT_MAX),
PORT_ITEM_ENU("ts2phc.extts_polarity", PTP_RISING_EDGE, extts_polarity_enu),
PORT_ITEM_INT("ts2phc.holdover", 0, 0, INT_MAX),
diff --git a/ts2phc.8 b/ts2phc.8
index f17ed71..d57402c 100644
--- a/ts2phc.8
+++ b/ts2phc.8
@@ -287,6 +287,20 @@ the SERVO_LOCKED_STABLE state. The servo state needs be enabled by the
\fB-a\fP option and when \fBts2phc.extts_polarity\fP is set to \fIboth\fP.
The default is 0 (disabled).
+.TP
+.B ts2phc.rh_external_pps
+This is a RHEL-specific experimental option which can be renamed,
+removed, or the functionality changed, in a future minor update.
+
+It enables an external reference with the \fB-a\fP option. If set to 1, ts2phc
+will assume the source of the PPS signal is a different clock from the PHCs
+used by ptp4l (configured with the \fBboundary_clock_jbod\fP option). The use
+case is a holdover using an externally controlled stabilized clock, which is
+expected to be synchronized to the PHC that is synchronized by ptp4l, and
+running free when ptp4l is not synchronizing any of the PHCs. Note that it is a
+different holdover than the one enabled by the \fBts2phc.holdover\fP option
+below. The default is 0 (disabled).
+
.TP
.B ts2phc.nmea_delay
Specifies the minimum expected delay of NMEA RMC messages in nanoseconds.
diff --git a/ts2phc.c b/ts2phc.c
index 39d31b6..5448496 100644
--- a/ts2phc.c
+++ b/ts2phc.c
@@ -348,18 +348,26 @@ static void ts2phc_reconfigure(struct ts2phc_private *priv)
}
num_target_clocks++;
break;
- case PS_UNCALIBRATED:
- num_ref_clocks++;
- break;
case PS_SLAVE:
ref_clk = c;
+ /* Fall through */
+ case PS_UNCALIBRATED:
num_ref_clocks++;
+ if (priv->external_pps && c->is_target) {
+ pr_info("unselecting %s for synchronization",
+ c->name);
+ c->is_target = false;
+ }
break;
default:
break;
}
last = c;
}
+ if (priv->external_pps) {
+ pr_info("assuming external reference clock");
+ return;
+ }
if (num_target_clocks >= 1 && !ref_clk) {
priv->ref_clock = last;
priv->ref_clock->is_target = false;
@@ -447,7 +455,7 @@ static void ts2phc_synchronize_clocks(struct ts2phc_private *priv, int autocfg)
struct ts2phc_clock *c;
int holdover, valid;
- if (autocfg) {
+ if (autocfg && !priv->external_pps) {
if (!priv->ref_clock) {
pr_debug("no reference clock, skipping");
return;
@@ -787,6 +795,8 @@ int main(int argc, char *argv[])
return -1;
}
+ priv.external_pps = config_get_int(cfg, NULL, "ts2phc.rh_external_pps");
+
priv.holdover_length = config_get_int(cfg, NULL, "ts2phc.holdover");
priv.holdover_start = 0;
diff --git a/ts2phc.h b/ts2phc.h
index 5dbde9b..63e6122 100644
--- a/ts2phc.h
+++ b/ts2phc.h
@@ -52,6 +52,7 @@ struct ts2phc_private {
struct config *cfg;
struct pmc_agent *agent;
struct ts2phc_clock *ref_clock;
+ bool external_pps;
bool state_changed;
LIST_HEAD(port_head, ts2phc_port) ports;
LIST_HEAD(clock_head, ts2phc_clock) clocks;
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
index af34e39..9076de9 100644
--- a/ts2phc_pps_sink.c
+++ b/ts2phc_pps_sink.c
@@ -441,6 +441,15 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
all_sinks_have_events = true;
for (i = 0; i < priv->n_sinks; i++) {
+ /*
+ * In the external PPS mode don't require non-target
+ * clocks to be receiving PPS to allow switching the
+ * PPS direction to synchronize the external clock.
+ */
+ if (priv->external_pps &&
+ !polling_array->sink[i]->clock->is_target)
+ continue;
+
if (!polling_array->collected_events[i]) {
all_sinks_have_events = false;
break;

150
linuxptp-nowait.patch Normal file
View File

@ -0,0 +1,150 @@
commit 2f5dd7261f2fc167ea1c8ef4154888fda0cf7db3
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Nov 26 15:10:32 2024 +0100
pmc_agent: Use longer update interval when not subscribed.
When phc2sys is started with the -w option, the pmc agent is not
subscribed to events by the pmc_agent_subscribe() function, which also
sets the update interval. The update interval in this case is zero,
which means the pmc agent is trying to update the currentUtcOffset value
on every call of pmc_agent_update(), i.e. on every clock update in
phc2sys.
Set a default update interval of 60 seconds to reduce the rate of
pmc requests.
Fixes: e3ca7ea90a9e ("pmc_agent: Make update interval configurable.")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/pmc_agent.c b/pmc_agent.c
index d1a3367..663adc0 100644
--- a/pmc_agent.c
+++ b/pmc_agent.c
@@ -33,6 +33,9 @@
#define UPDATES_PER_SUBSCRIPTION 3
#define MIN_UPDATE_INTERVAL 10
+/* Update interval if the agent not subscribed, just polling the UTC offset */
+#define DEFAULT_UPDATE_INTERVAL 60
+
struct pmc_agent {
struct pmc *pmc;
uint64_t pmc_last_update;
@@ -253,6 +256,7 @@ int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
}
node->recv_subscribed = recv_subscribed;
node->recv_context = context;
+ node->update_interval = DEFAULT_UPDATE_INTERVAL * NS_PER_SEC;
return 0;
}
commit b46f1bda3b13d17a67ffc9d0f9af76e2fc1af80a
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Nov 26 15:10:33 2024 +0100
phc2sys: Don't disable pmc agent with -s -d -w options.
When phc2sys is started with -s and -d options to combine a PPS device
and PHC device as a time source, but without an offset specified by
the -O option, the pmc agent is disabled after waiting for ptp4l to have
a port in a synchronized state. This prevents phc2sys from following
changes in the currentUtcOffset value.
Disable the pmc agent only if no PHC device is specified by the -s
option, i.e. there are no PHC readings to which the UTC offset could be
applied.
Fixes: 5f1b419c4102 ("phc2sys: Replace magical test with a proper test.")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/phc2sys.c b/phc2sys.c
index d09cb53..c98ecec 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -1594,7 +1594,7 @@ int main(int argc, char *argv[])
if (domains[0].forced_sync_offset ||
!phc2sys_using_systemclock(&domains[0]) ||
- hardpps_configured(pps_fd)) {
+ (hardpps_configured(pps_fd) && !src_name)) {
pmc_agent_disable(domains[0].agent);
}
}
commit 8bd0ee2f65c72fb45f95aca8e907514092fc9cd1
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Nov 26 15:10:34 2024 +0100
phc2sys: Don't require -O option without -a and -w.
Allow phc2sys to be started in the static mode without the -O option,
meaning it should fetch the UTC offset from ptp4l, even if the -w option
is not included on the command line to wait for ptp4l to have a port in
the master or slave state.
This is useful when the PHC is synchronized by ts2phc or other
application and the system clock needs to be synchronized to the PHC
even when ptp4l has all ports in the faulty state (e.g. all network
links are down).
It's the responsibility of the user to start phc2sys when ptp4l is
already running. phc2sys will exit with an error message if it cannot
get a response with the 1-second timeout.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/phc2sys.8 b/phc2sys.8
index 762a1b1..3246c8f 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -164,7 +164,10 @@ minimize the error caused by random delays in scheduling and bus utilization.
The default is 5.
.TP
.BI \-O " offset"
-Specify the offset between the sink and source times in seconds. Not
+Specify the offset between the sink and source times in seconds. If not
+specified, the offset will be set according to the currentUtcOffset value
+obtained from ptp4l and the direction of synchronization, assuming the system
+clock is keeping time in UTC and all used PHCs keep time in TAI. Not
compatible with the
.B \-a
option. See
diff --git a/phc2sys.c b/phc2sys.c
index c98ecec..ddd0a6a 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -1452,12 +1452,6 @@ int main(int argc, char *argv[])
goto bad_usage;
}
- if (!autocfg && !wait_sync && !settings.forced_sync_offset) {
- fprintf(stderr,
- "time offset must be specified using -w or -O\n");
- goto bad_usage;
- }
-
if (hardpps_configured(pps_fd) && (dst_cnt != 1 ||
strcmp(dst_names[0], "CLOCK_REALTIME"))) {
fprintf(stderr,
@@ -1559,7 +1553,7 @@ int main(int argc, char *argv[])
r = -1;
- if (wait_sync) {
+ if (wait_sync || !domains[0].forced_sync_offset) {
snprintf(uds_local, sizeof(uds_local),
"/var/run/phc2sys.%d", getpid());
@@ -1574,7 +1568,7 @@ int main(int argc, char *argv[])
phc2sys_recv_subscribed, &domains[0]))
goto end;
- while (is_running()) {
+ while (wait_sync && is_running()) {
r = run_pmc_wait_sync(domains[0].agent, 1000);
if (r < 0)
goto end;

79
linuxptp-ppsmiss.patch Normal file
View File

@ -0,0 +1,79 @@
commit 5d735c810c8f9fd9916a3eb87398f5f9d6b1d278
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Aug 28 15:14:01 2025 +0200
ts2phc: Better handle missing pulses with multiple sinks.
The ts2phc_pps_sink_poll() function waits until it has collected pulses
for all active sinks, or a timeout of 2 seconds between events is
reached.
If a sink missed a pulse (e.g. after a port state change and switching
PPS signal direction in the external PPS mode) and the next pulse of
that sink came before pulses of the other sinks, it was mixed with
events of the previous pulse and the measured offset had an error of
1/rate seconds.
To avoid mixing events corresponding to different pulses, adjust the
poll() timeout so that it waits only up to a third of the pulse period
after the first received event.
(Rebased to 4.4)
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
index 9076de9..72d8ea4 100644
--- a/ts2phc_pps_sink.c
+++ b/ts2phc_pps_sink.c
@@ -381,10 +381,11 @@ void ts2phc_pps_sink_cleanup(struct ts2phc_private *priv)
int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
{
struct ts2phc_sink_array *polling_array = priv->polling_array;
+ bool first_poll = true, ignore_any = false;
bool all_sinks_have_events = false;
- bool ignore_any = false;
+ struct timespec first_ts = {0}, ts;
+ int cnt, timeout;
unsigned int i;
- int cnt;
for (i = 0; i < priv->n_sinks; i++)
polling_array->collected_events[i] = 0;
@@ -395,7 +396,22 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
if (!is_running())
return 0;
- cnt = poll(polling_array->pfd, priv->n_sinks, 2000);
+ /*
+ * Collect only events within a third of the pulse period to
+ * avoid mixing events corresponding to different pulses.
+ */
+ if (first_poll) {
+ timeout = 2000;
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ timeout = 333;
+ timeout -= (ts.tv_sec - first_ts.tv_sec) * 1000 +
+ (ts.tv_nsec - first_ts.tv_nsec) / 1000000;
+ if (timeout < 0)
+ timeout = 0;
+ }
+
+ cnt = poll(polling_array->pfd, priv->n_sinks, timeout);
if (cnt < 0) {
if (errno == EINTR) {
return 0;
@@ -408,6 +424,11 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
return 0;
}
+ if (first_poll) {
+ clock_gettime(CLOCK_MONOTONIC, &first_ts);
+ first_poll = false;
+ }
+
for (i = 0; i < priv->n_sinks; i++) {
if (polling_array->pfd[i].revents & POLLERR) {
sink = polling_array->sink[i];

75
linuxptp-rtnlinit.patch Normal file
View File

@ -0,0 +1,75 @@
commit 01de33e91f9717d0cbae5af6eee2beb45deee219
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Mar 4 15:53:37 2025 +0100
port: Refresh link status on faults.
ptp4l gets the ENOBUFS error on the netlink socket when the kernel has
to drop messages due to full socket buffer. If ptp4l has a port in the
faulty state waiting for the link to go up and that event corresponds
to one of the dropped netlink messages, the port will be stuck in the
faulty state until the link goes down and up again.
To prevent the port from getting stuck, request the current link status
when dispatching the EV_FAULT_DETECTED event. Also, reopen the socket to
get rid of the buffered messages when handling the fault and again when
reinitializing the port.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/port.c b/port.c
index 7f945ac..1bb407c 100644
--- a/port.c
+++ b/port.c
@@ -1975,6 +1975,20 @@ static int port_cmlds_initialize(struct port *p)
return port_cmlds_renew(p, now.tv_sec);
}
+static void port_rtnl_initialize(struct port *p)
+{
+ /* Reopen the socket to get rid of buffered messages */
+ if (p->fda.fd[FD_RTNL] >= 0) {
+ rtnl_close(p->fda.fd[FD_RTNL]);
+ }
+ p->fda.fd[FD_RTNL] = rtnl_open();
+ if (p->fda.fd[FD_RTNL] >= 0) {
+ rtnl_link_query(p->fda.fd[FD_RTNL], interface_name(p->iface));
+ }
+
+ clock_fda_changed(p->clock);
+}
+
void port_disable(struct port *p)
{
int i;
@@ -2087,13 +2101,8 @@ int port_initialize(struct port *p)
if (p->bmca == BMCA_NOOP) {
port_set_delay_tmo(p);
}
- if (p->fda.fd[FD_RTNL] == -1) {
- p->fda.fd[FD_RTNL] = rtnl_open();
- }
- if (p->fda.fd[FD_RTNL] >= 0) {
- const char *ifname = interface_name(p->iface);
- rtnl_link_query(p->fda.fd[FD_RTNL], ifname);
- }
+
+ port_rtnl_initialize(p);
}
port_nrate_initialize(p);
@@ -3768,6 +3777,13 @@ int port_state_update(struct port *p, enum fsm_event event, int mdiff)
if (port_link_status_get(p) && clear_fault_asap(&i)) {
pr_notice("%s: clearing fault immediately", p->log_name);
next = p->state_machine(next, EV_FAULT_CLEARED, 0);
+ } else if (event == EV_FAULT_DETECTED) {
+ /*
+ * Reopen the netlink socket and refresh the link
+ * status in case the fault was triggered by a missed
+ * netlink message (ENOBUFS).
+ */
+ port_rtnl_initialize(p);
}
}

302
linuxptp-staticauto.patch Normal file
View File

@ -0,0 +1,302 @@
commit e57fe1786ed17e8f0a37d9319bde53c9985ed656
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Oct 17 15:05:21 2024 +0200
pmc: Avoid race conditions in agent update.
The pmc_agent_update() function updates the subscription to
notifications and also the current UTC offset. It uses a timeout of 0
to avoid blocking. When the pmc client sends the first request, the
response from ptp4l may not come quickly enough to be received in the
same run_pmc() call. It then sends the other request and checks for the
response. If it is the response to the first request, it will be ignored.
The update works correctly only if both responses are quick enough to be
received in the same call, or are both slow enough that they are
received in the next call of the pmc_agent_update() function.
The function needs to be called a random number of times in order to
finish one update. If the mismatch between requests and responses
happened consistently, the agent would never reach the up-to-date state
and phc2sys would not enter the main synchronization loop.
Split the update into two phases, where only one thing is updated at a
time. The function now needs to be called at most 3 times to update both
the subscription and UTC offset, assuming it is not interrupted by
another request outside of the agent's update.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/pmc_agent.c b/pmc_agent.c
index 86b6ee6..d1a3367 100644
--- a/pmc_agent.c
+++ b/pmc_agent.c
@@ -37,6 +37,7 @@ struct pmc_agent {
struct pmc *pmc;
uint64_t pmc_last_update;
uint64_t update_interval;
+ int update_phase;
struct defaultDS dds;
bool dds_valid;
@@ -427,16 +428,27 @@ int pmc_agent_update(struct pmc_agent *node)
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
if (ts - node->pmc_last_update >= node->update_interval) {
- if (node->stay_subscribed) {
- renew_subscription(node, 0);
- }
- if (!pmc_agent_query_utc_offset(node, 0)) {
+ switch (node->update_phase) {
+ case 0:
+ if (node->stay_subscribed &&
+ renew_subscription(node, 0))
+ break;
+ node->update_phase++;
+ /* Fall through */
+ case 1:
+ if (pmc_agent_query_utc_offset(node, 0))
+ break;
+ node->update_phase++;
+ /* Fall through */
+ default:
node->pmc_last_update = ts;
+ node->update_phase = 0;
+ break;
}
+ } else {
+ run_pmc(node, 0, -1, &msg);
}
- run_pmc(node, 0, -1, &msg);
-
return 0;
}
commit 341cdd74c1623cdf97c519abec7312ac11baea4d
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Oct 17 15:05:22 2024 +0200
phc2sys: Wait until pmc agent is subscribed.
When phc2sys is configured with multiple domains, different domains may
have their pmc agent subscribed after different number of calls of the
pmc_agent_update() function depending on how quickly responses from
ptp4l are received. If one domain triggers reconfiguration and the other
domain does not have its agent subscribed yet, it will not have any of
its clocks synchronized until a port changes state and triggers another
reconfiguration of the domain.
To avoid this problem, wait for each domain to have its agent subscribed
before entering the main synchronization loop. Use a 10ms update
interval to speed up the start of phc2sys.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/phc2sys.c b/phc2sys.c
index 6113539..47e896e 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -962,6 +962,12 @@ static int auto_init_ports(struct domain *domain)
return -1;
}
+ while (!pmc_agent_is_subscribed(domain->agent)) {
+ usleep(10000);
+ if (pmc_agent_update(domain->agent) < 0)
+ return -1;
+ }
+
for (i = 1; i <= number_ports; i++) {
err = pmc_agent_query_port_properties(domain->agent, 1000, i,
&state, &timestamping,
commit a6cab9f888f88edab28e90d57a5368bbb83f6702
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Oct 24 15:24:07 2024 +0200
phc2sys: Keep clocks in command-line or ptp4l order.
When adding a new clock to the domain, add it to the end of the list to
keep them in the same order as specified on the command line or the port
order of ptp4l.
This will be needed by new code in the domain reconfiguration expecting
the order of reinitialized clocks to be the same as in which they were
added to the domain.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
diff --git a/phc2sys.c b/phc2sys.c
index 47e896e..bf36c38 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -161,7 +161,7 @@ static struct servo *servo_add(struct domain *domain,
static struct clock *clock_add(struct domain *domain, const char *device,
int phc_index)
{
- struct clock *c;
+ struct clock *c, *c2;
clockid_t clkid = CLOCK_INVALID;
char phc_device[19];
@@ -217,7 +217,19 @@ static struct clock *clock_add(struct domain *domain, const char *device,
c->sysoff_method = sysoff_probe(CLOCKID_TO_FD(clkid),
domain->phc_readings);
- LIST_INSERT_HEAD(&domain->clocks, c, list);
+ /* Add the clock to the end of the list to keep them in the
+ command-line or ptp4l order */
+ if (LIST_EMPTY(&domain->clocks)) {
+ LIST_INSERT_HEAD(&domain->clocks, c, list);
+ } else {
+ LIST_FOREACH(c2, &domain->clocks, list) {
+ if (LIST_NEXT(c2, list))
+ continue;
+ LIST_INSERT_AFTER(c2, c, list);
+ break;
+ }
+ }
+
return c;
}
commit 5d2aeb54054453570014715be4445da80da57101
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Oct 24 15:24:08 2024 +0200
phc2sys: Allow static sink clocks in automatic mode.
Allow the -c option to be used together with the -a option. Add the
specified clocks to the first domain, where they will stay in the master
state and be synchronized when a source is available in the same domain
or other domains.
Mark the clocks added by -c as static and skip them in the domain
reconfiguration if they duplicate a clock following a ptp4l port.
A use case is synchronization of clocks of backup interfaces in an
active-backup bond to minimize the observed offset when the active
interface is switched. ptp4l tracks the active interface, which is
followed by the automatic mode of phc2sys. All interfaces included in
the bond are specified by the -c option to keep them all synchronized to
the same source. The interface which duplicates the current active
interface provided by ptp4l is skipped.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/phc2sys.8 b/phc2sys.8
index dd97a70..762a1b1 100644
--- a/phc2sys.8
+++ b/phc2sys.8
@@ -117,10 +117,13 @@ should no longer be used.
.TP
.BI \-c " device"
Specify the time sink by device (e.g. /dev/ptp1) or interface (e.g. eth1) or
-by name. The default is CLOCK_REALTIME (the system clock). Not compatible
-with the
+by name. If used together with the
.B \-a
-option. This option may be given up to 128 times.
+option, it is an additional sink clock added to the clocks provided by the
+first ptp4l instance (if
+.B \-z
+is specified multiple times). Duplicated clocks are allowed. The default is
+CLOCK_REALTIME (the system clock). This option may be given up to 128 times.
.TP
.BI \-E " servo"
Specify which clock servo should be used. Valid values are pi for a PI
diff --git a/phc2sys.c b/phc2sys.c
index bf36c38..d09cb53 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -79,6 +79,7 @@ struct clock {
int dest_only;
int state;
int new_state;
+ int static_state;
int sync_offset;
int leap_set;
int utc_offset_set;
@@ -391,6 +392,18 @@ static struct clock *find_dst_clock(struct domain *domain,
return c;
}
+static struct clock *find_nonstatic_clock(struct domain *domain,
+ int phc_index)
+{
+ struct clock *c = NULL;
+ LIST_FOREACH(c, &domain->clocks, list) {
+ if (!c->static_state && c->phc_index == phc_index) {
+ break;
+ }
+ }
+ return c;
+}
+
static int reconfigure_domain(struct domain *domain)
{
struct clock *c, *src = NULL, *dup = NULL;
@@ -422,6 +435,17 @@ static int reconfigure_domain(struct domain *domain)
c->new_state = 0;
}
+ /* Ignore the clock if its state is not following ptp4l and has
+ the same PHC index as a clock that is following ptp4l */
+ if (c->static_state) {
+ dup = find_nonstatic_clock(domain, c->phc_index);
+ if (dup) {
+ pr_info("skipping static %s: %s has the same clock",
+ c->device, dup->device);
+ continue;
+ }
+ }
+
switch (c->state) {
case PS_FAULTY:
case PS_DISABLED:
@@ -436,6 +460,8 @@ static int reconfigure_domain(struct domain *domain)
dst_cnt++;
LIST_INSERT_HEAD(&domain->dst_clocks,
c, dst_list);
+ if (c->sanity_check)
+ clockcheck_reset(c->sanity_check);
} else {
pr_info("skipping %s: %s has the same clock "
"and is already selected",
@@ -1128,6 +1154,7 @@ static int phc2sys_static_dst_configuration(struct domain *domain,
return -1;
}
dst->state = PS_MASTER;
+ dst->static_state = 1;
LIST_INSERT_HEAD(&domain->dst_clocks, dst, dst_list);
return 0;
@@ -1407,7 +1434,7 @@ int main(int argc, char *argv[])
dst_names[dst_cnt++] = "CLOCK_REALTIME";
}
- if (autocfg && (src_name || dst_cnt > 0 || hardpps_configured(pps_fd) ||
+ if (autocfg && (src_name || hardpps_configured(pps_fd) ||
wait_sync || settings.forced_sync_offset)) {
fprintf(stderr,
"autoconfiguration cannot be mixed with manual config options.\n");
@@ -1506,6 +1533,14 @@ int main(int argc, char *argv[])
if (auto_init_ports(&domains[i]) < 0)
goto end;
}
+
+ for (i = 0; i < dst_cnt; i++) {
+ r = phc2sys_static_dst_configuration(&domains[0],
+ dst_names[i]);
+ if (r)
+ goto end;
+ }
+
r = do_loop(domains, n_domains);
goto end;
}

85
linuxptp-udpaddr.patch Normal file
View File

@ -0,0 +1,85 @@
commit 77504ea63484dbc0c78b1ef58b29f06ced517223
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Sep 25 14:16:16 2024 +0200
udp: Fix port-specific ptp/p2p_dst_ipv4 configuration.
If different ports are configured with a different ptp_dst_ipv4 or
p2p_dst_ipv4 address, only the last port in the configuration works
correctly. This is caused by a global variable holding the
destination address for all ports using the udp transport.
Move the address to the udp structure to avoid the conflict between
different ports, same as when port-specific scope in udp6 was fixed
in commit a48666bee3dd ("udp6: Make mc6_addr transport-local").
Fixes: 8a26c94cc88e ("udp+udp6: Make IP addresses configurable.")
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/udp.c b/udp.c
index 38d0ec4..c9b5f39 100644
--- a/udp.c
+++ b/udp.c
@@ -44,6 +44,7 @@ struct udp {
struct transport t;
struct address ip;
struct address mac;
+ struct in_addr mcast_addr[2];
};
static int mcast_bind(int fd, int index)
@@ -146,8 +147,6 @@ no_socket:
enum { MC_PRIMARY, MC_PDELAY };
-static struct in_addr mcast_addr[2];
-
static int udp_open(struct transport *t, struct interface *iface,
struct fdarray *fda, enum timestamp_type ts_type)
{
@@ -165,22 +164,22 @@ static int udp_open(struct transport *t, struct interface *iface,
sk_interface_addr(name, AF_INET, &udp->ip);
str = config_get_string(t->cfg, name, "ptp_dst_ipv4");
- if (!inet_aton(str, &mcast_addr[MC_PRIMARY])) {
+ if (!inet_aton(str, &udp->mcast_addr[MC_PRIMARY])) {
pr_err("invalid ptp_dst_ipv4 %s", str);
return -1;
}
str = config_get_string(t->cfg, name, "p2p_dst_ipv4");
- if (!inet_aton(str, &mcast_addr[MC_PDELAY])) {
+ if (!inet_aton(str, &udp->mcast_addr[MC_PDELAY])) {
pr_err("invalid p2p_dst_ipv4 %s", str);
return -1;
}
- efd = open_socket(name, mcast_addr, EVENT_PORT, ttl);
+ efd = open_socket(name, udp->mcast_addr, EVENT_PORT, ttl);
if (efd < 0)
goto no_event;
- gfd = open_socket(name, mcast_addr, GENERAL_PORT, ttl);
+ gfd = open_socket(name, udp->mcast_addr, GENERAL_PORT, ttl);
if (gfd < 0)
goto no_general;
@@ -223,6 +222,7 @@ static int udp_send(struct transport *t, struct fdarray *fda,
enum transport_event event, int peer, void *buf, int len,
struct address *addr, struct hw_timestamp *hwts)
{
+ struct udp *udp = container_of(t, struct udp, t);
struct address addr_buf;
unsigned char junk[1600];
ssize_t cnt;
@@ -243,8 +243,8 @@ static int udp_send(struct transport *t, struct fdarray *fda,
if (!addr) {
memset(&addr_buf, 0, sizeof(addr_buf));
addr_buf.sin.sin_family = AF_INET;
- addr_buf.sin.sin_addr = peer ? mcast_addr[MC_PDELAY] :
- mcast_addr[MC_PRIMARY];
+ addr_buf.sin.sin_addr = peer ? udp->mcast_addr[MC_PDELAY] :
+ udp->mcast_addr[MC_PRIMARY];
addr_buf.len = sizeof(addr_buf.sin);
addr = &addr_buf;
}

104
linuxptp-unirecover.patch Normal file
View File

@ -0,0 +1,104 @@
commit 71241f3fdcff59b35ad5de0b8b37cb07a4b677bd
Author: Vincent Cheng <vscheng@gmail.com>
Date: Tue Sep 17 15:23:54 2024 -0400
port: Fix unicast negotiation doesn't recover after FAULT_DETECTED
_Problem_
After a port link down/up or a tx_timestamp timeout issue, a port acting
as unicast master does not issue ANNC messages after granting unicast
request for ANNC.
_Analysis_
When a port FAULT occurs, the port transitions to FAULTY on FAULT_DETECTED
and subsequently port_disable(p) and port_initialize(p) are called on port recovery.
A port acting as a unicast master, stores clients in p->unicast_service->queue.
When a port receives a unicast request, unicast_service_add() is called.
In unicast_service_add(), if the request does not match an entry in
p->unicast_service->queue, FD_UNICAST_SRV_TIMER is started via
unicast_service_rearm_timer().
If the unicast request matches an existing p->unicast_service->queue entry
the request is considered an extension and FD_UNICAST_SRV_TIMER must
already be running.
port_disable() clears FD_UNICAST_SRV_TIMER, ie. stops FD_UNICAST_SRV_TIMER.
However, port_disable() does not clear p->unicast_service->queue.
When the port is restarted, the port retains the previous client data.
After port recovery, when the client attempts to restart the unicast
service, the request matches an existing entry in p->unicast_service->queue,
and so FD_UNICAST_SRV_TIMER is not started because the port expected
that the FD_UNICAST_SRV_TIMER is already running.
_Fix_
This patch clears the unicast client data in port_disable() so
that upon recovery, the initial unicast request will be considered
a new request and trigger the start of the FD_UNICAST_SRV_TIMER.
v2:
- Add missing sign-off
- Send to develop-request instead of users list
Signed-off-by: Vincent Cheng <vincent.cheng.xh@renesas.com>
diff --git a/port.c b/port.c
index 1bb407c..90b0860 100644
--- a/port.c
+++ b/port.c
@@ -1999,6 +1999,7 @@ void port_disable(struct port *p)
flush_peer_delay(p);
p->best = NULL;
+ unicast_service_clear_clients(p);
free_foreign_masters(p);
transport_close(p->trp, &p->fda);
diff --git a/unicast_service.c b/unicast_service.c
index 2fc2fbe..cee6691 100644
--- a/unicast_service.c
+++ b/unicast_service.c
@@ -583,3 +583,24 @@ int unicast_service_timer(struct port *p)
}
return err;
}
+
+void unicast_service_clear_clients(struct port *p)
+{
+ struct unicast_client_address *client, *temp;
+ struct unicast_service_interval *interval;
+
+ if (!p->unicast_service) {
+ return;
+ }
+
+ while ((interval = pqueue_extract(p->unicast_service->queue)) != NULL) {
+
+ LIST_REMOVE(interval, list);
+
+ LIST_FOREACH_SAFE(client, &interval->clients, list, temp) {
+ LIST_REMOVE(client, list);
+ free(client);
+ }
+ free(interval);
+ }
+}
\ No newline at end of file
diff --git a/unicast_service.h b/unicast_service.h
index f0d6487..8ea1a59 100644
--- a/unicast_service.h
+++ b/unicast_service.h
@@ -87,4 +87,10 @@ void unicast_service_remove(struct port *p, struct ptp_message *m,
*/
int unicast_service_timer(struct port *p);
+/**
+ * Clears unicast clients on a given port.
+ * @param p The port in question.
+ */
+void unicast_service_clear_clients(struct port *p);
+
#endif

11
linuxptp.fc Normal file
View File

@ -0,0 +1,11 @@
/usr/lib/systemd/system/phc2sys.* -- gen_context(system_u:object_r:phc2sys_unit_file_t,s0)
/usr/lib/systemd/system/ptp4l.* -- gen_context(system_u:object_r:ptp4l_unit_file_t,s0)
/usr/lib/systemd/system/timemaster.* -- gen_context(system_u:object_r:timemaster_unit_file_t,s0)
/usr/sbin/ptp4l -- gen_context(system_u:object_r:ptp4l_exec_t,s0)
/usr/sbin/phc2sys -- gen_context(system_u:object_r:phc2sys_exec_t,s0)
/usr/sbin/timemaster -- gen_context(system_u:object_r:timemaster_exec_t,s0)
/run/timemaster(/.*)? gen_context(system_u:object_r:timemaster_var_run_t,s0)

178
linuxptp.if Normal file
View File

@ -0,0 +1,178 @@
## <summary>implementation of the Precision Time Protocol (PTP) according to IEEE standard 1588 for Linux.</summary>
########################################
## <summary>
## Execute domain in the phc2sys domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`linuxptp_domtrans_phc2sys',`
gen_require(`
type phc2sys_t, phc2sys_exec_t;
')
corecmd_search_bin($1)
domtrans_pattern($1, phc2sys_exec_t, phc2sys_t)
')
########################################
## <summary>
## Execute domain in the phc2sys domain.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`linuxptp_domtrans_ptp4l',`
gen_require(`
type ptp4l_t, ptp4l_exec_t;
')
corecmd_search_bin($1)
domtrans_pattern($1, ptp4l_exec_t, ptp4l_t)
')
######################################
## <summary>
## Connect to timemaster using a unix
## domain stream socket.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`timemaster_stream_connect',`
gen_require(`
type timemaster_t, timemaster_var_run_t;
')
files_search_pids($1)
stream_connect_pattern($1, timemaster_var_run_t, timemaster_var_run_t, timemaster_t)
')
########################################
## <summary>
## Read timemaster conf files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`timemaster_read_pid_files',`
gen_require(`
type timemaster_var_run_t;
')
read_files_pattern($1, timemaster_var_run_t, timemaster_var_run_t)
')
########################################
## <summary>
## Manage timemaster pid files.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`timemaster_manage_pid_sock_files',`
gen_require(`
type timemaster_var_run_t;
')
manage_sock_files_pattern($1, timemaster_var_run_t, timemaster_var_run_t)
')
########################################
## <summary>
## Read and write timemaster shared memory.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`timemaster_rw_shm',`
gen_require(`
type timemaster_t, timemaster_tmpfs_t;
')
allow $1 timemaster_t:shm rw_shm_perms;
list_dirs_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
rw_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
read_lnk_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_search_tmpfs($1)
')
########################################
## <summary>
## Read and write ptp4l_t shared memory.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`ptp4l_rw_shm',`
gen_require(`
type ptp4l_t, timemaster_tmpfs_t;
')
allow $1 ptp4l_t:shm rw_shm_perms;
list_dirs_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
rw_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
read_lnk_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_search_tmpfs($1)
')
########################################
## <summary>
## Read and write phc2sys_t shared memory.
## </summary>
## <param name="domain">
## <summary>
## Domain allowed access.
## </summary>
## </param>
#
interface(`phc2sys_rw_shm',`
gen_require(`
type phc2sys_t, timemaster_tmpfs_t;
')
allow $1 phc2sys_t:shm rw_shm_perms;
list_dirs_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
rw_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
read_lnk_files_pattern($1, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_search_tmpfs($1)
')
#######################################
## <summary>
## Get timemaster services status
## </summary>
## <param name="domain">
## <summary>
## Domain allowed to transition.
## </summary>
## </param>
#
interface(`timemaster_service_status',`
gen_require(`
type timemaster_unit_file_t;
')
allow $1 timemaster_unit_file_t:service status;
')

414
linuxptp.spec Normal file
View File

@ -0,0 +1,414 @@
%global _hardened_build 1
%global testsuite_ver d27dbd
%global clknetsim_ver 64df92
%global selinuxtype targeted
%bcond_without selinux
Name: linuxptp
Version: 4.4
Release: 5%{?dist}
Summary: PTP implementation for Linux
License: GPL-2.0-or-later
URL: https://www.linuxptp.org/
Source0: https://downloads.nwtime.org/%{name}/%{name}-%{version}.tgz
Source1: phc2sys.service
Source2: ptp4l.service
Source3: timemaster.service
Source4: timemaster.conf
Source5: ptp4l.conf
# external test suite
Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver}/linuxptp-testsuite-%{testsuite_ver}.tar.gz
# simulator for test suite
Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz
# selinux policy
Source20: linuxptp.fc
Source21: linuxptp.if
Source22: linuxptp.te
# limit unicast message rate per address and grant duration
Patch1: linuxptp-ucastrate.patch
# fix port-specific ptp/p2p_dst_ipv4 configuration
Patch2: linuxptp-udpaddr.patch
# support static sink clocks in phc2sys automatic mode
Patch3: linuxptp-staticauto.patch
# don't require -O option without -a and -w in phc2sys
Patch4: linuxptp-nowait.patch
# add experimental option for external PPS in ts2phc automatic mode
Patch8: linuxptp-externalpps.patch
# add command to set external grandmaster properties
Patch9: linuxptp-externalgm.patch
# refresh link status on faults
Patch10: linuxptp-rtnlinit.patch
# fix unicast server to recover after port fault
Patch11: linuxptp-unirecover.patch
# handle missing pulses in ts2phc
Patch13: linuxptp-ppsmiss.patch
BuildRequires: gcc gcc-c++ gnutls-devel make systemd
%{?systemd_requires}
%if 0%{?with_selinux}
Requires: (%{name}-selinux if selinux-policy-%{selinuxtype})
%endif
%description
This software is an implementation of the Precision Time Protocol (PTP)
according to IEEE standard 1588 for Linux. The dual design goals are to provide
a robust implementation of the standard and to use the most relevant and modern
Application Programming Interfaces (API) offered by the Linux kernel.
Supporting legacy APIs and other platforms is not a goal.
%if 0%{?with_selinux}
%package selinux
Summary: linuxptp SELinux policy
BuildArch: noarch
Requires: selinux-policy-%{selinuxtype}
Requires(post): selinux-policy-%{selinuxtype}
BuildRequires: selinux-policy-devel
%{?selinux_requires}
%description selinux
linuxptp SELinux policy module
%endif
%prep
%autosetup -N
# autosetup doesn't accept multiple -a options
%__rpmuncompress -x %{SOURCE10}
%__rpmuncompress -x %{SOURCE11}
%autopatch -p1
# disable nettle support in favor of gnutls
sed -i 's|find .*"nettle"|true|' incdefs.sh
mv linuxptp-testsuite-%{testsuite_ver}* testsuite
mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim
pushd testsuite/clknetsim
popd
mkdir selinux
cp -p %{SOURCE20} %{SOURCE21} %{SOURCE22} selinux
%build
%{make_build} \
EXTRA_CFLAGS="$RPM_OPT_FLAGS" \
EXTRA_LDFLAGS="$RPM_LD_FLAGS"
%if 0%{?with_selinux}
make -C selinux -f %{_datadir}/selinux/devel/Makefile linuxptp.pp
bzip2 -9 selinux/linuxptp.pp
%endif
%install
%makeinstall
mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/sysconfig,%{_unitdir},%{_mandir}/man5}
install -m 644 -p %{SOURCE1} %{SOURCE2} %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir}
install -m 644 -p %{SOURCE4} %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}
echo 'OPTIONS="-f /etc/ptp4l.conf"' > \
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ptp4l
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/timemaster.8' > $RPM_BUILD_ROOT%{_mandir}/man5/timemaster.conf.5
%if 0%{?with_selinux}
install -D -m 0644 selinux/linuxptp.pp.bz2 \
$RPM_BUILD_ROOT%{_datadir}/selinux/packages/%{selinuxtype}/linuxptp.pp.bz2
install -D -p -m 0644 selinux/linuxptp.if \
$RPM_BUILD_ROOT%{_datadir}/selinux/devel/include/distributed/linuxptp.if
%endif
%check
cd testsuite
# set random seed to get deterministic results
export CLKNETSIM_RANDOM_SEED=26743
%{make_build} -C clknetsim
PATH=..:$PATH ./run
%post
%systemd_post phc2sys.service ptp4l.service timemaster.service
%preun
%systemd_preun phc2sys.service ptp4l.service timemaster.service
%postun
%systemd_postun_with_restart phc2sys.service ptp4l.service timemaster.service
%if 0%{?with_selinux}
%pre selinux
%selinux_relabel_pre -s %{selinuxtype}
%post selinux
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/linuxptp.pp.bz2
%selinux_relabel_post -s %{selinuxtype}
%postun selinux
if [ $1 -eq 0 ]; then
%selinux_modules_uninstall -s %{selinuxtype} linuxptp
%selinux_relabel_post -s %{selinuxtype}
fi
%files selinux
%{_datadir}/selinux/packages/%{selinuxtype}/linuxptp.pp.*
%{_datadir}/selinux/devel/include/distributed/linuxptp.if
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/linuxptp
%endif
%files
%doc COPYING README.org configs
%config(noreplace) %{_sysconfdir}/ptp4l.conf
%config(noreplace) %{_sysconfdir}/sysconfig/phc2sys
%config(noreplace) %{_sysconfdir}/sysconfig/ptp4l
%config(noreplace) %{_sysconfdir}/timemaster.conf
%{_unitdir}/phc2sys.service
%{_unitdir}/ptp4l.service
%{_unitdir}/timemaster.service
%{_sbindir}/hwstamp_ctl
%{_sbindir}/nsm
%{_sbindir}/phc2sys
%{_sbindir}/phc_ctl
%{_sbindir}/pmc
%{_sbindir}/ptp4l
%{_sbindir}/timemaster
%{_sbindir}/ts2phc
%{_sbindir}/tz2alt
%{_mandir}/man5/*.5*
%{_mandir}/man8/*.8*
%changelog
* Tue Sep 23 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.4-5
- handle missing pulses in ts2phc (RHEL-112344)
* Wed May 28 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.4-4
- fix unicast server to recover after port fault (RHEL-93497)
* Wed May 14 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.4-3
- add experimental option for external PPS in ts2phc automatic mode
(RHEL-89605)
- add command to set external grandmaster properties (RHEL-91310)
- refresh link status on faults (RHEL-89811)
* Thu Jan 30 2025 Miroslav Lichvar <mlichvar@redhat.com> 4.4-2
- update selinux policy (RHEL-76786)
- harden systemd services (RHEL-76760)
* Tue Dec 03 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.4-1
- update to 4.4 (RHEL-58210)
- fix port-specific ptp/p2p_dst_ipv4 configuration (RHEL-60055)
- support static sink clocks in phc2sys automatic mode (RHEL-69145)
- don't require -O option without -a and -w in phc2sys (RHEL-69699)
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 4.3-2
- Bump release for October 2024 mass rebuild:
Resolves: RHEL-64018
* Mon Aug 19 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.3-1
- update to 4.3 (RHEL-54718)
- add holdover support to ts2phc (RHEL-54716)
- rework NMEA delay patch to fix PPS edge rejection (RHEL-54719)
- fix ts2phc to reset NMEA parser after RMC message (RHEL-54724)
- fix ts2phc to correctly handle leap seconds (RHEL-54721)
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 4.2-7
- Bump release for June 2024 mass rebuild
* Tue Apr 16 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-6
- disable mode verification of selinux module directory (RHEL-32904)
* Wed Mar 20 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-5
- rebuild
* Wed Mar 20 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-4
- update selinux policy (RHEL-29728)
- limit unicast message rate per address and grant duration (RHEL-29738)
- allow old syntax of SET SUBSCRIBE_EVENTS_NP command (RHEL-29738)
- fix loading and reloading of leapfile (RHEL-29738)
- fix ts2phc to handle large NMEA delay (RHEL-29737)
* Thu Jan 25 2024 Fedora Release Engineering <releng@fedoraproject.org> - 4.2-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 4.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Tue Jan 02 2024 Miroslav Lichvar <mlichvar@redhat.com> 4.2-1
- update to 4.2
- update default ptp4l.conf
* Wed Sep 06 2023 Miroslav Lichvar <mlichvar@redhat.com> 4.1-1
- update to 4.1
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 4.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Mon Jun 12 2023 Miroslav Lichvar <mlichvar@redhat.com> 4.0-1
- update to 4.0
- convert license tag to SPDX
- update URL to https
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 3.1.1-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Wed Jan 11 2023 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-6
- update selinux policy (#2159919)
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 3.1.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Tue Apr 26 2022 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-4
- fix tests on ppc64le (#2046706)
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 3.1.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Thu Jul 22 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-2
- package selinux policy
* Wed Jul 07 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1.1-1
- update to 3.1.1 (CVE-2021-3570, CVE-2021-3571)
* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 3.1-4
- Rebuilt for updated systemd-rpm-macros
See https://pagure.io/fesco/issue/2583.
* Thu Feb 25 2021 Miroslav Lichvar <mlichvar@redhat.com> 3.1-3
- fix handling of zero-length messages
- minimize default configuration
- remove obsolete build requirement
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 3.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Tue Sep 29 2020 Miroslav Lichvar <mlichvar@redhat.com> 3.1-1
- update to 3.1
* Mon Jul 27 2020 Miroslav Lichvar <mlichvar@redhat.com> 3.0-1
- update to 3.0
* Mon Feb 03 2020 Miroslav Lichvar <mlichvar@redhat.com> 2.0-7.20191225gite05809
- update to 20191225gite05809
- fix testing with new glibc
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-6.20190912git48e605
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Wed Sep 25 2019 Miroslav Lichvar <mlichvar@redhat.com> 2.0-5.20190912git48e605
- update to 20190912git48e605
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Nov 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-2
- start ptp4l, timemaster and phc2sys after network-online target
- fix building with new kernel headers
* Mon Aug 13 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-1
- update to 2.0
* Thu Aug 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 2.0-0.1.20180805gita27407
- update to 20180805gita27407
* Mon Jul 16 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-3
- add gcc and gcc-c++ to build requirements
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.9.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Mon Apr 09 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.9.2-1
- update to 1.9.2
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-7.20180101git303b08
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Tue Jan 30 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.8-6.20180101git303b08
- use macro for systemd scriptlet dependencies
* Thu Jan 11 2018 Miroslav Lichvar <mlichvar@redhat.com> 1.8-5.20180101git303b08
- update to 20180101git303b08
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.8-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Nov 07 2016 Miroslav Lichvar <mlichvar@redhat.com> 1.8-1
- update to 1.8
* Fri Jul 22 2016 Miroslav Lichvar <mlichvar@redhat.com> 1.7-1
- update to 1.7
- add delay option to default timemaster.conf
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Tue Sep 22 2015 Miroslav Lichvar <mlichvar@redhat.com> 1.6-1
- update to 1.6
- set random seed in testing to get deterministic results
- remove trailing whitespace in default timemaster.conf
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Mon Jan 05 2015 Miroslav Lichvar <mlichvar@redhat.com> 1.5-1
- update to 1.5
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Fri Feb 21 2014 Miroslav Lichvar <mlichvar@redhat.com> 1.4-1
- update to 1.4
- replace hardening build flags with _hardened_build
- include test suite
* Fri Aug 02 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.3-1
- update to 1.3
* Tue Jul 30 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-3.20130730git7789f0
- update to 20130730git7789f0
* Fri Jul 19 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-2.20130719git46db40
- update to 20130719git46db40
- drop old systemd scriptlets
- add man page link for ptp4l.conf
* Mon Apr 22 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.2-1
- update to 1.2
* Mon Feb 18 2013 Miroslav Lichvar <mlichvar@redhat.com> 1.1-1
- update to 1.1
- log phc2sys output
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Thu Dec 13 2012 Miroslav Lichvar <mlichvar@redhat.com> 1.0-1
- update to 1.0
* Fri Nov 09 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.3.20121109git4e8107
- update to 20121109git4e8107
- install unchanged default.cfg as ptp4l.conf
- drop conflicts from phc2sys service
* Fri Sep 21 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.2.20120920git6ce135
- fix issues found in package review (#859193)
* Thu Sep 20 2012 Miroslav Lichvar <mlichvar@redhat.com> 0-0.1.20120920git6ce135
- initial release

201
linuxptp.te Normal file
View File

@ -0,0 +1,201 @@
policy_module(linuxptp, 1.0.0)
########################################
#
# Declarations
#
type timemaster_t;
type timemaster_exec_t;
init_daemon_domain(timemaster_t, timemaster_exec_t)
type timemaster_var_run_t;
files_pid_file(timemaster_var_run_t)
type timemaster_tmpfs_t;
files_tmpfs_file(timemaster_tmpfs_t)
type timemaster_unit_file_t;
systemd_unit_file(timemaster_unit_file_t)
type phc2sys_t;
type phc2sys_exec_t;
init_daemon_domain(phc2sys_t, phc2sys_exec_t)
type phc2sys_unit_file_t;
systemd_unit_file(phc2sys_unit_file_t)
type ptp4l_t;
type ptp4l_exec_t;
init_daemon_domain(ptp4l_t, ptp4l_exec_t)
type ptp4l_unit_file_t;
systemd_unit_file(ptp4l_unit_file_t)
########################################
#
# timemaster local policy
#
allow timemaster_t self:process { signal_perms setcap};
allow timemaster_t self:fifo_file rw_fifo_file_perms;
allow timemaster_t self:capability { setuid sys_time kill setgid };
allow timemaster_t self:unix_stream_socket create_stream_socket_perms;
allow timemaster_t self:shm create_shm_perms;
allow timemaster_t self:udp_socket create_socket_perms;
allow timemaster_t ptp4l_t:process signal;
allow timemaster_t phc2sys_t:process signal;
allow timemaster_t ptp4l_t:shm rw_shm_perms;
manage_dirs_pattern(timemaster_t, timemaster_var_run_t, timemaster_var_run_t)
manage_files_pattern(timemaster_t, timemaster_var_run_t, timemaster_var_run_t)
manage_sock_files_pattern(timemaster_t, timemaster_var_run_t, timemaster_var_run_t)
files_pid_filetrans(timemaster_t, timemaster_var_run_t, { dir file sock_file })
manage_dirs_pattern(timemaster_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
manage_files_pattern(timemaster_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_tmpfs_filetrans(timemaster_t, timemaster_tmpfs_t, { dir file })
kernel_read_network_state(timemaster_t)
auth_use_nsswitch(timemaster_t)
corenet_udp_bind_generic_node(timemaster_t)
corenet_udp_bind_ntp_port(timemaster_t)
dev_read_urand(timemaster_t)
dev_list_sysfs(timemaster_t)
#dev_write_sysfs(timemaster_t)
write_files_pattern(timemaster_t, sysfs_t, sysfs_t)
read_lnk_files_pattern(timemaster_t, sysfs_t, sysfs_t)
logging_send_syslog_msg(timemaster_t)
sysnet_read_config(timemaster_t)
optional_policy(`
ntp_domtrans(timemaster_t)
ntp_signal(timemaster_t)
')
optional_policy(`
chronyd_dgram_send(timemaster_t)
chronyd_domtrans(timemaster_t)
chronyd_rw_shm(timemaster_t)
')
optional_policy(`
gpsd_rw_shm(timemaster_t)
')
optional_policy(`
chronyd_signal(timemaster_t)
')
optional_policy(`
linuxptp_domtrans_ptp4l(timemaster_t)
')
optional_policy(`
linuxptp_domtrans_phc2sys(timemaster_t)
')
########################################
#
# phc2sys local policy
#
allow phc2sys_t self:capability sys_time;
allow phc2sys_t self:fifo_file rw_fifo_file_perms;
allow phc2sys_t self:unix_stream_socket create_stream_socket_perms;
allow phc2sys_t self:shm create_shm_perms;
allow phc2sys_t self:udp_socket create_socket_perms;
allow phc2sys_t ptp4l_t:unix_dgram_socket sendto;
allow phc2sys_t timemaster_t:shm rw_shm_perms;
manage_dirs_pattern(phc2sys_t, timemaster_var_run_t, timemaster_var_run_t)
manage_files_pattern(phc2sys_t, timemaster_var_run_t, timemaster_var_run_t)
manage_sock_files_pattern(phc2sys_t, timemaster_var_run_t, timemaster_var_run_t)
files_pid_filetrans(phc2sys_t, timemaster_var_run_t, { dir file sock_file })
manage_dirs_pattern(phc2sys_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
manage_files_pattern(phc2sys_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_tmpfs_filetrans(phc2sys_t, timemaster_tmpfs_t, { dir file })
dev_rw_realtime_clock(phc2sys_t)
logging_send_syslog_msg(phc2sys_t)
optional_policy(`
chronyd_dgram_send(phc2sys_t)
chronyd_rw_shm(phc2sys_t)
')
optional_policy(`
gpsd_rw_shm(phc2sys_t)
')
optional_policy(`
ntp_rw_shm(phc2sys_t)
')
optional_policy(`
ptp4l_rw_shm(phc2sys_t)
')
########################################
#
# ptp4l local policy
#
allow ptp4l_t self:fifo_file rw_fifo_file_perms;
allow ptp4l_t self:netlink_generic_socket create_socket_perms;
allow ptp4l_t self:packet_socket create_socket_perms;
allow ptp4l_t self:unix_stream_socket create_stream_socket_perms;
allow ptp4l_t self:shm create_shm_perms;
allow ptp4l_t self:udp_socket create_socket_perms;
allow ptp4l_t self:capability { net_admin net_raw sys_admin sys_time };
allow ptp4l_t self:capability2 { bpf wake_alarm };
allow ptp4l_t self:netlink_route_socket rw_netlink_socket_perms;
allow ptp4l_t phc2sys_t:unix_dgram_socket sendto;
manage_dirs_pattern(ptp4l_t, timemaster_var_run_t, timemaster_var_run_t)
manage_files_pattern(ptp4l_t, timemaster_var_run_t, timemaster_var_run_t)
manage_sock_files_pattern(ptp4l_t, timemaster_var_run_t, timemaster_var_run_t)
files_pid_filetrans(ptp4l_t, timemaster_var_run_t, { dir file sock_file })
manage_dirs_pattern(ptp4l_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
manage_files_pattern(ptp4l_t, timemaster_tmpfs_t, timemaster_tmpfs_t)
fs_tmpfs_filetrans(ptp4l_t, timemaster_tmpfs_t, { dir file })
corenet_udp_bind_generic_node(ptp4l_t)
corenet_udp_bind_ptp_event_port(ptp4l_t)
corenet_udp_bind_reserved_port(ptp4l_t)
kernel_read_network_state(ptp4l_t)
kernel_request_load_module(ptp4l_t)
dev_rw_realtime_clock(ptp4l_t)
files_write_generic_pid_sockets(ptp4l_t)
logging_send_syslog_msg(ptp4l_t)
userdom_users_dgram_send(ptp4l_t)
optional_policy(`
chronyd_dgram_send(ptp4l_t)
chronyd_rw_shm(ptp4l_t)
')
optional_policy(`
gpsd_rw_shm(ptp4l_t)
')

36
phc2sys.service Normal file
View File

@ -0,0 +1,36 @@
[Unit]
Description=Synchronize system clock or PTP hardware clock (PHC)
After=ntpdate.service ptp4l.service
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/phc2sys
ExecStart=/usr/sbin/phc2sys $OPTIONS
CapabilityBoundingSet=CAP_SYS_TIME
DeviceAllow=char-pps rw
DeviceAllow=char-ptp rw
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
# This does not work with selinux
#NoNewPrivileges=yes
PrivateTmp=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
ReadWritePaths=/run
RestrictAddressFamilies=AF_UNIX
RestrictNamespaces=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io
SystemCallFilter=~@reboot @resources @swap
[Install]
WantedBy=multi-user.target

13
ptp4l.conf Normal file
View File

@ -0,0 +1,13 @@
# For more information about this file, see the ptp4l(8) man page.
# Examples are available in /usr/share/doc/linuxptp/configs.
[global]
domainNumber 0
clientOnly 1
time_stamping hardware
logging_level 6
summary_interval 0
[eth0]
network_transport UDPv4
hybrid_e2e 0

38
ptp4l.service Normal file
View File

@ -0,0 +1,38 @@
[Unit]
Description=Precision Time Protocol (PTP) service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/ptp4l
ExecStart=/usr/sbin/ptp4l $OPTIONS
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SYS_TIME
DeviceAllow=char-pps rw
DeviceAllow=char-ptp rw
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
# This does not work with selinux
#NoNewPrivileges=yes
PrivateTmp=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
ReadWritePaths=/run
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_PACKET AF_UNIX
RestrictNamespaces=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io
SystemCallFilter=~@reboot @resources @swap
[Install]
WantedBy=multi-user.target

3
sources Normal file
View File

@ -0,0 +1,3 @@
SHA512 (clknetsim-64df92.tar.gz) = 91b7a9c9d4e8eaa8903f1f612cdaa2865d094e1c3531e039da9ad75595f4f4cd6fdbce9afdb0dafa18573d8afcb33a0e101170fc02c6585a231133a10b0890ff
SHA512 (linuxptp-4.4.tgz) = f9c8ac0c812d9829b3bc4595412afbeea0cade4937c46efbe47789d0ced38894a65f38a174a65a59c51b4d85a7bbf970b5d575ae1389c504fbd36eb7f96bd282
SHA512 (linuxptp-testsuite-d27dbd.tar.gz) = e289f63d522eaac3deb1db81442805fb602ae5423c02afb2200e59518e9c3db8dcaa00e42a57f0d81d51bb2e7cbd4b82c1d3522abbb5e5569cfd795ba403d659

View File

@ -14,18 +14,11 @@ ntp_program chronyd
[chrony.conf]
include /etc/chrony.conf
[ntp.conf]
includefile /etc/ntp.conf
[ptp4l.conf]
[chronyd]
path /usr/sbin/chronyd
[ntpd]
path /usr/sbin/ntpd
options -u ntp:ntp -g
[phc2sys]
path /usr/sbin/phc2sys

40
timemaster.service Normal file
View File

@ -0,0 +1,40 @@
[Unit]
Description=Synchronize system clock to NTP and PTP time sources
After=chronyd.service ntpd.service ntpdate.service sntp.service network-online.target
Conflicts=chronyd.service ntpd.service phc2sys.service ptp4l.service
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/sbin/timemaster -f /etc/timemaster.conf
RuntimeDirectory=timemaster
CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_MKNOD
CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_MODULE CAP_SYS_PACCT
CapabilityBoundingSet=~CAP_SYS_PTRACE CAP_SYS_RAWIO CAP_SYS_TTY_CONFIG CAP_WAKE_ALARM
DeviceAllow=char-pps rw
DeviceAllow=char-ptp rw
DeviceAllow=char-rtc rw
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
PrivateTmp=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
ReadWritePaths=/run/timemaster /var/lib/chrony -/var/log -/var/spool
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_PACKET AF_UNIX
RestrictNamespaces=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @swap
[Install]
WantedBy=multi-user.target