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. Signed-off-by: Vedang Patel <[email protected]> --- msg.h | 6 ++++ port.c | 2 ++ port_private.h | 7 ++++ port_signaling.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tlv.h | 12 +++++++ 5 files changed, 125 insertions(+) diff --git a/msg.h b/msg.h index b5a57fec6d2d..f04b9f42a30f 100644 --- a/msg.h +++ b/msg.h @@ -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, diff --git a/port.c b/port.c index 84de123db170..fb6fc4cbadee 100644 --- a/port.c +++ b/port.c @@ -1591,6 +1591,7 @@ int port_initialize(struct port *p) p->logMinDelayReqInterval = config_get_int(cfg, p->name, "logMinDelayReqInterval"); p->peerMeanPathDelay = 0; p->logAnnounceInterval = config_get_int(cfg, p->name, "logAnnounceInterval"); + p->initialLogAnnounceInterval = p->logAnnounceInterval; 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"); @@ -1600,6 +1601,7 @@ int port_initialize(struct port *p) 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 = p->logSyncInterval; p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval"); p->logPdelayReqInterval = p->logMinPdelayReqInterval; p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); diff --git a/port_private.h b/port_private.h index 026d4a1645a3..c8a6c8b6f4e8 100644 --- a/port_private.h +++ b/port_private.h @@ -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; @@ -187,5 +189,10 @@ void process_sync(struct port *p, struct ptp_message *m); int source_pid_eq(struct ptp_message *m1, struct ptp_message *m2); void ts_add(tmv_t *ts, Integer64 correction); int port_capable(struct port *p); +int port_tx_signaling(struct port *p, + Integer8 announceInterval, + Integer8 timeSyncInterval, + Integer8 linkDelayInterval); + #endif diff --git a/port_signaling.c b/port_signaling.c index 9fda84ed88a8..b32e045bf4b7 100644 --- a/port_signaling.c +++ b/port_signaling.c @@ -17,7 +17,11 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA. */ +#include <errno.h> + +#include "port.h" #include "port_private.h" +#include "print.h" #include "unicast_client.h" #include "unicast_service.h" @@ -61,6 +65,48 @@ struct ptp_message *port_unicast_construct(struct port *p, return msg; } +static void set_interval(int8_t *current_interval, + int8_t new_interval, + int8_t initial_interval) +{ + switch (new_interval) { + case SIGNAL_NO_CHANGE: + break; + case SIGNAL_SET_INITIAL: + *current_interval = initial_interval; + break; + default: + *current_interval = new_interval; + break; + } +} + +static int process_interval_request(struct port *p, + struct tlv_extra *extra) +{ + struct msg_interval_req_tlv *r; + + r = (struct msg_interval_req_tlv *) extra->tlv; + + if (r->subtype[2] != 2) { + return -EBADMSG; + } + + set_interval(&p->logAnnounceInterval, + r->announceInterval, + p->initialLogAnnounceInterval); + + set_interval(&p->logSyncInterval, + r->timeSyncInterval, + p->initialLogSyncInterval); + + set_interval(&p->logPdelayReqInterval, + r->linkDelayInterval, + p->logMinPdelayReqInterval); + + return 0; +} + int process_signaling(struct port *p, struct ptp_message *m) { struct tlv_extra *extra; @@ -109,7 +155,59 @@ int process_signaling(struct port *p, struct ptp_message *m) case TLV_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION: break; + + case TLV_ORGANIZATION_EXTENSION: + err = process_interval_request(p, extra); + break; } } return err; } + +int port_tx_signaling(struct port *p, + Integer8 announceInterval, + Integer8 timeSyncInterval, + Integer8 linkDelayInterval) +{ + int err; + struct ptp_message *msg; + struct tlv_extra *extra; + struct msg_interval_req_tlv *mir; + struct PortIdentity tpid = {0}; + + tpid.portNumber = 0xFF; + + if (!port_capable(p)) { + return 0; + } + + 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; +} diff --git a/tlv.h b/tlv.h index 958555c4e280..bcbfdd9a1fde 100644 --- a/tlv.h +++ b/tlv.h @@ -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*/ -- 2.7.3 _______________________________________________ Linuxptp-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
