Merge the hybrid E2E work.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2015-09-05 21:40:48 +02:00
commit 776f772c36
11 changed files with 80 additions and 27 deletions

View File

@ -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;

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

47
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;
@ -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;
}
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; p->logMinDelayReqInterval = rsp->hdr.logMessageInterval;
pr_notice("port %hu: minimum delay request interval 2^%d", pr_notice("port %hu: minimum delay request interval 2^%d",
portnum(p), p->logMinDelayReqInterval); 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;
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;
} }
@ -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;

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.

9
raw.c
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;
} }