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

Reply via email to