| /* |
| * Copyright (c) 2017 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief gPTP message helpers. |
| * |
| * This is not to be included by the application. |
| */ |
| |
| #ifndef __GPTP_MESSAGES_H |
| #define __GPTP_MESSAGES_H |
| |
| #include <zephyr/net/net_pkt.h> |
| #include <zephyr/net/ethernet.h> |
| #include <zephyr/net/gptp.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* Helpers to access gPTP messages. */ |
| #define GPTP_HDR(pkt) gptp_get_hdr(pkt) |
| #define GPTP_ANNOUNCE(pkt) ((struct gptp_announce *)gptp_data(pkt)) |
| #define GPTP_SIGNALING(pkt) ((struct gptp_signaling *)gptp_data(pkt)) |
| #define GPTP_SYNC(pkt) ((struct gptp_sync *)gptp_data(pkt)) |
| #define GPTP_FOLLOW_UP(pkt) ((struct gptp_follow_up *)gptp_data(pkt)) |
| #define GPTP_DELAY_REQ(pkt) \ |
| ((struct gptp_delay_req *)gptp_data(pkt)) |
| #define GPTP_PDELAY_REQ(pkt) \ |
| ((struct gptp_pdelay_req *)gptp_data(pkt)) |
| #define GPTP_PDELAY_RESP(pkt) \ |
| ((struct gptp_pdelay_resp *)gptp_data(pkt)) |
| #define GPTP_PDELAY_RESP_FOLLOWUP(pkt) \ |
| ((struct gptp_pdelay_resp_follow_up *)gptp_data(pkt)) |
| |
| /* Field values. */ |
| #define GPTP_TRANSPORT_802_1_AS 0x1 |
| #define GPTP_VERSION 0x2 |
| |
| /* Message Lengths. */ |
| #define GPTP_PACKET_LEN(pkt) net_pkt_get_len(pkt) |
| #define GPTP_VALID_LEN(pkt, len) \ |
| (len > (NET_ETH_MINIMAL_FRAME_SIZE - GPTP_L2_HDR_LEN(pkt))) |
| #define GPTP_L2_HDR_LEN(pkt) \ |
| ((long)GPTP_HDR(pkt) - (long)NET_ETH_HDR(pkt)) |
| |
| #define GPTP_SYNC_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_sync)) |
| #define GPTP_FOLLOW_UP_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_follow_up)) |
| #define GPTP_PDELAY_REQ_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_req)) |
| #define GPTP_PDELAY_RESP_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp)) |
| #define GPTP_PDELAY_RESP_FUP_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp_follow_up)) |
| #define GPTP_SIGNALING_LEN \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_signaling)) |
| |
| /* For the Announce message, the TLV is variable length. The len field |
| * indicates the length of the TLV not accounting for tlvType and lengthField |
| * which are 4 bytes. |
| */ |
| #define GPTP_ANNOUNCE_LEN(pkt) \ |
| (sizeof(struct gptp_hdr) + sizeof(struct gptp_announce) \ |
| + ntohs(GPTP_ANNOUNCE(pkt)->tlv.len) \ |
| - sizeof(struct gptp_path_trace_tlv) + 4) |
| |
| #define GPTP_CHECK_LEN(pkt, len) \ |
| ((GPTP_PACKET_LEN(pkt) != len) && (GPTP_VALID_LEN(pkt, len))) |
| #define GPTP_ANNOUNCE_CHECK_LEN(pkt) \ |
| ((GPTP_PACKET_LEN(pkt) != GPTP_ANNOUNCE_LEN(pkt)) && \ |
| (GPTP_VALID_LEN(pkt, GPTP_ANNOUNCE_LEN(pkt)))) |
| |
| /* Header Flags. Byte 0. */ |
| #define GPTP_FLAG_ALT_MASTER BIT(0) |
| #define GPTP_FLAG_TWO_STEP BIT(1) |
| #define GPTP_FLAG_UNICAST BIT(2) |
| #define GPTP_FLAG_PROFILE_SPECIFIC1 BIT(5) |
| #define GPTP_FLAG_PROFILE_SPECIFIC2 BIT(6) |
| |
| /* Header Flags. Byte 1. */ |
| #define GPTP_FLAG_LEAP61 BIT(0) |
| #define GPTP_FLAG_LEAP59 BIT(1) |
| #define GPTP_FLAG_CUR_UTC_OFF_VALID BIT(2) |
| #define GPTP_FLAG_PTP_TIMESCALE BIT(3) |
| #define GPTP_FLAG_TIME_TRACEABLE BIT(4) |
| #define GPTP_FLAG_FREQ_TRACEABLE BIT(5) |
| |
| /* Signaling Interval Flags. */ |
| #define GPTP_FLAG_COMPUTE_NEIGHBOR_RATE_RATIO 0x1 |
| #define GPTP_FLAG_COMPUTE_NEIGHBOR_PROP_DELAY 0x2 |
| |
| /* Signaling Interval Values. */ |
| #define GPTP_ITV_KEEP -128 |
| #define GPTP_ITV_SET_TO_INIT 126 |
| #define GPTP_ITV_STOP 127 |
| |
| /* Control. Only set for header compatibility with v1. */ |
| #define GPTP_SYNC_CONTROL_VALUE 0x0 |
| #define GPTP_FUP_CONTROL_VALUE 0x2 |
| #define GPTP_OTHER_CONTROL_VALUE 0x5 |
| |
| /* Other default values. */ |
| #define GPTP_RESP_LOG_MSG_ITV 0x7F |
| #define GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE htons(0x8) |
| |
| /* Organization Id used for TLV. */ |
| #define GPTP_FUP_TLV_ORG_ID_BYTE_0 0x00 |
| #define GPTP_FUP_TLV_ORG_ID_BYTE_1 0x80 |
| #define GPTP_FUP_TLV_ORG_ID_BYTE_2 0xC2 |
| #define GPTP_FUP_TLV_ORG_SUB_TYPE 0x01 |
| |
| /** |
| * @brief gPTP Clock Quality |
| * |
| * Defines the quality of a clock. |
| * This is used by the Best Master Clock Algorithm. |
| */ |
| struct gptp_clock_quality { |
| uint8_t clock_class; |
| uint8_t clock_accuracy; |
| uint16_t offset_scaled_log_var; |
| } __packed; |
| |
| /** |
| * @brief gPTP Root System Identity |
| * |
| * Defines the Grand Master of a clock. |
| * This is used by the Best Master Clock Algorithm. |
| */ |
| struct gptp_root_system_identity { |
| /** Grand Master priority1 component. */ |
| uint8_t grand_master_prio1; |
| |
| /** Grand Master clock quality. */ |
| struct gptp_clock_quality clk_quality; |
| |
| /** Grand Master priority2 component. */ |
| uint8_t grand_master_prio2; |
| |
| /** Grand Master clock identity. */ |
| uint8_t grand_master_id[GPTP_CLOCK_ID_LEN]; |
| } __packed; |
| |
| /* Definition of all message types as defined by IEEE802.1AS. */ |
| |
| struct gptp_path_trace_tlv { |
| /** TLV type: 0x8. */ |
| uint16_t type; |
| |
| /** Length. Number of TLVs * 8 bytes. */ |
| uint16_t len; |
| |
| /** ClockIdentity array of the successive time-aware systems. */ |
| uint8_t path_sequence[1][8]; |
| } __packed; |
| |
| struct gptp_announce { |
| /** Reserved fields. */ |
| uint8_t reserved1[10]; |
| |
| /** Current UTC offset. */ |
| int16_t cur_utc_offset; |
| |
| /** Reserved field. */ |
| uint8_t reserved2; |
| |
| /* gmPriorityVector priority 1 of the peer sending the message. */ |
| struct gptp_root_system_identity root_system_id; |
| |
| /** masterStepsRemoved of the peer sending the message. */ |
| uint16_t steps_removed; |
| |
| /** timeSource of the peer sending the message. */ |
| uint8_t time_source; |
| |
| /* Path Trace TLV. This field has a variable length. */ |
| struct gptp_path_trace_tlv tlv; |
| } __packed; |
| |
| struct gptp_sync { |
| /** Reserved field. This field is used for PTPv2, unused in gPTP. */ |
| uint8_t reserved[10]; |
| } __packed; |
| |
| struct gptp_follow_up_tlv_hdr { |
| /** TLV type: 0x3. */ |
| uint16_t type; |
| |
| /** Length: 28. */ |
| uint16_t len; |
| } __packed; |
| |
| struct gptp_follow_up_tlv { |
| /** Organization Id: 00-80-C2. */ |
| uint8_t org_id[3]; |
| |
| /** Organization Sub Type: 1. */ |
| uint8_t org_sub_type[3]; |
| |
| /** Rate ratio relative to the grand master of the peer. */ |
| int32_t cumulative_scaled_rate_offset; |
| |
| /** Time Base Indicator of the current Grand Master. */ |
| uint16_t gm_time_base_indicator; |
| |
| /** Difference of the time between the current GM and the previous. */ |
| struct gptp_scaled_ns last_gm_phase_change; |
| |
| /** Diff of the frequency between the current GM and the previous. */ |
| int32_t scaled_last_gm_freq_change; |
| } __packed; |
| |
| struct gptp_follow_up { |
| /** Higher 16 bits of the seconds at which the sync was sent. */ |
| uint16_t prec_orig_ts_secs_high; |
| |
| /** Lower 32 bits of the seconds at which the sync was sent. */ |
| uint32_t prec_orig_ts_secs_low; |
| |
| /** Nanoseconds at which the sync was sent. */ |
| uint32_t prec_orig_ts_nsecs; |
| |
| /** Follow up TLV. */ |
| struct gptp_follow_up_tlv_hdr tlv_hdr; |
| struct gptp_follow_up_tlv tlv; |
| } __packed; |
| |
| struct gptp_pdelay_req { |
| /** Reserved fields. */ |
| uint8_t reserved1[10]; |
| |
| /** Reserved fields. */ |
| uint8_t reserved2[10]; |
| } __packed; |
| |
| struct gptp_pdelay_resp { |
| /** Higher 16 bits of the seconds at which the request was received. */ |
| uint16_t req_receipt_ts_secs_high; |
| |
| /** Lower 32 bits of the seconds at which the request was received. */ |
| uint32_t req_receipt_ts_secs_low; |
| |
| /** Nanoseconds at which the pdelay request was received. */ |
| uint32_t req_receipt_ts_nsecs; |
| |
| /** Source Port Id of the Path Delay Request. */ |
| struct gptp_port_identity requesting_port_id; |
| } __packed; |
| |
| struct gptp_pdelay_resp_follow_up { |
| /** Higher 16 bits of the seconds at which the response was sent. */ |
| uint16_t resp_orig_ts_secs_high; |
| |
| /** Lower 32 bits of the seconds at which the response was sent. */ |
| uint32_t resp_orig_ts_secs_low; |
| |
| /** Nanoseconds at which the response was received. */ |
| uint32_t resp_orig_ts_nsecs; |
| |
| /** Source Port Id of the Path Delay Request. */ |
| struct gptp_port_identity requesting_port_id; |
| } __packed; |
| |
| struct gptp_message_itv_req_tlv { |
| /** TLV type: 0x3. */ |
| uint16_t type; |
| |
| /** Length field: 12. */ |
| uint16_t len; |
| |
| /** Organization Id: 00-80-C2. */ |
| uint8_t org_id[3]; |
| |
| /** Organization sub type: 0x2. */ |
| uint8_t org_sub_type[3]; |
| |
| /** Log to base 2 of the mean time interval between pdelay requests. */ |
| int8_t link_delay_itv; |
| |
| /** Log to base 2 of the mean time interval between syncs. */ |
| int8_t time_sync_itv; |
| |
| /** Log to base 2 of the mean time interval between announces. */ |
| int8_t announce_itv; |
| |
| /** Flags (computeNeighborRateRatio and computeNeighborPropDelay). */ |
| union { |
| struct { |
| uint8_t compute_neighbor_rate_ratio : 1; |
| uint8_t compute_neighbor_prop_delay : 1; |
| }; |
| uint8_t flags; |
| }; |
| /** Reserved fields. */ |
| uint8_t reserved[2]; |
| } __packed; |
| |
| struct gptp_signaling { |
| /** Target Port Identity , always 0xFF. */ |
| struct gptp_port_identity target_port_id; |
| |
| /** Message Interval TLV. */ |
| struct gptp_message_itv_req_tlv tlv; |
| } __packed; |
| |
| /** |
| * @brief Compute gPTP message location. |
| * |
| * @param pkt Network Buffer containing a gPTP message. |
| * |
| * @return Pointer to the start of the gPTP message inside the packet. |
| */ |
| static inline uint8_t *gptp_data(struct net_pkt *pkt) |
| { |
| return (uint8_t *)GPTP_HDR(pkt) + sizeof(struct gptp_hdr); |
| } |
| |
| /* Functions to prepare messages. */ |
| |
| /** |
| * @brief Prepare Sync message. |
| * |
| * @param port gPTP port number. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_sync(int port); |
| |
| /** |
| * @brief Prepare Follow Up message. |
| * |
| * @param port gPTP port number. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync); |
| |
| /** |
| * @brief Prepare Path Delay Request message. |
| * |
| * @param port gPTP port number. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_pdelay_req(int port); |
| |
| /** |
| * @brief Prepare Path Delay Response message. |
| * |
| * @param port gPTP port number. |
| * @param req Path Delay Request to reply to. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_pdelay_resp(int port, |
| struct net_pkt *req); |
| |
| /** |
| * @brief Prepare Announce message. |
| * |
| * @param port gPTP port number. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_announce(int port); |
| |
| /** |
| * @brief Prepare Path Delay Response message. |
| * |
| * @param port gPTP port number. |
| * @param resp Related Path Delay Follow Up. |
| * |
| * @return Pointer to the prepared Network Buffer. |
| */ |
| struct net_pkt *gptp_prepare_pdelay_follow_up(int port, |
| struct net_pkt *resp); |
| |
| /* Functions to handle received messages. */ |
| |
| /** |
| * @brief Handle Sync message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer. |
| */ |
| void gptp_handle_sync(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Handle Follow Up message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer to parse. |
| * |
| * @return 0 if success, Error Code otherwise. |
| */ |
| int gptp_handle_follow_up(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Handle Path Delay Request message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer. |
| */ |
| void gptp_handle_pdelay_req(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Handle Path Delay Response message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer to parse. |
| * |
| * @return 0 if success, Error Code otherwise. |
| */ |
| int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Handle Path Delay Follow Up message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer to parse. |
| * |
| * @return 0 if success, Error Code otherwise. |
| */ |
| int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Handle Signaling message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer |
| */ |
| void gptp_handle_signaling(int port, struct net_pkt *pkt); |
| |
| /* Functions to send messages. */ |
| |
| /** |
| * @brief Send a Sync message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Sync message. |
| */ |
| void gptp_send_sync(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Send a Follow Up message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Follow Up message. |
| */ |
| void gptp_send_follow_up(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Send an Announce message. |
| * |
| * @param port gPTP port number. |
| * @param pkt Announce message. |
| */ |
| void gptp_send_announce(int port, struct net_pkt *pkt); |
| |
| /** |
| * @brief Send a Path Delay Request on the given port. |
| * |
| * @param port gPTP port number. |
| */ |
| void gptp_send_pdelay_req(int port); |
| |
| /** |
| * @brief Send a Path Delay Response for the given Path Delay Request. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer containing the prepared Path Delay Response. |
| * @param treq Time at which the Path Delay Request was received. |
| */ |
| void gptp_send_pdelay_resp(int port, struct net_pkt *pkt, |
| struct net_ptp_time *treq); |
| |
| /** |
| * @brief Send a Path Delay Response for the given Path Delay Request. |
| * |
| * @param port gPTP port number. |
| * @param pkt Network Buffer containing the prepared Path Delay Follow Up. |
| * @param tresp Time at which the Path Delay Response was sent. |
| */ |
| void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt, |
| struct net_ptp_time *tresp); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __GPTP_MESSAGES_H */ |