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
Jiri Benc 2014-05-06 18:41:47 +02:00 committed by Richard Cochran
parent 5104e3e56b
commit 0e8efe418c
3 changed files with 43 additions and 4 deletions

38
clock.c
View File

@ -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
View File

@ -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;
} }
} }

1
tlv.h
View File

@ -201,6 +201,7 @@ struct port_ds_np {
#define EVENT_BITMASK_CNT 64 #define EVENT_BITMASK_CNT 64
struct subscribe_events_np { struct subscribe_events_np {
uint16_t duration; /* seconds */
uint8_t bitmask[EVENT_BITMASK_CNT]; uint8_t bitmask[EVENT_BITMASK_CNT];
} PACKED; } PACKED;