The sequence of port_nrate_calculate() and tsproc_update_delay()
in port_peer_delay() is mixed up.
The peer delay depends on the nrate ratio so the nrate ratio
shall be updated before peer delay is calculated.
Signed-off-by: Burkhard Ilsen <burkhardilsen@gmail.com>
This global function used to return an error code, but now it always
returns zero. This patch converts the function signature to return void
and simplifies the main clock loop by removing the useless test.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The state machines in 1588 do not specify an event that causes a transition
out of the initializing state. This was left as a local issue. For this
transition, the current code assigns the next state outside of the FSM. But
doing so prevents an alternative FSM to handle this transition differently.
By introducing a new event, this patch places this transition where it
belongs, namely under the control of the FSM code,
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Although leaving the INITIALIZING state and clearing the FAULTY state
ASAP both result in a port entering the LISTENING state, still there
is no benefit from conflating the two. In the FAULTY case, the
current code actually skips the INITIALIZING state altogether.
This patch separates the two cases resulting in two benefits. First,
the check for ASAP fault status is only made when a fault is actually
present, unlike the present unconditional check. Second, this change
will allow us to cleanly support alternative state machines later on.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The code that decides whether a fault qualifies for ASAP treatment is
a tangle of logical operators. This patch replaces the open coded
logic with a helper function whose name makes the intent clear. This
is a cosmetic change only.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Looking at the fault logic in port_dispatch(), you might think that
the function, fault_interval(), checks whether a fault is active, but
you would be wrong, since that function always returns zero.
This patch removes the superfluous input error checking inside of
fault_interval() and changes the return type to void, making the
actual behavior explicit. Dropping the input check is safe because
that function has exactly two callers, both of whom always provide
valid inputs.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
If a non-slave port on a boundary clock see an announce message, then it
must decide whether it should take on the MASTER or the PASSIVE role. When
the GM fields from the local clock are identical to those in the announce,
then the sender/receiver ports are used as a tie breaker.
Following a typographical error in 1588, the code wrongly uses the port
identity of the upstream parent as the "receiver" id. As a result, a port
that should be PASSIVE may choose MASTER instead. This patch fixes the
code to use local port id.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
During the configuration rework, the announce span was wrongly converted
into a hard coded macro. In addition, the announceReceiptTimeout option
inadvertently became non-zero for the UDS port. As a result, the UDS port
sets a useless announce message timer, causing the code to close and reopen
the UDS port every few seconds.
This bug has an interesting history. It was first reported and fixed in
commit f36af8e0 ("uds: disable the accidentally enabled announce timer.").
That very fix was wrongly removed in commit 54f45063 ("port: change
'announce_span' into a macro."). Because of various code changes, this
bad commit cannot be simply reverted now.
This patch re-introduces the 'announce_span' variable and clears both it
and 'announceReceiptTimeout' for the UDS port, effectively disabling the
announce message timer.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The port code is not interested in the number of ports but rather the
clock type. Since the polymorphic clock object will be able to report
its own type, this patch changes the clock interface accordingly.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The message lists are implemented using a TAILQ from queue(3). The heads
of the list must be initialized using the provided macros, since the field
called 'tqh_last' is non-zero in the initial state. This patch fixes a
potential null pointer dereference by properly initializing the queues.
Note that there is no actual bug in the current code, because it uses the
lists in such a way as to initialize 'tqh_last' before any dereference.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Upgrade the message level to info so the user can see it, but print it
at most once per 5 minutes to not spam the syslog too much.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
The draft Enterprise Profile [1] specifies a hybrid E2E delay mechanism,
where the delay response message is sent "in kind". That is, if the
request is unicast, then the response is also unicast. Apparently this
scheme is already in widespread use in some industries. Also, it makes
sense, because those messages are of no interest to the other slaves in
the PTP network.
Because of the address work already in place, in turns out that adding
this mode is almost trivial. This patch introduces an "hybrid_e2e" option
that enabled the new mode.
1. https://datatracker.ietf.org/doc/draft-ietf-tictoc-ptp-enterprise-profile
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Buggy or mis-configured masters can place bogus logMessageInterval values
in their delay response messages. This patch places reasonable limits on
the range of values that we will accept.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The logMessageInterval field has an improbable range from 2^-128 to 2^127
seconds. The extreme ends cause an integer overflow in the calculation
of the "foreign master time window". Buggy or mis-configured foreign
masters advertising extreme values will cause incorrect announce message
aging.
This patch fixes the issue by adding thresholds for the bogus extremes.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This conversion is not straightforward due to the fact that these options
can take a value of "ASAP" or a number. We check for the special ASAP
case in a helper function and leave the numbers to the generic code.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Add new time stamp processing modes to return raw delay and offset based
on the raw delay instead of the long-term filtered delay, and to return
also a weight of the sample. The weight is set to the ratio between the
two delays. This gives smaller weight to samples where the sync and/or
delay messages were delayed significantly in the network and possibly
include a large error.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Introduce a time stamp processor for offset/delay calculations and use
it in the clock and port modules.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Convert time stamps to tmv_t and apply all corrections before passing
them to clock/port functions to reduce the number of parameters.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
If the user has configured the appropriate option, then simply warn
about the clock device mismatch, and then go on in "JBOD" mode.
Whenever the port enters the uncalibrated state, it tells the clock
to switch to the new PHC device.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Commit ea7a7882 removed the calls to transport_peer(), inadvertently
substituting them with transport_send(), resulting in PDelay messages
being sent with an incorrect destination address.
This patch fixes the issue by introducing peer_prepare_and_send(),
analogous to the port_prepare_and_send() function.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Jiri Benc <jbenc@redhat.com>
Remove the limit of MAX_PORTS ports (default 8) and keep the ports in
a linked list. This allows ptp4l to be used on large machines and in the
future, it will allow dynamic adding and removing of ports while ptp4l is
running.
For this to work, pollfd needs to be dynamically allocated. Changed pollfd
handling from clock_install_fda/clock_remove_fda to notification
(clock_fda_changed), where the clock will rebuild pollfd by querying all its
ports.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
The fault timer file descriptor is a per port item, put it inside struct
port where other per port file descriptors are kept.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Split management message creation to more fine-grained functions to allow
notification messages to be created.
The new clock_management_fill_response is called from
clock_management_get_response (so the function behaves exactly the same as
before this patch) and from a new clock_notify_event function. The
difference is clock_management_get_response uses the request message to
construct the reply message, while clock_notify_event constructs the reply
message based on the notification id.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Split management message creation to more fine-grained functions to allow
notification messages to be created.
The new port_management_fill_response is called from
port_management_get_response (so the function behaves exactly the same
as before this patch) and from a new port_notify_event function. The
difference is port_management_get_response uses the request message to
construct the reply message, while port_notify_event constructs the
reply message based on the notification id.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
The callers of those functions are all using ptp_message. As we're going to
return more information (the address), let those functions just fill in the
ptp_message fields directly.
Some minor reshuffling needed to prevent circular header dependencies.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
The task of preparing the message for transmission and sending it appears
at many places. Unify them into a new function.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
With the new linreg servo the frequency offset and time offset are
controlled separately. The ratio between master's frequency and the
current frequency of the local clock is known and can be used when
calculating delay or peer delay to improve their accuracy.
This greatly improves the stability of the delay when the servo is
correcting a large offset.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
When peer delay is < min_neighbor_prop_delay the port is flagged
as non 802.1AS capable. min_neighbor_prop_delay defaults to -20ms.
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
Previouly the peer delay was not taking into account the
frequency offset between the local clock and the peer's clock.
Reset neighborRateRatio to 1.0 in port_nrate_initialize().
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
Commit e425da2f inadvertently enabled the announce timer on the UDS port,
causing it to continually reopen the socket when in slave mode. This patch
fixes the issue by passing zero in the 'span' field of the new function,
set_tmo_random, which disables the timer again.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Rohrer Hansjoerg <hj.rohrer@mobatime.com>
According to 802.1AS, ports are always expected to transmit announce
messages, even if they never want to become the grand master. Instead
of using a slave only BMC state machine as in 1588, 802.1AS offers a
"grand master capable" flag which allows clocks to not send sync
messages.
This patch keeps a port from transmitting sync (but not announce)
messages when there is no other master.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
[ RC: the point is that a port may not be considered capable until
enough messages to compute the ratio have been received. ]
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
Reviewed-by: Richard Cochran <richardcochran@gmail.com>
Sync rx timeout should be set only after receiving the first sync, see
section 10.2.7, figure 10-4 PortSyncSyncReceive state machine in 802.1AS
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
Add new options delay_filter and delay_filter_length to select the
filter and its length. They set both the clock delay filter and the port
peer delay filter. The default is now moving median with 10 samples.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Similarly to the servo interface, allow multiple filters to be
used for delay filtering. Convert mave to the new interface.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Instead of maintaining a table of precalculated values, use the
newly added set_tmo_random() function to set the delay request timeout.
It saves some memory and improves the timeout granularity, but has a
higher computational cost. It follows the requirements from section
9.5.11.2 of the spec.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
According to 9.2.6.11 of the spec the ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
timeout in addition to announceReceiptTimeoutInterval includes a random
number up to one announceInterval.
Add a new function for setting random timeout and use it in
port_set_announce_tmo().
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Check the sanity of the synchronized clock by comparing its uncorrected
frequency with the system monotonic clock. When the measured frequency
offset is larger than the value of the sanity_freq_limit option (20% by
default), a warning message will be printed and the servo will be reset.
Setting the option to zero disables the check.
This is useful to detect when the clock is broken or adjusted by another
program.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
When a new master appears, it will start to respond to our delay_req
messages. Make sure we process only responses from our current master
before switching to the new master.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
When ptp4l was configured to use the auto delay mechanism and the first
pdelay request was not received in the slave or uncalibrated state, it
would not make any pdelay requests itself, because there was no delay
timer running.
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Because of packet reordering that can occur in the network, in the
hardware, or in the networking stack, a follow up message can appear
to arrive in the application before the matching sync message. As this
is a normal occurrence, and the sequenceID message field ensures
proper matching, the ptp4l program accepts out of order packets.
This patch adds an additional check using the software time stamps
from the networking stack to verify that the sync message did arrive
first. This check is only useful if the sequence IDs generated by
the master might possibly be incorrect.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch lets a port send the first announce message one millisecond
after the port state transition, rather than waiting one announce interval.
This change is needed because it is desirable to reconfigure the time
network without delay, especially in P2P mode.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch adds a new timer for use in 802.1AS-2011 applications. When
running as a slave in gPTP mode, the program must monitor both announce
and sync messages from the master. If either one goes missing, then we
trigger a BMC election. The sync timeout is actually reset by a valid
sync/follow up pair of messages.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch renames the per-port timer in order to make room in the
namespace for a timer that detects a sync message input timeout.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The closing and reopening of the transport when in slave only mode is not
necessary if the port is using the peer delay mechanism. In that case, the
port will discover the network error by transmitting a peer delay request.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Delio Brignoli <dbrignoli@audioscience.com>
Ken Ichikawa has identified a situation in which a sync message can be
wrongly associated with a follow up after the sequence counter wraps
around.
Port is LISTENING
Sync (seqId 0) : ignored
Fup (seqId 0) : ignored
Sync (seqId 1) : ignored
Port becomes UNCALIBRATED here
Fup (seqId 1) : cached!
Sync (seqId 2) : cached
Fup (seqId 2) : match
Sync (seqId 3) : cached
Fup (seqId 3) : match
...
Sync (seqId 65535) : cached
Fup (seqId 65535) : match
Sync (seqId 0) : cached
Fup (seqId 0) : match
Sync (seqId 1) : match with old Fup!!
Fup (seqId 1) : cached!
Sync (seqId 2) : cached
Fup (seqId 2) : match
Actually, I experienced 65500 secs offset every about 65500 secs.
I'm thinking this is the cause.
This patch fixes the issue by changing the port code to remember one
sync or one follow up, never both. The previous ad hoc logic has been
replaced with a small state machine that handles the messages in the
proper order.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
This patch fixes a bug with time mysteriously jumping back and forth:
ptp4l[930.687]: port 1: UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED
ptp4l[931.687]: master offset 17 s2 freq +33014 path delay 2728
ptp4l[932.687]: master offset -74 s2 freq +32928 path delay 2734
ptp4l[933.687]: master offset 2 s2 freq +32982 path delay 2734
ptp4l[934.687]: master offset -3 s2 freq +32977 path delay 2728
ptp4l[935.687]: master offset 17 s2 freq +32996 path delay 2729
ptp4l[936.687]: master offset -10 s2 freq +32974 path delay 2729
ptp4l[937.687]: master offset 35 s2 freq +33016 path delay 2727
ptp4l[938.686]: master offset 60001851388 s2 freq +62499999 path delay 2728
ptp4l[939.687]: master offset -62464938 s2 freq -62431946 path delay 2728
The last follow up message arriving out of order is cached. Before the state
machine changes to UNCALIBRATED, all sync and follow up messages are discarded.
If we get into that state between a sync and follow up message, the latter is
cached. When there's no real roerdering happening, it's kept cached forever.
When we restart the master, it starts numbering the messages from zero again.
The initial synchronization doesn't take always the same amount of time, so it
can happen that we get into UNCALIBRATED a little bit faster than before,
managing to get the sync message with the sequenceId that we missed last time.
As it has the same sequenceId as the cached (old) follow up message, it's
incorrectly assumed those two belong together.
Flush the cache when changing to UNCALIBRATED. Also, do similar thing for other
cached packets.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Management messages can cause a change in the clock quality. If this
happens, then it is time to run the Best Master Clock algorithm again.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Whenever a port enters the passive state, it should act like a slaved
port in one respect. Incoming announce messages from the grand master
are supposed to reset the announce timer. This patch fixes the port
logic to properly maintain the passive state.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Rohrer Hansjoerg <hj.rohrer@mobatime.com>
When there is a peer speaking PTPv1 in the network we want to silently ignore
the packets instead of flooding system log with error messages. At the same
time we still want to report malformed packets. For that we reuse standard
error numbers and do more fine-grained error reporting in packet processing
routines.
Signed-off-by: Libor Pechacek <lpechacek@suse.cz>
Handle reception of >=3 sequential multiple pdelay responses from
distinct peers as a fault of type FT_BAD_PEER_NETWORK.
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
This patch also changes port_capable() to reset the port's nrate every time asCapable changes
from true to false.
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>
If messages are not freed, it is possible (with purposely crafted traffic) to trigger
a peer delay calculation which will use message's data from the previous round.
Signed-off-by: Delio Brignoli <dbrignoli@audioscience.com>