Subscription time limit
Add expiration time to subscriptions; they need to be renewed before they expiry. This way, the subscription automatically times out when phc2sys is killed. Signed-off-by: Jiri Benc <jbenc@redhat.com>master
parent
5104e3e56b
commit
0e8efe418c
38
clock.c
38
clock.c
|
@ -66,6 +66,7 @@ struct clock_subscriber {
|
||||||
struct PortIdentity targetPortIdentity;
|
struct PortIdentity targetPortIdentity;
|
||||||
struct address addr;
|
struct address addr;
|
||||||
UInteger16 sequenceId;
|
UInteger16 sequenceId;
|
||||||
|
time_t expiration;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clock {
|
struct clock {
|
||||||
|
@ -134,10 +135,11 @@ static void remove_subscriber(struct clock_subscriber *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clock_update_subscription(struct clock *c, struct ptp_message *req,
|
static void clock_update_subscription(struct clock *c, struct ptp_message *req,
|
||||||
uint8_t *bitmask)
|
uint8_t *bitmask, uint16_t duration)
|
||||||
{
|
{
|
||||||
struct clock_subscriber *s;
|
struct clock_subscriber *s;
|
||||||
int i, remove = 1;
|
int i, remove = 1;
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
for (i = 0; i < EVENT_BITMASK_CNT; i++) {
|
for (i = 0; i < EVENT_BITMASK_CNT; i++) {
|
||||||
if (bitmask[i]) {
|
if (bitmask[i]) {
|
||||||
|
@ -154,6 +156,8 @@ static void clock_update_subscription(struct clock *c, struct ptp_message *req,
|
||||||
if (!remove) {
|
if (!remove) {
|
||||||
s->addr = req->address;
|
s->addr = req->address;
|
||||||
memcpy(s->events, bitmask, EVENT_BITMASK_CNT);
|
memcpy(s->events, bitmask, EVENT_BITMASK_CNT);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
s->expiration = now.tv_sec + duration;
|
||||||
} else {
|
} else {
|
||||||
remove_subscriber(s);
|
remove_subscriber(s);
|
||||||
}
|
}
|
||||||
|
@ -171,24 +175,33 @@ static void clock_update_subscription(struct clock *c, struct ptp_message *req,
|
||||||
s->targetPortIdentity = req->header.sourcePortIdentity;
|
s->targetPortIdentity = req->header.sourcePortIdentity;
|
||||||
s->addr = req->address;
|
s->addr = req->address;
|
||||||
memcpy(s->events, bitmask, EVENT_BITMASK_CNT);
|
memcpy(s->events, bitmask, EVENT_BITMASK_CNT);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
s->expiration = now.tv_sec + duration;
|
||||||
s->sequenceId = 0;
|
s->sequenceId = 0;
|
||||||
LIST_INSERT_HEAD(&c->subscribers, s, list);
|
LIST_INSERT_HEAD(&c->subscribers, s, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clock_get_subscription(struct clock *c, struct ptp_message *req,
|
static void clock_get_subscription(struct clock *c, struct ptp_message *req,
|
||||||
uint8_t *bitmask)
|
uint8_t *bitmask, uint16_t *duration)
|
||||||
{
|
{
|
||||||
struct clock_subscriber *s;
|
struct clock_subscriber *s;
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
LIST_FOREACH(s, &c->subscribers, list) {
|
LIST_FOREACH(s, &c->subscribers, list) {
|
||||||
if (!memcmp(&s->targetPortIdentity, &req->header.sourcePortIdentity,
|
if (!memcmp(&s->targetPortIdentity, &req->header.sourcePortIdentity,
|
||||||
sizeof(struct PortIdentity))) {
|
sizeof(struct PortIdentity))) {
|
||||||
memcpy(bitmask, s->events, EVENT_BITMASK_CNT);
|
memcpy(bitmask, s->events, EVENT_BITMASK_CNT);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
if (s->expiration < now.tv_sec)
|
||||||
|
*duration = 0;
|
||||||
|
else
|
||||||
|
*duration = s->expiration - now.tv_sec;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* A client without entry means the client has no subscriptions. */
|
/* A client without entry means the client has no subscriptions. */
|
||||||
memset(bitmask, 0, EVENT_BITMASK_CNT);
|
memset(bitmask, 0, EVENT_BITMASK_CNT);
|
||||||
|
*duration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clock_flush_subscriptions(struct clock *c)
|
static void clock_flush_subscriptions(struct clock *c)
|
||||||
|
@ -200,6 +213,21 @@ static void clock_flush_subscriptions(struct clock *c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clock_prune_subscriptions(struct clock *c)
|
||||||
|
{
|
||||||
|
struct clock_subscriber *s, *tmp;
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
LIST_FOREACH_SAFE(s, &c->subscribers, list, tmp) {
|
||||||
|
if (s->expiration <= now.tv_sec) {
|
||||||
|
pr_info("subscriber %s timed out",
|
||||||
|
pid2str(&s->targetPortIdentity));
|
||||||
|
remove_subscriber(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -410,7 +438,7 @@ static int clock_management_get_response(struct clock *c, struct port *p,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sen = (struct subscribe_events_np *)tlv->data;
|
sen = (struct subscribe_events_np *)tlv->data;
|
||||||
clock_get_subscription(c, req, sen->bitmask);
|
clock_get_subscription(c, req, sen->bitmask, &sen->duration);
|
||||||
respond = 1;
|
respond = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -450,7 +478,8 @@ static int clock_management_set(struct clock *c, struct port *p,
|
||||||
break;
|
break;
|
||||||
case SUBSCRIBE_EVENTS_NP:
|
case SUBSCRIBE_EVENTS_NP:
|
||||||
sen = (struct subscribe_events_np *)tlv->data;
|
sen = (struct subscribe_events_np *)tlv->data;
|
||||||
clock_update_subscription(c, req, sen->bitmask);
|
clock_update_subscription(c, req, sen->bitmask,
|
||||||
|
sen->duration);
|
||||||
respond = 1;
|
respond = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1103,6 +1132,7 @@ int clock_poll(struct clock *c)
|
||||||
if (sde)
|
if (sde)
|
||||||
handle_state_decision_event(c);
|
handle_state_decision_event(c);
|
||||||
|
|
||||||
|
clock_prune_subscriptions(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
tlv.c
8
tlv.c
|
@ -62,6 +62,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
||||||
struct port_ds_np *pdsnp;
|
struct port_ds_np *pdsnp;
|
||||||
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 mgmt_clock_description *cd;
|
struct mgmt_clock_description *cd;
|
||||||
int extra_len = 0, len;
|
int extra_len = 0, len;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
@ -245,6 +246,8 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
||||||
case SUBSCRIBE_EVENTS_NP:
|
case SUBSCRIBE_EVENTS_NP:
|
||||||
if (data_len != sizeof(struct subscribe_events_np))
|
if (data_len != sizeof(struct subscribe_events_np))
|
||||||
goto bad_length;
|
goto bad_length;
|
||||||
|
sen = (struct subscribe_events_np *)m->data;
|
||||||
|
sen->duration = ntohs(sen->duration);
|
||||||
break;
|
break;
|
||||||
case SAVE_IN_NON_VOLATILE_STORAGE:
|
case SAVE_IN_NON_VOLATILE_STORAGE:
|
||||||
case RESET_NON_VOLATILE_STORAGE:
|
case RESET_NON_VOLATILE_STORAGE:
|
||||||
|
@ -277,6 +280,7 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
|
||||||
struct port_ds_np *pdsnp;
|
struct port_ds_np *pdsnp;
|
||||||
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 mgmt_clock_description *cd;
|
struct mgmt_clock_description *cd;
|
||||||
switch (m->id) {
|
switch (m->id) {
|
||||||
case CLOCK_DESCRIPTION:
|
case CLOCK_DESCRIPTION:
|
||||||
|
@ -341,6 +345,10 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
|
||||||
pdsnp->neighborPropDelayThresh = htonl(pdsnp->neighborPropDelayThresh);
|
pdsnp->neighborPropDelayThresh = htonl(pdsnp->neighborPropDelayThresh);
|
||||||
pdsnp->asCapable = htonl(pdsnp->asCapable);
|
pdsnp->asCapable = htonl(pdsnp->asCapable);
|
||||||
break;
|
break;
|
||||||
|
case SUBSCRIBE_EVENTS_NP:
|
||||||
|
sen = (struct subscribe_events_np *)m->data;
|
||||||
|
sen->duration = htons(sen->duration);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue