port: implement message interval request processing
This implements transmission and receipt of message interval requests. Using this mechanism, a time-aware device can request change in sync, link delay and announce intervals on the device connected on the other end. As part of the commit, we are also saving the initial values of Announce and Sync Interval. For more information look at sections 10.2.4.4, 10.3.9.5, 10.3.14, 10.4, 10.5.4 and 11.2.17 of 802.1AS standard Please note that this commit does not implement logic related to computeNeighborRateRatio and computeNeighborPropDelay flags mentioned in Section 10.5.4.3.9 of 802.1AS Standard. [ RC - memset the targetPortIdentity to all ones. ] Signed-off-by: Vedang Patel <vedang.patel@intel.com> Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
888afcdbae
commit
630ce719fc
6
msg.h
6
msg.h
|
@ -57,6 +57,12 @@
|
||||||
#define TIME_TRACEABLE (1<<4)
|
#define TIME_TRACEABLE (1<<4)
|
||||||
#define FREQ_TRACEABLE (1<<5)
|
#define FREQ_TRACEABLE (1<<5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signaling interval special values. For more info look at 802.1AS table 10-11
|
||||||
|
*/
|
||||||
|
#define SIGNAL_NO_CHANGE -128
|
||||||
|
#define SIGNAL_SET_INITIAL 126
|
||||||
|
|
||||||
enum timestamp_type {
|
enum timestamp_type {
|
||||||
TS_SOFTWARE,
|
TS_SOFTWARE,
|
||||||
TS_HARDWARE,
|
TS_HARDWARE,
|
||||||
|
|
6
port.c
6
port.c
|
@ -1601,7 +1601,8 @@ int port_initialize(struct port *p)
|
||||||
p->last_fault_type = FT_UNSPECIFIED;
|
p->last_fault_type = FT_UNSPECIFIED;
|
||||||
p->logMinDelayReqInterval = config_get_int(cfg, p->name, "logMinDelayReqInterval");
|
p->logMinDelayReqInterval = config_get_int(cfg, p->name, "logMinDelayReqInterval");
|
||||||
p->peerMeanPathDelay = 0;
|
p->peerMeanPathDelay = 0;
|
||||||
p->logAnnounceInterval = config_get_int(cfg, p->name, "logAnnounceInterval");
|
p->initialLogAnnounceInterval = config_get_int(cfg, p->name, "logAnnounceInterval");
|
||||||
|
p->logAnnounceInterval = p->initialLogAnnounceInterval;
|
||||||
p->inhibit_announce = config_get_int(cfg, p->name, "inhibit_announce");
|
p->inhibit_announce = config_get_int(cfg, p->name, "inhibit_announce");
|
||||||
p->ignore_source_id = config_get_int(cfg, p->name, "ignore_source_id");
|
p->ignore_source_id = config_get_int(cfg, p->name, "ignore_source_id");
|
||||||
p->announceReceiptTimeout = config_get_int(cfg, p->name, "announceReceiptTimeout");
|
p->announceReceiptTimeout = config_get_int(cfg, p->name, "announceReceiptTimeout");
|
||||||
|
@ -1610,7 +1611,8 @@ int port_initialize(struct port *p)
|
||||||
p->transportSpecific <<= 4;
|
p->transportSpecific <<= 4;
|
||||||
p->match_transport_specific = !config_get_int(cfg, p->name, "ignore_transport_specific");
|
p->match_transport_specific = !config_get_int(cfg, p->name, "ignore_transport_specific");
|
||||||
p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority");
|
p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority");
|
||||||
p->logSyncInterval = config_get_int(cfg, p->name, "logSyncInterval");
|
p->initialLogSyncInterval = config_get_int(cfg, p->name, "logSyncInterval");
|
||||||
|
p->logSyncInterval = p->initialLogSyncInterval;
|
||||||
p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval");
|
p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval");
|
||||||
p->logPdelayReqInterval = p->logMinPdelayReqInterval;
|
p->logPdelayReqInterval = p->logMinPdelayReqInterval;
|
||||||
p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh");
|
p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh");
|
||||||
|
|
|
@ -107,12 +107,14 @@ struct port {
|
||||||
enum as_capable asCapable;
|
enum as_capable asCapable;
|
||||||
Integer8 logMinDelayReqInterval;
|
Integer8 logMinDelayReqInterval;
|
||||||
TimeInterval peerMeanPathDelay;
|
TimeInterval peerMeanPathDelay;
|
||||||
|
Integer8 initialLogAnnounceInterval;
|
||||||
Integer8 logAnnounceInterval;
|
Integer8 logAnnounceInterval;
|
||||||
UInteger8 announceReceiptTimeout;
|
UInteger8 announceReceiptTimeout;
|
||||||
int announce_span;
|
int announce_span;
|
||||||
UInteger8 syncReceiptTimeout;
|
UInteger8 syncReceiptTimeout;
|
||||||
UInteger8 transportSpecific;
|
UInteger8 transportSpecific;
|
||||||
UInteger8 localPriority;
|
UInteger8 localPriority;
|
||||||
|
Integer8 initialLogSyncInterval;
|
||||||
Integer8 logSyncInterval;
|
Integer8 logSyncInterval;
|
||||||
Enumeration8 delayMechanism;
|
Enumeration8 delayMechanism;
|
||||||
Integer8 logMinPdelayReqInterval;
|
Integer8 logMinPdelayReqInterval;
|
||||||
|
@ -174,6 +176,10 @@ struct ptp_message *port_signaling_uc_construct(struct port *p,
|
||||||
struct address *address,
|
struct address *address,
|
||||||
struct PortIdentity *tpid);
|
struct PortIdentity *tpid);
|
||||||
int port_tx_announce(struct port *p, struct address *dst);
|
int port_tx_announce(struct port *p, struct address *dst);
|
||||||
|
int port_tx_interval_request(struct port *p,
|
||||||
|
Integer8 announceInterval,
|
||||||
|
Integer8 timeSyncInterval,
|
||||||
|
Integer8 linkDelayInterval);
|
||||||
int port_tx_sync(struct port *p, struct address *dst);
|
int port_tx_sync(struct port *p, struct address *dst);
|
||||||
int process_announce(struct port *p, struct ptp_message *m);
|
int process_announce(struct port *p, struct ptp_message *m);
|
||||||
void process_delay_resp(struct port *p, struct ptp_message *m);
|
void process_delay_resp(struct port *p, struct ptp_message *m);
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
|
||||||
*/
|
*/
|
||||||
|
#include "port.h"
|
||||||
#include "port_private.h"
|
#include "port_private.h"
|
||||||
|
#include "print.h"
|
||||||
#include "unicast_client.h"
|
#include "unicast_client.h"
|
||||||
#include "unicast_service.h"
|
#include "unicast_service.h"
|
||||||
|
|
||||||
|
@ -68,9 +70,43 @@ struct ptp_message *port_signaling_uc_construct(struct port *p,
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int8_t set_interval(int8_t current_interval,
|
||||||
|
int8_t new_interval,
|
||||||
|
int8_t initial_interval)
|
||||||
|
{
|
||||||
|
switch (new_interval) {
|
||||||
|
case SIGNAL_NO_CHANGE:
|
||||||
|
return current_interval;
|
||||||
|
case SIGNAL_SET_INITIAL:
|
||||||
|
return initial_interval;
|
||||||
|
default:
|
||||||
|
return new_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_interval_request(struct port *p,
|
||||||
|
struct msg_interval_req_tlv *r)
|
||||||
|
{
|
||||||
|
|
||||||
|
p->logAnnounceInterval = set_interval(p->logAnnounceInterval,
|
||||||
|
r->announceInterval,
|
||||||
|
p->initialLogAnnounceInterval);
|
||||||
|
|
||||||
|
p->logSyncInterval = set_interval(p->logSyncInterval,
|
||||||
|
r->timeSyncInterval,
|
||||||
|
p->initialLogSyncInterval);
|
||||||
|
|
||||||
|
p->logPdelayReqInterval = set_interval(p->logPdelayReqInterval,
|
||||||
|
r->linkDelayInterval,
|
||||||
|
p->logMinPdelayReqInterval);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int process_signaling(struct port *p, struct ptp_message *m)
|
int process_signaling(struct port *p, struct ptp_message *m)
|
||||||
{
|
{
|
||||||
struct tlv_extra *extra;
|
struct tlv_extra *extra;
|
||||||
|
struct msg_interval_req_tlv *r;
|
||||||
int err = 0, result;
|
int err = 0, result;
|
||||||
|
|
||||||
switch (p->state) {
|
switch (p->state) {
|
||||||
|
@ -122,7 +158,58 @@ int process_signaling(struct port *p, struct ptp_message *m)
|
||||||
|
|
||||||
case TLV_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION:
|
case TLV_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TLV_ORGANIZATION_EXTENSION:
|
||||||
|
r = (struct msg_interval_req_tlv *) extra->tlv;
|
||||||
|
|
||||||
|
if (0 == memcmp(r->id, ieee8021_id, sizeof(ieee8021_id)) &&
|
||||||
|
r->subtype[0] == 0 && r->subtype[1] == 0 && r->subtype[2] == 2)
|
||||||
|
err = process_interval_request(p, r);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int port_tx_interval_request(struct port *p,
|
||||||
|
Integer8 announceInterval,
|
||||||
|
Integer8 timeSyncInterval,
|
||||||
|
Integer8 linkDelayInterval)
|
||||||
|
{
|
||||||
|
struct msg_interval_req_tlv *mir;
|
||||||
|
struct PortIdentity tpid;
|
||||||
|
struct ptp_message *msg;
|
||||||
|
struct tlv_extra *extra;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!port_capable(p)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(&tpid, 0xff, sizeof(tpid));
|
||||||
|
msg = port_signaling_construct(p, &tpid);
|
||||||
|
if (!msg) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
extra = msg_tlv_append(msg, sizeof(*mir));
|
||||||
|
if (!extra) {
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
mir = (struct msg_interval_req_tlv *) extra->tlv;
|
||||||
|
mir->type = TLV_ORGANIZATION_EXTENSION;
|
||||||
|
mir->length = sizeof(*mir) - sizeof(mir->type) - sizeof(mir->length);
|
||||||
|
memcpy(mir->id, ieee8021_id, sizeof(ieee8021_id));
|
||||||
|
mir->subtype[2] = 2;
|
||||||
|
mir->timeSyncInterval = timeSyncInterval;
|
||||||
|
mir->announceInterval = announceInterval;
|
||||||
|
mir->linkDelayInterval = linkDelayInterval;
|
||||||
|
mir->flags = 0;
|
||||||
|
|
||||||
|
err = port_prepare_and_send(p, msg, TRANS_GENERAL);
|
||||||
|
if (err) {
|
||||||
|
pr_err("port %hu: send signaling failed", portnum(p));
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
msg_put(msg);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
4
tlv.c
4
tlv.c
|
@ -517,6 +517,10 @@ static int org_post_recv(struct organization_tlv *org)
|
||||||
scaled_ns_n2h(&f->lastGmPhaseChange);
|
scaled_ns_n2h(&f->lastGmPhaseChange);
|
||||||
f->scaledLastGmPhaseChange = ntohl(f->scaledLastGmPhaseChange);
|
f->scaledLastGmPhaseChange = ntohl(f->scaledLastGmPhaseChange);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
if (org->length + sizeof(struct TLV) != sizeof(struct msg_interval_req_tlv))
|
||||||
|
goto bad_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
12
tlv.h
12
tlv.h
|
@ -230,6 +230,18 @@ struct follow_up_info_tlv {
|
||||||
Integer32 scaledLastGmPhaseChange;
|
Integer32 scaledLastGmPhaseChange;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
|
struct msg_interval_req_tlv {
|
||||||
|
Enumeration16 type;
|
||||||
|
UInteger16 length;
|
||||||
|
Octet id[3];
|
||||||
|
Octet subtype[3];
|
||||||
|
Integer8 linkDelayInterval;
|
||||||
|
Integer8 timeSyncInterval;
|
||||||
|
Integer8 announceInterval;
|
||||||
|
Octet flags;
|
||||||
|
Octet reserved[2];
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
struct time_status_np {
|
struct time_status_np {
|
||||||
int64_t master_offset; /*nanoseconds*/
|
int64_t master_offset; /*nanoseconds*/
|
||||||
int64_t ingress_time; /*nanoseconds*/
|
int64_t ingress_time; /*nanoseconds*/
|
||||||
|
|
Loading…
Reference in New Issue