If the unicast negotiation is disabled, the granted messages needs to be cancelled towards the server.
Signed-off-by: Anders Selhammer <[email protected]> --- unicast_client.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- unicast_client.h | 8 ++++++ unicast_fsm.c | 28 +++++++++++++++++++ unicast_fsm.h | 2 ++ 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/unicast_client.c b/unicast_client.c index de5eee9..49c7b00 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -32,6 +32,23 @@ static struct PortIdentity wildcard = { .portNumber = 0xffff, }; +static int attach_cancel(struct ptp_message *msg, uint8_t message_type_flags) +{ + struct cancel_unicast_xmit_tlv *cxl; + struct tlv_extra *extra; + + extra = msg_tlv_append(msg, sizeof(*cxl)); + if (!extra) { + return -1; + } + cxl = (struct cancel_unicast_xmit_tlv *) extra->tlv; + cxl->type = TLV_CANCEL_UNICAST_TRANSMISSION; + cxl->length = sizeof(*cxl) - sizeof(cxl->type) - sizeof(cxl->length); + cxl->message_type_flags = message_type_flags; + + return 0; +} + static int attach_ack(struct ptp_message *msg, uint8_t message_type_flags) { struct ack_cancel_unicast_xmit_tlv *ack; @@ -261,6 +278,34 @@ out: return err; } +static int unicast_client_ungrant(struct port *p, uint8_t mtype, + struct unicast_master_address *ucma) +{ + struct ptp_message *msg; + int err; + if (~ucma->granted & (1 << mtype)) { + return 0; + } + msg = port_signaling_construct(p, &ucma->address, &ucma->portIdentity); + if (!msg) { + return -1; + } + err = attach_cancel(msg, mtype << 4); + if (err) { + goto out; + } + err = port_prepare_and_send(p, msg, TRANS_GENERAL); + if (err <= 0) { + pr_err("port %hu: signaling message failed", portnum(p)); + goto out; + } + err = 0; + ucma->granted &= ~(1 << mtype); +out: + msg_put(msg); + return err; +} + /* public methods */ int unicast_client_cancel(struct port *p, struct ptp_message *m, @@ -383,10 +428,10 @@ void unicast_client_grant(struct port *p, struct ptp_message *m, mtype = g->message_type >> 4; if (!g->durationField) { - pr_warning("port %d: unicast grant of %s rejected", + pr_warning("port %d: unicast grant of %s denied", portnum(p), msg_type_string(mtype)); if (mtype != PDELAY_RESP) { - ucma->state = UC_WAIT; + ucma->state = UC_DENIED; } return; } @@ -398,6 +443,8 @@ void unicast_client_grant(struct port *p, struct ptp_message *m, case DELAY_RESP: return; case PDELAY_RESP: + p->unicast_master_table->peer_addr.granted |= + 1 << mtype; p->unicast_master_table->peer_addr.portIdentity = m->header.sourcePortIdentity; unicast_client_set_renewal(p, @@ -414,6 +461,7 @@ void unicast_client_grant(struct port *p, struct ptp_message *m, switch (ucma->state) { case UC_WAIT: + case UC_DENIED: if (mtype == ANNOUNCE) { ucma->state = unicast_fsm(ucma->state, UC_EV_GRANT_ANN); ucma->portIdentity = m->header.sourcePortIdentity; @@ -490,6 +538,7 @@ int unicast_client_timer(struct port *p) } switch (master->state) { case UC_WAIT: + case UC_DENIED: err = unicast_client_announce(p, master); break; case UC_HAVE_ANN: @@ -510,3 +559,35 @@ int unicast_client_timer(struct port *p) unicast_client_set_tmo(p); return err; } + +int unicast_client_disable(struct port *p) +{ + struct unicast_master_address *master, *peer; + + + if (p->delayMechanism == DM_P2P) { + peer = &p->unicast_master_table->peer_addr; + if (unicast_client_ungrant(p, PDELAY_RESP, peer)) { + return -1; + } + pr_debug("port %d: cancel unicast p2p subscriptions", portnum(p)); + } + + STAILQ_FOREACH(master, &p->unicast_master_table->addrs, list) { + if (master->type != transport_type(p->trp)) { + continue; + } + if (unicast_client_ungrant(p, ANNOUNCE, master) || + unicast_client_ungrant(p, SYNC, master) || + unicast_client_ungrant(p, DELAY_RESP, master)) { + return -1; + } + master->renewal_tmo = 0; + master->state = unicast_fsm(master->state, UC_EV_DISABLE); + pr_debug("port %d: cancel unicast e2e subscriptions", portnum(p)); + } + p->unicast_master_table->port = 0; + p->unicast_master_table = NULL; + set_tmo_log(p->fda.fd[FD_UNICAST_REQ_TIMER], 0, 0); + return 0; +} diff --git a/unicast_client.h b/unicast_client.h index fc8dc6f..6cbd439 100644 --- a/unicast_client.h +++ b/unicast_client.h @@ -76,4 +76,12 @@ void unicast_client_state_changed(struct port *p); */ int unicast_client_timer(struct port *p); +/** + * Disables the unicast request timer, cancel all negotiated grants + * and resets the unicast master table. + * @param p The port in question. + * @return Zero on success, non-zero otherwise. + */ +int unicast_client_disable(struct port *p); + #endif diff --git a/unicast_fsm.c b/unicast_fsm.c index f356541..4dda595 100644 --- a/unicast_fsm.c +++ b/unicast_fsm.c @@ -32,7 +32,11 @@ enum unicast_state unicast_fsm(enum unicast_state state, enum unicast_event ev) case UC_EV_SELECTED: case UC_EV_GRANT_SYDY: case UC_EV_UNSELECTED: + break; case UC_EV_CANCEL: + next = UC_DENIED; + break; + case UC_EV_DISABLE: break; } break; @@ -47,6 +51,9 @@ enum unicast_state unicast_fsm(enum unicast_state state, enum unicast_event ev) case UC_EV_UNSELECTED: break; case UC_EV_CANCEL: + next = UC_DENIED; + break; + case UC_EV_DISABLE: next = UC_WAIT; break; } @@ -63,6 +70,9 @@ enum unicast_state unicast_fsm(enum unicast_state state, enum unicast_event ev) next = UC_HAVE_ANN; break; case UC_EV_CANCEL: + next = UC_DENIED; + break; + case UC_EV_DISABLE: next = UC_WAIT; break; } @@ -77,6 +87,24 @@ enum unicast_state unicast_fsm(enum unicast_state state, enum unicast_event ev) next = UC_HAVE_ANN; break; case UC_EV_CANCEL: + next = UC_DENIED; + break; + case UC_EV_DISABLE: + next = UC_WAIT; + break; + } + break; + case UC_DENIED: + switch (ev) { + case UC_EV_GRANT_ANN: + next = UC_HAVE_ANN; + break; + case UC_EV_SELECTED: + case UC_EV_GRANT_SYDY: + case UC_EV_UNSELECTED: + case UC_EV_CANCEL: + break; + case UC_EV_DISABLE: next = UC_WAIT; break; } diff --git a/unicast_fsm.h b/unicast_fsm.h index 49fc9b2..6eb1cfa 100644 --- a/unicast_fsm.h +++ b/unicast_fsm.h @@ -25,6 +25,7 @@ enum unicast_state { UC_HAVE_ANN, UC_NEED_SYDY, UC_HAVE_SYDY, + UC_DENIED, }; enum unicast_event { @@ -33,6 +34,7 @@ enum unicast_event { UC_EV_GRANT_SYDY, UC_EV_UNSELECTED, UC_EV_CANCEL, + UC_EV_DISABLE, }; enum unicast_state unicast_fsm(enum unicast_state state, enum unicast_event ev); -- 1.8.3.1 _______________________________________________ Linuxptp-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
