-----Original Message----- From: Aya Levin via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net> Sent: Wednesday, June 8, 2022 11:01 AM
> > On 5/2/2022 12:05 PM, Arkadiusz Kubalewski wrote: > > Allow config interface to parse SyncE related config files. > > > > Co-developed-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com> > > Signed-off-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com> > > Co-developed-by: Michal Michalik <michal.micha...@intel.com> > > Signed-off-by: Michal Michalik <michal.micha...@intel.com> > > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalew...@intel.com> > > --- > > config.c | 198 ++++++++++++++++++++++++++++++++++++---------- > > config.h | 8 ++ > > configs/synce.cfg | 194 +++++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 358 insertions(+), 42 deletions(-) > > create mode 100644 configs/synce.cfg > > > > diff --git a/config.c b/config.c > > index 4f3ceb8a20d7..f0ad329a7f18 100644 > > --- a/config.c > > +++ b/config.c > > @@ -41,6 +41,7 @@ enum config_section { > > GLOBAL_SECTION, > > UC_MTAB_SECTION, > > PORT_SECTION, > > + DEVICE_SECTION, > > UNKNOWN_SECTION, > > }; > > > > @@ -68,6 +69,7 @@ typedef union { > > #define CFG_ITEM_LOCKED (1 << 1) /* command line value, may not be > > changed */ > > #define CFG_ITEM_PORT (1 << 2) /* item may appear in port sections */ > > #define CFG_ITEM_DYNSTR (1 << 4) /* string value dynamically allocated */ > > +#define CFG_ITEM_DEVICE (1 << 8) /* item may appear in device sections */ > > > > struct config_item { > > char label[CONFIG_LABEL_SIZE]; > > @@ -79,12 +81,18 @@ struct config_item { > > any_t max; > > }; > > > > -#define N_CONFIG_ITEMS (sizeof(config_tab) / sizeof(config_tab[0])) > > +#define N_CONFIG_ITEMS_PTP (sizeof(config_tab_ptp) / > > sizeof(config_tab_ptp[0])) > > +#define N_CONFIG_ITEMS_SYNCE ((sizeof(config_tab_synce) / \ > > + sizeof(config_tab_synce[0]))) > > + > > +#define PORT_TO_FLAG(_port) (_port == PORT_SECTION ? CFG_ITEM_PORT : \ > > + _port == DEVICE_SECTION ? CFG_ITEM_DEVICE : \ > > + CFG_ITEM_STATIC) > > > > #define CONFIG_ITEM_DBL(_label, _port, _default, _min, _max) { \ > > .label = _label, \ > > .type = CFG_TYPE_DOUBLE, \ > > - .flags = _port ? CFG_ITEM_PORT : 0, \ > > + .flags = PORT_TO_FLAG(_port), \ > > .val.d = _default, \ > > .min.d = _min, \ > > .max.d = _max, \ > > @@ -92,14 +100,14 @@ struct config_item { > > #define CONFIG_ITEM_ENUM(_label, _port, _default, _table) { \ > > .label = _label, \ > > .type = CFG_TYPE_ENUM, \ > > - .flags = _port ? CFG_ITEM_PORT : 0, \ > > + .flags = PORT_TO_FLAG(_port), \ > > .tab = _table, \ > > .val.i = _default, \ > > } > > #define CONFIG_ITEM_INT(_label, _port, _default, _min, _max) { \ > > .label = _label, \ > > .type = CFG_TYPE_INT, \ > > - .flags = _port ? CFG_ITEM_PORT : 0, \ > > + .flags = PORT_TO_FLAG(_port), \ > > .val.i = _default, \ > > .min.i = _min, \ > > .max.i = _max, \ > > @@ -107,33 +115,39 @@ struct config_item { > > #define CONFIG_ITEM_STRING(_label, _port, _default) { \ > > .label = _label, \ > > .type = CFG_TYPE_STRING, \ > > - .flags = _port ? CFG_ITEM_PORT : 0, \ > > + .flags = PORT_TO_FLAG(_port), \ > > .val.s = _default, \ > > } > > > > #define GLOB_ITEM_DBL(label, _default, min, max) \ > > - CONFIG_ITEM_DBL(label, 0, _default, min, max) > > + CONFIG_ITEM_DBL(label, GLOBAL_SECTION, _default, min, max) > > > > #define GLOB_ITEM_ENU(label, _default, table) \ > > - CONFIG_ITEM_ENUM(label, 0, _default, table) > > + CONFIG_ITEM_ENUM(label, GLOBAL_SECTION, _default, table) > > > > #define GLOB_ITEM_INT(label, _default, min, max) \ > > - CONFIG_ITEM_INT(label, 0, _default, min, max) > > + CONFIG_ITEM_INT(label, GLOBAL_SECTION, _default, min, max) > > > > #define GLOB_ITEM_STR(label, _default) \ > > - CONFIG_ITEM_STRING(label, 0, _default) > > + CONFIG_ITEM_STRING(label, GLOBAL_SECTION, _default) > > > > #define PORT_ITEM_DBL(label, _default, min, max) \ > > - CONFIG_ITEM_DBL(label, 1, _default, min, max) > > + CONFIG_ITEM_DBL(label, PORT_SECTION, _default, min, max) > > > > #define PORT_ITEM_ENU(label, _default, table) \ > > - CONFIG_ITEM_ENUM(label, 1, _default, table) > > + CONFIG_ITEM_ENUM(label, PORT_SECTION, _default, table) > > > > #define PORT_ITEM_INT(label, _default, min, max) \ > > - CONFIG_ITEM_INT(label, 1, _default, min, max) > > + CONFIG_ITEM_INT(label, PORT_SECTION, _default, min, max) > > > > #define PORT_ITEM_STR(label, _default) \ > > - CONFIG_ITEM_STRING(label, 1, _default) > > + CONFIG_ITEM_STRING(label, PORT_SECTION, _default) > > + > > +#define DEV_ITEM_INT(label, _default, min, max) \ > > + CONFIG_ITEM_INT(label, DEVICE_SECTION, _default, min, max) > > + > > +#define DEV_ITEM_STR(label, _default) \ > > + CONFIG_ITEM_STRING(label, DEVICE_SECTION, _default) > > > > static struct config_enum clock_servo_enu[] = { > > { "pi", CLOCK_SERVO_PI }, > > @@ -220,7 +234,7 @@ static struct config_enum bmca_enu[] = { > > { NULL, 0 }, > > }; > > > > -struct config_item config_tab[] = { > > +struct config_item config_tab_ptp[] = { > > PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX), > > PORT_ITEM_ENU("asCapable", AS_CAPABLE_AUTO, as_capable_enu), > > GLOB_ITEM_INT("assume_two_step", 0, 0, 1), > > @@ -341,7 +355,37 @@ struct config_item config_tab[] = { > > GLOB_ITEM_INT("write_phase_mode", 0, 0, 1), > > }; > > > > +struct config_item config_tab_synce[] = { > > + GLOB_ITEM_INT("logging_level", LOG_INFO, PRINT_LEVEL_MIN, > > PRINT_LEVEL_MAX), > > + GLOB_ITEM_STR("message_tag", NULL), > > + GLOB_ITEM_INT("use_syslog", 1, 0, 1), > > + GLOB_ITEM_STR("userDescription", ""), > > + GLOB_ITEM_INT("verbose", 0, 0, 1), > > + DEV_ITEM_INT("internal_input", 1, 0, 1), > > + DEV_ITEM_INT("external_input", 0, 0, 1), > > + DEV_ITEM_INT("external_input_QL", 0, 0, 15), > > + DEV_ITEM_INT("external_input_ext_QL", 0, 0, 255), > > + DEV_ITEM_INT("extended_tlv", 0, 0, 1), > > + DEV_ITEM_INT("network_option", 1, 1, 2), > > + DEV_ITEM_INT("recover_time", 300, 10, 720), > > + DEV_ITEM_STR("dpll_get_state_cmd", NULL), > > + DEV_ITEM_STR("dpll_holdover_value", NULL), > > + DEV_ITEM_STR("dpll_locked_ho_value", NULL), > > + DEV_ITEM_STR("dpll_locked_value", NULL), > > + DEV_ITEM_STR("dpll_freerun_value", NULL), > > + DEV_ITEM_STR("dpll_invalid_value", NULL), > > + PORT_ITEM_STR("allowed_qls", NULL), > > + PORT_ITEM_STR("allowed_ext_qls", NULL), > > + PORT_ITEM_INT("sync", 0, 0, 1), > > + PORT_ITEM_STR("recover_clock_enable_cmd", NULL), > > + PORT_ITEM_STR("recover_clock_disable_cmd", NULL), > > + PORT_ITEM_INT("tx_heartbeat_msec", 1000, 100, 3000), > > + PORT_ITEM_INT("rx_heartbeat_msec", 50, 10, 500), > > +}; > > + > > static struct unicast_master_table *current_uc_mtab; > > +static struct interface *__config_create_interface(const char *name, > > struct config *cfg, > > + const char *type); > > > > static enum parser_result > > parse_fault_interval(struct config *cfg, const char *section, > > @@ -392,6 +436,8 @@ static struct config_item *config_item_alloc(struct > > config *cfg, > > } > > strncpy(ci->label, name, CONFIG_LABEL_SIZE - 1); > > ci->type = type; > > + ci->val.s = NULL; > > + ci->flags = 0; > > > > snprintf(buf, sizeof(buf), "%s.%s", section, ci->label); > > if (hash_insert(cfg->htab, buf, ci)) { > > @@ -406,8 +452,11 @@ static struct config_item *config_item_alloc(struct > > config *cfg, > > static void config_item_free(void *ptr) > > { > > struct config_item *ci = ptr; > > - if (ci->type == CFG_TYPE_STRING && ci->flags & CFG_ITEM_DYNSTR) > > + if (ci->type == CFG_TYPE_STRING && ci->flags & CFG_ITEM_DYNSTR > > + && ci->val.s != NULL) { > > free(ci->val.s); > > + ci->val.s = NULL; > > + } > > if (ci->flags & CFG_ITEM_STATIC) > > return; > > free(ci); > > @@ -512,10 +561,13 @@ static enum parser_result parse_section_line(char *s, > > enum config_section *secti > > current_uc_mtab = NULL; > > } else if (s[0] == '[') { > > char c; > > - *section = PORT_SECTION; > > - /* Replace square brackets with white space. */ > > + if (s[1] == '<') > > + *section = DEVICE_SECTION; > > + else > > + *section = PORT_SECTION; > > + /* Replace brackets with white space. */ > > while (0 != (c = *s)) { > > - if (c == '[' || c == ']') > > + if (c == '[' || c == ']' || c == '<' || c == '>') > > *s = ' '; > > s++; > > } > > @@ -573,7 +625,8 @@ static enum parser_result parse_item(struct config *cfg, > > } > > > > if (section) { > > - if (!(cgi->flags & CFG_ITEM_PORT)) { > > + if (!(cgi->flags & CFG_ITEM_PORT) && > > + !(cgi->flags & CFG_ITEM_DEVICE)) { > > return NOT_PARSED; > > } > > /* Create or update this port specific item. */ > > @@ -601,8 +654,9 @@ static enum parser_result parse_item(struct config *cfg, > > dst->val.d = df; > > break; > > case CFG_TYPE_STRING: > > - if (dst->flags & CFG_ITEM_DYNSTR) { > > + if (dst->flags & CFG_ITEM_DYNSTR && dst->val.s != NULL) { > > free(dst->val.s); > > + dst->val.s = NULL; > > } > > dst->val.s = strdup(value); > > if (!dst->val.s) { > > @@ -728,18 +782,26 @@ static void check_deprecated_options(const char > > **option) > > } > > } > > > > -static struct option *config_alloc_longopts(void) > > +static struct option *config_alloc_longopts(enum feature_type type) > > { > > - struct config_item *ci; > > + struct config_item *ci, *ci_tab; > > struct option *opts; > > - int i; > > + int i, n_items; > > > > - opts = calloc(1, (1 + N_CONFIG_ITEMS) * sizeof(*opts)); > > + if (type == PTP) { > > + ci_tab = &config_tab_ptp[0]; > > + n_items = N_CONFIG_ITEMS_PTP; > > + } else { > > + ci_tab = &config_tab_synce[0]; > > + n_items = N_CONFIG_ITEMS_SYNCE; > > + } > > + n_items = (type == PTP ? N_CONFIG_ITEMS_PTP : N_CONFIG_ITEMS_SYNCE); > > + opts = calloc(1, (1 + n_items) * sizeof(*opts)); > > if (!opts) { > > return NULL; > > } > > - for (i = 0; i < N_CONFIG_ITEMS; i++) { > > - ci = &config_tab[i]; > > + for (i = 0; i < n_items; i++) { > > + ci = &ci_tab[i]; > > opts[i].name = ci->label; > > opts[i].has_arg = required_argument; > > /* Avoid bug in detection of ambiguous options in glibc */ > > @@ -757,6 +819,8 @@ int config_read(const char *name, struct config *cfg) > > char buf[1024], *line, *c; > > const char *option, *value; > > struct interface *current_port = NULL; > > + struct interface *current_device = NULL; > > + bool is_synce = (cfg->type == SYNCE); > > int line_num; > > > > fp = 0 == strncmp(name, "-", 2) ? stdin : fopen(name, "r"); > > @@ -787,6 +851,7 @@ int config_read(const char *name, struct config *cfg) > > if (parse_section_line(line, ¤t_section) == PARSED_OK) { > > if (current_section == PORT_SECTION) { > > char port[17]; > > + > > if (1 != sscanf(line, " %16s", port)) { > > fprintf(stderr, "could not parse port > > name on line %d\n", > > line_num); > > @@ -795,6 +860,27 @@ int config_read(const char *name, struct config *cfg) > > current_port = config_create_interface(port, > > cfg); > > if (!current_port) > > goto parse_error; > > + if (is_synce) { > > + if (current_device) { > > + > > interface_se_set_parent_dev(current_port, > > + > > interface_name(current_device)); > > + } else { > > + goto parse_error; > > + } > > + } > > + } else if (current_section == DEVICE_SECTION) { > > + /* clear port on new device found in config */ > > + current_port = NULL; > > + char device[17]; > > + > > + if (sscanf(line, " %16s", device) != 1) { > > + fprintf(stderr, "could not parse device > > name on line %d\n", > > + line_num); > > + goto parse_error; > > + } > > + current_device = > > __config_create_interface(device, cfg, "device"); > > + if (!current_device) > > + goto parse_error; > > } > > continue; > > } > > @@ -814,14 +900,16 @@ int config_read(const char *name, struct config *cfg) > > if (parse_setting_line(line, &option, &value)) { > > fprintf(stderr, "could not parse line %d in %s > > section\n", > > line_num, current_section == GLOBAL_SECTION ? > > - "global" : interface_name(current_port)); > > + "global" : interface_name(current_port ? > > + current_port : > > current_device)); > > goto parse_error; > > } > > > > check_deprecated_options(&option); > > > > parser_res = parse_item(cfg, 0, current_section == > > GLOBAL_SECTION ? > > - NULL : interface_name(current_port), > > + NULL : interface_name(current_port ? > > + current_port : > > current_device), > > option, value); > > switch (parser_res) { > > case PARSED_OK: > > @@ -830,7 +918,8 @@ int config_read(const char *name, struct config *cfg) > > fprintf(stderr, "unknown option %s at line %d in %s > > section\n", > > option, line_num, > > current_section == GLOBAL_SECTION ? "global" : > > - interface_name(current_port)); > > + interface_name(current_port ? > > + current_port : current_device)); > > goto parse_error; > > case BAD_VALUE: > > fprintf(stderr, "%s is a bad value for option %s at > > line %d\n", > > @@ -856,7 +945,7 @@ parse_error: > > return -2; > > } > > > > -struct interface *config_create_interface(const char *name, struct config > > *cfg) > > +struct interface *__config_create_interface(const char *name, struct > > config *cfg, const char *type) > > { > > struct interface *iface; > > const char *ifname; > > @@ -870,7 +959,7 @@ struct interface *config_create_interface(const char > > *name, struct config *cfg) > > > > iface = interface_create(name); > > if (!iface) { > > - fprintf(stderr, "cannot allocate memory for a port\n"); > > + fprintf(stderr, "cannot allocate memory for a %s\n", type); > > return NULL; > > } > > STAILQ_INSERT_TAIL(&cfg->interfaces, iface, list); > > @@ -879,12 +968,17 @@ struct interface *config_create_interface(const char > > *name, struct config *cfg) > > return iface; > > } > > > > -struct config *config_create(void) > > +struct interface *config_create_interface(const char *name, struct config > > *cfg) > > +{ > > + return __config_create_interface(name, cfg, "port"); > > +} > > + > > +struct config *__config_create(enum feature_type type) > > { > > char buf[CONFIG_LABEL_SIZE + 8]; > > - struct config_item *ci; > > + struct config_item *ci, *ci_tab; > > struct config *cfg; > > - int i; > > + int i, end; > > > > cfg = calloc(1, sizeof(*cfg)); > > if (!cfg) { > > @@ -893,7 +987,7 @@ struct config *config_create(void) > > STAILQ_INIT(&cfg->interfaces); > > STAILQ_INIT(&cfg->unicast_master_tables); > > > > - cfg->opts = config_alloc_longopts(); > > + cfg->opts = config_alloc_longopts(type); > > if (!cfg->opts) { > > free(cfg); > > return NULL; > > @@ -906,9 +1000,18 @@ struct config *config_create(void) > > return NULL; > > } > > > > + cfg->type = type; > > + if (type == PTP) { > > + ci_tab = &config_tab_ptp[0]; > > + end = N_CONFIG_ITEMS_PTP; > > + } else { > > + ci_tab = &config_tab_synce[0]; > > + end = N_CONFIG_ITEMS_SYNCE; > > + } > > + > > /* Populate the hash table with global defaults. */ > > - for (i = 0; i < N_CONFIG_ITEMS; i++) { > > - ci = &config_tab[i]; > > + for (i = 0; i < end; i++) { > > + ci = &ci_tab[i]; > > ci->flags |= CFG_ITEM_STATIC; > > snprintf(buf, sizeof(buf), "global.%s", ci->label); > > if (hash_insert(cfg->htab, buf, ci)) { > > @@ -918,12 +1021,12 @@ struct config *config_create(void) > > } > > > > /* Perform a Built In Self Test.*/ > > - for (i = 0; i < N_CONFIG_ITEMS; i++) { > > - ci = &config_tab[i]; > > + for (i = 0; i < end; i++) { > > + ci = &ci_tab[i]; > > ci = config_global_item(cfg, ci->label); > > - if (ci != &config_tab[i]) { > > + if (ci != &ci_tab[i]) { > > fprintf(stderr, "config BIST failed at %s\n", > > - config_tab[i].label); > > + ci_tab[i].label); > > goto fail; > > } > > } > > @@ -935,6 +1038,16 @@ fail: > > return NULL; > > } > > > > +struct config *config_create(void) > > +{ > > + return __config_create(PTP); > > +} > > + > > +struct config *config_create_synce(void) > > +{ > > + return __config_create(SYNCE); > > +} > > + > > void config_destroy(struct config *cfg) > > { > > struct unicast_master_address *address; > > @@ -1137,8 +1250,9 @@ int config_set_string(struct config *cfg, const char > > *option, > > return -1; > > } > > ci->flags |= CFG_ITEM_LOCKED; > > - if (ci->flags & CFG_ITEM_DYNSTR) { > > + if (ci->flags & CFG_ITEM_DYNSTR && ci->val.s != NULL) { > > free(ci->val.s); > > + ci->val.s = NULL; > > } > > ci->val.s = strdup(val); > > if (!ci->val.s) { > > diff --git a/config.h b/config.h > > index 14d2f64415dc..a32e0079cf21 100644 > > --- a/config.h > > +++ b/config.h > > @@ -32,10 +32,16 @@ > > #include "servo.h" > > #include "sk.h" > > > > +enum feature_type { > > + PTP = 0, > > + SYNCE > > +}; > > + > > struct config { > > /* configured interfaces */ > > STAILQ_HEAD(interfaces_head, interface) interfaces; > > int n_interfaces; > > + enum feature_type type; > > > > /* for parsing command line options */ > > struct option *opts; > > @@ -55,6 +61,8 @@ void config_destroy(struct config *cfg); > > > > struct config *config_create(void); > > > > +struct config *config_create_synce(void); > > + > > double config_get_double(struct config *cfg, const char *section, > > const char *option); > > > > diff --git a/configs/synce.cfg b/configs/synce.cfg > > new file mode 100644 > > index 000000000000..eadb318bad6f > > --- /dev/null > > +++ b/configs/synce.cfg > > @@ -0,0 +1,194 @@ > > +# Global section is for debuging mostly > > +[global] > > +# > > +# Runtime options > > +# > > +logging_level 7 > > +use_syslog 0 > > +verbose 1 > > +message_tag [synce4l] > > + > > + > > +# > > +# Device section > > +# Per-device configuration > > +# > > +# User defined name of a one logical device configured for SyncE in the > > system. > > +# All the ports configured after this section will be a part of this device > > +# (until next device section). > > +[<synce1>] > > + > > +# > > +# If internal inputs are allowed > > +# 0 if internal input sources shall not be used > > +# 1 if internal input sources shall be used > > +# default: 1 > > +# > > +# Internal inputs mean the inputs recovered from the PHY's. > > +# The ports configured (in the port-sections [<dev name>], under the device > > +# section) will be monitored for the QL (Quality Level). > > +# QL is sent by the peer connected to the port and represents the Holdover > > +# performance of the peer. > > +# The best QL (from all the ports where "sync = 1") is selected and > > frequency > > +# recovered on that port shall be used to feed its frequency to all the > > other > > +# ports. > > +# > > +internal_input 1 > > + > > +# > > +# If external inputs are allowed > > +# 0 if external input sources shall not be used > > +# 1 if external input sources shall be used > > +# default: 0 > > +# > > +# External inputs are either 1PPS from buil-in GPS module or 1PPS from the > > +# on-board SMA connectors > > +# > > +# Device must be pre-confiured to use this setting. > > +# Before running the application, one of the external inputs shall be > > selected. > > +# This is done through the interface supplied by the NIC vendor. > > +# > > +# In this mode synce4l application is only responsible for sending > > +# the QL to the peers on all configured ports (where "sync = 1") > > +# The QL value that is sent equals configured "external_input_QL" > > +# (and "external_input_ext_QL" in case of "extended_tlv=1") > > +# > > +external_input 0 > > + > > +# > > +# These values are sent to the peers on configured ports ONLY when > > 'external > > +# input' mode is enabled. > > +# Valid values are defined in Table 11-7 and Table 11-8 of recommendation > > +# ITU-T G.8264. > > +# They shall be configured appropriately so they are understood by the > > peer. > > +# > > +# external_input_QL corresponds to the SSM code column. > > +# > > +# external_input_ext_QL corresponds to the Enhanced SSM code column > > +# (is used only if "extended_tlv = 1") > > +# > > +external_input_QL 2 > > +external_input_ext_QL 255 > > + > > +# > > +# If extended TLV shall be supported on the device. > > +# 0 if no extended tlv shall be supported > > +# 1 if extended tlv shall be supported > > +# default: 0 > > +# > > +# In case of 0: > > +# - the port will always TX the non-extended TLV, for RX only > > +# non-extended TLV will be processed for reference signal selection > > +# In case of 1: > > +# - If port is configured with external_input=1, the TX will always > > use > > +# extended TLV (no RX is required in this case) > > +# - If port is configured with external_input=0 and > > internal_input=1, the > > +# TX version of TLV will be propagated from the port that was > > chosen as > > +# candidate for frequency synchronization > > +# > > +extended_tlv 1 > > + > > +# > > +# Which network option shall be supported > > +# > > +# 1 or 2 as defined in T-REC-G.8264 > > +# default: 1 > > +# > > +# This is rather per-network option, all device in SyncE network > > +# shall have this configured for the same value > > +# > > +network_option 1 > > + > > +# > > +# Seconds indicating minimum time to recover from the QL-failed state on > > the > > +# port. > > +# Range: 10-720 > > +# Default: 300 > > +# > > +# If valid QL was not received from one of the source ports within 5 > > seconds > > +# the port is no longer a valid source (marked as QL-failed) > > +# > > +# Valid QL must be received for more then "recover_time" seconds on that > > port > > +# to use its PHY recovered signal again as a valid source > > +# > > +recover_time 10 > > + > > +# > > +# Shell command to be executed in order to obtain current DPLL status of a > > +# device. > > +# > > +dpll_get_state_cmd cat /sys/class/net/enp1s0f0/device/cgu_state > > + > > +# > > +# DPLL state values, must equal to values produced by stdout of > > +# "dpll_get_state_cmd" command > > +# > > +dpll_holdover_value 4 > > +dpll_locked_ho_value 3 > > +dpll_locked_value 2 > > +dpll_freerun_value 1 > > +dpll_invalid_value 0 > > + > > +# > > +# Port section(s) > > +# > > +# It starts per-port configuration. > > +# Each port (of the device) that is used for SyncE, shall have its own > > section > > +# with at least sync = 1 (which defines port as synchronous mode) > > +# > > +[enp1s0f0] > > + > > +# > > +# msec resolution of TX the QL from this port to the peer > > +# [100-3000], default:1000 (1000 = 1 second is expected by the standard) > > +# > > +# As the standard expects 1 sec, it is not recommended to use different > > +# than a 1000. > > +# > > +tx_heartbeat_msec 2000 > The default should be 1000 > > + > > +# > > +# recovered PHY signal can be lost at anytime, this is msec resolution of > > +# reading the socket, acting on signal lost shall be done just after > > +# [10-500], default:50 > > +# > > +rx_heartbeat_msec 500 > > + > > +# > > +# Sync mode as defined by standard > > +# 0 (non-sync mode) - port not used for best signal source selection or TX > > its QL > > +# 1 (sync mode) - port used for best signal source selection or TX its QL > > +# > > +sync 1 > Unclear - if a port in a non-sync-mode is not SyncE operational > A port in non-sync-mode shouldn't be a part of the config file Yes, we tried to leave this explicit config item as standard defines "non-sync mode" and "sync mode" explicitly, but it is true that if it is not in sync it doesn't make much sense to have its entry in config file. IMHO we are safe to remove it. Will do that in next version. > > + > > +# > > +# Shell commands for enabling/disabling this port as main recovered clock > > on a > > +# device. > > +# > > +recover_clock_enable_cmd echo 1 0 > > > /sys/class/net/enp1s0f0/device/phy/synce > > +recover_clock_disable_cmd echo 0 0 > > > /sys/class/net/enp1s0f0/device/phy/synce > > + > > +# > > +# next configured interface for the device > > +# > > +[enp1s0f1] > > +sync 1 > > +recover_clock_enable_cmd echo 1 0 > > > /sys/class/net/enp1s0f1/device/phy/synce > > +recover_clock_disable_cmd echo 0 0 > > > /sys/class/net/enp1s0f1/device/phy/synce > > + > > + > > + > > +############################################################ > > +# > > +# next SyncE device section > > +# > > +#[<synce2>] > > +#internal_input 0 > > +#external_input 1 > What is the meaning of multiple SyncE devices? Shouldn't there be a > seperate execution for synce4l like in ptp4l Right now the user can either use: multiple config files (while running multiple synce4l instances) or define multiple devices in single config file (and control all of them with one instance of synce4l). Devices are implemented separately, the single synce_clock can step many devices. Thank you, Arkadiusz > > + > > +# > > +# new port belonging to the "new" device > > +# > > +#[enp7s0f0] > > +#sync 1 > > + > _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel