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.