-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Implement the 'Path trace' optional feature of IEEE1588-2019 section 16.2. This feature has two parts, sending and receiving. Either could be implemented independently but it would be desirable to present the two parts together to aid testability and review.
Option to append PATH_TRACE TLV to outgoing Announce messages
Implement the 'Path trace' optional feature of IEEE1588-2019 section 16.2 by appending PATH_TRACE TLVs to outgoing Announce messages, controlled via an instance-scope configuration option to the PTP sync module.
The PORT_COMMUNICATION_AVAILABILITY TLV provides an example of how to add an optional TLV to outgoing announce messages:
- Identifying the TLV:
sfptpd/src/ptp/ptpd2/constants.h
Line 335 in 3a4113b
PTPD_TLV_PATH_TRACE=0x0008, - Defining the TLV: https://github.com/Xilinx-CNS/sfptpd/blob/master/src/ptp/ptpd2/def/optional/port_communication_capabilities.def
- Packing functions for for TLV:
sfptpd/src/ptp/ptpd2/dep/msg.c
Lines 2463 to 2493 in 3a4113b
appendPortCommunicationCapabilitiesTLV(PortCommunicationCapabilities *data, Octet *buf, size_t space) { ssize_t result = PACK_INIT; int tlv_start = getHeaderLength(buf); int offset = tlv_start; int base; TLV tlv = { .tlvType = PTPD_TLV_PORT_COMMUNICATION_CAPABILITIES }; TLV_BOUNDARY_CHECK(offset, space); result = msgPackTLVHeader(buf + tlv_start, space - tlv_start, &tlv); if (!PACK_OK(result)) goto finish; offset += result; base = offset; #define OPERATE( name, size, type ) STANDARD_PACKING_OPERATION(name, size, type) #include "../def/optional/port_communication_capabilities.def" PAD_TO_EVEN_LENGTH(buf, offset, space, result, finish); /* Set TLV length */ setHeaderLength(buf + tlv_start, offset - base); /* Set message length */ setHeaderLength(buf, offset); result = PACK_SIZE(offset); finish: /* return length */ return result; } sfptpd/src/ptp/ptpd2/protocol.c
Lines 3235 to 3241 in 3a4113b
/* @task71885: append multicast/unicast capability information */ if (rtOpts->comm_caps_tlv_enabled) { pack_result = appendPortCommunicationCapabilitiesTLV(&rtOpts->comm_caps, ptpClock->msgObuf, sizeof ptpClock->msgObuf); assert(PACK_OK(pack_result)); }
Handle received PATH_TRACE TLVs for current parent.
Example for port communication capabilities:
- Handling the TLV:
sfptpd/src/ptp/ptpd2/protocol.c
Lines 192 to 198 in 3a4113b
{ .tlv_type = PTPD_TLV_PORT_COMMUNICATION_CAPABILITIES, .name = "PORT_COMMUNICATION_CAPABILITIES", .permitted_message_types_mask = 1 << PTPD_MSG_ANNOUNCE, .required_acl_types_mask = 0, .pass1_handler_fn = port_communication_capabilities_handler, .pass2_handler_fn = NULL, - Processing the TLV:
sfptpd/src/ptp/ptpd2/protocol.c
Lines 3184 to 3219 in 3a4113b
static enum ptpd_tlv_result port_communication_capabilities_handler(const MsgHeader *header, ssize_t length, TimeInternal *time, Boolean timestampValid, Boolean isFromSelf, RunTimeOpts *rtOpts, PtpClock *ptpClock, TLV *tlv, size_t tlv_offset) { ssize_t result; DBGV("PORT_COMMUNICATION_CAPABILITIES received : \n"); if (isFromSelf) { /* Ignore */ return PTPD_TLV_RESULT_CONTINUE; } if (rtOpts->ptp_version_minor < 1) { DBG2("ignore COMMUNICATION_CAPABILITIES TLV in version %d.%d mode\n", PTPD_PROTOCOL_VERSION, rtOpts->ptp_version_minor); ptpClock->counters.discardedMessages++; ptpClock->counters.versionMismatchErrors++; return PTPD_TLV_RESULT_CONTINUE; } /* Save a pointer for the announce handler to use */ result = unpackPortCommunicationCapabilities(tlv->valueField, tlv->lengthField, &ptpClock->transient_packet_state.port_comm_caps, ptpClock); if (!UNPACK_OK(result)) return PTPD_TLV_RESULT_ERROR; ptpClock->transient_packet_state.port_comm_caps_provided = true; return PTPD_TLV_RESULT_CONTINUE; } - Saving the traced clock list: - these are the foreign master records. It is a trade off between space for storing for all foreign masters and accessing later via FMR for selected master or a more complex solution. I suggest doing the former.
sfptpd/src/ptp/ptpd2/datatypes.h
Lines 83 to 84 in 3a4113b
/* The announce multicast/unicast capabilities */ PortCommunicationCapabilities comm_caps; - Expand the topology where the clock list for parent nodes is available: Other than the configuration, this is the only part of the solution which is outside of the
sfptpd/src/ptp/sfptpd_ptp_module.c
Lines 2762 to 2789 in 3a4113b
sfptpd_log_topology_write_field(stream, true, "grandmaster"); if (boundary) { sfptpd_log_topology_write_field(stream, true, SFPTPD_FORMAT_EUI64, gm[0], gm[1], gm[2], gm[3], gm[4], gm[5], gm[6], gm[7]); sfptpd_log_topology_write_1to1_connector(stream, false, true, steps_format, steps_removed); sfptpd_log_topology_write_field(stream, true, "parent"); } sfptpd_log_topology_write_field(stream, true, SFPTPD_FORMAT_EUI64 "/%d", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], instance->ptpd_port_snapshot.parent.port_num); if (instance->ptpd_port_snapshot.current.transparent_clock) { sfptpd_log_topology_write_1to1_connector(stream, false, true, NULL); sfptpd_log_topology_write_field(stream, true, "transparent"); sfptpd_log_topology_write_field(stream, true, "clock"); } if (state == PTPD_PASSIVE) { sfptpd_log_topology_write_1to1_connector(stream, false, true, "zzz"); } else { sfptpd_log_topology_write_1to1_connector(stream, false, true, SFPTPD_FORMAT_TOPOLOGY_FLOAT, ofm_ns); } break; ptpd2fork. The coding standard/convention is slightly different here. The nativesfptpdand vendoredptpd2parts of the application are broadly linked via theptpd_lib.candptpd_lib.hfiles. The configuration and state objects are incorporated into thesfptpd_ptp_module.cinstance state but preferably accessed via accessors inptpd_lib.