The PRP trailer detection used a minimum frame size of 70 octets. This
minimum applies to whole ethernet packet frames, consisting of headers,
payload and frame check sequence (FCS).

Under Linux, VLAN header and FCS are usually removed from messages
received from a packet socket, hence the real minimum is at least four
octets smaller (66 octets), but can also vary depending on additional
headers.

Therefore, the original implementation worked fine only for frames
larger than 70 octets, but failed for smaller and padded frames. This
mostly affected Sync and Follow_Up messages.
As a consequence, ptp4l reported bad messages and failed
synchronization with the port state stuck to UNCALIBRATED forever.

With additional VLAN header in the PTP frames this was even worse.
When the VLAN header was not properly detected, the header length used
for minimum packet length and padding was just not reliable. And
when using a logical VLAN device, there is no easy way to detect VLAN
header at all.

Therefore, the whole minimum length check and padding detection is
removed. Instead, the PRP trailer is always taken from the last six
octets of the message, as long as it fits between the end of the
PTP data and the FCS (end of message).

Signed-off-by: Stephan Wurm <stephan.w...@a-eberle.de>
---
The PRP standard is defined by IEC62493-3 and allows for redundant
connections, with automatic removal of duplicate frames and trailer
data from the logical PRP interface. In contrast, PTP has to handle
the redundant lower layer interfaces individually, hence it has to
detect the PRP trailer and remove it from the message on its own.
This PRP trailer handling was introduced with commit
02c7ab8436ced2e92524bb7b196189c8d381f883.

During tests with different PRP setups, we now found some issues with
the PRP trailer detection.

In one setup with our system connected via PRP to a redundancy device
(Siemens RedBox), the communication included all relevant messages, but
ptp4l reported

   port 1 (eth2): bad message
   port 1 (eth2): bad message
   port 1 (eth2): delay timeout

As a consequence, the port state was alternating between UNCALIBRATED
and FAULTY forever.

We found the PRP trailer not being removed from Sync and Follow_Up
messages, that had a length of exactly 66 octets, including 14 octets
ethernet header, 44 octets PTP message, 2 octets of padding and 6 octets
trailer.

Looking at the original implementation, we found the PRP_MIN_PACKET_LEN
to be configured to 70 octets, which would be correct for a whole
ethernet frame. But under Linux, a packet socket returns only ethernet
header and payload data, but not the frame check sequence (FCS) that is
part of the frame size calculation.

In another setup, we were using a MOXA RedBox with Power Profile
(IEEE C37.238-2011) that includes a mandatory VLAN header. When using
ptp4l on top of the physical ethernet interfaces (eth2, eth3), the ports
were also stuck to UNCALIBRATED, even after shortening the
PTP_MIN_PACKET_LEN to 66 octets.
We found that Linux also removes VLAN headers (802.1Q and 802.1ad) from
frames received from packet sockets, unless explicitly requesting all
additional headers. But this would only work when operating on the
physical interfaces. When using the logical VLAN interfaces (here
eth2.1 and eth3.1), the VLAN headers are stripped again and the
padding calculation in the original PRP trailer detection would fail
again for Sync and Follow_Up messages.

As a consequence, we removed both the PRP_MIN_PACKET_LEN and padding
calculation and are using always the last six octets of a message to
detect a PRP trailer, as long as it would fit between the end of a
PTP message and the end of a frame (before the FCS).

Fixes: 02c7ab8436ced2e92524bb7b196189c8d381f883
Reviewed-by: Johannes Eigner <johannes.eig...@a-eberle.de>
---
 raw.c | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/raw.c b/raw.c
index a76fab6..1b978f0 100644
--- a/raw.c
+++ b/raw.c
@@ -57,7 +57,6 @@ struct raw {
 
 #define PTP_GEN_BIT 0x08 /* indicates general message, if set in message type 
*/
 
-#define PRP_MIN_PACKET_LEN 70
 #define PRP_TRAILER_LEN 6
 
 /*
@@ -256,10 +255,10 @@ static void addr_to_mac(void *mac, struct address *addr)
 }
 
 /* Determines if the packet has Parallel Redundancy Protocol (PRP) trailer. */
-static bool has_prp_trailer(unsigned char *ptr, int cnt, int eth_hlen)
+static bool has_prp_trailer(unsigned char *ptr, int cnt)
 {
        unsigned short suffix_id, lane_size_field, lsdu_size;
-       int ptp_msg_len, trailer_start, padding_len;
+       int ptp_msg_len, trailer_start;
        struct ptp_header *hdr;
 
        /* try to parse like a PTP message to find out the message length */
@@ -272,18 +271,12 @@ static bool has_prp_trailer(unsigned char *ptr, int cnt, 
int eth_hlen)
 
        ptp_msg_len = ntohs(hdr->messageLength);
 
-       /* PRP requires ethernet packets to be minimum 70 bytes, including 
trailer */
-       trailer_start = ptp_msg_len;
-       padding_len = 0;
-       if ((eth_hlen + ptp_msg_len + PRP_TRAILER_LEN) < PRP_MIN_PACKET_LEN)
-       {
-               padding_len = PRP_MIN_PACKET_LEN - (eth_hlen + ptp_msg_len + 
PRP_TRAILER_LEN);
-               trailer_start += padding_len;
-       }
-
-       if (cnt < (trailer_start + PRP_TRAILER_LEN))
+       if (cnt < (ptp_msg_len + PRP_TRAILER_LEN))
                return false;
 
+       /* PRP trailer is always in the last six bytes before the FCS */
+       trailer_start = cnt - PRP_TRAILER_LEN;
+
        /* PRP trailer (RCT) consists of 3 uint16.
         | -------------------------------------------------------- |
         | SeqNr(0-15) | LanId(0-3) LSDUsize(4-15) | Suffix (0-15)  |
@@ -394,7 +387,7 @@ static int raw_recv(struct transport *t, int fd, void *buf, 
int buflen,
        if (cnt < 0)
                return cnt;
 
-       if (has_prp_trailer(buf, cnt, hlen))
+       if (has_prp_trailer(buf, cnt))
                cnt -= PRP_TRAILER_LEN;
 
        if (raw->vlan) {

---
base-commit: aa60db270be12e7144e7b0cef2f5dde4213b7057
change-id: 20230623-fix-prp-trailer-detection-f8d0b88a7128

Best regards,
-- 
Stephan Wurm <stephan.w...@a-eberle.de>



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to