-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
subsys: net: lib: Implement Precision Time Protocol (PTP) Support #73713
Conversation
- native_posix | ||
- native_posix/native/64 | ||
- native_sim | ||
- native_sim/native/64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you allow the 64 bit versions, I guess you also need a configuration overlay for them, or?
Thanks for the PR! Question, how does this related to the gPTP implementation we have as an L2 here: |
@carlescufi gPTP is just a subset of PTP, it works only on L2. You may consider it as one of PTP profiles. Whereas PTP supports L2 Ethernet, UDP IPv4 and IPv6, and even CAN. It has predefined profiles that target different use cases. This PR brings only part of features but in the future it can be extended and gPTP could be replaced with PTP and Kconfig symbol that configures PTP stack to be compliant with gPTP standard. If you look at ptp4l it implements gPTP as well. It's just a matter of passing proper .cfg file. Currently main advantage of the PTP over gPTP is IP support |
2932537
to
76e5f9c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is lot of commits and it might make sense to split the PR to two, first the enabling / infra non-ptp related commits, and the other with PTP specific stuff. Currently this is hard to review properly.
While I was reviewing and commenting the code, you submitted a new version so some of my comments might not be valid any more.
# Copyright (c) 2024 BayLibre | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
menuconfig PTP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add here a !dependency to gPTP so both cannot be enabled at the same time.
subsys/net/lib/ptp/ddt.h
Outdated
* @note 5.3.3 - timestamp with respect to epoch | ||
*/ | ||
struct ptp_timestamp { | ||
/* Seconds encoded on 48 bits. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add doxygen comments to all the fields in the structs as otherwise the generated documentation looks weird. Please check all the struct comments in this and other header files in this PR.
subsys/net/lib/ptp/ddt.h
Outdated
struct ptp_text name; | ||
struct ptp_text value; | ||
struct ptp_text desc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really going to work properly as you have now multiple flexible members in a one struct? How is the compiler going to know where the name,value and desc structs will start because the sizeof(struct ptp_text)
is 1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This structure is defined in the standard. These struct ptp_text
members are only containers for fault logs. You don't treat it as continuous space they are only pointers to some space where these values are stored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But how you have specified them means that they are not pointers. The first flexible member name
will indeed point to correct position, but the next one value
will point to second byte in name
because sizeof(name)
is 1.
Note that what I am talking about here is related to how one access the value or desc field from C code, I am not talking about how the memory layout of the protocol message. So if you try to access the desc field using ptp_fault_record.desc, the value will be garbage even if the memory layout is correct. This can be highly confusing to the user.
subsys/net/lib/ptp/Kconfig
Outdated
config PTP_SLAVE_ONLY | ||
bool "Configure Clock as slaveOnly PTP Instance" | ||
depends on PTP_ORDINARY_CLOCK | ||
default n |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to mention default n
as that is the default
subsys/net/lib/ptp/msg.c
Outdated
msg->ref--; | ||
if (msg->ref) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not atomic. Perhaps it should?
subsys/net/lib/ptp/transport.c
Outdated
}; | ||
|
||
socket = transport_socket_open(iface, (struct sockaddr *)&addr); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
if (IS_ENABLED(CONFIG_PTP_UDP_IPv4_PROTOCOL)) { | ||
m_addr.sa_family = AF_INET; | ||
net_sin(&m_addr)->sin_port = htons(port); | ||
net_sin(&m_addr)->sin_addr.s_addr = mcast_addr.s_addr; | ||
|
||
} else if (IS_ENABLED(CONFIG_PTP_UDP_IPv6_PROTOCOL)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be runtime configurable, so we should allow for example one interface to have IPv4, one IPv6 etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, in the future I could implement something that would allow to specify protocol per port but for now I would like to proceed with one protocol for all ports.
subsys/net/lib/ptp/transport.c
Outdated
msghdr.msg_controllen = sizeof(ctrl); | ||
|
||
cnt = zsock_recvmsg(port->socket[idx], &msghdr, ZSOCK_MSG_DONTWAIT); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line can be omitted
} | ||
|
||
switch (mgmt->id) { | ||
case PTP_MGMT_CLOCK_DESCRIPTION: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to add __fallthrough;
after each case if we do not break
subsys/net/lib/ptp/port.c
Outdated
return PTP_EVT_FAULT_DETECTED; | ||
} | ||
} | ||
/* fall through */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use __fallthrough;
instead of this comment
Add dynamic memory allocation for PTP messages. Memory allocation is done with Zephyr's memory slab. It's size can be configured with `PTP_MSG_POLL_SIZE` Kconfig symbol. Signed-off-by: Adam Wojasinski <[email protected]>
Add functions preparing messages to network byte order before sending and changing to host byte order after reception and before processing by PTP stack. Signed-off-by: Adam Wojasinski <[email protected]>
Add allocation of container used for TLVs and dummy functions for preparing correct byte order of data. TLV stands for Type, Length, Value, and it is extension of PTP messages that's used to transmit extra information. This data is attached at the end of PTP message. Signed-off-by: Adam Wojasinski <[email protected]>
This commit adds handling of Management TLVs Signed-off-by: Adam Wojasinski <[email protected]>
This commit introduces module responsible for sending and receiving messages. It is based on BSD Sockets API. Signed-off-by: Adam Wojasinski <[email protected]>
Based on Port ID decision about message processing can be made. Signed-off-by: Adam Wojasinski <[email protected]>
Foreign timeTransmitters are other PTP Clocks in a domain. They announce their parameters via announce messages. PTP Ports should record these foreign timeTransmitters. Signed-off-by: Adam Wojasinski <[email protected]>
Initial implementation of the clock adjustment and delay calculation. Timestamp values used for calculations will be obtained from proper PTP messages (Sync, Follow_Up, Delay_Req, and Delay_Resp) Signed-off-by: Adam Wojasinski <[email protected]>
This commit adds routines for handling incoming messages needed for correct operation of the PTP stack in end to end mode with multicast operation mode. Signed-off-by: Adam Wojasinski <[email protected]>
Add handler for STATE_DECISION_EVENT it consists of following routines: - state decision algorithm - best timeTransmitter clock algorithm - data sets comparison algorithm Based on IEEE 1588-2019 section 9.3.3 Signed-off-by: Adam Wojasinski <[email protected]>
Introduction of routines processing received PTP Management messages. The processing is split into clock-oriented and port-oriented parts. Signed-off-by: Adam Wojasinski <[email protected]>
This commit introduces routines for PTP message transmission. It includes transmission of three types of messages (Announce, Sync, Delay_Req) that should be send periodically depending on the PTP Port's state. Signed-off-by: Adam Wojasinski <[email protected]>
Timers are used to trigger message transmission and detect inactivity of other PTP Clocks what should result in an action of the PTP Port. Signed-off-by: Adam Wojasinski <[email protected]>
The commit adds functions that enable and disable PTP Port. This is going to be used by event handling routine. Signed-off-by: Adam Wojasinski <[email protected]>
Introduction of PTP stack's core functions responsible for event generation and handling of these events. Events are generated base on timeouts and/or PTP messages received via BSD sockets assigned to a specific PTP Port. These function will be used in PTP thread. Signed-off-by: Adam Wojasinski <[email protected]>
The STATE_DECISION_EVENT in PTP is a pivotal mechanism that facilitates dynamic state management within the protocol, allowing devices to adapt their operational states based on the BTCA's recommendations and the health of the network. Signed-off-by: Adam Wojasinski <[email protected]>
This commit adds implementation of the PTP thread that will poll sockets descriptors and PTP Port's timeres for timeouts, generate events and handle them and trigger STATE_DECISION_EVENT handling when needed. Signed-off-by: Adam Wojasinski <[email protected]>
Adding network interface status monitor function. Depending on the interface operation state and change of the state events are generated and handled by the function. Signed-off-by: Adam Wojasinski <[email protected]>
Add documentation page for IEEE 1588-2019 (PTP) library. Signed-off-by: Adam Wojasinski <[email protected]>
Add conditions to enable ptp_clock driver implementation for native_posix when PTP subsystem is enabled. Signed-off-by: Adam Wojasinski <[email protected]>
This application demonstrates PTP functionality Signed-off-by: Adam Wojasinski <[email protected]>
Introducing a new PTP maintenance entry with awojasinski as maintainer. Signed-off-by: Adam Wojasinski <[email protected]>
e1a189d
to
d6c510f
Compare
Pushed rebased branch to pull in fix for failing test |
This pull request introduces support for the Precision Time Protocol (PTP), enhancing time synchronization capabilities within the Zephyr. PTP is a protocol that allows precise clock synchronization between networked devices over packet-switched networks, such as Ethernet. This implementation is crucial for applications requiring high-precision timekeeping systems.
Key Features
Testing
The implementation has been tested with linuxptp Project on
nucleo_h563zi
- Nucleo H563ZI development board. Additionally sample has been validated onnative_sim
target executed in docker image with net-tools.The Pull Request could be split into two PRs. Following commits could be added as a separate PR:
However these changes are small compared to the rest of submitted code. In this PR it's clear why these commits are needed therefor I decided to included them in this PR.