With the latest kernels it is possible to create virtual PHCs on top of
a free-running physical PHC. In order for the application to get
timestamps captured by the clock which it is controlling, it needs to
bind its sockets to the clock using a new field in the SO_TIMESTAMPING
option.

Extend the interface structure with the vclock index and modify the
transport code to pass it to sk_timestamping_init() to bind the sockets
to the clock.

Signed-off-by: Miroslav Lichvar <mlich...@redhat.com>
---
 interface.c | 12 ++++++++++++
 interface.h | 14 ++++++++++++++
 missing.h   | 11 +++++++++++
 raw.c       |  3 ++-
 sk.c        | 11 +++++++++--
 sk.h        |  3 ++-
 udp.c       |  3 ++-
 udp6.c      |  3 ++-
 8 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/interface.c b/interface.c
index 65bdff0..445a270 100644
--- a/interface.c
+++ b/interface.c
@@ -12,6 +12,7 @@ struct interface {
        char name[MAX_IFNAME_SIZE + 1];
        char ts_label[MAX_IFNAME_SIZE + 1];
        struct sk_ts_info ts_info;
+       int vclock;
 };
 
 struct interface *interface_create(const char *name)
@@ -23,6 +24,7 @@ struct interface *interface_create(const char *name)
                return NULL;
        }
        strncpy(iface->name, name, MAX_IFNAME_SIZE);
+       iface->vclock = -1;
 
        return iface;
 }
@@ -76,3 +78,13 @@ bool interface_tsmodes_supported(struct interface *iface, 
int modes)
        }
        return false;
 }
+
+void interface_set_vclock(struct interface *iface, int vclock)
+{
+       iface->vclock = vclock;
+}
+
+int interface_get_vclock(struct interface *iface)
+{
+       return iface->vclock;
+}
diff --git a/interface.h b/interface.h
index 8bf2727..752f4f1 100644
--- a/interface.h
+++ b/interface.h
@@ -91,4 +91,18 @@ bool interface_tsinfo_valid(struct interface *iface);
  */
 bool interface_tsmodes_supported(struct interface *iface, int modes);
 
+/**
+ * Set the vclock (virtual PHC) to be used for timestamping on an interface.
+ * @param iface  The interface of interest.
+ * @param vclock The index of the vclock.
+ */
+void interface_set_vclock(struct interface *iface, int vclock);
+
+/**
+ * Get the vclock index set for the interface.
+ * @param iface  The interface of interest.
+ * @return       The index of the vclock, or -1 if not set.
+ */
+int interface_get_vclock(struct interface *iface);
+
 #endif
diff --git a/missing.h b/missing.h
index 14aa1e6..20f7193 100644
--- a/missing.h
+++ b/missing.h
@@ -62,6 +62,17 @@ enum {
 };
 #endif
 
+#ifndef HAVE_VCLOCKS
+enum {
+       SOF_TIMESTAMPING_BIND_PHC = (1 << 15),
+};
+
+struct so_timestamping {
+       int flags;
+       int bind_phc;
+};
+#endif
+
 #ifdef PTP_EXTTS_REQUEST2
 #define PTP_EXTTS_REQUEST_FAILED "PTP_EXTTS_REQUEST2 failed: %m"
 #else
diff --git a/raw.c b/raw.c
index 0bd15b0..ce64684 100644
--- a/raw.c
+++ b/raw.c
@@ -243,7 +243,8 @@ static int raw_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3))
+       if (sk_timestamping_init(efd, name, ts_type, TRANS_IEEE_802_3,
+                                interface_get_vclock(iface)))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
diff --git a/sk.c b/sk.c
index 8be0708..b55d6b5 100644
--- a/sk.c
+++ b/sk.c
@@ -447,9 +447,10 @@ int sk_set_priority(int fd, int family, uint8_t dscp)
 }
 
 int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
-                        enum transport_type transport)
+                        enum transport_type transport, int vclock)
 {
        int err, filter1, filter2 = 0, flags, tx_type = HWTSTAMP_TX_ON;
+       struct so_timestamping timestamping;
 
        switch (type) {
        case TS_SOFTWARE:
@@ -509,8 +510,14 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                        return err;
        }
 
+       if (vclock >= 0)
+               flags |= SOF_TIMESTAMPING_BIND_PHC;
+
+       timestamping.flags = flags;
+       timestamping.bind_phc = vclock;
+
        if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
-                      &flags, sizeof(flags)) < 0) {
+                      &timestamping, sizeof(timestamping)) < 0) {
                pr_err("ioctl SO_TIMESTAMPING failed: %m");
                return -1;
        }
diff --git a/sk.h b/sk.h
index 04d26ee..486dbc4 100644
--- a/sk.h
+++ b/sk.h
@@ -124,10 +124,11 @@ int sk_set_priority(int fd, int family, uint8_t dscp);
  * @param device      The name of the network interface to configure.
  * @param type        The requested flavor of time stamping.
  * @param transport   The type of transport used.
+ * @param vclock      Index of the virtual PHC, or -1 for the physical clock.
  * @return            Zero on success, non-zero otherwise.
  */
 int sk_timestamping_init(int fd, const char *device, enum timestamp_type type,
-                        enum transport_type transport);
+                        enum transport_type transport, int vclock);
 
 /**
  * Limits the time that RECVMSG(2) will poll while waiting for the tx timestamp
diff --git a/udp.c b/udp.c
index 826bd12..7c9402e 100644
--- a/udp.c
+++ b/udp.c
@@ -179,7 +179,8 @@ static int udp_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, interface_label(iface), ts_type, 
TRANS_UDP_IPV4))
+       if (sk_timestamping_init(efd, interface_label(iface), ts_type, 
TRANS_UDP_IPV4,
+                                interface_get_vclock(iface)))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
diff --git a/udp6.c b/udp6.c
index ba5482e..bde1710 100644
--- a/udp6.c
+++ b/udp6.c
@@ -196,7 +196,8 @@ static int udp6_open(struct transport *t, struct interface 
*iface,
        if (gfd < 0)
                goto no_general;
 
-       if (sk_timestamping_init(efd, interface_label(iface), ts_type, 
TRANS_UDP_IPV6))
+       if (sk_timestamping_init(efd, interface_label(iface), ts_type,
+                                TRANS_UDP_IPV6, interface_get_vclock(iface)))
                goto no_timestamping;
 
        if (sk_general_init(gfd))
-- 
2.35.1



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

Reply via email to