Allow the one-step mode to be enabled with software timestamping. In
this mode the transmit timestamp is captured in ptp4l with
clock_gettime() before sending the packet. This enables ptp4l to run on
interfaces that don't support SW TX timestamping.

It is mainly intended for testing, but it could be used also in normal
operation. A typical stability of user-space TX timestamping seem to be
better or at least comparable to kernel RX timestamping, so the
stability of synchronization shouldn't be much worse than with SW TX
timestamping.

The patch was tested only with OC and the delay request mechanism.
---
 clock.c     | 14 +++++++++++---
 config.c    | 10 ++++++++++
 msg.h       |  1 +
 port.c      |  5 +++--
 sk.c        |  8 +++++++-
 transport.c | 33 +++++++++++++++++++++++++++++++++
 6 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/clock.c b/clock.c
index ef9a008..edbd1ba 100644
--- a/clock.c
+++ b/clock.c
@@ -822,6 +822,10 @@ int clock_required_modes(struct clock *c)
                        SOF_TIMESTAMPING_RX_SOFTWARE |
                        SOF_TIMESTAMPING_SOFTWARE;
                break;
+       case TS_SOFTWARE_RX:
+               required_modes |= SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE;
+               break;
        case TS_LEGACY_HW:
                required_modes |= SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
@@ -946,7 +950,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                c->dds.flags |= DDS_TWO_STEP_FLAG;
        }
        timestamping = config_get_int(config, NULL, "time_stamping");
-       if (timestamping == TS_SOFTWARE) {
+       if (timestamping == TS_SOFTWARE || timestamping == TS_SOFTWARE_RX) {
                sw_ts = 1;
        } else {
                sw_ts = 0;
@@ -975,7 +979,9 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        /* determine PHC Clock index */
        if (config_get_int(config, NULL, "free_running")) {
                phc_index = -1;
-       } else if (timestamping == TS_SOFTWARE || timestamping == TS_LEGACY_HW) 
{
+       } else if (timestamping == TS_SOFTWARE ||
+                  timestamping == TS_SOFTWARE_RX ||
+                  timestamping == TS_LEGACY_HW) {
                phc_index = -1;
        } else if (phc_device) {
                if (1 != sscanf(phc_device, "/dev/ptp%d", &phc_index)) {
@@ -1037,7 +1043,9 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
 
        if (c->free_running) {
                c->clkid = CLOCK_INVALID;
-               if (timestamping == TS_SOFTWARE || timestamping == 
TS_LEGACY_HW) {
+               if (timestamping == TS_SOFTWARE ||
+                   timestamping == TS_SOFTWARE_RX ||
+                   timestamping == TS_LEGACY_HW) {
                        c->utc_timescale = 1;
                }
        } else if (phc_index >= 0) {
diff --git a/config.c b/config.c
index 2321310..241cab5 100644
--- a/config.c
+++ b/config.c
@@ -970,6 +970,15 @@ int config_harmonize_onestep(struct config *cfg)
 
        switch (tstype) {
        case TS_SOFTWARE:
+               if (!two_step_flag) {
+                       pr_debug("downgrading to user-space TX time stamping "
+                                "in order to match the twoStepFlag");
+                       if (config_set_int(cfg, "time_stamping",
+                                          TS_SOFTWARE_RX)) {
+                               return -1;
+                       }
+               }
+               break;
        case TS_LEGACY_HW:
                if (!two_step_flag) {
                        pr_err("one step is only possible "
@@ -986,6 +995,7 @@ int config_harmonize_onestep(struct config *cfg)
                        }
                }
                break;
+       case TS_SOFTWARE_RX:
        case TS_ONESTEP:
        case TS_P2P1STEP:
                if (two_step_flag) {
diff --git a/msg.h b/msg.h
index b5a57fe..4a6de3f 100644
--- a/msg.h
+++ b/msg.h
@@ -59,6 +59,7 @@
 
 enum timestamp_type {
        TS_SOFTWARE,
+       TS_SOFTWARE_RX,
        TS_HARDWARE,
        TS_LEGACY_HW,
        TS_ONESTEP,
diff --git a/port.c b/port.c
index 142b970..a2a870f 100644
--- a/port.c
+++ b/port.c
@@ -1398,6 +1398,7 @@ int port_tx_sync(struct port *p, struct address *dst)
        case TS_HARDWARE:
                event = TRANS_EVENT;
                break;
+       case TS_SOFTWARE_RX:
        case TS_ONESTEP:
                event = TRANS_ONESTEP;
                break;
@@ -1438,7 +1439,7 @@ int port_tx_sync(struct port *p, struct address *dst)
        msg->header.control            = CTL_SYNC;
        msg->header.logMessageInterval = p->logSyncInterval;
 
-       if (p->timestamping != TS_ONESTEP && p->timestamping != TS_P2P1STEP) {
+       if (event != TRANS_ONESTEP && event != TRANS_P2P1STEP) {
                msg->header.flagField[0] |= TWO_STEP;
        }
 
@@ -1452,7 +1453,7 @@ int port_tx_sync(struct port *p, struct address *dst)
                pr_err("port %hu: send sync failed", portnum(p));
                goto out;
        }
-       if (p->timestamping == TS_ONESTEP || p->timestamping == TS_P2P1STEP) {
+       if (event == TRANS_ONESTEP || event == TRANS_P2P1STEP) {
                goto out;
        } else if (msg_sots_missing(msg)) {
                pr_err("missing timestamp on transmitted sync");
diff --git a/sk.c b/sk.c
index 30162eb..58e3a1d 100644
--- a/sk.c
+++ b/sk.c
@@ -393,6 +393,7 @@ int sk_receive(int fd, void *buf, int buflen,
 
        switch (hwts->type) {
        case TS_SOFTWARE:
+       case TS_SOFTWARE_RX:
                hwts->ts = timespec_to_tmv(ts[0]);
                break;
        case TS_HARDWARE:
@@ -454,6 +455,10 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                        SOF_TIMESTAMPING_RX_SOFTWARE |
                        SOF_TIMESTAMPING_SOFTWARE;
                break;
+       case TS_SOFTWARE_RX:
+               flags = SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE;
+               break;
        case TS_HARDWARE:
        case TS_ONESTEP:
        case TS_P2P1STEP:
@@ -470,10 +475,11 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                return -1;
        }
 
-       if (type != TS_SOFTWARE) {
+       if (type != TS_SOFTWARE && type != TS_SOFTWARE_RX) {
                filter1 = HWTSTAMP_FILTER_PTP_V2_EVENT;
                switch (type) {
                case TS_SOFTWARE:
+               case TS_SOFTWARE_RX:
                        tx_type = HWTSTAMP_TX_OFF;
                        break;
                case TS_HARDWARE:
diff --git a/transport.c b/transport.c
index 9366fbf..5c52a46 100644
--- a/transport.c
+++ b/transport.c
@@ -42,11 +42,40 @@ int transport_recv(struct transport *t, int fd, struct 
ptp_message *msg)
        return t->recv(t, fd, msg, sizeof(msg->data), &msg->address, 
&msg->hwts);
 }
 
+static void sw_clock_event(enum transport_event *event, struct ptp_message 
*msg)
+{
+       struct Timestamp *ts;
+       struct timespec now;
+
+       if (msg->hwts.type != TS_SOFTWARE_RX)
+              return;
+
+       clock_gettime(CLOCK_REALTIME, &now);
+
+       switch (*event) {
+       case TRANS_EVENT:
+               msg->hwts.ts = timespec_to_tmv(now);
+               *event = TRANS_DEFER_EVENT;
+               break;
+       case TRANS_ONESTEP:
+               ts = &msg->sync.originTimestamp;
+               *ts = tmv_to_Timestamp(timespec_to_tmv(now));
+               ts->seconds_lsb = htonl(ts->seconds_lsb);
+               ts->seconds_msb = htons(ts->seconds_msb);
+               ts->nanoseconds = htonl(ts->nanoseconds);
+               break;
+       default:
+               break;
+       }
+}
+
 int transport_send(struct transport *t, struct fdarray *fda,
                   enum transport_event event, struct ptp_message *msg)
 {
        int len = ntohs(msg->header.messageLength);
 
+       sw_clock_event(&event, msg);
+
        return t->send(t, fda, event, 0, msg, len, NULL, &msg->hwts);
 }
 
@@ -55,6 +84,8 @@ int transport_peer(struct transport *t, struct fdarray *fda,
 {
        int len = ntohs(msg->header.messageLength);
 
+       sw_clock_event(&event, msg);
+
        return t->send(t, fda, event, 1, msg, len, NULL, &msg->hwts);
 }
 
@@ -63,6 +94,8 @@ int transport_sendto(struct transport *t, struct fdarray *fda,
 {
        int len = ntohs(msg->header.messageLength);
 
+       sw_clock_event(&event, msg);
+
        return t->send(t, fda, event, 0, msg, len, &msg->address, &msg->hwts);
 }
 
-- 
2.17.2



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

Reply via email to