blob: a59eb5facb462e967b963d4ff33331ad80819da4 [file] [log] [blame]
/*
* 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
#ifdef __cplusplus
extern "C" {
#endif
#include <net/net_pkt.h>
#include <net/ethernet.h>
#include <net/gptp.h>
/* 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) \
((int)GPTP_HDR(pkt) - (int)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 {
u8_t clock_class;
u8_t clock_accuracy;
u16_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. */
u8_t grand_master_prio1;
/** Grand Master clock quality. */
struct gptp_clock_quality clk_quality;
/** Grand Master priority2 component. */
u8_t grand_master_prio2;
/** Grand Master clock identity. */
u8_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. */
u16_t type;
/** Length. Number of TLVs * 8 bytes. */
u16_t len;
/** ClockIdentity array of the successive time-aware systems. */
u8_t path_sequence[1][8];
} __packed;
struct gptp_announce {
/** Reserved fields. */
u8_t reserved1[10];
/** Current UTC offset. */
s16_t cur_utc_offset;
/** Reserved field. */
u8_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. */
u16_t steps_removed;
/** timeSource of the peer sending the message. */
u8_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. */
u8_t reserved[10];
} __packed;
struct gptp_follow_up_tlv_hdr {
/** TLV type: 0x3. */
u16_t type;
/** Length: 28. */
u16_t len;
} __packed;
struct gptp_follow_up_tlv {
/** Organization Id: 00-80-C2. */
u8_t org_id[3];
/** Organization Sub Type: 1. */
u8_t org_sub_type[3];
/** Rate ratio relative to the grand master of the peer. */
s32_t cumulative_scaled_rate_offset;
/** Time Base Indicator of the current Grand Master. */
u16_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. */
s32_t scaled_last_gm_freq_change;
} __packed;
struct gptp_follow_up {
/** Higher 16 bits of the seconds at which the sync was sent. */
u16_t prec_orig_ts_secs_high;
/** Lower 32 bits of the seconds at which the sync was sent. */
u32_t prec_orig_ts_secs_low;
/** Nanoseconds at which the sync was sent. */
u32_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. */
u8_t reserved1[10];
/** Reserved fields. */
u8_t reserved2[10];
} __packed;
struct gptp_pdelay_resp {
/** Higher 16 bits of the seconds at which the request was received. */
u16_t req_receipt_ts_secs_high;
/** Lower 32 bits of the seconds at which the request was received. */
u32_t req_receipt_ts_secs_low;
/** Nanoseconds at which the pdelay request was received. */
u32_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. */
u16_t resp_orig_ts_secs_high;
/** Lower 32 bits of the seconds at which the response was sent. */
u32_t resp_orig_ts_secs_low;
/** Nanoseconds at which the response was received. */
u32_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. */
u16_t type;
/** Length field: 12. */
u16_t len;
/** Organization Id: 00-80-C2. */
u8_t org_id[3];
/** Organization sub type: 0x2. */
u8_t org_sub_type[3];
/** Log to base 2 of the mean time interval between pdelay requests. */
s8_t link_delay_itv;
/** Log to base 2 of the mean time interval between syncs. */
s8_t time_sync_itv;
/** Log to base 2 of the mean time interval between announces. */
s8_t announce_itv;
/** Flags (computeNeighborRateRatio and computeNeighborPropDelay). */
union {
struct {
u8_t compute_neighbor_rate_ratio : 1;
u8_t compute_neighbor_prop_delay : 1;
};
u8_t flags;
};
/** Reserved fields. */
u8_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 u8_t *gptp_data(struct net_pkt *pkt)
{
return (u8_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 */