/* * 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 #include #include #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 */