1 /*
2  * Copyright (c) 2024 BayLibre SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file port.h
9  * @brief PTP port data structure and interface to operate on PTP Ports.
10  *
11  * References are to version 2019 of IEEE 1588, ("PTP")
12  */
13 
14 #ifndef ZEPHYR_INCLUDE_PTP_PORT_H_
15 #define ZEPHYR_INCLUDE_PTP_PORT_H_
16 
17 #include <stdbool.h>
18 
19 #include <zephyr/kernel.h>
20 #include <zephyr/net/net_if.h>
21 
22 #include "ds.h"
23 #include "state_machine.h"
24 #include "tlv.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 #define PTP_PORT_TIMER_ANNOUNCE_TO	(0)
31 #define PTP_PORT_TIMER_DELAY_TO		(1)
32 #define PTP_PORT_TIMER_SYNC_TO		(2)
33 #define PTP_PORT_TIMER_QUALIFICATION_TO (3)
34 
35 /**
36  * @brief Structure describing PTP Port.
37  */
38 struct ptp_port {
39 	/** Object list. */
40 	sys_snode_t		       node;
41 	/** PTP Port Dataset*/
42 	struct ptp_port_ds	       port_ds;
43 	/** Interface related to the Port. */
44 	struct net_if		       *iface;
45 	/** Array of BSD sockets. */
46 	int			       socket[2];
47 	/** Status of a link. */
48 	uint8_t			       link_status;
49 	/** Link event callback. */
50 	struct net_mgmt_event_callback link_cb;
51 	/** Structure of system timers used by the Port. */
52 	struct {
53 		struct k_timer	       announce;
54 		struct k_timer	       delay;
55 		struct k_timer	       sync;
56 		struct k_timer	       qualification;
57 	} timers;
58 	/** Bitmask of timeouts. */
59 	atomic_t		       timeouts;
60 	/** Structure of unique sequence IDs used for messages. */
61 	struct {
62 		uint16_t	       announce;
63 		uint16_t	       delay;
64 		uint16_t	       signaling;
65 		uint16_t	       sync;
66 	} seq_id;
67 	/** Pointer to finite state machine. */
68 	enum ptp_port_state	       (*state_machine)(enum ptp_port_state state,
69 							enum ptp_port_event event,
70 							bool tt_diff);
71 	/** Pointer to the Port's best Foreign TimeTransmitter. */
72 	struct ptp_foreign_tt_clock    *best;
73 	/** List of Foreign TimeTransmitters discovered through received Announce messages. */
74 	sys_slist_t		       foreign_list;
75 	/** List of valid sent Delay_Req messages (in network byte order). */
76 	sys_slist_t		       delay_req_list;
77 	/** Pointer to the last received Sync or Follow_Up message. */
78 	struct ptp_msg		       *last_sync_fup;
79 	/** Timestamping callback for sent Delay_Req messages. */
80 	struct net_if_timestamp_cb     delay_req_ts_cb;
81 	/** Timestamping callback for sent Sync messages. */
82 	struct net_if_timestamp_cb     sync_ts_cb;
83 };
84 
85 /**
86  * @brief Function initializing PTP Port.
87  *
88  * @param[in] iface     Pointer to current network interface.
89  * @param[in] user_data Unused argument needed to comply with @ref net_if_cb_t type.
90  */
91 void ptp_port_init(struct net_if *iface, void *user_data);
92 
93 /**
94  * @brief Function returning PTP Port's state.
95  *
96  * @param[in] port Pointer to the PTP Port structure.
97  *
98  * @return PTP Port's current state.
99  */
100 enum ptp_port_state ptp_port_state(struct ptp_port *port);
101 
102 /**
103  * @brief Function generating PTP Port events based on PTP Port's timers.
104  *
105  * @param[in] port  Pointer to the PTP Port structure.
106  * @param[in] timer Pointer to the PTP Port's timer to be checked.
107  *
108  * @return PTP Port event.
109  */
110 enum ptp_port_event ptp_port_timer_event_gen(struct ptp_port *port, struct k_timer *timer);
111 /**
112  * @brief Function generating PTP Port events based on messages
113  * that has been received on a PTP Port's socket.
114  *
115  * @param[in] port  Pointer to the PTP Port structure.
116  * @param[in] idx   Index of the PTP Port's socket to be checked.
117  *
118  * @return PTP Port event.
119  */
120 enum ptp_port_event ptp_port_event_gen(struct ptp_port *port, int idx);
121 
122 /**
123  * @brief Function handling PTP Port event.
124  *
125  * @param[in] port    Pointer to the PTP Port structure.
126  * @param[in] event   PTP Port Event to be processed.
127  * @param[in] tt_diff Flag indicating whether PTP TimeTransmitter has changed.
128  */
129 void ptp_port_event_handle(struct ptp_port *port, enum ptp_port_event event, bool tt_diff);
130 
131 /**
132  * @brief Function checking if two port identities are equal.
133  *
134  * @param[in] p1 Pointer to the port identity structure.
135  * @param[in] p2 Pointer to the port identity structure.
136  *
137  * @return True if port identities are equal, False otherwise.
138  */
139 bool ptp_port_id_eq(const struct ptp_port_id *p1, const struct ptp_port_id *p2);
140 
141 /**
142  * @brief Function for getting a common dataset for the port's best foreign timeTransmitter clock.
143  *
144  * @param[in] port Pointer to the PTP Port structure.
145  *
146  * @return NULL if the port doesn't have best foreign timeTransmitter clock or
147  *  pointer to the ptp_dataset of the best foreign timeTransmitter clock.
148  */
149 struct ptp_dataset *ptp_port_best_foreign_ds(struct ptp_port *port);
150 
151 /**
152  * @brief Compute PTP Port's best Foreign TimeTransmitter Clock.
153  *
154  * @param[in] port Pointer to the PTP Port.
155  *
156  * @return Pointer to the PTP Port's best Foreign TimeTransmitter.
157  */
158 struct ptp_foreign_tt_clock *ptp_port_best_foreign(struct ptp_port *port);
159 
160 /**
161  * @brief Function adding foreign TimeTransmitter Clock for the PTP Port based on specified message.
162  *
163  * @param[in] port Pointer to the PTP Port.
164  * @param[in] msg  Pointer to the announce message containing PTP TimeTransmitter data.
165  *
166  * @return Non-zero if the announce message is different than the last.
167  */
168 int ptp_port_add_foreign_tt(struct ptp_port *port, struct ptp_msg *msg);
169 
170 /**
171  * @brief Function freeing memory used by foreign timeTransmitters assigned to given PTP Port.
172  *
173  * @param[in] port Pointer to the PTP Port.
174  */
175 void ptp_port_free_foreign_tts(struct ptp_port *port);
176 
177 /**
178  * @brief Function updating current PTP TimeTransmitter Clock of the PTP Port
179  * based on specified message.
180  *
181  * @param[in] port Pointer to the PTP Port.
182  * @param[in] msg  Pointer to the announce message containing PTP TimeTransmitter data.
183  *
184  * @return Non-zero if the announce message is different than the last.
185  */
186 int ptp_port_update_current_time_transmitter(struct ptp_port *port, struct ptp_msg *msg);
187 
188 /**
189  * @brief Function processing received PTP Management message on the PTP Port's level.
190  *
191  * @param[in] port    PTP Port to process the received message.
192  * @param[in] ingress Original PTP Port that received the message.
193  * @param[in] msg     PTP Management message to be processed.
194  * @param[in] tlv     Management TLV attached to the message.
195  *
196  * @return 0 on positive message processing, negative otherwise
197  */
198 int ptp_port_management_msg_process(struct ptp_port *port,
199 				    struct ptp_port *ingress,
200 				    struct ptp_msg *msg,
201 				    struct ptp_tlv_mgmt *tlv);
202 
203 /**
204  * @brief Function for sending Management Error resposnse message.
205  *
206  * @param[in] port PTP Port that is going to send Management Error response.
207  * @param[in] msg  PTP Management message that caused Management Error.
208  * @param[in] err  Management Error code.
209  *
210  * @return 0 if message sent successfully, negative otherwise.
211  */
212 int ptp_port_management_error(struct ptp_port *port, struct ptp_msg *msg, enum ptp_mgmt_err err);
213 
214 /**
215  * @brief Function for sending response on specific PTP PORT to received PTP Management message.
216  *
217  * @param[in] port PTP Port that will send response message.
218  * @param[in] req  Received PTP Management message.
219  * @param[in] tlv  Management TLV attached to the message.
220  *
221  * @return 0 if message sent successfully, negative otherwise.
222  */
223 int ptp_port_management_resp(struct ptp_port *port, struct ptp_msg *req, struct ptp_tlv_mgmt *tlv);
224 
225 #ifdef __cplusplus
226 }
227 #endif
228 
229 /**
230  * @}
231  */
232 
233 #endif /* ZEPHYR_INCLUDE_PTP_PORT_H_ */
234