Skip to content

Commit

Permalink
Add support for binding sockets to virtual clocks.
Browse files Browse the repository at this point in the history
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 <mlichvar@redhat.com>
  • Loading branch information
mlichvar authored and richardcochran committed Mar 8, 2022
1 parent 1efabfc commit 18dee45
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 6 deletions.
12 changes: 12 additions & 0 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
14 changes: 14 additions & 0 deletions interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 11 additions & 0 deletions missing.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
11 changes: 9 additions & 2 deletions sk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion sk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 2 additions & 1 deletion udp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 18dee45

Please sign in to comment.