Skip to content

Commit d463126

Browse files
yangbolu1991davem330
authored andcommitted
net: sock: extend SO_TIMESTAMPING for PHC binding
Since PTP virtual clock support is added, there can be several PTP virtual clocks based on one PTP physical clock for timestamping. This patch is to extend SO_TIMESTAMPING API to support PHC (PTP Hardware Clock) binding by adding a new flag SOF_TIMESTAMPING_BIND_PHC. When PTP virtual clocks are in use, user space can configure to bind one for timestamping, but PTP physical clock is not supported and not needed to bind. This patch is preparation for timestamp conversion from raw timestamp to a specific PTP virtual clock time in core net. Signed-off-by: Yangbo Lu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6c9a0a0 commit d463126

File tree

5 files changed

+101
-13
lines changed

5 files changed

+101
-13
lines changed

include/net/sock.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ struct bpf_local_storage;
316316
* @sk_timer: sock cleanup timer
317317
* @sk_stamp: time stamp of last packet received
318318
* @sk_stamp_seq: lock for accessing sk_stamp on 32 bit architectures only
319-
* @sk_tsflags: SO_TIMESTAMPING socket options
319+
* @sk_tsflags: SO_TIMESTAMPING flags
320+
* @sk_bind_phc: SO_TIMESTAMPING bind PHC index of PTP virtual clock
321+
* for timestamping
320322
* @sk_tskey: counter to disambiguate concurrent tstamp requests
321323
* @sk_zckey: counter to order MSG_ZEROCOPY notifications
322324
* @sk_socket: Identd and reporting IO signals
@@ -493,6 +495,7 @@ struct sock {
493495
seqlock_t sk_stamp_seq;
494496
#endif
495497
u16 sk_tsflags;
498+
int sk_bind_phc;
496499
u8 sk_shutdown;
497500
u32 sk_tskey;
498501
atomic_t sk_zckey;
@@ -2755,7 +2758,8 @@ void sock_def_readable(struct sock *sk);
27552758

27562759
int sock_bindtoindex(struct sock *sk, int ifindex, bool lock_sk);
27572760
void sock_set_timestamp(struct sock *sk, int optname, bool valbool);
2758-
int sock_set_timestamping(struct sock *sk, int optname, int val);
2761+
int sock_set_timestamping(struct sock *sk, int optname,
2762+
struct so_timestamping timestamping);
27592763

27602764
void sock_enable_timestamps(struct sock *sk);
27612765
void sock_no_linger(struct sock *sk);

include/uapi/linux/net_tstamp.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <linux/types.h>
1414
#include <linux/socket.h> /* for SO_TIMESTAMPING */
1515

16-
/* SO_TIMESTAMPING gets an integer bit field comprised of these values */
16+
/* SO_TIMESTAMPING flags */
1717
enum {
1818
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
1919
SOF_TIMESTAMPING_TX_SOFTWARE = (1<<1),
@@ -30,8 +30,9 @@ enum {
3030
SOF_TIMESTAMPING_OPT_STATS = (1<<12),
3131
SOF_TIMESTAMPING_OPT_PKTINFO = (1<<13),
3232
SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
33+
SOF_TIMESTAMPING_BIND_PHC = (1 << 15),
3334

34-
SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TX_SWHW,
35+
SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_BIND_PHC,
3536
SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
3637
SOF_TIMESTAMPING_LAST
3738
};
@@ -46,6 +47,18 @@ enum {
4647
SOF_TIMESTAMPING_TX_SCHED | \
4748
SOF_TIMESTAMPING_TX_ACK)
4849

50+
/**
51+
* struct so_timestamping - SO_TIMESTAMPING parameter
52+
*
53+
* @flags: SO_TIMESTAMPING flags
54+
* @bind_phc: Index of PTP virtual clock bound to sock. This is available
55+
* if flag SOF_TIMESTAMPING_BIND_PHC is set.
56+
*/
57+
struct so_timestamping {
58+
int flags;
59+
int bind_phc;
60+
};
61+
4962
/**
5063
* struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
5164
*

net/core/sock.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@
139139
#include <net/tcp.h>
140140
#include <net/busy_poll.h>
141141

142+
#include <linux/ethtool.h>
143+
142144
static DEFINE_MUTEX(proto_list_mutex);
143145
static LIST_HEAD(proto_list);
144146

@@ -810,8 +812,47 @@ void sock_set_timestamp(struct sock *sk, int optname, bool valbool)
810812
}
811813
}
812814

813-
int sock_set_timestamping(struct sock *sk, int optname, int val)
815+
static int sock_timestamping_bind_phc(struct sock *sk, int phc_index)
814816
{
817+
struct net *net = sock_net(sk);
818+
struct net_device *dev = NULL;
819+
bool match = false;
820+
int *vclock_index;
821+
int i, num;
822+
823+
if (sk->sk_bound_dev_if)
824+
dev = dev_get_by_index(net, sk->sk_bound_dev_if);
825+
826+
if (!dev) {
827+
pr_err("%s: sock not bind to device\n", __func__);
828+
return -EOPNOTSUPP;
829+
}
830+
831+
num = ethtool_get_phc_vclocks(dev, &vclock_index);
832+
for (i = 0; i < num; i++) {
833+
if (*(vclock_index + i) == phc_index) {
834+
match = true;
835+
break;
836+
}
837+
}
838+
839+
if (num > 0)
840+
kfree(vclock_index);
841+
842+
if (!match)
843+
return -EINVAL;
844+
845+
sk->sk_bind_phc = phc_index;
846+
847+
return 0;
848+
}
849+
850+
int sock_set_timestamping(struct sock *sk, int optname,
851+
struct so_timestamping timestamping)
852+
{
853+
int val = timestamping.flags;
854+
int ret;
855+
815856
if (val & ~SOF_TIMESTAMPING_MASK)
816857
return -EINVAL;
817858

@@ -832,6 +873,12 @@ int sock_set_timestamping(struct sock *sk, int optname, int val)
832873
!(val & SOF_TIMESTAMPING_OPT_TSONLY))
833874
return -EINVAL;
834875

876+
if (val & SOF_TIMESTAMPING_BIND_PHC) {
877+
ret = sock_timestamping_bind_phc(sk, timestamping.bind_phc);
878+
if (ret)
879+
return ret;
880+
}
881+
835882
sk->sk_tsflags = val;
836883
sock_valbool_flag(sk, SOCK_TSTAMP_NEW, optname == SO_TIMESTAMPING_NEW);
837884

@@ -907,6 +954,7 @@ EXPORT_SYMBOL(sock_set_mark);
907954
int sock_setsockopt(struct socket *sock, int level, int optname,
908955
sockptr_t optval, unsigned int optlen)
909956
{
957+
struct so_timestamping timestamping;
910958
struct sock_txtime sk_txtime;
911959
struct sock *sk = sock->sk;
912960
int val;
@@ -1073,7 +1121,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
10731121

10741122
case SO_TIMESTAMPING_NEW:
10751123
case SO_TIMESTAMPING_OLD:
1076-
ret = sock_set_timestamping(sk, optname, val);
1124+
if (optlen == sizeof(timestamping)) {
1125+
if (copy_from_sockptr(&timestamping, optval,
1126+
sizeof(timestamping)))
1127+
return -EFAULT;
1128+
} else {
1129+
memset(&timestamping, 0, sizeof(timestamping));
1130+
timestamping.flags = val;
1131+
}
1132+
ret = sock_set_timestamping(sk, optname, timestamping);
10771133
break;
10781134

10791135
case SO_RCVLOWAT:
@@ -1348,6 +1404,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
13481404
struct __kernel_old_timeval tm;
13491405
struct __kernel_sock_timeval stm;
13501406
struct sock_txtime txtime;
1407+
struct so_timestamping timestamping;
13511408
} v;
13521409

13531410
int lv = sizeof(int);
@@ -1451,7 +1508,9 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
14511508
break;
14521509

14531510
case SO_TIMESTAMPING_OLD:
1454-
v.val = sk->sk_tsflags;
1511+
lv = sizeof(v.timestamping);
1512+
v.timestamping.flags = sk->sk_tsflags;
1513+
v.timestamping.bind_phc = sk->sk_bind_phc;
14551514
break;
14561515

14571516
case SO_RCVTIMEO_OLD:

net/ethtool/common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = {
398398
[const_ilog2(SOF_TIMESTAMPING_OPT_STATS)] = "option-stats",
399399
[const_ilog2(SOF_TIMESTAMPING_OPT_PKTINFO)] = "option-pktinfo",
400400
[const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw",
401+
[const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc",
401402
};
402403
static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);
403404

net/mptcp/sockopt.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,25 @@ static int mptcp_setsockopt_sol_socket_timestamping(struct mptcp_sock *msk,
207207
{
208208
struct mptcp_subflow_context *subflow;
209209
struct sock *sk = (struct sock *)msk;
210-
int val, ret;
210+
struct so_timestamping timestamping;
211+
int ret;
211212

212-
ret = mptcp_get_int_option(msk, optval, optlen, &val);
213-
if (ret)
214-
return ret;
213+
if (optlen == sizeof(timestamping)) {
214+
if (copy_from_sockptr(&timestamping, optval,
215+
sizeof(timestamping)))
216+
return -EFAULT;
217+
} else if (optlen == sizeof(int)) {
218+
memset(&timestamping, 0, sizeof(timestamping));
219+
220+
if (copy_from_sockptr(&timestamping.flags, optval, sizeof(int)))
221+
return -EFAULT;
222+
} else {
223+
return -EINVAL;
224+
}
215225

216226
ret = sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname,
217-
KERNEL_SOCKPTR(&val), sizeof(val));
227+
KERNEL_SOCKPTR(&timestamping),
228+
sizeof(timestamping));
218229
if (ret)
219230
return ret;
220231

@@ -224,7 +235,7 @@ static int mptcp_setsockopt_sol_socket_timestamping(struct mptcp_sock *msk,
224235
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
225236
bool slow = lock_sock_fast(ssk);
226237

227-
sock_set_timestamping(sk, optname, val);
238+
sock_set_timestamping(sk, optname, timestamping);
228239
unlock_sock_fast(ssk, slow);
229240
}
230241

0 commit comments

Comments
 (0)