diff --git a/config.c b/config.c index acd5f45..6d00641 100644 --- a/config.c +++ b/config.c @@ -24,6 +24,7 @@ #include #include "bmc.h" +#include "clock.h" #include "config.h" #include "ether.h" #include "hash.h" @@ -135,6 +136,14 @@ static struct config_enum clock_servo_enu[] = { { NULL, 0 }, }; +static struct config_enum clock_type_enu[] = { + { "OC", CLOCK_TYPE_ORDINARY }, + { "BC", CLOCK_TYPE_BOUNDARY }, + { "P2P_TC", CLOCK_TYPE_P2P }, + { "E2E_TC", CLOCK_TYPE_E2E }, + { NULL, 0 }, +}; + static struct config_enum dataset_comp_enu[] = { { "ieee1588", DS_CMP_IEEE1588 }, { "G.8275.x", DS_CMP_G8275 }, @@ -186,6 +195,7 @@ struct config_item config_tab[] = { GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX), GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX), GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu), + GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu), GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu), PORT_ITEM_INT("delayAsymmetry", 0, INT_MIN, INT_MAX), PORT_ITEM_ENU("delay_filter", FILTER_MOVING_MEDIAN, delay_filter_enu), diff --git a/default.cfg b/default.cfg index 408022d..f70f386 100644 --- a/default.cfg +++ b/default.cfg @@ -75,6 +75,7 @@ uds_address /var/run/ptp4l # # Default interface options # +clock_type OC network_transport UDPv4 delay_mechanism E2E time_stamping hardware diff --git a/ptp4l.8 b/ptp4l.8 index 2aee03e..003d54e 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -1,6 +1,6 @@ -.TH PTP4l 8 "Novemver 2017" "linuxptp" +.TH PTP4l 8 "March 2018" "linuxptp" .SH NAME -ptp4l - PTP Boundary/Ordinary Clock +ptp4l - PTP Boundary/Ordinary/Transparent Clock .SH SYNOPSIS .B ptp4l @@ -23,8 +23,8 @@ ptp4l - PTP Boundary/Ordinary Clock .SH DESCRIPTION .B ptp4l is an implementation of the Precision Time Protocol (PTP) according to IEEE -standard 1588 for Linux. It implements Boundary Clock (BC) and Ordinary Clock -(OC). +standard 1588 for Linux. It implements Boundary Clock (BC), Ordinary Clock +(OC), and Transparent Clock (TC). .SH OPTIONS .TP @@ -425,6 +425,13 @@ number is set to the domain number), and "nullf" for a servo that always dials frequency offset zero (for use in SyncE nodes). The default is "pi." .TP +.B clock_type +Specifies the kind of PTP clock. Valid values are "OC" for ordinary +clock, "BC" for boundary clock, "P2P_TC" for peer to peer transparent +clock, and "E2E_TC" for end to end transparent clock. An multi-port +ordinary clock will automatically be configured as a boundary clock. +The default is "OC". +.TP .B pi_proportional_const The proportional constant of the PI controller. When set to 0.0, the proportional constant will be set by the following formula from the current diff --git a/ptp4l.c b/ptp4l.c index ee31718..9ef8169 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -1,6 +1,6 @@ /** * @file ptp4l.c - * @brief PTP Boundary Clock main program + * @brief PTP Boundary Clock or Transparent Clock main program * @note Copyright (C) 2011 Richard Cochran * * This program is free software; you can redistribute it and/or modify @@ -59,6 +59,7 @@ static void usage(char *progname) " -p [dev] PTP hardware clock device to use, default auto\n" " (ignored for SOFTWARE/LEGACY HW time stamping)\n" " -s slave only mode (overrides configuration file)\n" + " -t transparent clock\n" " -l [num] set the logging level to 'num'\n" " -m print messages to stdout\n" " -q do not print messages to the syslog\n" @@ -71,6 +72,7 @@ static void usage(char *progname) int main(int argc, char *argv[]) { char *config = NULL, *req_phc = NULL, *progname; + enum clock_type type = CLOCK_TYPE_ORDINARY; int c, err = -1, index, print_level; struct clock *clock = NULL; struct option *opts; @@ -201,8 +203,44 @@ int main(int argc, char *argv[]) goto out; } - clock = clock_create(cfg->n_interfaces > 1 ? CLOCK_TYPE_BOUNDARY : - CLOCK_TYPE_ORDINARY, cfg, req_phc); + type = config_get_int(cfg, NULL, "clock_type"); + switch (type) { + case CLOCK_TYPE_ORDINARY: + if (cfg->n_interfaces > 1) { + type = CLOCK_TYPE_BOUNDARY; + } + break; + case CLOCK_TYPE_BOUNDARY: + if (cfg->n_interfaces < 2) { + fprintf(stderr, "BC needs at least two interfaces\n"); + goto out; + } + break; + case CLOCK_TYPE_P2P: + if (cfg->n_interfaces < 2) { + fprintf(stderr, "TC needs at least two interfaces\n"); + goto out; + } + if (DM_P2P != config_get_int(cfg, NULL, "delay_mechanism")) { + fprintf(stderr, "P2P_TC needs P2P delay mechanism\n"); + goto out; + } + break; + case CLOCK_TYPE_E2E: + if (cfg->n_interfaces < 2) { + fprintf(stderr, "TC needs at least two interfaces\n"); + goto out; + } + if (DM_E2E != config_get_int(cfg, NULL, "delay_mechanism")) { + fprintf(stderr, "E2E_TC needs E2E delay mechanism\n"); + goto out; + } + break; + case CLOCK_TYPE_MANAGEMENT: + goto out; + } + + clock = clock_create(type, cfg, req_phc); if (!clock) { fprintf(stderr, "failed to create a clock\n"); goto out;