]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/linuxptp.git/blob - msg.h
phc2sys: update '-s' option
[processor-sdk/linuxptp.git] / msg.h
1 /**
2  * @file msg.h
3  * @brief Implements the various PTP message types.
4  * @note Copyright (C) 2011 Richard Cochran <richardcochran@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 #ifndef HAVE_MSG_H
21 #define HAVE_MSG_H
23 #include <stdio.h>
24 #include <sys/queue.h>
25 #include <time.h>
27 #include "address.h"
28 #include "ddt.h"
29 #include "tlv.h"
31 #define PTP_VERSION 2
33 /* Values for the messageType field */
34 #define SYNC                  0x0
35 #define DELAY_REQ             0x1
36 #define PDELAY_REQ            0x2
37 #define PDELAY_RESP           0x3
38 #define FOLLOW_UP             0x8
39 #define DELAY_RESP            0x9
40 #define PDELAY_RESP_FOLLOW_UP 0xA
41 #define ANNOUNCE              0xB
42 #define SIGNALING             0xC
43 #define MANAGEMENT            0xD
45 /* Bits for flagField[0] */
46 #define ALT_MASTER     (1<<0)
47 #define TWO_STEP       (1<<1)
48 #define UNICAST        (1<<2)
50 /* Bits for flagField[1] */
51 #define LEAP_61        (1<<0)
52 #define LEAP_59        (1<<1)
53 #define UTC_OFF_VALID  (1<<2)
54 #define PTP_TIMESCALE  (1<<3)
55 #define TIME_TRACEABLE (1<<4)
56 #define FREQ_TRACEABLE (1<<5)
58 enum timestamp_type {
59         TS_SOFTWARE,
60         TS_HARDWARE,
61         TS_LEGACY_HW,
62         TS_ONESTEP,
63 };
65 struct hw_timestamp {
66         enum timestamp_type type;
67         struct timespec ts;
68         struct timespec sw;
69 };
71 enum controlField {
72         CTL_SYNC,
73         CTL_DELAY_REQ,
74         CTL_FOLLOW_UP,
75         CTL_DELAY_RESP,
76         CTL_MANAGEMENT,
77         CTL_OTHER,
78 };
80 struct ptp_header {
81         uint8_t             tsmt; /* transportSpecific | messageType */
82         uint8_t             ver;  /* reserved          | versionPTP  */
83         UInteger16          messageLength;
84         UInteger8           domainNumber;
85         Octet               reserved1;
86         Octet               flagField[2];
87         Integer64           correction;
88         UInteger32          reserved2;
89         struct PortIdentity sourcePortIdentity;
90         UInteger16          sequenceId;
91         UInteger8           control;
92         Integer8            logMessageInterval;
93 } PACKED;
95 struct announce_msg {
96         struct ptp_header    hdr;
97         struct Timestamp     originTimestamp;
98         Integer16            currentUtcOffset;
99         Octet                reserved;
100         UInteger8            grandmasterPriority1;
101         struct ClockQuality  grandmasterClockQuality;
102         UInteger8            grandmasterPriority2;
103         struct ClockIdentity grandmasterIdentity;
104         UInteger16           stepsRemoved;
105         Enumeration8         timeSource;
106         uint8_t              suffix[0];
107 } PACKED;
109 struct sync_msg {
110         struct ptp_header   hdr;
111         struct Timestamp    originTimestamp;
112 } PACKED;
114 struct delay_req_msg {
115         struct ptp_header   hdr;
116         struct Timestamp    originTimestamp;
117 } PACKED;
119 struct follow_up_msg {
120         struct ptp_header   hdr;
121         struct Timestamp    preciseOriginTimestamp;
122         uint8_t             suffix[0];
123 } PACKED;
125 struct delay_resp_msg {
126         struct ptp_header   hdr;
127         struct Timestamp    receiveTimestamp;
128         struct PortIdentity requestingPortIdentity;
129         uint8_t             suffix[0];
130 } PACKED;
132 struct pdelay_req_msg {
133         struct ptp_header   hdr;
134         struct Timestamp    originTimestamp;
135         struct PortIdentity reserved;
136 } PACKED;
138 struct pdelay_resp_msg {
139         struct ptp_header   hdr;
140         struct Timestamp    requestReceiptTimestamp;
141         struct PortIdentity requestingPortIdentity;
142 } PACKED;
144 struct pdelay_resp_fup_msg {
145         struct ptp_header   hdr;
146         struct Timestamp    responseOriginTimestamp;
147         struct PortIdentity requestingPortIdentity;
148         uint8_t             suffix[0];
149 } PACKED;
151 struct signaling_msg {
152         struct ptp_header   hdr;
153         struct PortIdentity targetPortIdentity;
154         uint8_t             suffix[0];
155 } PACKED;
157 struct management_msg {
158         struct ptp_header   hdr;
159         struct PortIdentity targetPortIdentity;
160         UInteger8           startingBoundaryHops;
161         UInteger8           boundaryHops;
162         uint8_t             flags; /* reserved | actionField */
163         uint8_t             reserved;
164         uint8_t             suffix[0];
165 } PACKED;
167 struct message_data {
168         uint8_t buffer[1500];
169 } PACKED;
171 struct ptp_message {
172         union {
173                 struct ptp_header          header;
174                 struct announce_msg        announce;
175                 struct sync_msg            sync;
176                 struct delay_req_msg       delay_req;
177                 struct follow_up_msg       follow_up;
178                 struct delay_resp_msg      delay_resp;
179                 struct pdelay_req_msg      pdelay_req;
180                 struct pdelay_resp_msg     pdelay_resp;
181                 struct pdelay_resp_fup_msg pdelay_resp_fup;
182                 struct signaling_msg       signaling;
183                 struct management_msg      management;
184                 struct message_data        data;
185         } PACKED;
186         /**/
187         int tail_room;
188         int refcnt;
189         TAILQ_ENTRY(ptp_message) list;
190         struct {
191                 /**
192                  * Contains the time stamp from the packet data in a
193                  * native binary format for the host machine. The
194                  * exact source of the time stamp's value depends on
195                  * the message type:
196                  *
197                  * - announce    originTimestamp
198                  * - follow_up   preciseOriginTimestamp
199                  * - sync        originTimestamp
200                  * - delay_req   originTimestamp
201                  * - pdelay_resp     requestReceiptTimestamp
202                  * - pdelay_resp_fup responseOriginTimestamp
203                  */
204                 struct timestamp pdu;
205                 /**
206                  * Approximate ingress time stamp using the relative
207                  * CLOCK_MONOTONIC. Used to determine when announce
208                  * messages have expired.
209                  */
210                 struct timespec host;
211         } ts;
212         /**
213          * Contains the ingress time stamp obtained by the
214          * SO_TIMESTAMPING socket option.
215          */
216         struct hw_timestamp hwts;
217         /**
218          * Contains the address this message was received from or should be
219          * sent to.
220          */
221         struct address address;
222         /**
223          * Contains the number of TLVs in the suffix.
224          */
225         int tlv_count;
226         /**
227          * Used to hold the data of the last TLV in the message when
228          * the layout of the TLV makes it difficult to access the data
229          * directly from the message's buffer.
230          */
231         struct tlv_extra last_tlv;
232 };
234 /**
235  * Obtain the action field from a management message.
236  * @param m  A management message.
237  * @return   The value of the action field.
238  */
239 static inline uint8_t management_action(struct ptp_message *m)
241         return m->management.flags & 0x0f;
244 /**
245  * Test a given bit in a message's flag field.
246  * @param m      Message to test.
247  * @param index  Index into flag field, either 0 or 1.
248  * @param bit    Bit mask of one bit to test.
249  * @return       One if bit is set, zero otherwise.
250  */
251 static inline Boolean field_is_set(struct ptp_message *m, int index, Octet bit)
253         return m->header.flagField[index] & bit ? TRUE : FALSE;
256 /**
257  * Obtain the transportSpecific field from a message.
258  * @param m  Message to test.
259  * @return   The value of the transportSpecific field. Note that the
260  *           value is returned unshifted, in the upper nibble.
261  */
262 static inline UInteger8 msg_transport_specific(struct ptp_message *m)
264         return m->header.tsmt & 0xf0;
267 /**
268  * Obtain the message type.
269  * @param m  Message to test.
270  * @return   The value of the messageType field.
271  */
272 static inline int msg_type(struct ptp_message *m)
274         return m->header.tsmt & 0x0f;
277 /**
278  * Allocate a new message instance.
279  *
280  * Messages are reference counted, and newly allocated messages have a
281  * reference count of one. Allocated messages are freed using the
282  * function @ref msg_put().
283  *
284  * @return Pointer to a message on success, NULL otherwise.
285  */
286 struct ptp_message *msg_allocate(void);
288 /**
289  * Release all of the memory in the message cache.
290  */
291 void msg_cleanup(void);
293 /**
294  * Obtain a reference to a message, increasing its reference count by one.
295  * @param m A message obtained using @ref msg_allocate().
296  */
297 void msg_get(struct ptp_message *m);
299 /**
300  * Process messages after reception.
301  * @param m    A message obtained using @ref msg_allocate().
302  * @param cnt  The size of 'm' in bytes.
303  * @return   Zero on success, non-zero if the message is invalid.
304  */
305 int msg_post_recv(struct ptp_message *m, int cnt);
307 /**
308  * Prepare messages for transmission.
309  * @param m  A message obtained using @ref msg_allocate().
310  * @return   Zero on success, non-zero if the message is invalid.
311  */
312 int msg_pre_send(struct ptp_message *m);
314 /**
315  * Print messages for debugging purposes.
316  * @param type  Value of the messageType field as returned by @ref msg_type().
317  * @return      String describing the message type.
318  */
319 const char *msg_type_string(int type);
321 /**
322  * Print messages for debugging purposes.
323  * @param m   A message obtained using @ref msg_allocate().
324  * @param fp  An open file pointer.
325  */
326 void msg_print(struct ptp_message *m, FILE *fp);
328 /**
329  * Release a reference to a message, decreasing its reference count by one.
330  * @param m A message obtained using @ref msg_allocate().
331  */
332 void msg_put(struct ptp_message *m);
334 /**
335  * Test whether an event message received a valid SO_TIMESTAMPING time stamp.
336  * @param m  Message to test.
337  * @return   One if the message is an event without a time stamp, zero otherwise.
338  */
339 int msg_sots_missing(struct ptp_message *m);
341 /**
342  * Test whether a message has a valid SO_TIMESTAMPING time stamp.
343  * @param m  Message to test.
344  * @return   One if the message has a valid time stamp, zero otherwise.
345  */
346 static inline int msg_sots_valid(struct ptp_message *m)
348         return (m->hwts.ts.tv_sec || m->hwts.ts.tv_nsec) ? 1 : 0;
351 /**
352  * Work around buggy 802.1AS switches.
353  */
354 extern int assume_two_step;
356 /**
357  * Test whether a message is one-step message.
358  * @param m  Message to test.
359  * @return   One if the message is a one-step, zero otherwise.
360  */
361 static inline Boolean one_step(struct ptp_message *m)
363         if (assume_two_step)
364                 return 0;
365         return !field_is_set(m, 0, TWO_STEP);
368 /**
369  * Convert a 64 bit word into network byte order.
370  */
371 int64_t host2net64(int64_t val);
373 /**
374  * Convert a 64 bit word into host byte order.
375  */
376 int64_t net2host64(int64_t val);
378 #endif