In certain scenarios it is useful to know whether a remote port is
synchronized, for example when the local system is the PTP master and we
are trying to send time-synchronized data to a slave.

Introduce a new option in ptp4l, which defaults to false, and which
allows the following:

- a remote PMC agent to subscribe to a given data set
- the clock API to push notifications towards a non-local subscriber

The only SET that is supported is adding a subscription, no clock state
can be modified remotely. Nonetheless, there is no authentication
implemented, so the option should be used with care.

Signed-off-by: Vladimir Oltean <olte...@gmail.com>
---
 clock.c  | 22 +++++++++++++++-------
 config.c |  1 +
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/clock.c b/clock.c
index d1c85ec5a7b1..0689360db410 100644
--- a/clock.c
+++ b/clock.c
@@ -76,6 +76,7 @@ struct clock_subscriber {
        struct address addr;
        UInteger16 sequenceId;
        time_t expiration;
+       struct port *port;
 };
 
 struct clock {
@@ -152,8 +153,9 @@ static void remove_subscriber(struct clock_subscriber *s)
        free(s);
 }
 
-static void clock_update_subscription(struct clock *c, struct ptp_message *req,
-                                     uint8_t *bitmask, uint16_t duration)
+static void clock_update_subscription(struct clock *c, struct port *p,
+                                     struct ptp_message *req, uint8_t *bitmask,
+                                     uint16_t duration)
 {
        struct clock_subscriber *s, *tmp;
        struct timespec now;
@@ -175,6 +177,7 @@ static void clock_update_subscription(struct clock *c, 
struct ptp_message *req,
                                memcpy(s->events, bitmask, EVENT_BITMASK_CNT);
                                clock_gettime(CLOCK_MONOTONIC, &now);
                                s->expiration = now.tv_sec + duration;
+                               s->port = p;
                        } else {
                                remove_subscriber(s);
                        }
@@ -195,6 +198,7 @@ static void clock_update_subscription(struct clock *c, 
struct ptp_message *req,
        clock_gettime(CLOCK_MONOTONIC, &now);
        s->expiration = now.tv_sec + duration;
        s->sequenceId = 0;
+       s->port = p;
        LIST_INSERT_HEAD(&c->subscribers, s, list);
 }
 
@@ -248,10 +252,11 @@ static void clock_prune_subscriptions(struct clock *c)
 void clock_send_notification(struct clock *c, struct ptp_message *msg,
                             enum notification event)
 {
-       struct port *uds = c->uds_rw_port;
        struct clock_subscriber *s;
 
        LIST_FOREACH(s, &c->subscribers, list) {
+               struct port *port = s->port ? s->port : c->uds_rw_port;
+
                if (!event_bitmask_get(s->events, event))
                        continue;
                /* send event */
@@ -262,7 +267,7 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
                msg->management.targetPortIdentity.portNumber =
                        htons(s->targetPortIdentity.portNumber);
                msg->address = s->addr;
-               port_forward_to(uds, msg);
+               port_forward_to(port, msg);
        }
 }
 
@@ -532,7 +537,7 @@ static int clock_management_set(struct clock *c, struct 
port *p,
                break;
        case MID_SUBSCRIBE_EVENTS_NP:
                sen = (struct subscribe_events_np *)tlv->data;
-               clock_update_subscription(c, req, sen->bitmask, sen->duration);
+               clock_update_subscription(c, p, req, sen->bitmask, 
sen->duration);
                respond = 1;
                break;
        case MID_SYNCHRONIZATION_UNCERTAIN_NP:
@@ -1436,6 +1441,7 @@ tmv_t clock_ingress_time(struct clock *c)
 
 int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
 {
+       bool allow_remote_subscriptions = config_get_int(c->config, NULL, 
"allow_remote_subscriptions");
        int changed = 0, res, answers;
        struct port *piter;
        struct management_tlv *mgt;
@@ -1472,7 +1478,9 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
                        clock_management_send_error(p, msg, MID_WRONG_LENGTH);
                        return changed;
                }
-               if (p != c->uds_rw_port) {
+               if (p != c->uds_rw_port &&
+                   (!allow_remote_subscriptions ||
+                    mgt->id != MID_SUBSCRIBE_EVENTS_NP)) {
                        /* Sorry, only allowed on the UDS-RW port. */
                        clock_management_send_error(p, msg, MID_NOT_SUPPORTED);
                        return changed;
@@ -1493,7 +1501,7 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
 
        switch (mgt->id) {
        case MID_PORT_PROPERTIES_NP:
-               if (p != c->uds_rw_port) {
+               if (p != c->uds_rw_port && !allow_remote_subscriptions) {
                        /* Only the UDS-RW port allowed. */
                        clock_management_send_error(p, msg, MID_NOT_SUPPORTED);
                        return 0;
diff --git a/config.c b/config.c
index 760d0e12b0b6..6ee46b448adc 100644
--- a/config.c
+++ b/config.c
@@ -221,6 +221,7 @@ static struct config_enum bmca_enu[] = {
 };
 
 struct config_item config_tab[] = {
+       PORT_ITEM_INT("allow_remote_subscriptions", 0, 0, 1),
        PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX),
        PORT_ITEM_ENU("asCapable", AS_CAPABLE_AUTO, as_capable_enu),
        GLOB_ITEM_INT("assume_two_step", 0, 0, 1),
-- 
2.25.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to