Merge the hybrid E2E work.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
commit
776f772c36
|
@ -21,6 +21,7 @@
|
|||
#define HAVE_ADDRESS_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
|
@ -28,6 +29,7 @@ struct address {
|
|||
socklen_t len;
|
||||
union {
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr_ll sll;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
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),
|
||||
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),
|
||||
|
|
|
@ -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
|
||||
|
|
1
gPTP.cfg
1
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
|
||||
|
|
47
port.c
47
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;
|
||||
|
@ -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;
|
||||
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);
|
||||
else
|
||||
} else {
|
||||
tmo = 4LL * (1 << m->header.logMessageInterval) * NSEC2SEC;
|
||||
}
|
||||
|
||||
return t2 - t1 < tmo;
|
||||
}
|
||||
|
@ -1218,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;
|
||||
|
@ -1625,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));
|
||||
|
@ -1661,13 +1679,23 @@ static void process_delay_resp(struct port *p, struct ptp_message *m)
|
|||
|
||||
clock_path_delay(p->clock, t3, t4c);
|
||||
|
||||
if (p->logMinDelayReqInterval != rsp->hdr.logMessageInterval) {
|
||||
// TODO - validate the input.
|
||||
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",
|
||||
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)
|
||||
{
|
||||
|
@ -2308,7 +2336,11 @@ int port_prepare_and_send(struct port *p, struct ptp_message *msg, int event)
|
|||
|
||||
if (msg_pre_send(msg))
|
||||
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);
|
||||
}
|
||||
if (cnt <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -2539,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");
|
||||
|
@ -2553,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;
|
||||
|
|
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.
|
||||
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.
|
||||
|
|
9
raw.c
9
raw.c
|
@ -188,14 +188,15 @@ no_socket:
|
|||
|
||||
static void mac_to_addr(struct address *addr, void *mac)
|
||||
{
|
||||
addr->sa.sa_family = AF_UNSPEC;
|
||||
memcpy(&addr->sa.sa_data, mac, MAC_LEN);
|
||||
addr->len = sizeof(addr->sa.sa_family) + MAC_LEN;
|
||||
addr->sll.sll_family = AF_PACKET;
|
||||
addr->sll.sll_halen = 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)
|
||||
{
|
||||
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,
|
||||
|
|
6
sk.c
6
sk.c
|
@ -170,8 +170,10 @@ int sk_interface_macaddr(const char *name, struct address *mac)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&mac->sa, &ifreq.ifr_hwaddr, sizeof(ifreq.ifr_hwaddr));
|
||||
mac->len = sizeof(ifreq.ifr_hwaddr.sa_family) + MAC_LEN;
|
||||
mac->sll.sll_family = AF_PACKET;
|
||||
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);
|
||||
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_addr = peer ? mcast_addr[MC_PDELAY] :
|
||||
mcast_addr[MC_PRIMARY];
|
||||
addr_buf.sin.sin_port = htons(event ? EVENT_PORT :
|
||||
GENERAL_PORT);
|
||||
addr_buf.len = sizeof(addr_buf.sin);
|
||||
addr = &addr_buf;
|
||||
}
|
||||
|
||||
addr->sin.sin_port = htons(event ? EVENT_PORT : GENERAL_PORT);
|
||||
|
||||
/*
|
||||
* Extend the payload by two, for UDP checksum correction.
|
||||
* 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) {
|
||||
len = MAC_LEN;
|
||||
memcpy(addr, udp->mac.sa.sa_data, len);
|
||||
memcpy(addr, udp->mac.sll.sll_addr, 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_addr = peer ? mc6_addr[MC_PDELAY] :
|
||||
mc6_addr[MC_PRIMARY];
|
||||
addr_buf.sin6.sin6_port = htons(event ? EVENT_PORT :
|
||||
GENERAL_PORT);
|
||||
|
||||
if (is_link_local(&addr_buf.sin6.sin6_addr))
|
||||
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->sin6.sin6_port = htons(event ? EVENT_PORT : GENERAL_PORT);
|
||||
|
||||
len += 2; /* Extend the payload by two, for UDP checksum corrections. */
|
||||
|
||||
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) {
|
||||
len = MAC_LEN;
|
||||
memcpy(addr, udp6->mac.sa.sa_data, len);
|
||||
memcpy(addr, udp6->mac.sll.sll_addr, 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))
|
||||
return -1;
|
||||
ci->id[0] = addr.sa.sa_data[0];
|
||||
ci->id[1] = addr.sa.sa_data[1];
|
||||
ci->id[2] = addr.sa.sa_data[2];
|
||||
ci->id[0] = addr.sll.sll_addr[0];
|
||||
ci->id[1] = addr.sll.sll_addr[1];
|
||||
ci->id[2] = addr.sll.sll_addr[2];
|
||||
ci->id[3] = 0xFF;
|
||||
ci->id[4] = 0xFE;
|
||||
ci->id[5] = addr.sa.sa_data[3];
|
||||
ci->id[6] = addr.sa.sa_data[4];
|
||||
ci->id[7] = addr.sa.sa_data[5];
|
||||
ci->id[5] = addr.sll.sll_addr[3];
|
||||
ci->id[6] = addr.sll.sll_addr[4];
|
||||
ci->id[7] = addr.sll.sll_addr[5];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue