Support hybrid E2E using unicast delay requests and responses.

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 <richardcochran@gmail.com>
master
Richard Cochran 2015-08-28 20:41:50 +02:00
parent d0eb73c87b
commit e85cb68320
5 changed files with 39 additions and 1 deletions

View File

@ -189,6 +189,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("free_running", 0, 0, 1), GLOB_ITEM_INT("free_running", 0, 0, 1),
PORT_ITEM_INT("freq_est_interval", 1, 0, INT_MAX), PORT_ITEM_INT("freq_est_interval", 1, 0, INT_MAX),
GLOB_ITEM_INT("gmCapable", 1, 0, 1), GLOB_ITEM_INT("gmCapable", 1, 0, 1),
PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX), PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX),
GLOB_ITEM_INT("kernel_leap", 1, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1),
PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX),

View File

@ -31,6 +31,7 @@ assume_two_step 0
logging_level 6 logging_level 6
path_trace_enabled 0 path_trace_enabled 0
follow_up_info 0 follow_up_info 0
hybrid_e2e 0
tx_timestamp_timeout 1 tx_timestamp_timeout 1
use_syslog 1 use_syslog 1
verbose 0 verbose 0

View File

@ -31,6 +31,7 @@ assume_two_step 1
logging_level 6 logging_level 6
path_trace_enabled 1 path_trace_enabled 1
follow_up_info 1 follow_up_info 1
hybrid_e2e 0
tx_timestamp_timeout 1 tx_timestamp_timeout 1
use_syslog 1 use_syslog 1
verbose 0 verbose 0

28
port.c
View File

@ -111,6 +111,7 @@ struct port {
UInteger32 neighborPropDelayThresh; UInteger32 neighborPropDelayThresh;
int follow_up_info; int follow_up_info;
int freq_est_interval; int freq_est_interval;
int hybrid_e2e;
int min_neighbor_prop_delay; int min_neighbor_prop_delay;
int path_trace_enabled; int path_trace_enabled;
int rx_timestamp_offset; int rx_timestamp_offset;
@ -1223,6 +1224,12 @@ static int port_delay_request(struct port *p)
msg->header.control = CTL_DELAY_REQ; msg->header.control = CTL_DELAY_REQ;
msg->header.logMessageInterval = 0x7f; 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)) { if (port_prepare_and_send(p, msg, 1)) {
pr_err("port %hu: send delay request failed", portnum(p)); pr_err("port %hu: send delay request failed", portnum(p));
goto out; 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; 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); err = port_prepare_and_send(p, msg, 0);
if (err) if (err)
pr_err("port %hu: send delay response failed", portnum(p)); 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) { if (p->logMinDelayReqInterval == rsp->hdr.logMessageInterval) {
return; return;
} }
if (m->header.flagField[0] & UNICAST) {
/* Unicast responses have logMinDelayReqInterval set to 0x7F. */
return;
}
if (rsp->hdr.logMessageInterval < -10 || if (rsp->hdr.logMessageInterval < -10 ||
rsp->hdr.logMessageInterval > 22) { rsp->hdr.logMessageInterval > 22) {
pr_debug("port %hu: ignore bogus delay request interval 2^%d", 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)) if (msg_pre_send(msg))
return -1; 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) { if (cnt <= 0) {
return -1; return -1;
} }
@ -2550,6 +2571,7 @@ struct port *port_open(int phc_index,
p->asymmetry <<= 16; p->asymmetry <<= 16;
p->follow_up_info = config_get_int(cfg, p->name, "follow_up_info"); 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->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->path_trace_enabled = config_get_int(cfg, p->name, "path_trace_enabled");
p->rx_timestamp_offset = config_get_int(cfg, p->name, "ingressLatency"); p->rx_timestamp_offset = config_get_int(cfg, p->name, "ingressLatency");
p->tx_timestamp_offset = config_get_int(cfg, p->name, "egressLatency"); 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->delayMechanism = config_get_int(cfg, p->name, "delay_mechanism");
p->versionNumber = PTP_VERSION; 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 */ /* Set fault timeouts to a default value */
for (i = 0; i < FT_CNT; i++) { for (i = 0; i < FT_CNT; i++) {
p->flt_interval_pertype[i].type = FTMO_LOG2_SECONDS; p->flt_interval_pertype[i].type = FTMO_LOG2_SECONDS;

View File

@ -185,6 +185,15 @@ The default is 16 seconds.
Select the delay mechanism. Possible values are E2E, P2P and Auto. Select the delay mechanism. Possible values are E2E, P2P and Auto.
The default is E2E. The default is E2E.
.TP .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 .B ptp_dst_mac
The MAC address to which PTP messages should be sent. The MAC address to which PTP messages should be sent.
Relevant only with L2 transport. The default is 01:1B:19:00:00:00. Relevant only with L2 transport. The default is 01:1B:19:00:00:00.