There are two aspects. First, on the receive path, we reply to
unicast peer delay requests in kind. That is, if the peer sends a
unicast delay request, then reply with unicast, too, since this is
obviously what the peer expects.
Second, if configured, we transmit peer delay requests to the
specified unicast peer address.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
All of the callers of transport_peer() use hard coded magic numbers.
This patch fixes them to use the corresponding enumerated values instead.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Consistenly use the pid_eq() and cid_eq() helper functions. Move the
functions into utils.h (making them inline functions) because they are
used in multiple source files.
Signed-off-by: Michael Walle <michael@walle.cc>
ptp4l runs clockcheck on an incoming PTP message before checking its
domain number. If the time on another domain is different, then
clockcheck will trigger spurious synchronization faults.
This patch reorders the logic so that clockcheck only runs on messages
in the same time domain.
Reported-By: Filip Perich <perich@google.com>
Signed-off-by: Cliff Spradlin <cspradlin@google.com>
With increasing unicast support, the code needs to identify unicast
messages more often. This patch replaces the open coded bit field
tests with a more readable in line helper function call.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
According to the standard, unicast Sync messages are to be sent with
the interval field set to 127. This patch adds a test to avoid
incorrectly adopting that value as a new interval.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Richard Hill reported an occasional NULL pointer deference in
port_delay_request() when in hybrid mode.
if (p->hybrid_e2e) {
struct ptp_message *dst = TAILQ_FIRST(&p->best->messages);
msg->address = dst->address;
...
}
The code assumes that the p->best->messages list can't be empty
because:
The function, port_delay_request(), is called only when
FD_DELAY_TIMER expires. That timer is only set by the function,
port_set_delay_tmo(), which is called:
1. from process_delay_resp(), but only when state is UNCALIBRATED
or SLAVE.
2. from port_e2e_transition(), but only when state is UNCALIBRATED
or SLAVE.
Looking at handle_state_decision_event(), a port can only enter
UNCALIBRATED or SLAVE when it has a valid foreign master record,
ie p->best->messages is not null.
A port also only clears p->best->messages when it leaves
UNCALIBRATED or SLAVE, at which point the FD_DELAY_TIMER is also
cleared.
*However* the p->best->messages list *can* be empty if the
FD_ANNOUNCE_TIMER and the FD_DELAY_TIMER expire at the same time. In
this case, the poll() call indicates events on both file descriptors.
The announce timeout is handled like this:
case FD_ANNOUNCE_TIMER:
case FD_SYNC_RX_TIMER:
if (p->best)
fc_clear(p->best);
So then the port_delay_request() call de-references the null
TAILQ_FIRST message pointer.
This patch fixes the issue by re-ordering the timer file descriptors
within the polling list.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Reported-by: Richard Hill <plonta@gmx.de>
According to 1588, PTP message loops are simply someone else's problem
with respect to transparent clocks. Since we are running the BMCA for
syntonization anyway, we might as well go ahead and implement the spanning
tree for PTP messages.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The E2E TC forwards Announce, Delay_Req, Delay_Resp, Management,
Signaling, and Sync messages, and drops P2P Delay messages.
This implementation tracks the GM using the BMCA in order
to syntonize (or possibly even synchronize) with it.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The P2P TC forwards Announce, Management, Signaling, and Sync
messages, consumes P2P Delay messages, and drops E2E Delay messages.
This implementation tracks the GM using the BMCA in order
to syntonize (or possibly even synchronize) with it.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch adds code that sends an event messages received on one port out
all the other ports and calculates the residence time. The correction,
ingress port, and the original message are remembered in a TC transmit
descriptor. These descriptors are recycled in a memory pool in a similar
way to the message buffers.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The transparent clock code will want to set qualification timeouts and
perform end to end delay measurements. This patch exposes the needed
methods.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
When masterOnly is true, the port always returns NULL when computing
its best foreign master. As a result, the port will never enter the
SLAVE state, and the clock will ignore Announce messages received on
that port.
This attribute is specifically called out in G.8275.1 and G.8275.2,
and it is implied by the "master only" mode G.8265.1. In addition,
this option will probably appear in the next revision of IEEE 1588.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The Telecom Profiles G.8275.1 and G.8275.2 have invented a new
per-port and per-clock attribute, not in 1588, called "localPriority".
The use of this attribute is a distinguishing feature of the telecom
data set comparison algorithm.
This patch adds the attribute, hard coded to its default value.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
There is no need to keep two copies of the data set comparison
function. This patch adds a method that allows the port code to
obtain the function from the clock code.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The majority of the callers of transport_send() use hard coded magic
numbers. This patch fixes them to use the corresponding enumerated
values instead.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The PortAddress structure has no space for the actual address and should
be used only as a pointer to a larger buffer.
The issue was reported by gcc with enabled source fortification.
[ RC: Replace magic number with sizeof() macro. ]
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch makes a number of subroutines into global functions in order
to share code with the TC implementations to come.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch places the internal port data structure into a common header
for use by the original BC and the new TC code.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
When computing the next port state based on a FSM event, much of the logic
will stay the same for OC, BC, and TC nodes.
- handling a fault ASAP
- INITIALIZING state handling
- showing the transition in the log
- sending notifications
This patch moves this common code into a global port method, making it
available to future TC implementations.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This paves the way to allow different implementations for the upcoming
Transparent Clock code.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The 1588 standard defines one step operation for both Sync and
PDelay_Resp messages. Up until now, hardware with P2P one step has
been rare, and kernel support was lacking. This patch adds support of
the mode in anticipation of new kernel and hardware developments.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
On the transmit path, the port-level code calls msg_sots_missing()
directly, but on receive this check is buried in the message layer.
With the coming addition of peer to peer one step, the ingress check
will need knowledge of the configured time stamping option. This
patch moves the check in order to accommodate the exceptional case.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
In a ptp unaware network (like the telecom profile for frequency sync
G.8265.1), both the RTD and the PDV can be substantially higher than
in a ptp aware network. To achieve more accurate measurements, the
rate may need to be configured higher to get more data and increase
the chance of lucky packets.
In a combination of a high configured rate of delay_req and high
RTD/PDV in network, the risk that the response from the previously
sent delay_req have not been received before a new delay_req is sent
also become high. In that case, the need of storing more than the
latest sent delay_req arise.
This patch adds a queue for sent delay requests so several request can
be ongoing in parallel. When a delay response is received, a matching
request will be searched for in the queue and after processed removed
from the queue.
The stored delay_req will be removed if older than 5 seconds. Check is
made before a new delay_req is sent or announce receipt tmo expires.
Signed-off-by: Anders Selhammer <anders.selhammer@est.tech>
The function ts_to_Timestamp() is now just a wrapper around
tmv_to_Timestamp(). Simplify code by using tmv_to_Timestamp()
directly.
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
Convert a software timestamp to the internal tmv_t representation at
the earliest possible opportunity, to match the behaviour for hardware
timestamps.
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
Convert a hardware timestamp to the internal tmv_t representation at
the earliest possible opportunity. This allows us to:
- eliminate multiple redundant calls to timespec_to_tmv()
- use tmv_add() instead of open-coded manipulation of a struct
timespec in ts_add()
- use tmv_to_Timestamp() instead of open-coded manipulation of a
struct timespec and struct Timestamp in ts_to_Timestamp()
- use tmv_is_zero() instead of open-coded manipulation of a struct
timespec in msg_sots_valid()
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
The function ts_to_timestamp() currently performs open-coded
manipulation of a struct timespec and struct Timestamp instead of
using the tmv_t abstractions.
Prepare for the removal of this code by matching the calling
convention for tmv_to_Timestamp(): returning a struct Timestamp rather
than accepting a pointer to a struct Timestamp.
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
The function ts_add() currently performs open-coded manipulation of a
struct timespec instead of using the tmv_t abstractions.
Prepare for the removal of this code by storing ingressLatency and
egressLatency as corrections (matching the behaviour for
delayAsymmetry).
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
The function clock_check_ts() performs open-coded manipulation of a
struct timespec instead of using the tmv_t abstractions.
Use the existing tmv_t abstractions to convert from struct timespec to
nanoseconds, and modify the prototype of clock_check_ts() to match
that of the underlying clockcheck_sample().
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>
When NSM is enabled on a given port, that port always replies to a NSM
delay request with a delay response, sync, and follow up, regardless
of the current state of the port.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The port will need to send unicast Sync messages in order to support
the NSM protocol. Besides that, we will need this ability anyhow if
we ever want to implement unicast operation.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Path trace TLVs and Follow-Up info TLVs might be mixed in among other
random TLVs. This patch fixes the parsing code to find these TLVs even
when multiple other TLVs are present.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The current code uses an ad hoc method of appending TLVs. When
constructing a message, the code computes the total PDU length by adding
the message size to the TLV size. By using the new API, this patch
simplifies message construction, letting each TLV add its own length
to the total.
As a result of the this change, the return value for the helper
functions, follow_up_info_append() and path_trace_append(), has
changed meaning. Instead of returning the TLV length, these functions
now provide an error code.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This patch changes the receive message parsing code to place each TLV
into the list. A method is introduced that allows attaching TLVs to
the end of the list.
In addition, msg.last_tlv is converted into a pointer to the last item
in the list. Because of this change, the transmit code that uses this
field now allocates a TLV before using it.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Time values are compared using an inequality test in mmedian.c
Generalise tmv_eq() to tmv_cmp() (by analogy with memcmp()) and
replace existing uses of tmv_eq().
Signed-off-by: Michael Brown <mbrown@fensystems.co.uk>