Thread: [Linuxptp-users] How to use common (v)clock for physically different PHCs?
PTP IEEE 1588 stack for Linux
Brought to you by:
rcochran
|
From: Osterried M. (ETAS-DAP/XPC-Fe3) <mar...@et...> - 2023-11-08 20:31:31
|
Hi, I am using a custom board with NXP LS1027A SoC which has an integrated ethernet controller (which provides one front facing port, eno0) and an integrated ethernet switch (which provides four front facing ports, swp0-swp3). I want to implement an IEEE1588 boundary clock supporting all five ports. The ethernet controller has attached a different PHC as the ports of the switch has, /dev/ptp0 resp. /dev/ptp1. Nevertheless, with hardware trigger signal, I can ensure that both clocks start at the same time and runs with same frequency, so they will always have the same value (within granularity of about 5 ns) - as long as they are free running, because frequency adjustments and time jumps can not be done atomically for both clocks. The idea was to create a virtual PHC (vclock, /dev/ptp2), based on either one of the two physical PHCs. But while ptp4l prints this info port 1 (eno0): /dev/ptp2 is virtual clock port 2 (swp0): taking /dev/ptp2 from the command line, not the attached ptp1 it seems that swp0 still uses the PHC /dev/ptp1 and frames send on this port contains timestamps derived from /dev/ptp1, while eno0 uses /dev/ptp2, so timestamps on both ports are quite different. I do not really understand what ptp4l is doing when p->phc_index and p->phc_from_cmdline is set - but it seems it is not as I have expected. But I have also recognized that setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ...) fails when used with SOF_TIMESTAMPING_BIND_PHC when vclock is not derived from natively attached PHC. What would be the best solution to use a common (v)clock for all the interfaces? I want to avoid to synchronize the physical PHCs with phc2sys, because that would be less accurate then using hardware trigger signal which keeps (free running) PHCs on the same value. Many thanks Markus |
|
From: Vladimir O. <ol...@gm...> - 2023-11-09 16:42:59
|
Hello Markus,
On Wed, Nov 08, 2023 at 04:58:54PM +0000, Osterried Markus (ETAS-DAP/XPC-Fe3) via Linuxptp-users wrote:
> Hi,
>
> I am using a custom board with NXP LS1027A SoC which has an integrated
> ethernet controller (which provides one front facing port, eno0) and
> an integrated ethernet switch (which provides four front facing ports,
> swp0-swp3).
>
> I want to implement an IEEE1588 boundary clock supporting all five
> ports. The ethernet controller has attached a different PHC as the
> ports of the switch has, /dev/ptp0 resp. /dev/ptp1.
>
> Nevertheless, with hardware trigger signal, I can ensure that both
> clocks start at the same time and runs with same frequency, so they
> will always have the same value (within granularity of about 5 ns) -
> as long as they are free running, because frequency adjustments and
> time jumps can not be done atomically for both clocks.
>
> The idea was to create a virtual PHC (vclock, /dev/ptp2), based on
> either one of the two physical PHCs.
>
> But while ptp4l prints this info
> port 1 (eno0): /dev/ptp2 is virtual clock
> port 2 (swp0): taking /dev/ptp2 from the command line, not the attached ptp1
>
> it seems that swp0 still uses the PHC /dev/ptp1 and frames send on
> this port contains timestamps derived from /dev/ptp1, while eno0 uses
> /dev/ptp2, so timestamps on both ports are quite different.
>
> I do not really understand what ptp4l is doing when p->phc_index and
> p->phc_from_cmdline is set - but it seems it is not as I have
> expected.
>
> But I have also recognized that setsockopt(fd, SOL_SOCKET,
> SO_TIMESTAMPING, ...) fails when used with SOF_TIMESTAMPING_BIND_PHC
> when vclock is not derived from natively attached PHC.
>
> What would be the best solution to use a common (v)clock for all the
> interfaces?
> I want to avoid to synchronize the physical PHCs with phc2sys, because
> that would be less accurate then using hardware trigger signal which
> keeps (free running) PHCs on the same value.
Virtual clocks (which btw can have a single parent, not two as you seem
to expect) don't work that way. The physical MACs always take timestamps
in their physical PHC's time domain, and depending on which socket
should receive the timestamped packets, the physical timestamps are
translated to the time base of the vclock associated with that socket.
You cannot make the switch port MACs take timestamps that are translated
into a time domain associated with a vclock of the ENETC. They don't
seem to help you here. They are used if you want multiple ptp4l instances,
associated with multiple domains, on top of the same Ethernet port.
If I understand your use case correctly, you are looking for ways to
keep the /dev/ptp0 clock (shared by eno0, eno1, eno2, eno3) in sync with
the /dev/ptp1 clock (shared by swp0, swp1, swp2, swp3, swp4, swp5), so
that you can run ptp4l with the boundary_clock_jbod option between all
front-facing Ethernet ports.
There are 2 ways in which you can do that.
First, here's a diagram of the Ethernet system on the LS1028A family,
for the viewers not familiar with it:
+-------------------------+------------------------------------------------+
| +--------+ | LS1028A |
| | eno3 |--|-----------------------------+ |
| +--------+ | internal port (1G) | |
| | | |
| +--------+ | internal port (2.5G) | |
| | eno2 |--|-----------------+ | |
| +--------+ | | | |
| +------------------------------------------------+
| ENETC | | | |
| | Felix +--------+ +--------+ /dev/ptp1 |
| /dev/ptp0 | switch | swp4 | | swp5 | |
| | +--------+ +--------+ |
| | |
| +--------+ +--------+ | +--------+ +--------+ +--------+ +--------+ |
| | eno0 | | eno1 | | | swp0 | | swp1 | | swp2 | | swp3 | |
+-------------------------+------------------------------------------------+
| | | | | |
SerDes RGMII SerDes SerDes SerDes SerDes
The first option is to run a pair of ptp4l instances on a pair of
Ethernet ports internal to the SoC: one on eno2 and another on swp4.
These internal Ethernet ports are capable of hardware timestamping,
so the PHC of eno2 (aka /dev/ptp0) will be kept in sync within very
low tolerances to the PHC of swp3 (aka /dev/ptp1).
The second option needs collaboration from your board. If you set the
RCW field EC1_SAI4_5_PMUX to the value of 0b101, you make the pinmuxing
of the SoC disable the eno1 RGMII port, and you make those pins available
for the auxiliary PTP pins of /dev/ptp0 and /dev/ptp1.
The idea here is to connect (externally to the SoC) the EC1_1588_PULSE_OUT1
pin of /dev/ptp0 to the SWITCH_1588_DAT[0] pin of /dev/ptp1. Then you
use the ts2phc program to keep in sync the 2 hardware clocks. This is
way more precise than phc2sys and comparable to the ptp4l option, because
the PPS signal is timestamped in hardware using the extts functionality
of the Felix PHC. One small note is that I never had access to a board
with the PPS layout I'm proposing, but based on what I know, it should
work.
There is no option to connect a PPS signal from one PHC to the other
internally to the SoC, unfortunately.
By the way, can you tell more about that hardware trigger signal? I am
familiar with the LS1028A family but I don't know what you are talking
about.
|
|
From: Osterried M. (ETAS-DAP/XPC-Fe3) <mar...@et...> - 2023-11-13 11:15:30
|
Hi Vladimir,
thanks for your answer.
We do not have a connection between EC1_1588_PULSE_OUT1 and SWITCH_1588_DAT0 on our board, so this option is not possible for us.
But we use this trigger signal, which actually is EC1_1588_TRIG_IN1 and SWITCH_1588_DAT1. Both pins are connected together to a GPIO pin.
In ES_DEVCPU_PTP_PTP_PINS_PTP_PIN_CFG register, SWITCH_1588_DAT1 is configured for STORE action.
Generating an edge on these trigger signals is latching a timestamp of the ENETC (aka /dev/ptp0) and SWITCH (aka /dev/ptp1).
As the input clocks of ENETC and SWITCH is derived from the same clock source, the PHCs always run at the same speed (with period configured in ENETC TMR_CTRL and ES_DEVCPU_PTP_PTP_CFG_PTP_SYS_CLK_CFG).
When latching the timestamps of ENETC and SWITCH, we can calculate the offset between them, which in turn we use to clock_adjtime(ADJ_SETOFFSET|ADJ_NANO) one PHC to the other.
Doing this in the startup phase, we can guarantee that /dev/ptp0 and /dev/ptp1 is synchronized, but yes, PHC subsystem does not know that they are now actually equivalent.
When later ptp4l wants to adjust the PHC according to an external PTP master, it will do this only on one of the two PHCs, therefore they will be no longer in sync.
To avoid this, the idea was to create a vclock /dev/ptp2 based on /dev/ptp0. And to let /dev/ptp0 and /dev/ptp1 free running and in sync.
But because PHC subsystem does not know that /dev/ptp0 and /dev/ptp1 is actually equivalent, it forbids to bind /dev/ptp2 to the socket of swpX.
If I understand your suggested options correctly, the ptp4l instance which handles the external front-facing interfaces, will just adjust one physical PHC, while the other PHC is re-adjusted by either internal ptp4l instance or ts2phc, but of course within some latency. Is this correct?
Back to our original problem:
We want to use ptp4l between all front-facing ports, while physical PHCs of eno0-eno3 and swp0-swp5 are already in sync - known by us, but not known by PHC subsystem.
For this, you have mentioned boundary_clock_jbod can be used.
I do not know what boundary_clock_jbod is doing in detail and if and how this could be used to provide a solution in this use case.
Could you please explain.
Many thanks and regards
Markus
Hello Markus,
On Wed, Nov 08, 2023 at 04:58:54PM +0000, Osterried Markus (ETAS-DAP/XPC-Fe3) via Linuxptp-users wrote:
> Hi,
>
> I am using a custom board with NXP LS1027A SoC which has an integrated
> ethernet controller (which provides one front facing port, eno0) and
> an integrated ethernet switch (which provides four front facing ports,
> swp0-swp3).
>
> I want to implement an IEEE1588 boundary clock supporting all five
> ports. The ethernet controller has attached a different PHC as the
> ports of the switch has, /dev/ptp0 resp. /dev/ptp1.
>
> Nevertheless, with hardware trigger signal, I can ensure that both
> clocks start at the same time and runs with same frequency, so they
> will always have the same value (within granularity of about 5 ns) -
> as long as they are free running, because frequency adjustments and
> time jumps can not be done atomically for both clocks.
>
> The idea was to create a virtual PHC (vclock, /dev/ptp2), based on
> either one of the two physical PHCs.
>
> But while ptp4l prints this info
> port 1 (eno0): /dev/ptp2 is virtual clock port 2 (swp0): taking
> /dev/ptp2 from the command line, not the attached ptp1
>
> it seems that swp0 still uses the PHC /dev/ptp1 and frames send on
> this port contains timestamps derived from /dev/ptp1, while eno0 uses
> /dev/ptp2, so timestamps on both ports are quite different.
>
> I do not really understand what ptp4l is doing when p->phc_index and
> p->phc_from_cmdline is set - but it seems it is not as I have
> expected.
>
> But I have also recognized that setsockopt(fd, SOL_SOCKET,
> SO_TIMESTAMPING, ...) fails when used with SOF_TIMESTAMPING_BIND_PHC
> when vclock is not derived from natively attached PHC.
>
> What would be the best solution to use a common (v)clock for all the
> interfaces?
> I want to avoid to synchronize the physical PHCs with phc2sys, because
> that would be less accurate then using hardware trigger signal which
> keeps (free running) PHCs on the same value.
Virtual clocks (which btw can have a single parent, not two as you seem to expect) don't work that way. The physical MACs always take timestamps in their physical PHC's time domain, and depending on which socket should receive the timestamped packets, the physical timestamps are translated to the time base of the vclock associated with that socket.
You cannot make the switch port MACs take timestamps that are translated into a time domain associated with a vclock of the ENETC. They don't seem to help you here. They are used if you want multiple ptp4l instances, associated with multiple domains, on top of the same Ethernet port.
If I understand your use case correctly, you are looking for ways to keep the /dev/ptp0 clock (shared by eno0, eno1, eno2, eno3) in sync with the /dev/ptp1 clock (shared by swp0, swp1, swp2, swp3, swp4, swp5), so that you can run ptp4l with the boundary_clock_jbod option between all front-facing Ethernet ports.
There are 2 ways in which you can do that.
First, here's a diagram of the Ethernet system on the LS1028A family, for the viewers not familiar with it:
+-------------------------+------------------------------------------------+
| +--------+ | LS1028A |
| | eno3 |--|-----------------------------+ |
| +--------+ | internal port (1G) | |
| | | |
| +--------+ | internal port (2.5G) | |
| | eno2 |--|-----------------+ | |
| +--------+ | | | |
| +------------------------------------------------+
| ENETC | | | |
| | Felix +--------+ +--------+ /dev/ptp1 |
| /dev/ptp0 | switch | swp4 | | swp5 | |
| | +--------+ +--------+ |
| | |
| +--------+ +--------+ | +--------+ +--------+ +--------+ +--------+ |
| | eno0 | | eno1 | | | swp0 | | swp1 | | swp2 | | swp3 | |
+-------------------------+------------------------------------------------+
| | | | | |
SerDes RGMII SerDes SerDes SerDes SerDes
The first option is to run a pair of ptp4l instances on a pair of Ethernet ports internal to the SoC: one on eno2 and another on swp4.
These internal Ethernet ports are capable of hardware timestamping, so the PHC of eno2 (aka /dev/ptp0) will be kept in sync within very low tolerances to the PHC of swp3 (aka /dev/ptp1).
The second option needs collaboration from your board. If you set the RCW field EC1_SAI4_5_PMUX to the value of 0b101, you make the pinmuxing of the SoC disable the eno1 RGMII port, and you make those pins available for the auxiliary PTP pins of /dev/ptp0 and /dev/ptp1.
The idea here is to connect (externally to the SoC) the EC1_1588_PULSE_OUT1 pin of /dev/ptp0 to the SWITCH_1588_DAT[0] pin of /dev/ptp1. Then you use the ts2phc program to keep in sync the 2 hardware clocks. This is way more precise than phc2sys and comparable to the ptp4l option, because the PPS signal is timestamped in hardware using the extts functionality of the Felix PHC. One small note is that I never had access to a board with the PPS layout I'm proposing, but based on what I know, it should work.
There is no option to connect a PPS signal from one PHC to the other internally to the SoC, unfortunately.
By the way, can you tell more about that hardware trigger signal? I am familiar with the LS1028A family but I don't know what you are talking about.
|
|
From: Vladimir O. <ol...@gm...> - 2023-11-16 13:17:16
|
On Mon, Nov 13, 2023 at 10:43:01AM +0000, Osterried Markus (ETAS-DAP/XPC-Fe3) wrote: > Hi Vladimir, > > thanks for your answer. > > We do not have a connection between EC1_1588_PULSE_OUT1 and SWITCH_1588_DAT0 on our board, so this option is not possible for us. > > But we use this trigger signal, which actually is EC1_1588_TRIG_IN1 and SWITCH_1588_DAT1. Both pins are connected together to a GPIO pin. > In ES_DEVCPU_PTP_PTP_PINS_PTP_PIN_CFG register, SWITCH_1588_DAT1 is configured for STORE action. > Generating an edge on these trigger signals is latching a timestamp of the ENETC (aka /dev/ptp0) and SWITCH (aka /dev/ptp1). > As the input clocks of ENETC and SWITCH is derived from the same clock source, the PHCs always run at the same speed (with period configured in ENETC TMR_CTRL and ES_DEVCPU_PTP_PTP_CFG_PTP_SYS_CLK_CFG). Have you studied the clock distribution trees for the ENETC and the Felix switch IPs before drawing the conclusion that their input clocks are derived from the same source? As far as I see, ENETC, through HWA_CGA_M4_CLK_SEL, uses Cluster Group A PLL 2 divided by 3 as clock (400 MHz), whereas Felix has its sys_clk at 156.25 MHz and it comes from one of the SerDes PLLs, depending on the particular RCW configuration. > When latching the timestamps of ENETC and SWITCH, we can calculate the offset between them, which in turn we use to clock_adjtime(ADJ_SETOFFSET|ADJ_NANO) one PHC to the other. > Doing this in the startup phase, we can guarantee that /dev/ptp0 and /dev/ptp1 is synchronized, but yes, PHC subsystem does not know that they are now actually equivalent. Aha, so you've implemented the extts API in the ocelot ptp driver? Do you plan to upstream that work? A pulse output from the ENETC PHC which is an input to the Felix PHC is not strictly necessary. Your way should be just fine - a GPIO output which is input both to ENETC and to Felix is equally fine, and ts2phc should be able to work with that. I guess you're looking at a "generic" source of 1-PPS signal, when you open up the ts2phc manual. > When later ptp4l wants to adjust the PHC according to an external PTP master, it will do this only on one of the two PHCs, therefore they will be no longer in sync. This is a similar reason to the one for which I modified ts2phc to monitor the direction of ptp4l's synchronization dynamically. If the slave port of the ptp4l BC is an ENETC port, then the Felix PHC gets synchronized to the ENETC PHC, otherwise the ENETC PHC gets synchronized to the Felix PHC. https://sourceforge.net/p/linuxptp/mailman/linuxptp-devel/thread/20200830234525.3311891-11-olteanv%40gmail.com/ I've only tried it with the "PHC" kind of sources of 1-PPS signals. If it doesn't work with a "generic" source, it probably isn't too hard to modify ts2phc to treat that case reasonably. > To avoid this, the idea was to create a vclock /dev/ptp2 based on /dev/ptp0. And to let /dev/ptp0 and /dev/ptp1 free running and in sync. > But because PHC subsystem does not know that /dev/ptp0 and /dev/ptp1 is actually equivalent, it forbids to bind /dev/ptp2 to the socket of swpX. It's not that the PHC subsystem doesn't know that /dev/ptp0 and /dev/ptp1 are "actually equivalent". They _aren't_ actually equivalent. They are completely independent clocks, independently adjustable. Synchronized once and then left alone, I don't see what will prevent them from starting to drift. The sync process needs to be continuous, like for any other independent hardware clocks. That, plus the fact that vclocks don't do what you think they do. Even if there were 2 PTP clocks which could be proven to be equivalent, a vclock only has a single PTP clock as parent, not 2. > If I understand your suggested options correctly, the ptp4l instance which handles the external front-facing interfaces, will just adjust one physical PHC, while the other PHC is re-adjusted by either internal ptp4l instance or ts2phc, but of course within some latency. Is this correct? Yes. > Back to our original problem: > We want to use ptp4l between all front-facing ports, while physical PHCs of eno0-eno3 and swp0-swp5 are already in sync - known by us, but not known by PHC subsystem. > For this, you have mentioned boundary_clock_jbod can be used. > I do not know what boundary_clock_jbod is doing in detail and if and how this could be used to provide a solution in this use case. > Could you please explain. man ptp4l boundary_clock_jbod When running as a boundary clock (that is, when more than one network interface is configured), ptp4l performs a sanity check to make sure that all of the ports share the same hardware clock device. This option allows ptp4l to work as a boundary clock using "just a bunch of devices" that are not synchronized to each other. For this mode, the collection of clocks must be synchronized by an external program, for example phc2sys(8) in "automatic" mode. The default is 0 (disabled). "physical PHCs of eno0-eno3 and swp0-swp5 are already in sync - known by us, but not known by PHC subsystem" -> TL;DR: this option tells ptp4l "trust me, the clocks are in sync, within an unknown tolerance, despite being different, you can make a boundary clock out of these ports". They'd better be in robust sync, though, because ptp4l can make an attempt to adjust any of those PHCs. |
|
From: Osterried M. (ETAS-DAP/XPC-Fe3) <mar...@et...> - 2023-11-20 12:55:28
|
Hi Vladimir, I had a look at the clock distribution internal and external of SoC, as far as understood, both PHCs use clocks which are phase locked to each other. Also run a test for several days, repeatedly sampled the PHCs and it shows they are in sync, without the need to re-sync. In current development phase, just to evaluate the options, we have direct register access from user space, not changed the ocelot ptp driver. Thanks for your info, which helped a lot. > Hi Vladimir, > > thanks for your answer. > > We do not have a connection between EC1_1588_PULSE_OUT1 and SWITCH_1588_DAT0 on our board, so this option is not possible for us. > > But we use this trigger signal, which actually is EC1_1588_TRIG_IN1 and SWITCH_1588_DAT1. Both pins are connected together to a GPIO pin. > In ES_DEVCPU_PTP_PTP_PINS_PTP_PIN_CFG register, SWITCH_1588_DAT1 is configured for STORE action. > Generating an edge on these trigger signals is latching a timestamp of the ENETC (aka /dev/ptp0) and SWITCH (aka /dev/ptp1). > As the input clocks of ENETC and SWITCH is derived from the same clock source, the PHCs always run at the same speed (with period configured in ENETC TMR_CTRL and ES_DEVCPU_PTP_PTP_CFG_PTP_SYS_CLK_CFG). Have you studied the clock distribution trees for the ENETC and the Felix switch IPs before drawing the conclusion that their input clocks are derived from the same source? As far as I see, ENETC, through HWA_CGA_M4_CLK_SEL, uses Cluster Group A PLL 2 divided by 3 as clock (400 MHz), whereas Felix has its sys_clk at 156.25 MHz and it comes from one of the SerDes PLLs, depending on the particular RCW configuration. > When latching the timestamps of ENETC and SWITCH, we can calculate the offset between them, which in turn we use to clock_adjtime(ADJ_SETOFFSET|ADJ_NANO) one PHC to the other. > Doing this in the startup phase, we can guarantee that /dev/ptp0 and /dev/ptp1 is synchronized, but yes, PHC subsystem does not know that they are now actually equivalent. Aha, so you've implemented the extts API in the ocelot ptp driver? Do you plan to upstream that work? A pulse output from the ENETC PHC which is an input to the Felix PHC is not strictly necessary. Your way should be just fine - a GPIO output which is input both to ENETC and to Felix is equally fine, and ts2phc should be able to work with that. I guess you're looking at a "generic" source of 1-PPS signal, when you open up the ts2phc manual. > When later ptp4l wants to adjust the PHC according to an external PTP master, it will do this only on one of the two PHCs, therefore they will be no longer in sync. This is a similar reason to the one for which I modified ts2phc to monitor the direction of ptp4l's synchronization dynamically. If the slave port of the ptp4l BC is an ENETC port, then the Felix PHC gets synchronized to the ENETC PHC, otherwise the ENETC PHC gets synchronized to the Felix PHC. https://sourceforge.net/p/linuxptp/mailman/linuxptp-devel/thread/20200830234525.3311891-11-olteanv%40gmail.com/ I've only tried it with the "PHC" kind of sources of 1-PPS signals. If it doesn't work with a "generic" source, it probably isn't too hard to modify ts2phc to treat that case reasonably. > To avoid this, the idea was to create a vclock /dev/ptp2 based on /dev/ptp0. And to let /dev/ptp0 and /dev/ptp1 free running and in sync. > But because PHC subsystem does not know that /dev/ptp0 and /dev/ptp1 is actually equivalent, it forbids to bind /dev/ptp2 to the socket of swpX. It's not that the PHC subsystem doesn't know that /dev/ptp0 and /dev/ptp1 are "actually equivalent". They _aren't_ actually equivalent. They are completely independent clocks, independently adjustable. Synchronized once and then left alone, I don't see what will prevent them from starting to drift. The sync process needs to be continuous, like for any other independent hardware clocks. That, plus the fact that vclocks don't do what you think they do. Even if there were 2 PTP clocks which could be proven to be equivalent, a vclock only has a single PTP clock as parent, not 2. > If I understand your suggested options correctly, the ptp4l instance which handles the external front-facing interfaces, will just adjust one physical PHC, while the other PHC is re-adjusted by either internal ptp4l instance or ts2phc, but of course within some latency. Is this correct? Yes. > Back to our original problem: > We want to use ptp4l between all front-facing ports, while physical PHCs of eno0-eno3 and swp0-swp5 are already in sync - known by us, but not known by PHC subsystem. > For this, you have mentioned boundary_clock_jbod can be used. > I do not know what boundary_clock_jbod is doing in detail and if and how this could be used to provide a solution in this use case. > Could you please explain. man ptp4l boundary_clock_jbod When running as a boundary clock (that is, when more than one network interface is configured), ptp4l performs a sanity check to make sure that all of the ports share the same hardware clock device. This option allows ptp4l to work as a boundary clock using "just a bunch of devices" that are not synchronized to each other. For this mode, the collection of clocks must be synchronized by an external program, for example phc2sys(8) in "automatic" mode. The default is 0 (disabled). "physical PHCs of eno0-eno3 and swp0-swp5 are already in sync - known by us, but not known by PHC subsystem" -> TL;DR: this option tells ptp4l "trust me, the clocks are in sync, within an unknown tolerance, despite being different, you can make a boundary clock out of these ports". They'd better be in robust sync, though, because ptp4l can make an attempt to adjust any of those PHCs. |