The draft Enterprise Profile [1] specifies a hybrid E2E delay mechanism,
where the delay response message is sent "in kind". That is, if the
request is unicast, then the response is also unicast. Apparently this
scheme is already in widespread use in some industries. Also, it makes
sense, because those messages are of no interest to the other slaves in
the PTP network.
Because of the address work already in place, in turns out that adding
this mode is almost trivial. This patch introduces an "hybrid_e2e" option
that enabled the new mode.
1. https://datatracker.ietf.org/doc/draft-ietf-tictoc-ptp-enterprise-profile
Signed-off-by: Richard Cochran <***@gmail.com>
---
config.c | 1 +
default.cfg | 1 +
gPTP.cfg | 1 +
port.c | 28 +++++++++++++++++++++++++++-
ptp4l.8 | 9 +++++++++
5 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/config.c b/config.c
index 9fa2ecb..d462410 100644
--- a/config.c
+++ b/config.c
@@ -189,6 +189,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("free_running", 0, 0, 1),
PORT_ITEM_INT("freq_est_interval", 1, 0, INT_MAX),
GLOB_ITEM_INT("gmCapable", 1, 0, 1),
+ PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX),
GLOB_ITEM_INT("kernel_leap", 1, 0, 1),
PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX),
diff --git a/default.cfg b/default.cfg
index b46c0f6..d398d7c 100644
--- a/default.cfg
+++ b/default.cfg
@@ -31,6 +31,7 @@ assume_two_step 0
logging_level 6
path_trace_enabled 0
follow_up_info 0
+hybrid_e2e 0
tx_timestamp_timeout 1
use_syslog 1
verbose 0
diff --git a/gPTP.cfg b/gPTP.cfg
index 34fa238..75e996c 100644
--- a/gPTP.cfg
+++ b/gPTP.cfg
@@ -31,6 +31,7 @@ assume_two_step 1
logging_level 6
path_trace_enabled 1
follow_up_info 1
+hybrid_e2e 0
tx_timestamp_timeout 1
use_syslog 1
verbose 0
diff --git a/port.c b/port.c
index 91bb4e9..9c804cf 100644
--- a/port.c
+++ b/port.c
@@ -111,6 +111,7 @@ struct port {
UInteger32 neighborPropDelayThresh;
int follow_up_info;
int freq_est_interval;
+ int hybrid_e2e;
int min_neighbor_prop_delay;
int path_trace_enabled;
int rx_timestamp_offset;
@@ -1223,6 +1224,12 @@ static int port_delay_request(struct port *p)
msg->header.control = CTL_DELAY_REQ;
msg->header.logMessageInterval = 0x7f;
+ if (p->hybrid_e2e) {
+ struct ptp_message *dst = TAILQ_FIRST(&p->best->messages);
+ msg->address = dst->address;
+ msg->header.flagField[0] |= UNICAST;
+ }
+
if (port_prepare_and_send(p, msg, 1)) {
pr_err("port %hu: send delay request failed", portnum(p));
goto out;
@@ -1630,6 +1637,12 @@ static int process_delay_req(struct port *p, struct ptp_message *m)
msg->delay_resp.requestingPortIdentity = m->header.sourcePortIdentity;
+ if (p->hybrid_e2e && m->header.flagField[0] & UNICAST) {
+ msg->address = m->address;
+ msg->header.flagField[0] |= UNICAST;
+ msg->header.logMessageInterval = 0x7f;
+ }
+
err = port_prepare_and_send(p, msg, 0);
if (err)
pr_err("port %hu: send delay response failed", portnum(p));
@@ -1669,6 +1682,10 @@ static void process_delay_resp(struct port *p, struct ptp_message *m)
if (p->logMinDelayReqInterval == rsp->hdr.logMessageInterval) {
return;
}
+ if (m->header.flagField[0] & UNICAST) {
+ /* Unicast responses have logMinDelayReqInterval set to 0x7F. */
+ return;
+ }
if (rsp->hdr.logMessageInterval < -10 ||
rsp->hdr.logMessageInterval > 22) {
pr_debug("port %hu: ignore bogus delay request interval 2^%d",
@@ -2319,7 +2336,11 @@ int port_prepare_and_send(struct port *p, struct ptp_message *msg, int event)
if (msg_pre_send(msg))
return -1;
- cnt = transport_send(p->trp, &p->fda, event, msg);
+ if (msg->header.flagField[0] & UNICAST) {
+ cnt = transport_sendto(p->trp, &p->fda, event, msg);
+ } else {
+ cnt = transport_send(p->trp, &p->fda, event, msg);
+ }
if (cnt <= 0) {
return -1;
}
@@ -2550,6 +2571,7 @@ struct port *port_open(int phc_index,
p->asymmetry <<= 16;
p->follow_up_info = config_get_int(cfg, p->name, "follow_up_info");
p->freq_est_interval = config_get_int(cfg, p->name, "freq_est_interval");
+ p->hybrid_e2e = config_get_int(cfg, p->name, "hybrid_e2e");
p->path_trace_enabled = config_get_int(cfg, p->name, "path_trace_enabled");
p->rx_timestamp_offset = config_get_int(cfg, p->name, "ingressLatency");
p->tx_timestamp_offset = config_get_int(cfg, p->name, "egressLatency");
@@ -2564,6 +2586,10 @@ struct port *port_open(int phc_index,
p->delayMechanism = config_get_int(cfg, p->name, "delay_mechanism");
p->versionNumber = PTP_VERSION;
+ if (p->hybrid_e2e && p->delayMechanism != DM_E2E) {
+ pr_warning("port %d: hybrid_e2e only works with E2E", number);
+ }
+
/* Set fault timeouts to a default value */
for (i = 0; i < FT_CNT; i++) {
p->flt_interval_pertype[i].type = FTMO_LOG2_SECONDS;
diff --git a/ptp4l.8 b/ptp4l.8
index 14830c5..6eae40f 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -185,6 +185,15 @@ The default is 16 seconds.
Select the delay mechanism. Possible values are E2E, P2P and Auto.
The default is E2E.
.TP
+.B hybrid_e2e
+Enables the "hybrid" delay mechanism from the draft Enterprise
+Profile. When enabled, ports in the slave state send their delay
+request messages to the unicast address taken from the master's
+announce message. Ports in the master state will reply to unicast
+delay requests using unicast delay responses. This option has no
+effect if the delay_mechanism is set to P2P.
+The default is 0 (disabled).
+.TP
.B ptp_dst_mac
The MAC address to which PTP messages should be sent.
Relevant only with L2 transport. The default is 01:1B:19:00:00:00.
--
2.1.4
------------------------------------------------------------------------------