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:
|
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:
|
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; |
|
} |
|
/* @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:
|
{ |
|
.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:
|
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:
|
/* The announce multicast/unicast capabilities */ |
|
PortCommunicationCapabilities comm_caps; |
- 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.
- Expand the topology where the clock list for parent nodes is available:
|
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; |
Other than the configuration, this is the only part of the solution which is outside of the ptpd2 fork. The coding standard/convention is slightly different here. The native sfptpd and vendored ptpd2 parts of the application are broadly linked via the ptpd_lib.c and ptpd_lib.h files. The configuration and state objects are incorporated into the sfptpd_ptp_module.c instance state but preferably accessed via accessors in ptpd_lib.
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_TRACETLV to outgoing Announce messagesImplement the 'Path trace' optional feature of IEEE1588-2019 section 16.2 by appending
PATH_TRACETLVs to outgoing Announce messages, controlled via an instance-scope configuration option to the PTP sync module.The
PORT_COMMUNICATION_AVAILABILITYTLV provides an example of how to add an optional TLV to outgoing announce messages:sfptpd/src/ptp/ptpd2/constants.h
Line 335 in 3a4113b
sfptpd/src/ptp/ptpd2/dep/msg.c
Lines 2463 to 2493 in 3a4113b
sfptpd/src/ptp/ptpd2/protocol.c
Lines 3235 to 3241 in 3a4113b
Handle received
PATH_TRACETLVs for current parent.Example for port communication capabilities:
sfptpd/src/ptp/ptpd2/protocol.c
Lines 192 to 198 in 3a4113b
sfptpd/src/ptp/ptpd2/protocol.c
Lines 3184 to 3219 in 3a4113b
sfptpd/src/ptp/ptpd2/datatypes.h
Lines 83 to 84 in 3a4113b
sfptpd/src/ptp/sfptpd_ptp_module.c
Lines 2762 to 2789 in 3a4113b
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.