Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Path Trace optional feature of IEEE1588-2019 #3

Open
abower-amd opened this issue Oct 19, 2023 · 0 comments
Open

Implement Path Trace optional feature of IEEE1588-2019 #3

abower-amd opened this issue Oct 19, 2023 · 0 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@abower-amd
Copy link
Collaborator

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:

    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;
    }
  • /* @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.
@abower-amd abower-amd added enhancement New feature or request good first issue Good for newcomers labels Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant