flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
msg_utils.c
Go to the documentation of this file.
1/* (C) AndrĂ¡s Wiesner, 2020-2022 */
2
3#include "ptp_types.h"
4#include "format_utils.h"
5
6#include <string.h>
7
8#include "msg_utils.h"
9#include "ptp_defs.h"
10
11// load ptp flags from bitfield
12void ptp_load_flags(PtpFlags *pFlags, uint16_t bitfield) {
14#define GET_FLAG_FROM_BITFIELD(flag, n) (pFlags->flag) = (bitfield >> (n)) & 1
16
17 GET_FLAG_FROM_BITFIELD(PTP_SECURITY, 15);
18 GET_FLAG_FROM_BITFIELD(PTP_ProfileSpecific_2, 14);
19 GET_FLAG_FROM_BITFIELD(PTP_ProfileSpecific_1, 13);
20 GET_FLAG_FROM_BITFIELD(PTP_UNICAST, 10);
21 GET_FLAG_FROM_BITFIELD(PTP_TWO_STEP, 9);
22 GET_FLAG_FROM_BITFIELD(PTP_ALTERNATE_MASTER, 8);
23 GET_FLAG_FROM_BITFIELD(FREQUENCY_TRACEABLE, 7);
24 GET_FLAG_FROM_BITFIELD(TIME_TRACEABLE, 4);
25 GET_FLAG_FROM_BITFIELD(PTP_TIMESCALE, 3);
26 GET_FLAG_FROM_BITFIELD(PTP_UTC_REASONABLE, 2);
27 GET_FLAG_FROM_BITFIELD(PTP_LI_59, 1);
28 GET_FLAG_FROM_BITFIELD(PTP_LI_61, 0);
29}
30
31// write flags to bitfield
32uint16_t ptp_write_flags(const PtpFlags *pFlags) {
34#define SET_BIT_IN_FLAG_BITFIELD(flag, n) bitfield |= (pFlags->flag) ? (1 << (n)) : 0
36
37 uint16_t bitfield = 0;
38 SET_BIT_IN_FLAG_BITFIELD(PTP_SECURITY, 15);
39 SET_BIT_IN_FLAG_BITFIELD(PTP_ProfileSpecific_2, 14);
40 SET_BIT_IN_FLAG_BITFIELD(PTP_ProfileSpecific_1, 13);
41 SET_BIT_IN_FLAG_BITFIELD(PTP_UNICAST, 10);
42 SET_BIT_IN_FLAG_BITFIELD(PTP_TWO_STEP, 9);
43 SET_BIT_IN_FLAG_BITFIELD(PTP_ALTERNATE_MASTER, 8);
44 SET_BIT_IN_FLAG_BITFIELD(FREQUENCY_TRACEABLE, 7);
45 SET_BIT_IN_FLAG_BITFIELD(TIME_TRACEABLE, 4);
46 SET_BIT_IN_FLAG_BITFIELD(PTP_TIMESCALE, 3);
47 SET_BIT_IN_FLAG_BITFIELD(PTP_UTC_REASONABLE, 2);
48 SET_BIT_IN_FLAG_BITFIELD(PTP_LI_59, 1);
49 SET_BIT_IN_FLAG_BITFIELD(PTP_LI_61, 0);
50
51 return bitfield;
52}
53
54// extract fields from a PTP header
55void ptp_extract_header(PtpHeader *pHeader, const void *pPayload) {
56 // cast header to byte accessible form
57 uint8_t *p = (uint8_t *)pPayload;
58
59 uint16_t flags;
60
61 // copy header fields
62 memcpy(&pHeader->messageType, p + 0, 1);
63 memcpy(&pHeader->versionPTP, p + 1, 1);
64 memcpy(&pHeader->messageLength, p + 2, 2);
65 memcpy(&pHeader->domainNumber, p + 4, 1);
66 memcpy(&flags, p + 6, 2);
67 memcpy(&pHeader->correction_ns, p + 8, 8);
68 memcpy(&pHeader->clockIdentity, p + 20, 8);
69 memcpy(&pHeader->sourcePortID, p + 28, 2);
70 memcpy(&pHeader->sequenceID, p + 30, 2);
71 memcpy(&pHeader->control, p + 32, 1);
72 memcpy(&pHeader->logMessagePeriod, p + 33, 1);
73
74 pHeader->transportSpecific = (0xf0 & pHeader->messageType) >> 4;
75 pHeader->messageType &= 0x0f;
76
77 // read flags
78 ptp_load_flags(&pHeader->flags, FLEXPTP_ntohs(flags));
79
80 // read correction field
81 pHeader->correction_subns = FLEXPTP_ntohll(pHeader->correction_ns) & 0xffff;
82 pHeader->correction_ns = FLEXPTP_ntohll(pHeader->correction_ns) >> 16;
83
84 pHeader->messageLength = FLEXPTP_ntohs(pHeader->messageLength);
85 pHeader->sourcePortID = FLEXPTP_ntohs(pHeader->sourcePortID);
86 pHeader->sequenceID = FLEXPTP_ntohs(pHeader->sequenceID);
87}
88
89// construct binary header from header structure
90void ptp_construct_binary_header(void *pData, const PtpHeader *pHeader) {
91 uint8_t *p = (uint8_t *)pData;
92 uint8_t firstByte, secondByte;
93
94 // host->network
95 uint16_t messageLength = FLEXPTP_htons(pHeader->messageLength);
96 uint16_t sourcePortID = FLEXPTP_htons(pHeader->sourcePortID);
97 uint16_t sequenceID = FLEXPTP_htons(pHeader->sequenceID);
98
99 // fill in flags
100 uint16_t flags = FLEXPTP_htons(ptp_write_flags(&pHeader->flags)); // convert from header fields
101
102 // fill in correction value
103 uint64_t correction = FLEXPTP_htonll((pHeader->correction_ns << 16) | (pHeader->correction_subns));
104
105 // copy fields
106 firstByte = (pHeader->transportSpecific << 4) | (pHeader->messageType & 0x0f);
107 memcpy(p, &firstByte, 1);
108 secondByte = (pHeader->minorVersionPTP << 4) | (pHeader->versionPTP & 0x0f);
109 memcpy(p + 1, &secondByte, 1);
110 memcpy(p + 2, &messageLength, 2);
111 memcpy(p + 4, &pHeader->domainNumber, 1);
112 memcpy(p + 6, &flags, 2);
113 memcpy(p + 8, &correction, 8);
114 memcpy(p + 20, &pHeader->clockIdentity, 8);
115 memcpy(p + 28, &sourcePortID, 2);
116 memcpy(p + 30, &sequenceID, 2);
117 memcpy(p + 32, &pHeader->control, 1);
118 memcpy(p + 33, &pHeader->logMessagePeriod, 1);
119}
120
121// extract announce message
122void ptp_extract_announce_message(PtpAnnounceBody *pAnnounce, void *pPayload) {
123 // cast header to byte accessible form
124 uint8_t *p = (uint8_t *)pPayload + (PTP_HEADER_LENGTH + PTP_TIMESTAMP_LENGTH);
125
126 // copy header fields
127 memcpy(&pAnnounce->currentUTCOffset, p + 0, 2);
128 memcpy(&pAnnounce->priority1, p + 3, 1);
129 memcpy(&pAnnounce->grandmasterClockClass, p + 4, 1);
130 memcpy(&pAnnounce->grandmasterClockAccuracy, p + 5, 1);
131 memcpy(&pAnnounce->grandmasterClockVariance, p + 6, 2);
132 memcpy(&pAnnounce->priority2, p + 8, 1);
133 memcpy(&pAnnounce->grandmasterClockIdentity, p + 9, 8);
134 memcpy(&pAnnounce->localStepsRemoved, p + 17, 2);
135 memcpy(&pAnnounce->timeSource, p + 19, 1);
136
137 pAnnounce->currentUTCOffset = FLEXPTP_ntohs(pAnnounce->currentUTCOffset);
140 pAnnounce->localStepsRemoved = FLEXPTP_ntohs(pAnnounce->localStepsRemoved);
141}
142
143void ptp_construct_binary_announce_message(void * pData, const PtpAnnounceBody * pAnnounce) {
144 // cast header to byte accessible form
145 uint8_t *p = (uint8_t *)pData + (PTP_HEADER_LENGTH + PTP_TIMESTAMP_LENGTH);
146
147 // convert to big endian
148 uint16_t currentUTCOffset = FLEXPTP_ntohs(pAnnounce->currentUTCOffset);
149 uint16_t grandmasterClockVariance = FLEXPTP_ntohs(pAnnounce->grandmasterClockVariance);
150 uint16_t localStepsRemoved = FLEXPTP_ntohs(pAnnounce->localStepsRemoved);
151
152 // copy header fields
153 memcpy(p + 0, &currentUTCOffset, 2);
154 memcpy(p + 3, &pAnnounce->priority1, 1);
155 memcpy(p + 4, &pAnnounce->grandmasterClockClass, 1);
156 memcpy(p + 5, &pAnnounce->grandmasterClockAccuracy, 1);
157 memcpy(p + 6, &grandmasterClockVariance, 2);
158 memcpy(p + 8, &pAnnounce->priority2, 1);
159 memcpy(p + 9, &pAnnounce->grandmasterClockIdentity, 8);
160 memcpy(p + 17, &localStepsRemoved, 2);
161 memcpy(p + 19, &pAnnounce->timeSource, 1);
162}
163
164// write n timestamps following the header in to packet
165void ptp_write_binary_timestamps(void *pPayload, const TimestampI *ts, uint8_t n) {
166 uint8_t *p = ((uint8_t *)pPayload) + PTP_HEADER_LENGTH;
167
168 // write n times
169 uint8_t i;
170 for (i = 0; i < n; i++) {
171 // get timestamp data
172 uint64_t sec = FLEXPTP_htonll(ts->sec << 16);
173 uint64_t nanosec = FLEXPTP_htonl(ts->nanosec);
174
175 // fill in time data
176 memcpy(p, &sec, 6); // 48-bit
177 p += 6;
178
179 memcpy(p, &nanosec, 4);
180 p += 4;
181
182 // step onto next element
183 ts++;
184 }
185}
186
187// extract n timestamps from a message
188void ptp_extract_timestamps(TimestampI *ts, void *pPayload, uint8_t n) {
189 uint8_t *p = ((uint8_t *)pPayload) + PTP_HEADER_LENGTH; // pointer at the beginning of first timestamp
190
191 // read n times
192 uint8_t i;
193 for (i = 0; i < n; i++) {
194 // seconds
195 ts->sec = 0;
196 memcpy(&ts->sec, p, 6); // 48-bit
197 p += 6;
198
199 // nanoseconds
200 memcpy(&ts->nanosec, p, 4);
201 p += 4;
202
203 // network->host
204 ts->sec = FLEXPTP_ntohll(ts->sec << 16);
205 ts->nanosec = FLEXPTP_ntohl(ts->nanosec);
206
207 // step to next timestamp
208 ts++;
209 }
210}
211
212// extract Delay_Resp ID data
214 uint8_t *p = (uint8_t *)pPayload;
215 memcpy(&pDRData->requestingSourceClockIdentity, p + 44, 8);
216 memcpy(&pDRData->requestingSourcePortIdentity, p + 52, 2);
217
218 // network->host
220}
221
222// insert Delay_Resp ID data
223void ptp_write_delay_resp_id_data(void *pPayload, const PtpDelay_RespIdentification *pDRData) {
224 uint8_t *p = (uint8_t *)pPayload;
225 uint16_t reqSrcPortId = FLEXPTP_htons(pDRData->requestingSourcePortIdentity); // host->network
226 memcpy(p + 44, &pDRData->requestingSourceClockIdentity, 8);
227 memcpy(p + 52, &reqSrcPortId, 2);
228}
229
230// clear flag structure
232 memset(pFlags, 0, sizeof(PtpFlags));
233}
uint64_t FLEXPTP_htonll(uint64_t in)
Definition: format_utils.c:35
uint64_t FLEXPTP_ntohll(uint64_t in)
Definition: format_utils.c:30
This module defines format conversion functions between network and host byte order and conversion fu...
void ptp_write_delay_resp_id_data(void *pPayload, const PtpDelay_RespIdentification *pDRData)
Definition: msg_utils.c:223
void ptp_construct_binary_announce_message(void *pData, const PtpAnnounceBody *pAnnounce)
Definition: msg_utils.c:143
void ptp_extract_header(PtpHeader *pHeader, const void *pPayload)
Definition: msg_utils.c:55
void ptp_extract_timestamps(TimestampI *ts, void *pPayload, uint8_t n)
Definition: msg_utils.c:188
void ptp_extract_announce_message(PtpAnnounceBody *pAnnounce, void *pPayload)
Definition: msg_utils.c:122
void ptp_read_delay_resp_id_data(PtpDelay_RespIdentification *pDRData, void *pPayload)
Definition: msg_utils.c:213
void ptp_load_flags(PtpFlags *pFlags, uint16_t bitfield)
Definition: msg_utils.c:12
void ptp_construct_binary_header(void *pData, const PtpHeader *pHeader)
Definition: msg_utils.c:90
uint16_t ptp_write_flags(const PtpFlags *pFlags)
Definition: msg_utils.c:32
void ptp_write_binary_timestamps(void *pPayload, const TimestampI *ts, uint8_t n)
Definition: msg_utils.c:165
void ptp_clear_flags(PtpFlags *pFlags)
Definition: msg_utils.c:231
This module defines functions that deal with actual PTP messages; they can extract or insert headers,...
In here reside a multitude of fundamental PTP-related constants and definitions.
#define FLEXPTP_htonl(a)
Definition: ptp_defs.h:222
#define PTP_HEADER_LENGTH
Length of the PTP header.
Definition: ptp_defs.h:48
#define PTP_TIMESTAMP_LENGTH
Length of a single timestamp.
Definition: ptp_defs.h:49
#define FLEXPTP_ntohl(a)
Definition: ptp_defs.h:228
#define FLEXPTP_ntohs(a)
Definition: ptp_defs.h:234
#define FLEXPTP_htons(a)
Definition: ptp_defs.h:230
This module defines the fundamental PTP message and state machine type, flags, bitfields and the PTP ...
Contents of a PTP Announce message without the common PTP header.
Definition: ptp_types.h:262
uint16_t currentUTCOffset
Current UTC Offset.
Definition: ptp_types.h:263
uint64_t grandmasterClockIdentity
Grandmaster Clock Identity.
Definition: ptp_types.h:269
uint8_t grandmasterClockClass
Grandmaster Clock Class.
Definition: ptp_types.h:265
uint8_t grandmasterClockAccuracy
Grandmaster Clock Accuracy.
Definition: ptp_types.h:266
uint16_t localStepsRemoved
Local Steps Removed.
Definition: ptp_types.h:270
uint16_t grandmasterClockVariance
Grandmaster Clock Variance.
Definition: ptp_types.h:267
uint8_t priority2
Priority 2.
Definition: ptp_types.h:268
uint8_t timeSource
Time Source.
Definition: ptp_types.h:271
uint8_t priority1
Priority 1.
Definition: ptp_types.h:264
Identification carrying Delay_Resp message.
Definition: ptp_types.h:128
uint64_t requestingSourceClockIdentity
Requesting Source Clock Identity.
Definition: ptp_types.h:129
uint16_t requestingSourcePortIdentity
Requesting Source Port Identity.
Definition: ptp_types.h:130
PTP flags structure.
Definition: ptp_types.h:62
PTP message header structure.
Definition: ptp_types.h:81
int8_t logMessagePeriod
Definition: ptp_types.h:122
uint8_t versionPTP
PTP version.
Definition: ptp_types.h:87
uint8_t messageType
ID.
Definition: ptp_types.h:83
uint64_t clockIdentity
Clock Identity.
Definition: ptp_types.h:110
uint16_t sequenceID
Sequence ID.
Definition: ptp_types.h:116
uint16_t messageLength
Length.
Definition: ptp_types.h:91
uint16_t sourcePortID
Source Port ID.
Definition: ptp_types.h:113
PtpFlags flags
Flags.
Definition: ptp_types.h:100
uint8_t minorVersionPTP
Definition: ptp_types.h:88
uint8_t control
Control.
Definition: ptp_types.h:119
uint64_t correction_ns
Correction nanoseconds.
Definition: ptp_types.h:103
uint8_t domainNumber
Domain.
Definition: ptp_types.h:94
uint32_t correction_subns
Correction subnanoseconds.
Definition: ptp_types.h:104
uint8_t transportSpecific
Transport Specific.
Definition: ptp_types.h:84
Timestamp (signed)
Definition: timeutils.h:33
int32_t nanosec
nanoseconds
Definition: timeutils.h:35
int64_t sec
seconds
Definition: timeutils.h:34