The application's main event loop (clock_poll) is woken up by poll() and
dispatches the socket receive queue events to the corresponding ports as
needed.
So it is a bug if poll() wakes up the process for data availability on a
socket's receive queue, and then recvmsg(), called immediately
afterwards, goes to sleep trying to retrieve it. This patch will
generate an error that will be propagated to the user if this condition
happens.
Can it happen?
As of this patch, ptp4l uses the SO_SELECT_ERR_QUEUE socket option,
which means that poll() will wake the process up, with revents ==
(POLLIN | POLLERR), if data is available in the error queue. But
clock_poll() does not check POLLERR, just POLLIN, and draws the wrong
conclusion that there is data available in the receive queue (when it is
in fact available in the error queue).
When the above condition happens, recvmsg() will sleep typically for a
whole sync interval waiting for data on the event socket, and will be
woken up when the new real frame arrives. It will not dequeue follow-up
messages during this time (which are sent to the general message socket)
and when it does, it will already be late for them (their seqid will be
out of order). So it will drop them and everything that comes after. The
synchronization process will fail.
The above condition shouldn't typically happen, but exceptional kernel
events will trigger it. It helps to be strict in ptp4l in order for
those events to not blow up in even stranger symptoms unrelated to the
root cause of the problem.
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
The transport layer's functional interface foresees having error codes
percolate back up to the caller. However, up until now, the udp module
simply returned -1 for any error. This patch lets the code return the
specific error instead.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Up until now, the code has always fetched the time stamp immediately
after transmitting a message. However, a transparent clock will want
to forward a given incoming message out all egress ports with as
little delay as possible, in order to minimize the residence time of
the message within the switch.
This patch adds a new transmit mode for event messages that will be
used to signal the new behavior.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Originally the 'event' parameter to transport_send() was a single
Boolean flag. Over time, we grew an enumerated list of event
flavors, but the function signatures were never updated. This patch
changes the methods to use the proper type.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
netdb.h pulls in a large chain of include files:
rpc/netdb.h
rpc/types.h
rpc/types.h re-defines TRUE/FALSE and does it in this way:
#ifndef FALSE
# define FALSE (0)
#endif
#ifndef TRUE
# define TRUE (1)
#endif
And this later causes build problems that appear in this way:
mipsel-linux-gnu-gcc -Wall -DVER=1.8 -D_GNU_SOURCE -DHAVE_CLOCK_ADJTIME
-DHAVE_POSIX_SPAWN -DHAVE_ONESTEP_SYNC -Os -pipe -mno-branch-likely
-mips32r2 -mtune=24kc -fno-caller-saves -Wno-unused-result
-D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro
-I/home/florian/dev/openwrt/trunk/staging_dir/target-mipsel-unknown-linux-gnu_glibc/usr/include
-I/home/florian/dev/openwrt/trunk/staging_dir/target-mipsel-unknown-linux-gnu_glibc/include
-I/home/florian/dev/toolchains/stbgcc-4.8-1.5/usr/include
-I/home/florian/dev/toolchains/stbgcc-4.8-1.5/include
-DHAVE_CLOCK_ADJTIME -DHAVE_POSIX_SPAWN -DHAVE_ONESTEP_SYNC -c -o
udp.o udp.c
In file included from
/home/florian/dev/openwrt/trunk/staging_dir/target-mipsel-unknown-linux-gnu_glibc/usr/include/rpc/netdb.h:45:0,
from
/home/florian/dev/toolchains/stbgcc-4.8-1.5/mipsel-linux-gnu/sys-root/usr/include/netdb.h:32,
from udp.c:23:
pdt.h:25:7: error: expected identifier before '(' token
enum {FALSE, TRUE};
^
<builtin>: recipe for target 'udp.o' failed
Upon inspection, it does not appear that netdb.h is providing any useful
definition or declaration, so let's just remove its inclusion.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
In the last years there are several media streaming standards
evolving that are relying on PTP. These standards make requirements
about the DSCP priority of PTP messages. This patch introduces two
new configuration options 'dscp_event' and 'dscp_general' to address
that issue and to be able to set the DSCP priority separately for
PTP event messages and PTP general messages.
Signed-off-by: Henry Jesuiter <henry.jesuiter@alcnetworx.de>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
The raw Ethernet transport code invented its own way of storing the MAC
address into our "struct address" data structure. However, this private
format is incompatible with the sockaddr_ll returned from the networking
stack. This patch converts the code to use the proper format.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Even if the caller provides the destination address, still the port must
depend on the passed 'event' value for correct delivery.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
This modifies all transports to use a new common address type, struct
address. This address is stored in a ptp_message for all received messages.
For sending, the "default" address is used with the default sending
functions, transport_send and transport_peer. The default address depends on
the transport; it's supposed to be the multicast address assigned by the
transport specification.
Later, a new transport_sendto function will be implemented that sends to the
address contained in the passed ptp_message.
Signed-off-by: Jiri Benc <jbenc@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>
The phyter offers one step sync transmission, but it alters the UDP
checksum by changing the last two bytes, after the PTP payload. While this
is only standardized for IPv6, we will go with it for IPv4 as well, since
the phyter is the only hardware out there.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
It is safer and more correct to clear the addresses before use. The IPv6
fields flowinfo and scope_id in particular should not be set to random
values from the stack.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
It was a cute idea to have the raw Ethernet layer use just one socket,
but it ended up not working on some specific PTP time stamping hardware.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Although the UDP/IPv4 layer does not need any state per instance (other
than the two file descriptors), the raw Ethernet layer will need this.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
If the networking stack fails to provide a transmit time stamp, then we
might feed uninitialized stack data to the CMSG(3) macros. This can result
in a segfault or other badness.
The fix is to simply clear the control buffer in advance.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Commit 32133050 introduced a bug that gives a bogus error message on
every 'general' (non-event) PTP packet. If we want to catch missing
time stamps, then it has to occur at the port level.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Without this Linux specific option, multicast packets arrive on one
interface are delivered by the kernel to all others.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
For some reason, MCAST_JOIN_GROUP is not working under uClinux. We can
just stick with the more traditional method.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Even though the MCAST_JOIN_GROUP socket option includes the interface
index, this applies to the received packets only. To bind the outgoing
packets to a particular interface, the IP_MULTICAST_IF option is needed.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>