Add main code of synce4l - user space application implementing standard - Recommendation ITU-T G.8264/Y.1364. On init the application parses SyncE config file and initializes a synce_clock with SyncE devices and configured ports. synce_clock is later polled until application termination.
Add documentation in form of Linux manual and 'synce4l_README.md'. Add synce4l to the linuxptp makefile. Co-developed-by: Andrzej Sawula <andrzej.saw...@intel.com> Signed-off-by: Andrzej Sawula <andrzej.saw...@intel.com> 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> --- v2: - fix duplicated entry in synce4l.8 - updated license headers v3: - rebase patch series - fix typo in 'usage' - add synce4l to .gitignore .gitignore | 1 + README.org | 2 + makefile | 9 +- synce4l.8 | 239 ++++++++++++++++++++++++++++++++++++++++++++++ synce4l.c | 132 +++++++++++++++++++++++++ synce4l_README.md | 194 +++++++++++++++++++++++++++++++++++++ 6 files changed, 575 insertions(+), 2 deletions(-) create mode 100644 synce4l.8 create mode 100644 synce4l.c create mode 100644 synce4l_README.md diff --git a/.gitignore b/.gitignore index 1e7d1ca..8c65e47 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ /ptp4l /phc_ctl /snmp4lptp +/synce4l /timemaster /ts2phc diff --git a/README.org b/README.org index 063b542..ab0d5a0 100644 --- a/README.org +++ b/README.org @@ -51,6 +51,8 @@ - Supports bonded, IPoIB, and vlan interfaces. + - Supports Synchronous Ethernet (Recommendation ITU-T G.8264/Y.1364). + * Getting the Code You can download the latest released version at Source Forge. diff --git a/makefile b/makefile index 5295b60..b7263a9 100644 --- a/makefile +++ b/makefile @@ -22,12 +22,14 @@ CC = $(CROSS_COMPILE)gcc VER = -DVER=$(version) CFLAGS = -Wall $(VER) $(incdefs) $(DEBUG) $(EXTRA_CFLAGS) LDLIBS = -lm -lrt -pthread $(EXTRA_LDFLAGS) -PRG = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc +PRG = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc synce4l FILTERS = filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o TRANSP = raw.o transport.o udp.o udp6.o uds.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o +SYNCE = esmc_socket.o synce_clock.o synce_dev.o synce_dev_ctrl.o \ + synce_msg.o synce_port.o synce_port_ctrl.o synce_transport.o OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ e2e_tc.o fault.o $(FILTERS) fsm.o hash.o interface.o monitor.o msg.o phc.o \ port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o $(SERVOS) \ @@ -35,7 +37,7 @@ OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ unicast_fsm.o unicast_service.o util.o version.o OBJECTS = $(OBJ) hwstamp_ctl.o nsm.o phc2sys.o phc_ctl.o pmc.o pmc_agent.o \ - pmc_common.o sysoff.o timemaster.o $(TS2PHC) + pmc_common.o $(SYNCE) sysoff.o timemaster.o $(TS2PHC) SRC = $(OBJECTS:.o=.c) DEPEND = $(OBJECTS:.o=.d) srcdir := $(dir $(lastword $(MAKEFILE_LIST))) @@ -50,6 +52,9 @@ man8dir = $(mandir)/man8 all: $(PRG) +synce4l: config.o hash.o interface.o phc.o print.o sk.o $(SYNCE) util.o \ + version.o + ptp4l: $(OBJ) nsm: config.o $(FILTERS) hash.o interface.o msg.o nsm.o phc.o print.o \ diff --git a/synce4l.8 b/synce4l.8 new file mode 100644 index 0000000..a266e80 --- /dev/null +++ b/synce4l.8 @@ -0,0 +1,239 @@ +.\" Manpage for synce4l. +.\" Contact linuxptp-devel@lists.sourceforge.net to correct errors or typos. +.TH man 8 "21 Apr 2022" "1.0" "synce4l man page" + +.SH NAME +synce4l \- Synchronous Ethernet (Sync-E) controller application + +.SH SYNOPSIS +synce4l -f [file] [-l <num>] [-m] [-q] [-v] [-h] + +.SH DESCRIPTION +synce4l is an implementation of the Synchronous Ethernet (Sync-E) protocol +according to ITU-T Rec. G.8264. The design goal is to provide logic to supported +hardware by processing Ethernet Synchronization Messaging Channel (ESMC) and +control Digital Phase Locked Loop (DPLL) clock on Network Card Interface (NIC). +.P +Application can operate in two mutually exclusive modes. If both modes are +configured simultaneously, the external input takes precedence over internal one +(internal is disabled implicitly). + +.TP +External input +If `synce4l` is configured to run in "external input" mode then DPLL needs to +have external 1PPS source attached (GPS or other generator). +In this scenario `synce4l` always broadcasts clock quality level (QL) defined +in configuration file. Additionally, for "external input" mode incoming Sync-E +frames do not participate in best source selection algorithm for DPLL. + +.TP +Internal input +In "internal input" mode incoming Sync-E frames are processed and best clock +source is extracted from the link having the best quality level. +`synce4l` configures such "best quality" port as a source to recover clock +for DPLL. The recovered QL is broadcasted to all other interfaces then. +An external clock cannot be used in this mode. + +.SH OPTIONS +.TP +.B \-f [file] +read configuration from 'file' (config file takes precedence over +command line arguments) +.TP +.B \-l [num] +set the logging level to 'num' (0: least detailed, 7: most detailed) +.TP +.B \-m +print messages to stdout +.TP +.B \-q +do not print messages to the syslog +.TP +.B \-v +print synce4l version and exit +.TP +.B \-h +print this message and exit + +.SH CONFIGURATION FILE +Configuration file contains three sections: +.IP - +global, +.IP - +device, +.IP - +port. + +.SS Global section +This section starts with `[global]` keyword. It sets the logging options. +.RS +Available options: +.IP logging_level +Minimum log level required to appear in a log. +.P +.RS +Defaults to 6, valid values are 0 - 7 +.RE +.IP message_tag +Tag reported in a log. +.IP use_syslog +Set to 1 if `syslog` should be used. +.P +.RS +Defaults to 1, valid values are 0 or 1 +.RE +.IP verbose +Set to 1 to log extra information. +.P +.RS +Defaults to 0, valid values are 0 or 1 +.RE +.RE + +.SS Device section +This section specifies the configuration of a device e.g. ptp1. +It starts with the full path name of a device e.g. [/dev/ptp1]. +DPLL state is retrieved using shell command defined by the user. Expected values +for each dpll state are also defined by the user. +.RS +Available options: +.IP internal_input +Set to 1 to enable "internal input" mode. Mutually exclusive with +"external_input" parameter. +.P +.RS +Defaults to 1, valid values are 0 or 1 +.RE +.IP external_input +Set to 1 to enable "external input" mode. Mutually exclusive with +"internal_input" parameter. Takes precedence over "internal_input" parameter. +.P +.RS +Defaults to 0, valid values are 0 or 1 +.RE +.IP external_input_QL +Quality Level (QL) for "external input" mode. +.P +.RS +Valid values specified in ITU-T Recommendations +.RE +.IP external_input_ext_QL +Extended Quality Level for "external input" mode. +.P +.RS +Valid values specified in ITU-T Recommendations +.RE +.IP extended_tlv +Set to 1 to enable extended QL. +.P +.RS +Defaults to 0, valid values are 0 or 1 +.RE +.IP network_option +Network option according to T-REC-G.8264. All devices in Sync-E domain +should have the same option configured. +.P +.RS +Defaults to 1, valid values are 1 or 2 +.RE +.IP recover_time +Seconds indicating the minimum time to recover from the QL-failed state on the port. +.P +.RS +Defaults to 60, valid values are 10 - 720 +.RE +.IP get_dpll_state_cmd +Defines a shell command which will be executed by synce4l to acquire current +state of a Sync-E DPLL on the device. Separated command must be provided by the +user for each device confgured for frequency synchronization. The command shall +output current state of DPLL to stdout, expected values are defined (also by the +user) with following configuration items: +dpll_holdover_value, dpll_locked_ho_value, dpll_locked_value, +dpll_freerun_value, dpll_invalid_value. +.RS +.RE +.IP dpll_holdover_value +Defines a string value expected on stdout stream when DPLL is in HOLDOVER state. +.P +.RS +.RE +.IP dpll_locked_ho_value +Defines a string value expected on stdout stream when DPLL is in LOCKED HOLDOVER +state. +.P +.RS +.RE +.IP dpll_locked_value +Defines a string value expected on stdout stream when DPLL is in LOCKED state. +.P +.RS +.RE +.IP dpll_freerun_value +Defines a string value expected on stdout stream when DPLL is in FREERUN state. +.P +.RS +.RE +.IP dpll_invalid_value +Defines a string value expected on stdout stream when DPLL is in INVALID state. +.P +.RE + +.SS Port section +Any other section not starting with `/` (e.g. [eth0]) is the port section. +Multiple port sections are allowed. Each port participates in Sync-E +communication. +.RS +Available options: +.IP sync +Set to 1 to enable the port for Sync-E communication (i.e. best source +selection and QLs advertisement). +.P +.RS +Defaults to 0, valid values are 0 or 1 +.RE +.IP tx_heartbeat_msec +Interval between consecutive Sync-E frame transmissions (1000ms recommended). +.P +.RS +Defaults to 1000, valid values are 100 - 3000 +.RE +.IP rx_heartbeat_msec +Interval between consecutive Sync-E socket polls (frame receive). +.P +.RS +Defaults to 50, valid values are 10 - 500 +.RE +.IP recover_clock_enable_cmd +A shell command which enables PHY port pointed by this Port section as a source +of frequency for the Sync-E DPLL on this device (required only in +"internal input" mode). +.RS +.RE +.IP recover_clock_disable_cmd +A shell command which disables PHY port pointed by this Port section as a source +of frequency for the Sync-E DPLL on this device (required only in +"internal input" mode). +.IP allowed_qls +List of integers containing allowed SSM QLs separated by comma (`,`), other +received ones would be discarded. If parameter is not provided, all QLs will be +accepted. +.P +.IP allowed_ext_qls +List of integers containing allowed extended SSM QLs separated by comma (`,`), +other received ones would be discarded. If parameter is not provided, all QLs will +be accepted. +.P +.RE + +.SH SEE ALSO +.BR ptp4l (8) + +.SH BUGS +No known bugs. + +.SH AUTHOR +Arkadiusz Kubalewski <arkadiusz.kubalew...@intel.com> +.P +Michal Michalik <michal.micha...@intel.com> +.P +Piotr Kwapulinski <piotr.kwapulin...@intel.com> diff --git a/synce4l.c b/synce4l.c new file mode 100644 index 0000000..0ce42b4 --- /dev/null +++ b/synce4l.c @@ -0,0 +1,132 @@ +/** + * @file synce4l.c + * @brief Synchronous Ethernet (Sync-E) userspace client + * @note SPDX-FileCopyrightText: Copyright 2022 Intel Corporation + * @note SPDX-License-Identifier: GPL-2.0+ + */ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/queue.h> +#include <errno.h> + +#include "synce_clock.h" +#include "config.h" +#include "print.h" +#include "version.h" + +static void usage(char *progname) +{ + fprintf(stderr, + "\nusage: %s [options]\n\n" + " \n\n" + " options:\n\n" + " -f [file] read configuration from 'file'\n" + " (config file takes precedence over command line arguments)\n" + " -l [num] set the logging level to 'num'\n" + " (%d: least detailed, %d: most detailed)\n" + " -m print messages to stdout\n" + " -q do not print messages to the syslog\n" + " -v print synce4l version and exit\n" + " -h print this message and exit\n" + "\n", + progname, PRINT_LEVEL_MIN, PRINT_LEVEL_MAX); +} + +static void synce4l_cleanup(struct config *cfg) +{ + if (cfg) + config_destroy(cfg); +} + +int main(int argc, char *argv[]) +{ + int c, err = -EACCES, index, print_level; + char *config = NULL, *progname; + struct synce_clock *clock; + struct option *opts; + struct config *cfg; + + if (handle_term_signals()) + return -EPERM; + + cfg = config_create_synce(); + if (!cfg) { + return -EINVAL; + } + opts = config_long_options(cfg); + + /* Process the command line arguments. */ + progname = strrchr(argv[0], '/'); + progname = progname ? 1+progname : argv[0]; + while (EOF != (c = getopt_long(argc, argv, "f:l:mqvh", + opts, &index))) { + switch (c) { + case 'f': + config = optarg; + break; + case 'l': + if (get_arg_val_i(c, optarg, &print_level, + PRINT_LEVEL_MIN, PRINT_LEVEL_MAX)) + goto out; + config_set_int(cfg, "logging_level", print_level); + break; + case 'm': + config_set_int(cfg, "verbose", 1); + break; + case 'q': + config_set_int(cfg, "use_syslog", 0); + break; + case 'v': + version_show(stdout); + synce4l_cleanup(cfg); + return 0; + case 'h': + usage(progname); + synce4l_cleanup(cfg); + return 0; + case '?': + usage(progname); + goto out; + default: + usage(progname); + goto out; + } + } + + if (config && (c = config_read(config, cfg))) { + synce4l_cleanup(cfg); + return c; + } + + print_set_progname(progname); + print_set_tag(config_get_string(cfg, NULL, "message_tag")); + print_set_verbose(config_get_int(cfg, NULL, "verbose")); + print_set_syslog(config_get_int(cfg, NULL, "use_syslog")); + print_set_level(config_get_int(cfg, NULL, "logging_level")); + + if (STAILQ_EMPTY(&cfg->interfaces)) { + fprintf(stderr, "%s", "no interface specified\n"); + usage(progname); + goto out; + } + + clock = synce_clock_create(cfg); + if (!clock) { + fprintf(stderr, "%s", "failed to create a synce clock\n"); + goto out; + } + + while (is_running()) + if (synce_clock_poll(clock)) + break; + + synce_clock_destroy(clock); + + err = 0; +out: + synce4l_cleanup(cfg); + return err; +} diff --git a/synce4l_README.md b/synce4l_README.md new file mode 100644 index 0000000..a1fb593 --- /dev/null +++ b/synce4l_README.md @@ -0,0 +1,194 @@ +# Table of contents + +1. Introduction +2. Compilation +3. Installation +4. Usage +5. Config + +--- +## 1\. Introduction +`synce4l` is a software implementation of Synchronous Ethernet (Sync-E) according +to ITU-T Recommendation G.8264. The design goal is to provide logic to supported +hardware by processing Ethernet Synchronization Messaging Channel (ESMC) and +control Digital Phase Locked Loop (DPLL) clock on Network Card Interface (NIC). + +Application can operate in two mutually exclusive modes. If both modes are +configured simultaneously, the "external input" mode takes precedence over +internal one ("internal input" mode is disabled implicitly). + +The best source selection is done according to ITU-T Recommendations G.781 and +G.8264. Two network options are supported: option 1 and option 2. + +Table showing priority of quality levels (QLs) in option 1 networks: +| Quality Level | Priority* | SSM | Extended SSM** | +| ------------- | --------- | --- | -------------- | +| ePRTC | 0 | 0x2 | 0x21 | +| PRTC | 1 | 0x2 | 0x20 | +| PRC | 2 | 0x2 | 0xFF | +| SSU-A | 3 | 0x4 | 0xFF | +| SSU-B | 4 | 0x8 | 0xFF | + +Table showing priority of quality levels (QLs) in option 2 networks: +| Quality Level | Priority* | SSM | Extended SSM** | +| ------------- | --------- | --- | -------------- | +| ePRTC | 0 | 0x1 | 0x21 | +| PRTC | 1 | 0x1 | 0x20 | +| PRS | 2 | 0x1 | 0xFF | +| STU | 3 | 0x0 | 0xFF | +| ST2 | 4 | 0x7 | 0xFF | +| TNC | 5 | 0x4 | 0xFF | +| ST3E | 6 | 0xD | 0xFF | +| PROV | 7 | 0xE | 0xFF | + +> *Remark:* *Lower number means higher priority + +> *Remark:* **If extended SSM is not enabled, it's implicitly assumed as `0xFF` + +### External input +If `synce4l` is configured to run in "external" input mode then DPLL needs to +have external 1PPS source attached (GPS or other generator). +In this scenario `synce4l` always broadcasts clock quality level (QL) defined +in configuration file. Additionally, for “external” mode incoming Sync-E +frames do not participate in best source selection algorithm for DPLL. + +### Internal input +In "internal input" mode incoming Sync-E frames are processed and best clock +source is extracted from the link having the best quality level. +`synce4l` configures such "best quality" port as a source to recover clock +for DPLL. The recovered QL is broadcasted to all other interfaces then. +An external clock cannot be used in this mode. + +--- +## 2\. Compilation +Makefile rules are included in linuxptp `makefile` and compilation is done using +the command: +``` +make synce4l +``` + +--- +## 3\. Installation +Use `make install` target to install `synce4l` in a system. + +--- +## 4\. Usage +Use `-h` command line argument to print the help page: +``` +$? ./synce4l -h +usage: synce4l [options] + + ... + + Other Options + + -f [file] read configuration from 'file' + (config file takes precedence over command line arguments) + -l [num] set the logging level to 'num' + (0: least detailed, 7: most detailed) + -m print messages to stdout + -q do not print messages to the syslog + -v print synce4l version and exit + -h print this message and exit +``` + +> *Remark:* `synce4l` requires root privileges since it opens raw sockets. + +--- +## 5\. Config +### Configuration file contains three sections: +- global, +- device, +- port. + +### Global section +This section starts with `[global]` keyword. It sets the logging options. + +| Parameter | Default | Valid values | Description | +| --------------- | ------- | ------------ | ---------------------------------------------- | +| `logging_level` | `6` | `0-7` | Minimum log level required to appear in a log. | +| `message_tag` | None | string | Tag reported in a log. | +| `use_syslog` | `1` | `0`, `1` | Set to 1 if `syslog` should be used. | +| `verbose` | `0` | `0`, `1` | Set to 1 to log extra information. | + +### Device section +This section specifies the configuration of a one logical device e.g. 'synce1'. +The name is defined by the user. The name has no impact for any functionality +except traces. +The name must be enclosed in extra angle bracket when defining new device +section e.g. [<synce1>]. +All ports defined by port sections after the device section will create one +SyncE device (until next device section). + +| Parameter | Default | Valid values | Description | +| ----------------------- | ------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `internal_input` | `1` | `0`, `1` | Set to 1 to enable "internal input" mode. Mutually exclusive with `external_input` parameter. | +| `external_input` | `0` | `0`, `1` | Set to 1 to enable "external input" mode. Mutually exclusive with `internal_input` parameter. Takes precedence over `internal_input` parameter. | +| `external_input_QL` | `0` | `0-15` | Quality Level (QL) for "external input" mode. | +| `external_input_ext_QL` | `0` | `0-255` | Extended Quality Level for "external input" mode. | +| `extended_tlv` | `0` | `0`, `1` | Set to 1 to enable extended QL. | +| `network_option` | `1` | `1`, `2` | Network option according to T-REC-G.8264. All devices in Sync-E domain should have the same option configured. | +| `recover_time` | `60` | `10-720` | Seconds indicating the minimum time to recover from the QL-failed state on the port. | +| `get_dpll_state_cmd` | None | string | Shell command which will be executed by synce4l to acquire current state of a Sync-E DPLL on the device. The command shall output current state of DPLL to stdout. | +| `dpll_holdover_value` | None | string | Value expected on stdout stream when DPLL is in HOLDOVER state, after calling command defined in get_dpll_state_cmd | +| `dpll_locked_ho_value` | None | string | Value expected on stdout stream when DPLL is in LOCKED HOLDOVER state, after calling command defined in get_dpll_state_cmd | +| `dpll_locked_value` | None | string | Value expected on stdout stream when DPLL is in LOCKED state, after calling command defined in get_dpll_state_cmd | +| `dpll_freerun_value` | None | string | Value expected on stdout stream when DPLL is in FREERUN state, after calling command defined in get_dpll_state_cmd | +| `dpll_invalid_value` | None | string | Value expected on stdout stream when DPLL is in INVALID state, after calling command defined in get_dpll_state_cmd | + +### Port section +Any other section not starting with `<` (e.g. [eth0]) is the port section. +Multiple port sections are allowed. Each port participates in Sync-E +communication. + +| Parameter | Default | Valid values | Description | +| --------------------------- | ------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `sync` | `0` | `0`, `1` | Set to 1 to enable the port for Sync-E communication (i.e. best source selection and QLs advertisement). | +| `tx_heartbeat_msec` | `1000` | `100-3000` | Interval between consecutive Sync-E frame transmissions (1000ms is recommended). | +| `rx_heartbeat_msec` | `50` | `10-500` | Interval between consecutive Sync-E socket polls (frame receive). | +| `recover_clock_enable_cmd` | None | string | Shell command which enables PHY port pointed by this Port section as a source of frequency for the Sync-E DPLL on this device (required only in "internal_input" mode). | +| `recover_clock_disable_cmd` | None | string | Shell command which disables PHY port pointed by this Port section as a source of frequency for the Sync-E DPLL on this device (required only in "internal_input" mode). | +| `allowed_qls` | None | string | List of integers containing allowed SSM QLs separated by comma (`,`), other received ones would be discarded - if parameter is not provided, all QLs will be accepted | +| `allowed_ext_qls` | None | string | List of integers containing allowed extended SSM QLs separated by comma (`,`), other received ones would be discarded - if parameter is not provided, all QLs will be accepted | + +> *Remark:* Please do not use backslashes in config file in 'string' fields - for example do not use it like this: `"/sys/kernel/debug/ice/0000\:5e\:00\.0/cgu_state"` + +### Config example + +``` +[global] +logging_level 7 +use_syslog 0 +verbose 1 +message_tag [synce4l] + +[<synce1>] +internal_input 0 +external_input 1 +network_option 1 +external_input_QL 11 +external_input_ext_QL 33 +extended_tlv 1 +recover_time 20 +dpll_get_state_cmd cat /sys/class/net/eth0/device/cgu_state +dpll_holdover_value 4 +dpll_locked_ho_value 3 +dpll_locked_value 2 +dpll_freerun_value 1 +dpll_invalid_value 0 + +[eth0] +sync 1 +tx_heartbeat_msec 1000 +rx_heartbeat_msec 500 +recover_clock_enable_cmd echo 1 0 > /sys/class/net/eth0/device/phy/synce +recover_clock_disable_cmd echo 0 0 > /sys/class/net/eth0/device/phy/synce +allowed_qls 3,4,7 +allowed_ext_qls 20,21 + +[eth1] +sync 0 +``` + +--- + -- 2.26.0 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel