From 18dee4563fd81cd1c1fd139fceff8decc4a7b727 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 8 Mar 2022 11:47:00 +0100 Subject: [PATCH] Add support for binding sockets to virtual clocks. 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 --- 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 65bdff0f..445a2708 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 8bf2727c..752f4f14 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 14aa1e6a..20f71933 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 0bd15b08..ce646849 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 8be07081..b55d6b54 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) { + ×tamping, sizeof(timestamping)) < 0) { pr_err("ioctl SO_TIMESTAMPING failed: %m"); return -1; } diff --git a/sk.h b/sk.h index 04d26ee5..486dbc43 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 826bd124..7c9402ea 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 ba5482e3..bde1710b 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))