Thread: [Linuxptp-devel] [PATCH v1 0/7] Support for Automotive Profile (Part II)
PTP IEEE 1588 stack for Linux
Brought to you by:
rcochran
From: Vedang P. <ved...@in...> - 2018-10-05 23:25:29
|
This series is the continuation of the automotive series posted at [1]. Following are the main changes this series makes: - Provide a mechanism to save the initial values of Sync and Announce intervals. - Implement “Message Interval Request” support for linuxptp described as part of 10.5.4 in 802.1AS[2]. - Use the interval request mechanism for slave to request a change the interval of Sync messages to operLogSyncInterval. Signaling message will be sent to the master after the interval update timer expires. The timer is setup when the first Sync Message is received by slave. More information for this in sections 6.2.1.6, 6.2.3.1 and 6.2.4 of AVnu Automotive Profile[3]. - The timer expiration also sets the pdelay request interval to operPdelayReqInterval on slave. This adds functionality mentioned in Sections 6.2.1.5 and 6.2.3.2. - Add a flag to inhibit delay requests. This will be used by the master in the automotive network because master devices do not need to send pdelay request messages. Thanks, Vedang Patel [1]- https://sourceforge.net/p/linuxptp/mailman/message/36431575/ [2]- IEEE 802.1AS Standard: https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5741898&tag=1 [3]- Automotive Ethernet AVB Functional and Interoperability Specification - http://avnu.org/wp-content/uploads/2014/05/ Automotive-Ethernet-AVB-Func-Interop-Spec-v1.5-Public.pdf Vedang Patel (7): port: Make port_capable() accessible outside port.c port: Split port_signaling_construct() to support Interval Request port: Add logPdelayReqInterval. port: implement message interval request processing port: Add ignore_update_interval_req. port: Add interval update timer. port: Add inhibit_delay_req. config.c | 5 ++ configs/automotive-master.cfg | 1 + configs/automotive-slave.cfg | 4 ++ configs/default.cfg | 4 ++ fd.h | 3 +- msg.h | 6 +++ port.c | 55 ++++++++++++++++++-- port_private.h | 20 ++++++- port_signaling.c | 118 +++++++++++++++++++++++++++++++++++++++++- ptp4l.8 | 32 ++++++++++++ tlv.h | 12 +++++ unicast_client.c | 14 ++--- unicast_service.c | 4 +- 13 files changed, 261 insertions(+), 17 deletions(-) -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:51:58
|
The changes from the last version are as follows: - Refactoring servo_sample to make it more readable with the new code. - Change port_unicast_construct() to port_signaling_uc_construct(). - Other changes to config.c (reordering the config options to be alphabetical), missed checks for signaling and offset checking code. More information about the series is in the original cover letter at: https://sourceforge.net/p/linuxptp/mailman/message/36433837/ Thanks, Vedang Vedang Patel (7): port: Make port_capable() accessible outside port.c port: Separate unicast specific code from port_signaling_construct() port: Add logPdelayReqInterval. port: implement message interval request processing clock: add APIs to access servo and servo_state port: Add interval update mechanism. port: Add inhibit_delay_req. clock.c | 11 ++++ clock.h | 14 ++++++ config.c | 7 ++- configs/automotive-master.cfg | 1 + configs/automotive-slave.cfg | 4 ++ configs/default.cfg | 5 ++ msg.h | 6 +++ phc2sys.c | 1 + port.c | 46 ++++++++++++++--- port_private.h | 17 +++++-- port_signaling.c | 113 ++++++++++++++++++++++++++++++++++++++++-- ptp4l.8 | 35 +++++++++++++ servo.c | 31 +++++++++++- servo.h | 6 +++ servo_private.h | 3 ++ tlv.c | 4 ++ tlv.h | 12 +++++ unicast_client.c | 14 +++--- unicast_service.c | 4 +- 19 files changed, 309 insertions(+), 25 deletions(-) -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:00
|
Make sure port_capable() can be accessed by the signaling construct in port_signaling.c Signed-off-by: Vedang Patel <ved...@in...> Change-Id: I8be15fd8dabfd7938eb6f7dbbc1dd6ea5abee751 --- port.c | 3 +-- port_private.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/port.c b/port.c index ad9554f02a49..336b14424ed0 100644 --- a/port.c +++ b/port.c @@ -55,7 +55,6 @@ enum syfu_event { FUP_MATCH, }; -static int port_capable(struct port *p); static int port_is_ieee8021as(struct port *p); static void port_nrate_initialize(struct port *p); @@ -602,7 +601,7 @@ static int peer_prepare_and_send(struct port *p, struct ptp_message *msg, return 0; } -static int port_capable(struct port *p) +int port_capable(struct port *p) { if (!port_is_ieee8021as(p)) { /* Normal 1588 ports are always capable. */ diff --git a/port_private.h b/port_private.h index 593eb76fbe48..b0b2a5dcde09 100644 --- a/port_private.h +++ b/port_private.h @@ -157,6 +157,7 @@ void delay_req_prune(struct port *p); void fc_clear(struct foreign_clock *fc); void flush_delay_req(struct port *p); void flush_last_sync(struct port *p); +int port_capable(struct port *p); int port_clr_tmo(int fd); int port_delay_request(struct port *p); void port_disable(struct port *p); -- 2.7.3 |
[Linuxptp-devel] [PATCH v4 2/7] port: Separate unicast specific
code from port_signaling_construct()
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:02
|
Make port_signaling_construct() to create a generic signaling ptp_message. Move the unicast specific code to port_signaling_uc_construct(). This is done to support the creation of Message Interval Request TLV (as defined in 802.1AS Section 10.5.4.3). This TLV can be used to request change in Announce Interval, Sync Interval or Link Delay Interval on a remote system. Signed-off-by: Vedang Patel <ved...@in...> Change-Id: Ie0675cd2fd43e8a7a08c8a7d20b37c68c7919b84 --- port_private.h | 6 +++--- port_signaling.c | 20 +++++++++++++++++--- unicast_client.c | 10 +++++----- unicast_service.c | 4 ++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/port_private.h b/port_private.h index b0b2a5dcde09..1bc1c3f5f33d 100644 --- a/port_private.h +++ b/port_private.h @@ -169,9 +169,9 @@ int port_set_delay_tmo(struct port *p); int port_set_qualification_tmo(struct port *p); void port_show_transition(struct port *p, enum port_state next, enum fsm_event event); -struct ptp_message *port_signaling_construct(struct port *p, - struct address *address, - struct PortIdentity *tpid); +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_sync(struct port *p, struct address *dst); int process_announce(struct port *p, struct ptp_message *m); diff --git a/port_signaling.c b/port_signaling.c index f845d36f6e61..69a1ad414204 100644 --- a/port_signaling.c +++ b/port_signaling.c @@ -21,9 +21,8 @@ #include "unicast_client.h" #include "unicast_service.h" -struct ptp_message *port_signaling_construct(struct port *p, - struct address *address, - struct PortIdentity *tpid) +static struct ptp_message *port_signaling_construct(struct port *p, + struct PortIdentity *tpid) { struct ptp_message *msg; @@ -41,6 +40,21 @@ struct ptp_message *port_signaling_construct(struct port *p, msg->header.control = CTL_OTHER; msg->header.logMessageInterval = 0x7F; msg->signaling.targetPortIdentity = *tpid; + + return msg; +} + +struct ptp_message *port_signaling_uc_construct(struct port *p, + struct address *address, + struct PortIdentity *tpid) +{ + struct ptp_message *msg; + + msg = port_signaling_construct(p, tpid); + if (!msg) { + return NULL; + } + msg->header.flagField[0] |= UNICAST; msg->address = *address; diff --git a/unicast_client.c b/unicast_client.c index de5eee9f4574..337765a19f17 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -75,7 +75,7 @@ static int unicast_client_announce(struct port *p, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -140,7 +140,7 @@ static int unicast_client_peer_renew(struct port *p) peer->renewal_tmo = 0; pr_debug("port %d: time to renew P2P unicast subscription", portnum(p)); - msg = port_signaling_construct(p, &peer->address, &peer->portIdentity); + msg = port_signaling_uc_construct(p, &peer->address, &peer->portIdentity); if (!msg) { return -1; } @@ -176,7 +176,7 @@ static int unicast_client_renew(struct port *p, dst->renewal_tmo = 0; pr_debug("port %d: time to renew unicast subscriptions", portnum(p)); - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -236,7 +236,7 @@ static int unicast_client_sydy(struct port *p, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -296,7 +296,7 @@ int unicast_client_cancel(struct port *p, struct ptp_message *m, ucma->granted &= ~(1 << mtype); /* Respond with ACK. */ - msg = port_signaling_construct(p, &ucma->address, &ucma->portIdentity); + msg = port_signaling_uc_construct(p, &ucma->address, &ucma->portIdentity); if (!msg) { return -1; } diff --git a/unicast_service.c b/unicast_service.c index 9c9b95b05187..ec5ee6ca2fff 100644 --- a/unicast_service.c +++ b/unicast_service.c @@ -241,8 +241,8 @@ static int unicast_service_reply(struct port *p, struct ptp_message *dst, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, - &dst->header.sourcePortIdentity); + msg = port_signaling_uc_construct(p, &dst->address, + &dst->header.sourcePortIdentity); if (!msg) { return -1; } -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:04
|
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 <ved...@in...> Change-Id: I8ca0ce8c34dd70592027b4ced37298b2160ee3eb --- msg.h | 6 ++++ port.c | 6 ++-- port_private.h | 6 ++++ port_signaling.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tlv.c | 4 +++ tlv.h | 12 ++++++++ 6 files changed, 125 insertions(+), 2 deletions(-) diff --git a/msg.h b/msg.h index 02e45fd9f490..c1294c23f6c3 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 ff2f10db4ebc..6512c43b7896 100644 --- a/port.c +++ b/port.c @@ -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"); diff --git a/port_private.h b/port_private.h index 37dc4b3db777..d28ab0712798 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; @@ -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); diff --git a/port_signaling.c b/port_signaling.c index 69a1ad414204..1b89338d4a11 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,9 +65,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) { @@ -109,7 +147,62 @@ 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.clockIdentity, 0, sizeof(tpid.clockIdentity)); + tpid.portNumber = 0xFF; + + 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.c b/tlv.c index b647160ac9eb..6a5387ea8083 100644 --- a/tlv.c +++ b/tlv.c @@ -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; 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 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:03
|
It will be used to store the current value of Pdelay Request Interval. It will be represented as power of two in seconds. Signed-off-by: Vedang Patel <ved...@in...> Change-Id: I0469d166b41d416f32d1823de54641dbed74eb1a --- port.c | 7 ++++--- port_private.h | 1 + unicast_client.c | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/port.c b/port.c index 336b14424ed0..ff2f10db4ebc 100644 --- a/port.c +++ b/port.c @@ -1025,7 +1025,7 @@ static void port_nrate_calculate(struct port *p, tmv_t origin, tmv_t ingress) static void port_nrate_initialize(struct port *p) { - int shift = p->freq_est_interval - p->logMinPdelayReqInterval; + int shift = p->freq_est_interval - p->logPdelayReqInterval; if (shift < 0) shift = 0; @@ -1058,7 +1058,7 @@ int port_set_delay_tmo(struct port *p) { if (p->delayMechanism == DM_P2P) { return set_tmo_log(p->fda.fd[FD_DELAY_TIMER], 1, - p->logMinPdelayReqInterval); + p->logPdelayReqInterval); } else { return set_tmo_random(p->fda.fd[FD_DELAY_TIMER], 0, 2, p->logMinDelayReqInterval); @@ -1254,7 +1254,7 @@ static int port_pdelay_request(struct port *p) msg->header.sequenceId = p->seqnum.delayreq++; msg->header.control = CTL_OTHER; msg->header.logMessageInterval = port_is_ieee8021as(p) ? - p->logMinPdelayReqInterval : 0x7f; + p->logPdelayReqInterval : 0x7f; if (unicast_client_enabled(p) && p->unicast_master_table->peer_name) { msg->address = p->unicast_master_table->peer_addr.address; @@ -1612,6 +1612,7 @@ int port_initialize(struct port *p) p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority"); p->logSyncInterval = config_get_int(cfg, p->name, "logSyncInterval"); p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval"); + p->logPdelayReqInterval = p->logMinPdelayReqInterval; p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); diff --git a/port_private.h b/port_private.h index 1bc1c3f5f33d..37dc4b3db777 100644 --- a/port_private.h +++ b/port_private.h @@ -116,6 +116,7 @@ struct port { Integer8 logSyncInterval; Enumeration8 delayMechanism; Integer8 logMinPdelayReqInterval; + Integer8 logPdelayReqInterval; UInteger32 neighborPropDelayThresh; int follow_up_info; int freq_est_interval; diff --git a/unicast_client.c b/unicast_client.c index 337765a19f17..e3523530f432 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -144,7 +144,7 @@ static int unicast_client_peer_renew(struct port *p) if (!msg) { return -1; } - err = attach_request(msg, p->logMinPdelayReqInterval, PDELAY_RESP, + err = attach_request(msg, p->logPdelayReqInterval, PDELAY_RESP, p->unicast_req_duration); if (err) { goto out; @@ -403,7 +403,7 @@ void unicast_client_grant(struct port *p, struct ptp_message *m, unicast_client_set_renewal(p, &p->unicast_master_table->peer_addr, g->durationField); - p->logMinPdelayReqInterval = g->logInterMessagePeriod; + p->logPdelayReqInterval = g->logInterMessagePeriod; return; default: break; -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:05
|
Add provision to disable delay requests. Designated masters who do not need to calculate pdelay can use this option. This is required by Automotive Profile to reduce network load. Change-Id: Iba4dbc4f6243f9e895393a1a20a5328ea89b5a36 Signed-off-by: Vedang Patel <ved...@in...> --- config.c | 3 ++- configs/automotive-master.cfg | 1 + configs/default.cfg | 1 + port.c | 10 ++++++++++ port_private.h | 1 + ptp4l.8 | 5 +++++ 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/config.c b/config.c index 0da7ce462c21..93ea5da0edf3 100644 --- a/config.c +++ b/config.c @@ -244,8 +244,9 @@ struct config_item config_tab[] = { PORT_ITEM_INT("ignore_transport_specific", 0, 0, 1), PORT_ITEM_INT("ingressLatency", 0, INT_MIN, INT_MAX), PORT_ITEM_INT("inhibit_announce", 0, 0, 1), - PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("initial_delay", 0, 0, INT_MAX), + PORT_ITEM_INT("inhibit_delay_req", 0, 0, 1), + PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), PORT_ITEM_INT("logMinDelayReqInterval", 0, INT8_MIN, INT8_MAX), diff --git a/configs/automotive-master.cfg b/configs/automotive-master.cfg index e3ad5a35ebe2..2edee7666877 100644 --- a/configs/automotive-master.cfg +++ b/configs/automotive-master.cfg @@ -26,3 +26,4 @@ BMCA noop masterOnly 1 inhibit_announce 1 asCapable true +inhibit_delay_req 1 diff --git a/configs/default.cfg b/configs/default.cfg index 243355357829..e23dfd7c60f8 100644 --- a/configs/default.cfg +++ b/configs/default.cfg @@ -37,6 +37,7 @@ G.8275.portDS.localPriority 128 asCapable auto BMCA ptp inhibit_announce 0 +inhibit_pdelay_req 0 ignore_source_id 0 # # Run time options diff --git a/port.c b/port.c index 373bc886eb27..0816ad2f4ac0 100644 --- a/port.c +++ b/port.c @@ -1056,6 +1056,10 @@ int port_set_announce_tmo(struct port *p) int port_set_delay_tmo(struct port *p) { + if (p->inhibit_delay_req) { + return 0; + } + if (p->delayMechanism == DM_P2P) { return set_tmo_log(p->fda.fd[FD_DELAY_TIMER], 1, p->logPdelayReqInterval); @@ -1642,6 +1646,12 @@ int port_initialize(struct port *p) p->asCapable = NOT_CAPABLE; } + p->inhibit_delay_req = config_get_int(cfg, p->name, "inhibit_delay_req"); + if (p->inhibit_delay_req && p->asCapable != ALWAYS_CAPABLE) { + pr_err("inhibit_delay_req can only be set when asCapable == 'true'."); + return -1; + } + for (i = 0; i < N_TIMER_FDS; i++) { fd[i] = -1; } diff --git a/port_private.h b/port_private.h index bb1d86e08fb5..9a5022d80750 100644 --- a/port_private.h +++ b/port_private.h @@ -100,6 +100,7 @@ struct port { int bmca; int inhibit_announce; int ignore_source_id; + int inhibit_delay_req; /* portDS */ struct PortIdentity portIdentity; enum port_state state; /*portState*/ diff --git a/ptp4l.8 b/ptp4l.8 index fad21bf57724..bca81afe7ecc 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -186,6 +186,11 @@ the interval specified by this config option after the interval_update_timer expires. It's specified as a power of two in seconds. The default value is 0 (1 second). .TP +.B inhibit_delay_req +Don't send any delay requests. This will need the asCapable config option to be +set to 'true'. This is useful when running as a designated master who does not +need to calculate offset from slave. The default is 0 (disabled). +.TP .B announceReceiptTimeout The number of missed Announce messages before the last Announce messages expires. -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:04
|
Make servo and it's current state available outside clock.c Signed-off-by: Vedang Patel <ved...@in...> Change-Id: I2a9a3855059511b793fa4966912b4455a68aa23a --- clock.c | 10 ++++++++++ clock.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/clock.c b/clock.c index 8533b3939658..beca9d61e96a 100644 --- a/clock.c +++ b/clock.c @@ -1835,3 +1835,13 @@ double clock_rate_ratio(struct clock *c) } return servo_rate_ratio(c->servo); } + +struct servo *clock_servo(struct clock *c) +{ + return c->servo; +} + +enum servo_state clock_servo_state(struct clock *c) +{ + return c->servo_state; +} diff --git a/clock.h b/clock.h index 07aba18db329..9d3133a60934 100644 --- a/clock.h +++ b/clock.h @@ -254,6 +254,20 @@ void clock_set_sde(struct clock *c, int sde); int clock_poll(struct clock *c); /** + * Obtain the servo struct. + * @param c The clock instance. + * @return A pointer to the clock's servo. + */ +struct servo *clock_servo(struct clock *c); + +/** + * Obtain the current state of clock's servo. + * @param c The clock instance. + * @return The current state of the clock's servo. + */ +enum servo_state clock_servo_state(struct clock *c); + +/** * Obtain the slave-only flag from a clock's default data set. * @param c The clock instance. * @return The value of the clock's slave-only flag. -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-18 22:52:05
|
This commit adds functionality to increase the sync and pdelay request intervals once gptp synchronization has been achieved. This is useful while running Automotive Profile where the network is usually static. Here, we are assuming that the gPTP synchronization is achieved whenever the last 'n' offsets calculated using the Sync messages are below a certain threshold. Both, the number of offsets to consider and the offset threshold are configurable. In order to support the interval update, a new clock servo state CLOCK_SERVO_STABLE has been added. The clock will transition to this state whenever the above condition is satisfied. When this transition occurs, the slave will send an "interval request" signaling message asking the master to change the sync interval. It will also update the pdelay request interval locally. Four new config options have been added to provide this functionality: - servo_offset_threshold: All the offset values being considered should be below this value. - servo_num_offset_values: number of previously received offset values to consider. - operLogSyncInterval: slave will ask the master to switch to this interval for sending sync messages when the offset stabilizes. - operLogPdelayReqInterval: the slave will set this interval for pdelay request messages when the offset stabilizes. Signed-off-by: Vedang Patel <ved...@in...> Change-Id: I6b846561ba712815be70aee8bb80936f51525843 --- clock.c | 1 + config.c | 4 ++++ configs/automotive-slave.cfg | 4 ++++ configs/default.cfg | 4 ++++ phc2sys.c | 1 + port.c | 20 +++++++++++++++++++- port_private.h | 2 ++ ptp4l.8 | 30 ++++++++++++++++++++++++++++++ servo.c | 31 ++++++++++++++++++++++++++++++- servo.h | 6 ++++++ servo_private.h | 3 +++ 11 files changed, 104 insertions(+), 2 deletions(-) diff --git a/clock.c b/clock.c index beca9d61e96a..642f6887eb2f 100644 --- a/clock.c +++ b/clock.c @@ -1690,6 +1690,7 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin) tsproc_reset(c->tsproc, 0); break; case SERVO_LOCKED: + case SERVO_LOCKED_STABLE: clockadj_set_freq(c->clkid, -adj); if (c->clkid == CLOCK_REALTIME) { sysclk_set_sync(); diff --git a/config.c b/config.c index 232131082b2e..0da7ce462c21 100644 --- a/config.c +++ b/config.c @@ -263,6 +263,8 @@ struct config_item config_tab[] = { PORT_ITEM_ENU("network_transport", TRANS_UDP_IPV4, nw_trans_enu), GLOB_ITEM_INT("ntpshm_segment", 0, INT_MIN, INT_MAX), GLOB_ITEM_INT("offsetScaledLogVariance", 0xffff, 0, UINT16_MAX), + PORT_ITEM_INT("operLogPdelayReqInterval", 0, INT8_MIN, INT8_MAX), + PORT_ITEM_INT("operLogSyncInterval", 0, INT8_MIN, INT8_MAX), PORT_ITEM_INT("path_trace_enabled", 0, 0, 1), GLOB_ITEM_DBL("pi_integral_const", 0.0, 0.0, DBL_MAX), GLOB_ITEM_DBL("pi_integral_exponent", 0.4, -DBL_MAX, DBL_MAX), @@ -279,6 +281,8 @@ struct config_item config_tab[] = { PORT_ITEM_STR("p2p_dst_mac", "01:80:C2:00:00:0E"), GLOB_ITEM_STR("revisionData", ";;"), GLOB_ITEM_INT("sanity_freq_limit", 200000000, 0, INT_MAX), + GLOB_ITEM_INT("servo_num_offset_values", 10, 0, INT_MAX), + GLOB_ITEM_INT("servo_offset_threshold", 0, 0, INT_MAX), GLOB_ITEM_INT("slaveOnly", 0, 0, 1), GLOB_ITEM_DBL("step_threshold", 0.0, 0.0, DBL_MAX), GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX), diff --git a/configs/automotive-slave.cfg b/configs/automotive-slave.cfg index 94d45b640ae5..8cc7221eaa3a 100644 --- a/configs/automotive-slave.cfg +++ b/configs/automotive-slave.cfg @@ -31,3 +31,7 @@ asCapable true ignore_source_id 1 # Required to quickly correct Time Jumps in master step_threshold 1 +operLogSyncInterval 0 +operLogPdelayReqInterval 2 +servo_offset_threshold 30 +servo_num_offset_values 10 diff --git a/configs/default.cfg b/configs/default.cfg index 3ee3a9b57fed..243355357829 100644 --- a/configs/default.cfg +++ b/configs/default.cfg @@ -23,8 +23,10 @@ maxStepsRemoved 255 # logAnnounceInterval 1 logSyncInterval 0 +operLogSyncInterval 0 logMinDelayReqInterval 0 logMinPdelayReqInterval 0 +operLogPdelayReqInterval 0 announceReceiptTimeout 3 syncReceiptTimeout 0 delayAsymmetry 0 @@ -73,6 +75,8 @@ max_frequency 900000000 clock_servo pi sanity_freq_limit 200000000 ntpshm_segment 0 +servo_num_offset_values 10 +servo_offset_threshold 0 # # Transport options # diff --git a/phc2sys.c b/phc2sys.c index a476e63a59cc..cc48f18d92c3 100644 --- a/phc2sys.c +++ b/phc2sys.c @@ -619,6 +619,7 @@ static void update_clock(struct node *node, struct clock *clock, clockcheck_step(clock->sanity_check, -offset); /* Fall through. */ case SERVO_LOCKED: + case SERVO_LOCKED_STABLE: clockadj_set_freq(clock->clkid, -ppb); if (clock->clkid == CLOCK_REALTIME) sysclk_set_sync(); diff --git a/port.c b/port.c index 6512c43b7896..373bc886eb27 100644 --- a/port.c +++ b/port.c @@ -1112,7 +1112,7 @@ static void port_synchronize(struct port *p, struct timestamp origin_ts, Integer64 correction1, Integer64 correction2) { - enum servo_state state; + enum servo_state state, last_state; tmv_t t1, t1c, t2, c1, c2; port_set_sync_rx_tmo(p); @@ -1123,10 +1123,16 @@ static void port_synchronize(struct port *p, c2 = correction_to_tmv(correction2); t1c = tmv_add(t1, tmv_add(c1, c2)); + last_state = clock_servo_state(p->clock); state = clock_synchronize(p->clock, t2, t1c); switch (state) { case SERVO_UNLOCKED: port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); + p->logPdelayReqInterval = p->logMinPdelayReqInterval; + p->logSyncInterval = p->initialLogSyncInterval; + port_tx_interval_request(p, SIGNAL_NO_CHANGE, + p->logSyncInterval, + SIGNAL_NO_CHANGE); break; case SERVO_JUMP: port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); @@ -1139,6 +1145,16 @@ static void port_synchronize(struct port *p, case SERVO_LOCKED: port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); break; + case SERVO_LOCKED_STABLE: + if (last_state == SERVO_LOCKED) { + p->logPdelayReqInterval = p->operLogPdelayReqInterval; + p->logSyncInterval = p->operLogSyncInterval; + port_tx_interval_request(p, SIGNAL_NO_CHANGE, + p->logSyncInterval, + SIGNAL_NO_CHANGE); + } + port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); + break; } } @@ -1613,8 +1629,10 @@ int port_initialize(struct port *p) p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority"); p->initialLogSyncInterval = config_get_int(cfg, p->name, "logSyncInterval"); p->logSyncInterval = p->initialLogSyncInterval; + p->operLogSyncInterval = config_get_int(cfg, p->name, "operLogSyncInterval"); p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval"); p->logPdelayReqInterval = p->logMinPdelayReqInterval; + p->operLogPdelayReqInterval = config_get_int(cfg, p->name, "operLogPdelayReqInterval"); p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); diff --git a/port_private.h b/port_private.h index d28ab0712798..bb1d86e08fb5 100644 --- a/port_private.h +++ b/port_private.h @@ -115,9 +115,11 @@ struct port { UInteger8 transportSpecific; UInteger8 localPriority; Integer8 initialLogSyncInterval; + Integer8 operLogSyncInterval; Integer8 logSyncInterval; Enumeration8 delayMechanism; Integer8 logMinPdelayReqInterval; + Integer8 operLogPdelayReqInterval; Integer8 logPdelayReqInterval; UInteger32 neighborPropDelayThresh; int follow_up_info; diff --git a/ptp4l.8 b/ptp4l.8 index 99b085c148c9..fad21bf57724 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -161,6 +161,13 @@ The mean time interval between Sync messages. A shorter interval may improve accuracy of the local clock. It's specified as a power of two in seconds. The default is 0 (1 second). .TP +.B operLogSyncInterval +The mean time interval between Sync messages. This value is only used by the +slave device when interval_update_timer is enabled. Slave will send this +interval to the master to switch to. This is done via a signaling message after +interval_update_timer expires. It's specified as a power of two in seconds. The +default value is 0 (1 second). +.TP .B logMinDelayReqInterval The minimum permitted mean time interval between Delay_Req messages. A shorter interval makes ptp4l react faster to the changes in the path delay. It's @@ -172,6 +179,13 @@ The minimum permitted mean time interval between Pdelay_Req messages. It's specified as a power of two in seconds. The default is 0 (1 second). .TP +.B operLogPdelayReqInterval +The mean time interval between Pdelay Request messages. This value is only used +by the slave device when interval_update_timer is enabled. Slave will switch to +the interval specified by this config option after the interval_update_timer +expires. It's specified as a power of two in seconds. The default value is 0 (1 +second). +.TP .B announceReceiptTimeout The number of missed Announce messages before the last Announce messages expires. @@ -715,6 +729,22 @@ This will disable source port identity checking for Sync and Follow_Up messages. This is useful when the announce messages are disabled in the master and the slave does not have any way to know it's identity. The default is 0 (disabled). +.TP +.B servo_num_offset_values +The number of offset values calculated in previously received Sync messages to +consider when adjusting the Sync and Pdelay request intervals. More information +provided in the description of 'offset_threshold'. The default value is 10. +.TP +.B servo_offset_threshold +This value is used by the slave for adjusting the intervals for Sync and Pdelay +request messages. The slave will check the last 'num_offset_values' offsets and +if all those offsets are less than the offset_threshold, it will adjust both +the intervals. The Sync interval is adjusted via the signaling mechanism and +the pdelay request interval is just adjusted locally. The new values to use for +sync message intervals and pdelay request intervals can be indicated by +operLogSyncInterval and operLogPdelayReqInterval respectively. This mechanism +is currently only supported when BMCA == 'noop'. The default +value of offset_threshold is 0 (disabled). .SH UNICAST DISCOVERY OPTIONS diff --git a/servo.c b/servo.c index 8be4b92875de..483ad31487f1 100644 --- a/servo.c +++ b/servo.c @@ -17,6 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include <string.h> +#include <stdlib.h> #include "config.h" #include "linreg.h" @@ -79,6 +80,8 @@ struct servo *servo_create(struct config *cfg, enum servo_type type, } servo->first_update = 1; + servo->offset_threshold = config_get_int(cfg, NULL, "servo_offset_threshold"); + servo->num_offset_values = config_get_int(cfg, NULL, "servo_num_offset_values"); return servo; } @@ -88,6 +91,19 @@ void servo_destroy(struct servo *servo) servo->destroy(servo); } +static int check_offset_threshold(struct servo *s, int64_t offset) +{ + uint64_t abs_offset = abs(offset); + + if (s->offset_threshold) { + if (abs_offset < INT64_MAX && abs_offset < s->offset_threshold + && s->curr_offset_values) + s->curr_offset_values--; + return s->curr_offset_values ? 0 : 1; + } + return 0; +} + double servo_sample(struct servo *servo, int64_t offset, uint64_t local_ts, @@ -98,8 +114,21 @@ double servo_sample(struct servo *servo, r = servo->sample(servo, offset, local_ts, weight, state); - if (*state != SERVO_UNLOCKED) + switch (*state) { + case SERVO_UNLOCKED: + servo->curr_offset_values = servo->num_offset_values; + break; + case SERVO_LOCKED: + if (check_offset_threshold(servo, offset)) { + *state = SERVO_LOCKED_STABLE; + } + /* fall through. */ + case SERVO_JUMP: servo->first_update = 0; + break; + case SERVO_LOCKED_STABLE: + break; + } return r; } diff --git a/servo.h b/servo.h index f90befd9976a..220f4feca288 100644 --- a/servo.h +++ b/servo.h @@ -57,6 +57,12 @@ enum servo_state { * The servo is tracking the master clock. */ SERVO_LOCKED, + + /** + * The Servo has stabilized. The last 'servo_num_offset_values' values + * of the estimated threshold are less than servo_offset_threshold. + */ + SERVO_LOCKED_STABLE, }; /** diff --git a/servo_private.h b/servo_private.h index 1c5cfdfa18d1..48bdd1662715 100644 --- a/servo_private.h +++ b/servo_private.h @@ -29,6 +29,9 @@ struct servo { double step_threshold; double first_step_threshold; int first_update; + int offset_threshold; + int num_offset_values; + int curr_offset_values; void (*destroy)(struct servo *servo); -- 2.7.3 |
From: Richard C. <ric...@gm...> - 2019-03-25 13:59:43
|
On Mon, Mar 18, 2019 at 03:51:30PM -0700, Vedang Patel wrote: > This commit adds functionality to increase the sync and pdelay request > intervals once gptp synchronization has been achieved. This is useful > while running Automotive Profile where the network is usually static. When testing this patch with the linuxptp-testsuite, I get two failures: 11-syncinterval 23-basedelay Please have a look. Thanks, Richard |
From: Richard C. <ric...@gm...> - 2019-03-25 14:12:37
|
On Mon, Mar 18, 2019 at 03:51:30PM -0700, Vedang Patel wrote: > @@ -1123,10 +1123,16 @@ static void port_synchronize(struct port *p, > c2 = correction_to_tmv(correction2); > t1c = tmv_add(t1, tmv_add(c1, c2)); > > + last_state = clock_servo_state(p->clock); > state = clock_synchronize(p->clock, t2, t1c); > switch (state) { > case SERVO_UNLOCKED: > port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); > + p->logPdelayReqInterval = p->logMinPdelayReqInterval; > + p->logSyncInterval = p->initialLogSyncInterval; > + port_tx_interval_request(p, SIGNAL_NO_CHANGE, > + p->logSyncInterval, > + SIGNAL_NO_CHANGE); This sends a message with every Sync. That isn't what we want. Instead, we should send the request only when entering SERVO_UNLOCKED, and only if the relevant options are configured. > break; > case SERVO_JUMP: > port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); > @@ -1139,6 +1145,16 @@ static void port_synchronize(struct port *p, > case SERVO_LOCKED: > port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); > break; > + case SERVO_LOCKED_STABLE: > + if (last_state == SERVO_LOCKED) { > + p->logPdelayReqInterval = p->operLogPdelayReqInterval; > + p->logSyncInterval = p->operLogSyncInterval; > + port_tx_interval_request(p, SIGNAL_NO_CHANGE, > + p->logSyncInterval, > + SIGNAL_NO_CHANGE); In contrast, this one is okay, since it only sends once, and only if the options are set (otherwise you can't enter SERVO_LOCKED_STABLE). > + } > + port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); > + break; > } > } > > @@ -1613,8 +1629,10 @@ int port_initialize(struct port *p) > p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority"); > p->initialLogSyncInterval = config_get_int(cfg, p->name, "logSyncInterval"); > p->logSyncInterval = p->initialLogSyncInterval; > + p->operLogSyncInterval = config_get_int(cfg, p->name, "operLogSyncInterval"); > p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval"); > p->logPdelayReqInterval = p->logMinPdelayReqInterval; > + p->operLogPdelayReqInterval = config_get_int(cfg, p->name, "operLogPdelayReqInterval"); > p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); > p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); > > diff --git a/port_private.h b/port_private.h > index d28ab0712798..bb1d86e08fb5 100644 > --- a/port_private.h > +++ b/port_private.h > @@ -115,9 +115,11 @@ struct port { > UInteger8 transportSpecific; > UInteger8 localPriority; > Integer8 initialLogSyncInterval; > + Integer8 operLogSyncInterval; > Integer8 logSyncInterval; > Enumeration8 delayMechanism; > Integer8 logMinPdelayReqInterval; > + Integer8 operLogPdelayReqInterval; > Integer8 logPdelayReqInterval; > UInteger32 neighborPropDelayThresh; > int follow_up_info; > diff --git a/ptp4l.8 b/ptp4l.8 > index 99b085c148c9..fad21bf57724 100644 > --- a/ptp4l.8 > +++ b/ptp4l.8 > @@ -161,6 +161,13 @@ The mean time interval between Sync messages. A shorter interval may improve > accuracy of the local clock. It's specified as a power of two in seconds. > The default is 0 (1 second). > .TP > +.B operLogSyncInterval > +The mean time interval between Sync messages. This value is only used by the > +slave device when interval_update_timer is enabled. Slave will send this > +interval to the master to switch to. This is done via a signaling message after > +interval_update_timer expires. It's specified as a power of two in seconds. The > +default value is 0 (1 second). > +.TP > .B logMinDelayReqInterval > The minimum permitted mean time interval between Delay_Req messages. A shorter > interval makes ptp4l react faster to the changes in the path delay. It's > @@ -172,6 +179,13 @@ The minimum permitted mean time interval between Pdelay_Req messages. It's > specified as a power of two in seconds. > The default is 0 (1 second). > .TP > +.B operLogPdelayReqInterval > +The mean time interval between Pdelay Request messages. This value is only used > +by the slave device when interval_update_timer is enabled. Slave will switch to > +the interval specified by this config option after the interval_update_timer > +expires. It's specified as a power of two in seconds. The default value is 0 (1 > +second). > +.TP > .B announceReceiptTimeout > The number of missed Announce messages before the last Announce messages > expires. > @@ -715,6 +729,22 @@ This will disable source port identity checking for Sync and Follow_Up > messages. This is useful when the announce messages are disabled in the master > and the slave does not have any way to know it's identity. The default is 0 > (disabled). > +.TP > +.B servo_num_offset_values > +The number of offset values calculated in previously received Sync messages to > +consider when adjusting the Sync and Pdelay request intervals. More information > +provided in the description of 'offset_threshold'. The default value is 10. > +.TP > +.B servo_offset_threshold > +This value is used by the slave for adjusting the intervals for Sync and Pdelay > +request messages. The slave will check the last 'num_offset_values' offsets and > +if all those offsets are less than the offset_threshold, it will adjust both > +the intervals. The Sync interval is adjusted via the signaling mechanism and > +the pdelay request interval is just adjusted locally. The new values to use for > +sync message intervals and pdelay request intervals can be indicated by > +operLogSyncInterval and operLogPdelayReqInterval respectively. This mechanism > +is currently only supported when BMCA == 'noop'. The default > +value of offset_threshold is 0 (disabled). > > .SH UNICAST DISCOVERY OPTIONS > > diff --git a/servo.c b/servo.c > index 8be4b92875de..483ad31487f1 100644 > --- a/servo.c > +++ b/servo.c > @@ -17,6 +17,7 @@ > * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > */ > #include <string.h> > +#include <stdlib.h> > > #include "config.h" > #include "linreg.h" > @@ -79,6 +80,8 @@ struct servo *servo_create(struct config *cfg, enum servo_type type, > } > > servo->first_update = 1; > + servo->offset_threshold = config_get_int(cfg, NULL, "servo_offset_threshold"); > + servo->num_offset_values = config_get_int(cfg, NULL, "servo_num_offset_values"); > > return servo; > } > @@ -88,6 +91,19 @@ void servo_destroy(struct servo *servo) > servo->destroy(servo); > } > > +static int check_offset_threshold(struct servo *s, int64_t offset) > +{ > + uint64_t abs_offset = abs(offset); abs() returns an int... > + if (s->offset_threshold) { > + if (abs_offset < INT64_MAX && abs_offset < s->offset_threshold ^^^^^^^^^^^^^^^^^^^^^^ ... so this test is always true > + && s->curr_offset_values) > + s->curr_offset_values--; > + return s->curr_offset_values ? 0 : 1; > + } > + return 0; > +} > + > double servo_sample(struct servo *servo, > int64_t offset, > uint64_t local_ts, Thanks, Richard |
From: Richard C. <ric...@gm...> - 2019-03-25 14:16:06
|
On Mon, Mar 18, 2019 at 03:51:30PM -0700, Vedang Patel wrote: > @@ -98,8 +114,21 @@ double servo_sample(struct servo *servo, > > r = servo->sample(servo, offset, local_ts, weight, state); > > - if (*state != SERVO_UNLOCKED) > + switch (*state) { > + case SERVO_UNLOCKED: > + servo->curr_offset_values = servo->num_offset_values; > + break; > + case SERVO_LOCKED: > + if (check_offset_threshold(servo, offset)) { > + *state = SERVO_LOCKED_STABLE; > + } > + /* fall through. */ > + case SERVO_JUMP: > servo->first_update = 0; > + break; > + case SERVO_LOCKED_STABLE: Once you are in this state, and the offset exceeds the threshold, shouldn't the FSM transition back to SERVO_LOCKED? In this case I would expect the slave to request the higher Sync rate once again. Thoughts? Thanks, Richard |
From: Patel, V. <ved...@in...> - 2019-03-25 19:46:28
|
> On Mar 25, 2019, at 7:12 AM, Richard Cochran <ric...@gm...> wrote: > > On Mon, Mar 18, 2019 at 03:51:30PM -0700, Vedang Patel wrote: >> @@ -1123,10 +1123,16 @@ static void port_synchronize(struct port *p, >> c2 = correction_to_tmv(correction2); >> t1c = tmv_add(t1, tmv_add(c1, c2)); >> >> + last_state = clock_servo_state(p->clock); >> state = clock_synchronize(p->clock, t2, t1c); >> switch (state) { >> case SERVO_UNLOCKED: >> port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); >> + p->logPdelayReqInterval = p->logMinPdelayReqInterval; >> + p->logSyncInterval = p->initialLogSyncInterval; >> + port_tx_interval_request(p, SIGNAL_NO_CHANGE, >> + p->logSyncInterval, >> + SIGNAL_NO_CHANGE); > > This sends a message with every Sync. That isn't what we want. > Instead, we should send the request only when entering SERVO_UNLOCKED, > and only if the relevant options are configured. > Yes. You are right. We should check whether last state was SERVO_UNLOCKED and the servo_offset_threshold config option is not 0. Also, p->logSyncInterval here should be replaced by SIGNAL_SET_INITIAL so slave does not enforce it’s own config options on the master. This is the reason why the 11-syncinterval and 23-basedelay were failing. >> break; >> case SERVO_JUMP: >> port_dispatch(p, EV_SYNCHRONIZATION_FAULT, 0); >> @@ -1139,6 +1145,16 @@ static void port_synchronize(struct port *p, >> case SERVO_LOCKED: >> port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); >> break; >> + case SERVO_LOCKED_STABLE: >> + if (last_state == SERVO_LOCKED) { >> + p->logPdelayReqInterval = p->operLogPdelayReqInterval; >> + p->logSyncInterval = p->operLogSyncInterval; >> + port_tx_interval_request(p, SIGNAL_NO_CHANGE, >> + p->logSyncInterval, >> + SIGNAL_NO_CHANGE); > > In contrast, this one is okay, since it only sends once, and only if > the options are set (otherwise you can't enter SERVO_LOCKED_STABLE). > >> + } >> + port_dispatch(p, EV_MASTER_CLOCK_SELECTED, 0); >> + break; >> } >> } >> >> @@ -1613,8 +1629,10 @@ int port_initialize(struct port *p) >> p->localPriority = config_get_int(cfg, p->name, "G.8275.portDS.localPriority"); >> p->initialLogSyncInterval = config_get_int(cfg, p->name, "logSyncInterval"); >> p->logSyncInterval = p->initialLogSyncInterval; >> + p->operLogSyncInterval = config_get_int(cfg, p->name, "operLogSyncInterval"); >> p->logMinPdelayReqInterval = config_get_int(cfg, p->name, "logMinPdelayReqInterval"); >> p->logPdelayReqInterval = p->logMinPdelayReqInterval; >> + p->operLogPdelayReqInterval = config_get_int(cfg, p->name, "operLogPdelayReqInterval"); >> p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); >> p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); >> >> diff --git a/port_private.h b/port_private.h >> index d28ab0712798..bb1d86e08fb5 100644 >> --- a/port_private.h >> +++ b/port_private.h >> @@ -115,9 +115,11 @@ struct port { >> UInteger8 transportSpecific; >> UInteger8 localPriority; >> Integer8 initialLogSyncInterval; >> + Integer8 operLogSyncInterval; >> Integer8 logSyncInterval; >> Enumeration8 delayMechanism; >> Integer8 logMinPdelayReqInterval; >> + Integer8 operLogPdelayReqInterval; >> Integer8 logPdelayReqInterval; >> UInteger32 neighborPropDelayThresh; >> int follow_up_info; >> diff --git a/ptp4l.8 b/ptp4l.8 >> index 99b085c148c9..fad21bf57724 100644 >> --- a/ptp4l.8 >> +++ b/ptp4l.8 >> @@ -161,6 +161,13 @@ The mean time interval between Sync messages. A shorter interval may improve >> accuracy of the local clock. It's specified as a power of two in seconds. >> The default is 0 (1 second). >> .TP >> +.B operLogSyncInterval >> +The mean time interval between Sync messages. This value is only used by the >> +slave device when interval_update_timer is enabled. Slave will send this >> +interval to the master to switch to. This is done via a signaling message after >> +interval_update_timer expires. It's specified as a power of two in seconds. The >> +default value is 0 (1 second). >> +.TP >> .B logMinDelayReqInterval >> The minimum permitted mean time interval between Delay_Req messages. A shorter >> interval makes ptp4l react faster to the changes in the path delay. It's >> @@ -172,6 +179,13 @@ The minimum permitted mean time interval between Pdelay_Req messages. It's >> specified as a power of two in seconds. >> The default is 0 (1 second). >> .TP >> +.B operLogPdelayReqInterval >> +The mean time interval between Pdelay Request messages. This value is only used >> +by the slave device when interval_update_timer is enabled. Slave will switch to >> +the interval specified by this config option after the interval_update_timer >> +expires. It's specified as a power of two in seconds. The default value is 0 (1 >> +second). >> +.TP >> .B announceReceiptTimeout >> The number of missed Announce messages before the last Announce messages >> expires. >> @@ -715,6 +729,22 @@ This will disable source port identity checking for Sync and Follow_Up >> messages. This is useful when the announce messages are disabled in the master >> and the slave does not have any way to know it's identity. The default is 0 >> (disabled). >> +.TP >> +.B servo_num_offset_values >> +The number of offset values calculated in previously received Sync messages to >> +consider when adjusting the Sync and Pdelay request intervals. More information >> +provided in the description of 'offset_threshold'. The default value is 10. >> +.TP >> +.B servo_offset_threshold >> +This value is used by the slave for adjusting the intervals for Sync and Pdelay >> +request messages. The slave will check the last 'num_offset_values' offsets and >> +if all those offsets are less than the offset_threshold, it will adjust both >> +the intervals. The Sync interval is adjusted via the signaling mechanism and >> +the pdelay request interval is just adjusted locally. The new values to use for >> +sync message intervals and pdelay request intervals can be indicated by >> +operLogSyncInterval and operLogPdelayReqInterval respectively. This mechanism >> +is currently only supported when BMCA == 'noop'. The default >> +value of offset_threshold is 0 (disabled). >> >> .SH UNICAST DISCOVERY OPTIONS >> >> diff --git a/servo.c b/servo.c >> index 8be4b92875de..483ad31487f1 100644 >> --- a/servo.c >> +++ b/servo.c >> @@ -17,6 +17,7 @@ >> * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >> */ >> #include <string.h> >> +#include <stdlib.h> >> >> #include "config.h" >> #include "linreg.h" >> @@ -79,6 +80,8 @@ struct servo *servo_create(struct config *cfg, enum servo_type type, >> } >> >> servo->first_update = 1; >> + servo->offset_threshold = config_get_int(cfg, NULL, "servo_offset_threshold"); >> + servo->num_offset_values = config_get_int(cfg, NULL, "servo_num_offset_values"); >> >> return servo; >> } >> @@ -88,6 +91,19 @@ void servo_destroy(struct servo *servo) >> servo->destroy(servo); >> } >> >> +static int check_offset_threshold(struct servo *s, int64_t offset) >> +{ >> + uint64_t abs_offset = abs(offset); > > abs() returns an int... > >> + if (s->offset_threshold) { >> + if (abs_offset < INT64_MAX && abs_offset < s->offset_threshold > ^^^^^^^^^^^^^^^^^^^^^^ > ... so this test is always true > Sorry I missed this. Will change it to INT_MAX. Thanks, Vedang >> + && s->curr_offset_values) >> + s->curr_offset_values--; >> + return s->curr_offset_values ? 0 : 1; >> + } >> + return 0; >> +} >> + >> double servo_sample(struct servo *servo, >> int64_t offset, >> uint64_t local_ts, > > Thanks, > Richard |
From: Patel, V. <ved...@in...> - 2019-03-25 20:03:43
|
> On Mar 25, 2019, at 7:15 AM, Richard Cochran <ric...@gm...> wrote: > > On Mon, Mar 18, 2019 at 03:51:30PM -0700, Vedang Patel wrote: >> @@ -98,8 +114,21 @@ double servo_sample(struct servo *servo, >> >> r = servo->sample(servo, offset, local_ts, weight, state); >> >> - if (*state != SERVO_UNLOCKED) >> + switch (*state) { >> + case SERVO_UNLOCKED: >> + servo->curr_offset_values = servo->num_offset_values; >> + break; >> + case SERVO_LOCKED: >> + if (check_offset_threshold(servo, offset)) { >> + *state = SERVO_LOCKED_STABLE; >> + } >> + /* fall through. */ >> + case SERVO_JUMP: >> servo->first_update = 0; >> + break; >> + case SERVO_LOCKED_STABLE: > > Once you are in this state, and the offset exceeds the threshold, > shouldn't the FSM transition back to SERVO_LOCKED? > > In this case I would expect the slave to request the higher Sync rate > once again. > > Thoughts? > It might be a good idea to transition to the SERVO_LOCKED state. But, I am wondering if it should be the same as initial interval because it assumes that the clock offset will be huge in the beginning. If the rate is increased suddenly because of a single spike in the offset, it might affect other critical streams which are trying to transmit. The initial offset is probably assuming that the clock offset is a huge and the system is still booting so other critical processes have not started yet. What do you think? -Vedang > Thanks, > Richard |
From: Richard C. <ric...@gm...> - 2019-03-26 04:09:09
|
On Mon, Mar 25, 2019 at 07:46:19PM +0000, Patel, Vedang wrote: > >> +static int check_offset_threshold(struct servo *s, int64_t offset) > >> +{ > >> + uint64_t abs_offset = abs(offset); > > > > abs() returns an int... > > > >> + if (s->offset_threshold) { > >> + if (abs_offset < INT64_MAX && abs_offset < s->offset_threshold > > ^^^^^^^^^^^^^^^^^^^^^^ > > ... so this test is always true > > > Sorry I missed this. Will change it to INT_MAX. But are you sure that works? What happens when your 'int64_t offset' is degraded into an 'int' in the call to abs()? Better to use llabs(), don't you think? Thanks, Richard |
From: Richard C. <ric...@gm...> - 2019-03-26 04:12:25
|
On Mon, Mar 25, 2019 at 08:03:32PM +0000, Patel, Vedang wrote: > What do you think? Perhaps the profile explains this case... Thanks, Richard |
From: Patel, V. <ved...@in...> - 2019-03-26 16:58:55
|
> On Mar 25, 2019, at 9:08 PM, Richard Cochran <ric...@gm...> wrote: > > On Mon, Mar 25, 2019 at 07:46:19PM +0000, Patel, Vedang wrote: >>>> +static int check_offset_threshold(struct servo *s, int64_t offset) >>>> +{ >>>> + uint64_t abs_offset = abs(offset); >>> >>> abs() returns an int... >>> >>>> + if (s->offset_threshold) { >>>> + if (abs_offset < INT64_MAX && abs_offset < s->offset_threshold >>> ^^^^^^^^^^^^^^^^^^^^^^ >>> ... so this test is always true >>> >> Sorry I missed this. Will change it to INT_MAX. > > But are you sure that works? > > What happens when your 'int64_t offset' is degraded into an 'int' in > the call to abs()? > > Better to use llabs(), don't you think? Yeah llabs should work. But, depending on the machine, int64_t will translate to either ‘long int’ or 'long long int’. So, do you think imaxabs will be better to use instead? Thanks, Vedang > > Thanks, > Richard |
From: Richard C. <ric...@gm...> - 2019-03-27 02:31:26
|
On Tue, Mar 26, 2019 at 04:58:46PM +0000, Patel, Vedang wrote: > Yeah llabs should work. But, depending on the machine, int64_t will translate to either ‘long int’ or 'long long int’. So, do you think imaxabs will be better to use instead? I'm not familiar with intmax_t. But I think llabs will work correctly with either 'long' on 64 bit archs or 'long long' on 32 bit. Thanks, Richard |
From: Patel, V. <ved...@in...> - 2019-03-26 17:00:59
|
> On Mar 25, 2019, at 9:12 PM, Richard Cochran <ric...@gm...> wrote: > > On Mon, Mar 25, 2019 at 08:03:32PM +0000, Patel, Vedang wrote: >> What do you think? > > Perhaps the profile explains this case… > Unfortunately, the profile only mentions what to do when there are link-down and link-up events. Nothing about what to do when the offset exceeds a certain value. I am guessing that implementation will be OEM specific. Thanks, Vedang > Thanks, > Richard |
From: Patel, V. <ved...@in...> - 2019-03-27 19:36:43
|
> On Mar 26, 2019, at 10:00 AM, Patel, Vedang <ved...@in...> wrote: > > > >> On Mar 25, 2019, at 9:12 PM, Richard Cochran <ric...@gm...> wrote: >> >> On Mon, Mar 25, 2019 at 08:03:32PM +0000, Patel, Vedang wrote: >>> What do you think? >> >> Perhaps the profile explains this case… >> > Unfortunately, the profile only mentions what to do when there are link-down and link-up events. Nothing about what to do when the offset exceeds a certain value. I am guessing that implementation will be OEM specific. > Since the behavior is not defined in the profile and it can be OEM specific, I suggest we leave it out for now. The OEMs can use script this behavior using pmc if they want. We will just have to provide a way to set LOG_SYNC_INTERVAL using PMC. We can revisit this behavior again when 802.1AS-rev is publicly released. Thoughts? Thanks, Vedang > Thanks, > Vedang >> Thanks, >> Richard > > > _______________________________________________ > Linuxptp-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linuxptp-devel |
From: Richard C. <ric...@gm...> - 2019-03-28 03:09:40
|
On Wed, Mar 27, 2019 at 07:36:26PM +0000, Patel, Vedang wrote: > Since the behavior is not defined in the profile and it can be OEM > specific, I suggest we leave it out for now. The OEMs can use script > this behavior using pmc if they want. We will just have to provide a > way to set LOG_SYNC_INTERVAL using PMC. Ok, but let's leave that out until someone wants it. > We can revisit this behavior again when 802.1AS-rev is publicly released. > > Thoughts? Just leave it as a one-shot Sync rate change, as you first had it. Thanks, Richard |
From: Vedang P. <ved...@in...> - 2019-03-29 03:32:51
|
This are the changes from the last version: - Change abs() -> llabs() in servo.c - Reset the servo when slave detects the logSyncInterval rate mentioned in the signaling message is not the same as it’s own rate. This will probably occur when master restarts. - Remove unused header file (errno.h) from port_signaling.c. More information about the series is in the original cover letter at: https://sourceforge.net/p/linuxptp/mailman/message/36433837/ Thanks, Vedang Patel Vedang Patel (7): port: Make port_capable() accessible outside port.c port: Separate unicast specific code from port_signaling_construct() port: Add logPdelayReqInterval. port: implement message interval request processing clock: add APIs to access servo and servo_state port: Add interval update mechanism. port: Add inhibit_delay_req. clock.c | 11 +++++ clock.h | 14 ++++++ config.c | 7 ++- configs/automotive-master.cfg | 1 + configs/automotive-slave.cfg | 4 ++ configs/default.cfg | 5 ++ msg.h | 6 +++ phc2sys.c | 1 + port.c | 70 +++++++++++++++++++++----- port_private.h | 17 +++++-- port_signaling.c | 111 ++++++++++++++++++++++++++++++++++++++++-- ptp4l.8 | 35 +++++++++++++ servo.c | 45 ++++++++++++++++- servo.h | 13 +++++ servo_private.h | 3 ++ tlv.c | 4 ++ tlv.h | 12 +++++ unicast_client.c | 14 +++--- unicast_service.c | 4 +- 19 files changed, 348 insertions(+), 29 deletions(-) -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-29 03:32:53
|
Make sure port_capable() can be accessed by the signaling construct in port_signaling.c Signed-off-by: Vedang Patel <ved...@in...> --- port.c | 3 +-- port_private.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/port.c b/port.c index facebd270c5a..b8ae77e5c190 100644 --- a/port.c +++ b/port.c @@ -55,7 +55,6 @@ enum syfu_event { FUP_MATCH, }; -static int port_capable(struct port *p); static int port_is_ieee8021as(struct port *p); static void port_nrate_initialize(struct port *p); @@ -602,7 +601,7 @@ static int peer_prepare_and_send(struct port *p, struct ptp_message *msg, return 0; } -static int port_capable(struct port *p) +int port_capable(struct port *p) { if (!port_is_ieee8021as(p)) { /* Normal 1588 ports are always capable. */ diff --git a/port_private.h b/port_private.h index 593eb76fbe48..b0b2a5dcde09 100644 --- a/port_private.h +++ b/port_private.h @@ -157,6 +157,7 @@ void delay_req_prune(struct port *p); void fc_clear(struct foreign_clock *fc); void flush_delay_req(struct port *p); void flush_last_sync(struct port *p); +int port_capable(struct port *p); int port_clr_tmo(int fd); int port_delay_request(struct port *p); void port_disable(struct port *p); -- 2.7.3 |
[Linuxptp-devel] [PATCH v5 2/7] port: Separate unicast specific
code from port_signaling_construct()
From: Vedang P. <ved...@in...> - 2019-03-29 03:32:55
|
Make port_signaling_construct() to create a generic signaling ptp_message. Move the unicast specific code to port_signaling_uc_construct(). This is done to support the creation of Message Interval Request TLV (as defined in 802.1AS Section 10.5.4.3). This TLV can be used to request change in Announce Interval, Sync Interval or Link Delay Interval on a remote system. Signed-off-by: Vedang Patel <ved...@in...> --- port_private.h | 6 +++--- port_signaling.c | 20 +++++++++++++++++--- unicast_client.c | 10 +++++----- unicast_service.c | 4 ++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/port_private.h b/port_private.h index b0b2a5dcde09..1bc1c3f5f33d 100644 --- a/port_private.h +++ b/port_private.h @@ -169,9 +169,9 @@ int port_set_delay_tmo(struct port *p); int port_set_qualification_tmo(struct port *p); void port_show_transition(struct port *p, enum port_state next, enum fsm_event event); -struct ptp_message *port_signaling_construct(struct port *p, - struct address *address, - struct PortIdentity *tpid); +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_sync(struct port *p, struct address *dst); int process_announce(struct port *p, struct ptp_message *m); diff --git a/port_signaling.c b/port_signaling.c index f845d36f6e61..69a1ad414204 100644 --- a/port_signaling.c +++ b/port_signaling.c @@ -21,9 +21,8 @@ #include "unicast_client.h" #include "unicast_service.h" -struct ptp_message *port_signaling_construct(struct port *p, - struct address *address, - struct PortIdentity *tpid) +static struct ptp_message *port_signaling_construct(struct port *p, + struct PortIdentity *tpid) { struct ptp_message *msg; @@ -41,6 +40,21 @@ struct ptp_message *port_signaling_construct(struct port *p, msg->header.control = CTL_OTHER; msg->header.logMessageInterval = 0x7F; msg->signaling.targetPortIdentity = *tpid; + + return msg; +} + +struct ptp_message *port_signaling_uc_construct(struct port *p, + struct address *address, + struct PortIdentity *tpid) +{ + struct ptp_message *msg; + + msg = port_signaling_construct(p, tpid); + if (!msg) { + return NULL; + } + msg->header.flagField[0] |= UNICAST; msg->address = *address; diff --git a/unicast_client.c b/unicast_client.c index de5eee9f4574..337765a19f17 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -75,7 +75,7 @@ static int unicast_client_announce(struct port *p, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -140,7 +140,7 @@ static int unicast_client_peer_renew(struct port *p) peer->renewal_tmo = 0; pr_debug("port %d: time to renew P2P unicast subscription", portnum(p)); - msg = port_signaling_construct(p, &peer->address, &peer->portIdentity); + msg = port_signaling_uc_construct(p, &peer->address, &peer->portIdentity); if (!msg) { return -1; } @@ -176,7 +176,7 @@ static int unicast_client_renew(struct port *p, dst->renewal_tmo = 0; pr_debug("port %d: time to renew unicast subscriptions", portnum(p)); - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -236,7 +236,7 @@ static int unicast_client_sydy(struct port *p, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, &dst->portIdentity); + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); if (!msg) { return -1; } @@ -296,7 +296,7 @@ int unicast_client_cancel(struct port *p, struct ptp_message *m, ucma->granted &= ~(1 << mtype); /* Respond with ACK. */ - msg = port_signaling_construct(p, &ucma->address, &ucma->portIdentity); + msg = port_signaling_uc_construct(p, &ucma->address, &ucma->portIdentity); if (!msg) { return -1; } diff --git a/unicast_service.c b/unicast_service.c index 9c9b95b05187..ec5ee6ca2fff 100644 --- a/unicast_service.c +++ b/unicast_service.c @@ -241,8 +241,8 @@ static int unicast_service_reply(struct port *p, struct ptp_message *dst, struct ptp_message *msg; int err; - msg = port_signaling_construct(p, &dst->address, - &dst->header.sourcePortIdentity); + msg = port_signaling_uc_construct(p, &dst->address, + &dst->header.sourcePortIdentity); if (!msg) { return -1; } -- 2.7.3 |
From: Vedang P. <ved...@in...> - 2019-03-29 03:32:57
|
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 <ved...@in...> --- msg.h | 6 ++++ port.c | 6 ++-- port_private.h | 6 ++++ port_signaling.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tlv.c | 4 +++ tlv.h | 12 ++++++++ 6 files changed, 123 insertions(+), 2 deletions(-) diff --git a/msg.h b/msg.h index 02e45fd9f490..c1294c23f6c3 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 d86900d87eb4..982daf22f841 100644 --- a/port.c +++ b/port.c @@ -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"); diff --git a/port_private.h b/port_private.h index 37dc4b3db777..d28ab0712798 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; @@ -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); diff --git a/port_signaling.c b/port_signaling.c index 69a1ad414204..c3abbcf9222b 100644 --- a/port_signaling.c +++ b/port_signaling.c @@ -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" @@ -61,9 +63,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) { @@ -109,7 +145,62 @@ 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.clockIdentity, 0, sizeof(tpid.clockIdentity)); + tpid.portNumber = 0xFF; + + 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.c b/tlv.c index b647160ac9eb..6a5387ea8083 100644 --- a/tlv.c +++ b/tlv.c @@ -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; 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 |