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
Vedang Patel 2019-03-28 20:32:28 -07:00 committed by Richard Cochran
parent 888afcdbae
commit 630ce719fc
6 changed files with 119 additions and 2 deletions

6
msg.h
View File

@ -57,6 +57,12 @@
#define TIME_TRACEABLE (1<<4)
#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 {
TS_SOFTWARE,
TS_HARDWARE,

6
port.c
View File

@ -1601,7 +1601,8 @@ int port_initialize(struct port *p)
p->last_fault_type = FT_UNSPECIFIED;
p->logMinDelayReqInterval = config_get_int(cfg, p->name, "logMinDelayReqInterval");
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->ignore_source_id = config_get_int(cfg, p->name, "ignore_source_id");
p->announceReceiptTimeout = config_get_int(cfg, p->name, "announceReceiptTimeout");
@ -1610,7 +1611,8 @@ int port_initialize(struct port *p)
p->transportSpecific <<= 4;
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->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->logPdelayReqInterval = p->logMinPdelayReqInterval;
p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh");

View File

@ -107,12 +107,14 @@ struct port {
enum as_capable asCapable;
Integer8 logMinDelayReqInterval;
TimeInterval peerMeanPathDelay;
Integer8 initialLogAnnounceInterval;
Integer8 logAnnounceInterval;
UInteger8 announceReceiptTimeout;
int announce_span;
UInteger8 syncReceiptTimeout;
UInteger8 transportSpecific;
UInteger8 localPriority;
Integer8 initialLogSyncInterval;
Integer8 logSyncInterval;
Enumeration8 delayMechanism;
Integer8 logMinPdelayReqInterval;
@ -174,6 +176,10 @@ struct ptp_message *port_signaling_uc_construct(struct port *p,
struct address *address,
struct PortIdentity *tpid);
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 process_announce(struct port *p, struct ptp_message *m);
void process_delay_resp(struct port *p, struct ptp_message *m);

View File

@ -17,7 +17,9 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
*/
#include "port.h"
#include "port_private.h"
#include "print.h"
#include "unicast_client.h"
#include "unicast_service.h"
@ -68,9 +70,43 @@ struct ptp_message *port_signaling_uc_construct(struct port *p,
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)
{
struct tlv_extra *extra;
struct msg_interval_req_tlv *r;
int err = 0, result;
switch (p->state) {
@ -122,7 +158,58 @@ int process_signaling(struct port *p, struct ptp_message *m)
case TLV_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION:
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;
}
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
View File

@ -517,6 +517,10 @@ static int org_post_recv(struct organization_tlv *org)
scaled_ns_n2h(&f->lastGmPhaseChange);
f->scaledLastGmPhaseChange = ntohl(f->scaledLastGmPhaseChange);
break;
case 2:
if (org->length + sizeof(struct TLV) != sizeof(struct msg_interval_req_tlv))
goto bad_length;
}
}
return 0;

12
tlv.h
View File

@ -230,6 +230,18 @@ struct follow_up_info_tlv {
Integer32 scaledLastGmPhaseChange;
} 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 {
int64_t master_offset; /*nanoseconds*/
int64_t ingress_time; /*nanoseconds*/