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
parent
d0eb73c87b
commit
e85cb68320
1
config.c
1
config.c
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
1
gPTP.cfg
1
gPTP.cfg
|
@ -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
|
||||||
|
|
26
port.c
26
port.c
|
@ -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;
|
||||||
|
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);
|
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;
|
||||||
|
|
9
ptp4l.8
9
ptp4l.8
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue