Merge the hybrid E2E work.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
commit
776f772c36
|
@ -21,6 +21,7 @@
|
||||||
#define HAVE_ADDRESS_H
|
#define HAVE_ADDRESS_H
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <netpacket/packet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ struct address {
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
union {
|
union {
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
|
struct sockaddr_ll sll;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
|
|
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
|
||||||
|
|
53
port.c
53
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;
|
||||||
|
@ -163,10 +164,15 @@ static int msg_current(struct ptp_message *m, struct timespec now)
|
||||||
t1 = m->ts.host.tv_sec * NSEC2SEC + m->ts.host.tv_nsec;
|
t1 = m->ts.host.tv_sec * NSEC2SEC + m->ts.host.tv_nsec;
|
||||||
t2 = now.tv_sec * NSEC2SEC + now.tv_nsec;
|
t2 = now.tv_sec * NSEC2SEC + now.tv_nsec;
|
||||||
|
|
||||||
if (m->header.logMessageInterval < 0)
|
if (m->header.logMessageInterval < -63) {
|
||||||
|
tmo = 0;
|
||||||
|
} else if (m->header.logMessageInterval > 31) {
|
||||||
|
tmo = INT64_MAX;
|
||||||
|
} else if (m->header.logMessageInterval < 0) {
|
||||||
tmo = 4LL * NSEC2SEC / (1 << -m->header.logMessageInterval);
|
tmo = 4LL * NSEC2SEC / (1 << -m->header.logMessageInterval);
|
||||||
else
|
} else {
|
||||||
tmo = 4LL * (1 << m->header.logMessageInterval) * NSEC2SEC;
|
tmo = 4LL * (1 << m->header.logMessageInterval) * NSEC2SEC;
|
||||||
|
}
|
||||||
|
|
||||||
return t2 - t1 < tmo;
|
return t2 - t1 < tmo;
|
||||||
}
|
}
|
||||||
|
@ -1218,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;
|
||||||
|
@ -1625,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));
|
||||||
|
@ -1661,12 +1679,22 @@ static void process_delay_resp(struct port *p, struct ptp_message *m)
|
||||||
|
|
||||||
clock_path_delay(p->clock, t3, t4c);
|
clock_path_delay(p->clock, t3, t4c);
|
||||||
|
|
||||||
if (p->logMinDelayReqInterval != rsp->hdr.logMessageInterval) {
|
if (p->logMinDelayReqInterval == rsp->hdr.logMessageInterval) {
|
||||||
// TODO - validate the input.
|
return;
|
||||||
p->logMinDelayReqInterval = rsp->hdr.logMessageInterval;
|
|
||||||
pr_notice("port %hu: minimum delay request interval 2^%d",
|
|
||||||
portnum(p), p->logMinDelayReqInterval);
|
|
||||||
}
|
}
|
||||||
|
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",
|
||||||
|
portnum(p), rsp->hdr.logMessageInterval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->logMinDelayReqInterval = rsp->hdr.logMessageInterval;
|
||||||
|
pr_notice("port %hu: minimum delay request interval 2^%d",
|
||||||
|
portnum(p), p->logMinDelayReqInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_follow_up(struct port *p, struct ptp_message *m)
|
static void process_follow_up(struct port *p, struct ptp_message *m)
|
||||||
|
@ -2308,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;
|
||||||
}
|
}
|
||||||
|
@ -2539,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");
|
||||||
|
@ -2553,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.
|
||||||
|
|
9
raw.c
9
raw.c
|
@ -188,14 +188,15 @@ no_socket:
|
||||||
|
|
||||||
static void mac_to_addr(struct address *addr, void *mac)
|
static void mac_to_addr(struct address *addr, void *mac)
|
||||||
{
|
{
|
||||||
addr->sa.sa_family = AF_UNSPEC;
|
addr->sll.sll_family = AF_PACKET;
|
||||||
memcpy(&addr->sa.sa_data, mac, MAC_LEN);
|
addr->sll.sll_halen = MAC_LEN;
|
||||||
addr->len = sizeof(addr->sa.sa_family) + MAC_LEN;
|
memcpy(addr->sll.sll_addr, mac, MAC_LEN);
|
||||||
|
addr->len = sizeof(addr->sll);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addr_to_mac(void *mac, struct address *addr)
|
static void addr_to_mac(void *mac, struct address *addr)
|
||||||
{
|
{
|
||||||
memcpy(mac, &addr->sa.sa_data, MAC_LEN);
|
memcpy(mac, &addr->sll.sll_addr, MAC_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raw_open(struct transport *t, const char *name,
|
static int raw_open(struct transport *t, const char *name,
|
||||||
|
|
6
sk.c
6
sk.c
|
@ -170,8 +170,10 @@ int sk_interface_macaddr(const char *name, struct address *mac)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&mac->sa, &ifreq.ifr_hwaddr, sizeof(ifreq.ifr_hwaddr));
|
mac->sll.sll_family = AF_PACKET;
|
||||||
mac->len = sizeof(ifreq.ifr_hwaddr.sa_family) + MAC_LEN;
|
mac->sll.sll_halen = MAC_LEN;
|
||||||
|
memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN);
|
||||||
|
mac->len = sizeof(mac->sll);
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
6
udp.c
6
udp.c
|
@ -218,12 +218,12 @@ static int udp_send(struct transport *t, struct fdarray *fda, int event,
|
||||||
addr_buf.sin.sin_family = AF_INET;
|
addr_buf.sin.sin_family = AF_INET;
|
||||||
addr_buf.sin.sin_addr = peer ? mcast_addr[MC_PDELAY] :
|
addr_buf.sin.sin_addr = peer ? mcast_addr[MC_PDELAY] :
|
||||||
mcast_addr[MC_PRIMARY];
|
mcast_addr[MC_PRIMARY];
|
||||||
addr_buf.sin.sin_port = htons(event ? EVENT_PORT :
|
|
||||||
GENERAL_PORT);
|
|
||||||
addr_buf.len = sizeof(addr_buf.sin);
|
addr_buf.len = sizeof(addr_buf.sin);
|
||||||
addr = &addr_buf;
|
addr = &addr_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr->sin.sin_port = htons(event ? EVENT_PORT : GENERAL_PORT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extend the payload by two, for UDP checksum correction.
|
* Extend the payload by two, for UDP checksum correction.
|
||||||
* This is not really part of the standard, but it is the way
|
* This is not really part of the standard, but it is the way
|
||||||
|
@ -256,7 +256,7 @@ static int udp_physical_addr(struct transport *t, uint8_t *addr)
|
||||||
|
|
||||||
if (udp->mac.len) {
|
if (udp->mac.len) {
|
||||||
len = MAC_LEN;
|
len = MAC_LEN;
|
||||||
memcpy(addr, udp->mac.sa.sa_data, len);
|
memcpy(addr, udp->mac.sll.sll_addr, len);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
7
udp6.c
7
udp6.c
|
@ -229,9 +229,6 @@ static int udp6_send(struct transport *t, struct fdarray *fda, int event,
|
||||||
addr_buf.sin6.sin6_family = AF_INET6;
|
addr_buf.sin6.sin6_family = AF_INET6;
|
||||||
addr_buf.sin6.sin6_addr = peer ? mc6_addr[MC_PDELAY] :
|
addr_buf.sin6.sin6_addr = peer ? mc6_addr[MC_PDELAY] :
|
||||||
mc6_addr[MC_PRIMARY];
|
mc6_addr[MC_PRIMARY];
|
||||||
addr_buf.sin6.sin6_port = htons(event ? EVENT_PORT :
|
|
||||||
GENERAL_PORT);
|
|
||||||
|
|
||||||
if (is_link_local(&addr_buf.sin6.sin6_addr))
|
if (is_link_local(&addr_buf.sin6.sin6_addr))
|
||||||
addr_buf.sin6.sin6_scope_id = udp6->index;
|
addr_buf.sin6.sin6_scope_id = udp6->index;
|
||||||
|
|
||||||
|
@ -239,6 +236,8 @@ static int udp6_send(struct transport *t, struct fdarray *fda, int event,
|
||||||
addr = &addr_buf;
|
addr = &addr_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr->sin6.sin6_port = htons(event ? EVENT_PORT : GENERAL_PORT);
|
||||||
|
|
||||||
len += 2; /* Extend the payload by two, for UDP checksum corrections. */
|
len += 2; /* Extend the payload by two, for UDP checksum corrections. */
|
||||||
|
|
||||||
cnt = sendto(fd, buf, len, 0, &addr->sa, sizeof(addr->sin6));
|
cnt = sendto(fd, buf, len, 0, &addr->sa, sizeof(addr->sin6));
|
||||||
|
@ -265,7 +264,7 @@ static int udp6_physical_addr(struct transport *t, uint8_t *addr)
|
||||||
|
|
||||||
if (udp6->mac.len) {
|
if (udp6->mac.len) {
|
||||||
len = MAC_LEN;
|
len = MAC_LEN;
|
||||||
memcpy(addr, udp6->mac.sa.sa_data, len);
|
memcpy(addr, udp6->mac.sll.sll_addr, len);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
12
util.c
12
util.c
|
@ -134,14 +134,14 @@ int generate_clock_identity(struct ClockIdentity *ci, const char *name)
|
||||||
|
|
||||||
if (sk_interface_macaddr(name, &addr))
|
if (sk_interface_macaddr(name, &addr))
|
||||||
return -1;
|
return -1;
|
||||||
ci->id[0] = addr.sa.sa_data[0];
|
ci->id[0] = addr.sll.sll_addr[0];
|
||||||
ci->id[1] = addr.sa.sa_data[1];
|
ci->id[1] = addr.sll.sll_addr[1];
|
||||||
ci->id[2] = addr.sa.sa_data[2];
|
ci->id[2] = addr.sll.sll_addr[2];
|
||||||
ci->id[3] = 0xFF;
|
ci->id[3] = 0xFF;
|
||||||
ci->id[4] = 0xFE;
|
ci->id[4] = 0xFE;
|
||||||
ci->id[5] = addr.sa.sa_data[3];
|
ci->id[5] = addr.sll.sll_addr[3];
|
||||||
ci->id[6] = addr.sa.sa_data[4];
|
ci->id[6] = addr.sll.sll_addr[4];
|
||||||
ci->id[7] = addr.sa.sa_data[5];
|
ci->id[7] = addr.sll.sll_addr[5];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue