From: Vincent Cheng <vincent.cheng...@renesas.com> ptp4l currently does not cancel unicast service on program exit. This causes problems for subsequent ptp4l session that is using different masters.
Below example has debug statements to print out announce master address and received packet address. Start unicast slave session with master 10.64.10.13, and unicast_req_duration 300. ptp4l[682807.352]: port 1 (eth0): INITIALIZING to LISTENING on INIT_COMPLETE ptp4l[682811.352]: debug: announce master 10.64.10.13 ptp4l[682812.770]: debug: sk_receive from 10.64.10.13 ptp4l[682812.810]: debug: sk_receive from 10.64.10.13 ptp4l[682813.120]: selected local clock 000a35.fffe.002201 as best master ptp4l[682814.755]: port 1 (eth0): new foreign master 84c807.fffe.10c570-1 Exit ptp4l. The unicast master continues to send SYNC packets to slave until renewal period expires. Start unicast same slave, but different master 10.64.10.14. This master is not online, so ptp4l should choose local clock as best master. However, because there is no checking of received unicast master to configured unicast table, ptp4l is quite content with packets from previous master 10.64.10.13. ptp4l[682848.858]: port 1 (eth0): INITIALIZING to LISTENING on INIT_COMPLETE ptp4l[682848.892]: debug: sk_receive from 10.64.10.13 ... ptp4l[682850.704]: debug: sk_receive from 10.64.10.13 ptp4l[682850.751]: debug: sk_receive from 10.64.10.13 ptp4l[682850.751]: port 1 (eth0): new foreign master 84c807.fffe.10c570-1 ptp4l[682850.766]: debug: sk_receive from 10.64.10.13 ... ptp4l[682852.829]: debug: sk_receive from 10.64.10.13 ptp4l[682852.858]: debug: announce master 10.64.10.14 ptp4l[682852.891]: debug: sk_receive from 10.64.10.13 ptp4l[682854.751]: port 1 (eth0): LISTENING to UNCALIBRATED on RS_SLAVE ptp4l[682854.766]: debug: sk_receive from 10.64.10.13 ... ptp4l[682854.891]: master offset -3269 s0 freq -397 path delay 4757 This patch implements a workaround by canceling unicast session on exit so that subsequent session is not polluted by lingering unicast session traffic. Signed-off-by: Vincent Cheng <vincent.cheng...@renesas.com> --- port.c | 1 + unicast_service.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ unicast_service.h | 7 +++++ 3 files changed, 92 insertions(+) diff --git a/port.c b/port.c index f2b666c..ebc345f 100644 --- a/port.c +++ b/port.c @@ -2462,6 +2462,7 @@ void process_sync(struct port *p, struct ptp_message *m) void port_close(struct port *p) { if (port_is_enabled(p)) { + unicast_service_cancel(p); port_disable(p); } diff --git a/unicast_service.c b/unicast_service.c index 3154894..ac5f6fb 100644 --- a/unicast_service.c +++ b/unicast_service.c @@ -84,6 +84,23 @@ static int attach_grant(struct ptp_message *msg, return 0; } +static int attach_cancel(struct ptp_message *msg, uint8_t message_type) +{ + struct cancel_unicast_xmit_tlv *req; + struct tlv_extra *extra; + + extra = msg_tlv_append(msg, sizeof(*req)); + if (!extra) { + return -1; + } + req = (struct cancel_unicast_xmit_tlv *) extra->tlv; + req->type = TLV_CANCEL_UNICAST_TRANSMISSION; + req->length = sizeof(*req) - sizeof(req->type) - sizeof(req->length); + req->message_type_flags = message_type << 4; + + return 0; +} + static int compare_timeout(void *ain, void *bin) { struct unicast_service_interval *a, *b; @@ -94,6 +111,58 @@ static int compare_timeout(void *ain, void *bin) return timespec_compare(&a->tmo, &b->tmo); } +static int unicast_client_cancel_announce(struct port *p, + struct unicast_master_address *dst) +{ + struct ptp_message *msg; + int err; + + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); + if (!msg) { + return -1; + } + err = attach_cancel(msg, ANNOUNCE); + if (err) { + goto out; + } + err = port_prepare_and_send(p, msg, TRANS_GENERAL); + if (err) { + pr_err("%s: signaling message failed", p->log_name); + } +out: + msg_put(msg); + return err; +} + +static int unicast_client_cancel_sydy(struct port *p, + struct unicast_master_address *dst) +{ + struct ptp_message *msg; + int err; + + msg = port_signaling_uc_construct(p, &dst->address, &dst->portIdentity); + if (!msg) { + return -1; + } + err = attach_cancel(msg, SYNC); + if (err) { + goto out; + } + if (p->delayMechanism != DM_P2P) { + err = attach_cancel(msg, DELAY_RESP); + if (err) { + goto out; + } + } + err = port_prepare_and_send(p, msg, TRANS_GENERAL); + if (err) { + pr_err("%s: signaling message failed", p->log_name); + } +out: + msg_put(msg); + return err; +} + static void initialize_interval(struct unicast_service_interval *interval, int log_period) { @@ -429,6 +498,21 @@ int unicast_service_initialize(struct port *p) return 0; } +void unicast_service_cancel(struct port *p) +{ + struct unicast_master_address *master; + + if (!p->unicast_service) { + return; + } + STAILQ_FOREACH(master, &p->unicast_master_table->addrs, list) { + if (master->state != UC_WAIT) { + unicast_client_cancel_announce(p, master); + unicast_client_cancel_sydy(p, master); + } + } +} + void unicast_service_remove(struct port *p, struct ptp_message *m, struct tlv_extra *extra) { diff --git a/unicast_service.h b/unicast_service.h index f0d6487..2b55ecd 100644 --- a/unicast_service.h +++ b/unicast_service.h @@ -71,6 +71,13 @@ int unicast_service_grant(struct port *p, struct ptp_message *m, */ int unicast_service_initialize(struct port *p); + +/** + * Cancel a port's unicast service. + * @param p The port in question. + */ +void unicast_service_cancel(struct port *p); + /** * Handle a unicast service cancellation. * @param p The port on which the signaling message was received. -- 2.7.4 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel