diff --git a/clock.c b/clock.c index e5d58ba..32ba490 100644 --- a/clock.c +++ b/clock.c @@ -314,23 +314,22 @@ static void clock_management_send_error(struct port *p, pr_err("failed to send management error status"); } -static int clock_management_get_response(struct clock *c, struct port *p, - int id, struct ptp_message *req) +/* The 'p' and 'req' paremeters are needed for the GET actions that operate + * on per-client datasets. If such actions do not apply to the caller, it is + * allowed to pass both of them as NULL. + */ +static int clock_management_fill_response(struct clock *c, struct port *p, + struct ptp_message *req, + struct ptp_message *rsp, int id) { int datalen = 0, respond = 0; struct management_tlv *tlv; struct management_tlv_datum *mtd; - struct ptp_message *rsp; struct time_status_np *tsn; struct grandmaster_settings_np *gsn; struct subscribe_events_np *sen; - struct PortIdentity pid = port_identity(p); struct PTPText *text; - rsp = port_management_reply(pid, p, req); - if (!rsp) { - return 0; - } tlv = (struct management_tlv *) rsp->management.suffix; tlv->type = TLV_MANAGEMENT; tlv->id = id; @@ -450,10 +449,26 @@ static int clock_management_get_response(struct clock *c, struct port *p, tlv->length = sizeof(tlv->id) + datalen; rsp->header.messageLength += sizeof(*tlv) + datalen; rsp->tlv_count = 1; - port_prepare_and_send(p, rsp, 0); } + return respond; +} + +static int clock_management_get_response(struct clock *c, struct port *p, + int id, struct ptp_message *req) +{ + struct PortIdentity pid = port_identity(p); + struct ptp_message *rsp; + int respond; + + rsp = port_management_reply(pid, p, req); + if (!rsp) { + return 0; + } + respond = clock_management_fill_response(c, p, req, rsp, id); + if (respond) + port_prepare_and_send(p, rsp, 0); msg_put(rsp); - return respond ? 1 : 0; + return respond; } static int clock_management_set(struct clock *c, struct port *p, @@ -1064,6 +1079,34 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) return changed; } +void clock_notify_event(struct clock *c, enum notification event) +{ + struct port *uds = c->port[c->nports]; + struct PortIdentity pid = port_identity(uds); + struct ptp_message *msg; + UInteger16 msg_len; + int id; + + switch (event) { + /* set id */ + default: + return; + } + /* targetPortIdentity and sequenceId will be filled by + * clock_send_notification */ + msg = port_management_notify(pid, uds); + if (!msg) + return; + if (!clock_management_fill_response(c, NULL, NULL, msg, id)) + goto err; + msg_len = msg->header.messageLength; + if (msg_pre_send(msg)) + goto err; + clock_send_notification(c, msg, msg_len, event); +err: + msg_put(msg); +} + struct parent_ds *clock_parent_ds(struct clock *c) { return &c->dad; diff --git a/clock.h b/clock.h index 8718f2d..92ec163 100644 --- a/clock.h +++ b/clock.h @@ -144,6 +144,14 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg); void clock_send_notification(struct clock *c, struct ptp_message *msg, int msglen, enum notification event); +/** + * Construct and send notification to subscribers about an event that + * occured on the clock. + * @param c The clock instance. + * @param event The identification of the event. + */ +void clock_notify_event(struct clock *c, enum notification event); + /** * Obtain a clock's parent data set. * @param c The clock instance. diff --git a/port.c b/port.c index bdddd3a..388f757 100644 --- a/port.c +++ b/port.c @@ -2337,6 +2337,12 @@ struct ptp_message *port_management_reply(struct PortIdentity pid, management_action(req)); } +struct ptp_message *port_management_notify(struct PortIdentity pid, + struct port *port) +{ + return port_management_construct(pid, port, 0, NULL, 1, GET); +} + void port_notify_event(struct port *p, enum notification event) { struct PortIdentity pid = port_identity(p); @@ -2351,7 +2357,7 @@ void port_notify_event(struct port *p, enum notification event) } /* targetPortIdentity and sequenceId will be filled by * clock_send_notification */ - msg = port_management_construct(pid, p, 0, NULL, 1, GET); + msg = port_management_notify(pid, p); if (!msg) return; if (!port_management_fill_response(p, msg, id)) diff --git a/port.h b/port.h index 34c18a3..a1b8ad7 100644 --- a/port.h +++ b/port.h @@ -156,6 +156,20 @@ struct ptp_message *port_management_reply(struct PortIdentity pid, struct port *ingress, struct ptp_message *req); +/** + * Allocate a standalone reply management message. + * + * See note in @ref port_management_reply description about freeing the + * message. Also note that the constructed message does not have + * targetPortIdentity and sequenceId filled. + * + * @param pid The id of the responding port. + * @param port The port to which the message will be sent. + * @return Pointer to a message on success, NULL otherwise. + */ +struct ptp_message *port_management_notify(struct PortIdentity pid, + struct port *port); + /** * Construct and send notification to subscribers about an event that * occured on the port.