clock: event notification

Split management message creation to more fine-grained functions to allow
notification messages to be created.

The new clock_management_fill_response is called from
clock_management_get_response (so the function behaves exactly the same as
before this patch) and from a new clock_notify_event function. The
difference is clock_management_get_response uses the request message to
construct the reply message, while clock_notify_event constructs the reply
message based on the notification id.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
master
Jiri Benc 2014-05-06 18:41:49 +02:00 committed by Richard Cochran
parent 122314926a
commit 648197153e
4 changed files with 82 additions and 11 deletions

63
clock.c
View File

@ -314,23 +314,22 @@ static void clock_management_send_error(struct port *p,
pr_err("failed to send management error status"); pr_err("failed to send management error status");
} }
static int clock_management_get_response(struct clock *c, struct port *p, /* The 'p' and 'req' paremeters are needed for the GET actions that operate
int id, struct ptp_message *req) * 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; int datalen = 0, respond = 0;
struct management_tlv *tlv; struct management_tlv *tlv;
struct management_tlv_datum *mtd; struct management_tlv_datum *mtd;
struct ptp_message *rsp;
struct time_status_np *tsn; struct time_status_np *tsn;
struct grandmaster_settings_np *gsn; struct grandmaster_settings_np *gsn;
struct subscribe_events_np *sen; struct subscribe_events_np *sen;
struct PortIdentity pid = port_identity(p);
struct PTPText *text; struct PTPText *text;
rsp = port_management_reply(pid, p, req);
if (!rsp) {
return 0;
}
tlv = (struct management_tlv *) rsp->management.suffix; tlv = (struct management_tlv *) rsp->management.suffix;
tlv->type = TLV_MANAGEMENT; tlv->type = TLV_MANAGEMENT;
tlv->id = id; 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; tlv->length = sizeof(tlv->id) + datalen;
rsp->header.messageLength += sizeof(*tlv) + datalen; rsp->header.messageLength += sizeof(*tlv) + datalen;
rsp->tlv_count = 1; 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); msg_put(rsp);
return respond ? 1 : 0; return respond;
} }
static int clock_management_set(struct clock *c, struct port *p, 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; 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) struct parent_ds *clock_parent_ds(struct clock *c)
{ {
return &c->dad; return &c->dad;

View File

@ -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, void clock_send_notification(struct clock *c, struct ptp_message *msg,
int msglen, enum notification event); 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. * Obtain a clock's parent data set.
* @param c The clock instance. * @param c The clock instance.

8
port.c
View File

@ -2337,6 +2337,12 @@ struct ptp_message *port_management_reply(struct PortIdentity pid,
management_action(req)); 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) void port_notify_event(struct port *p, enum notification event)
{ {
struct PortIdentity pid = port_identity(p); 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 /* targetPortIdentity and sequenceId will be filled by
* clock_send_notification */ * clock_send_notification */
msg = port_management_construct(pid, p, 0, NULL, 1, GET); msg = port_management_notify(pid, p);
if (!msg) if (!msg)
return; return;
if (!port_management_fill_response(p, msg, id)) if (!port_management_fill_response(p, msg, id))

14
port.h
View File

@ -156,6 +156,20 @@ struct ptp_message *port_management_reply(struct PortIdentity pid,
struct port *ingress, struct port *ingress,
struct ptp_message *req); 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 * Construct and send notification to subscribers about an event that
* occured on the port. * occured on the port.