History

net-timestamp: introduce SOF_TIMESTAMPING_OPT_RX_FILTER flag

introduce a new flag SOF_TIMESTAMPING_OPT_RX_FILTER in the receive path. User can set it with SOF_TIMESTAMPING_SOFTWARE to filter out rx software timestamp report, especially after a process turns on netstamp_needed_key which can time stamp every incoming skb. Previously, we found out if an application starts first which turns on netstamp_needed_key, then another one only passing SOF_TIMESTAMPING_SOFTWARE could also get rx timestamp. Now we handle this case by introducing this new flag without breaking users. Quoting Willem to explain why we need the flag: "why a process would want to request software timestamp reporting, but not receive software timestamp generation. The only use I see is when the application does request SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_SOFTWARE." Similarly, this new flag could also be used for hardware case where we can set it with SOF_TIMESTAMPING_RAW_HARDWARE, then we won't receive hardware receive timestamp. Another thing about errqueue in this patch I have a few words to say: In this case, we need to handle the egress path carefully, or else reporting the tx timestamp will fail. Egress path and ingress path will finally call sock_recv_timestamp(). We have to distinguish them. Errqueue is a good indicator to reflect the flow direction.

Jason Xing committed 2 years ago

Commit be8e9eb1 parent e503f825 files · +35 −5Browse files

Unified · Split

5 files
  1. Documentation/networking/timestamping.rst +17 −0
  2. include/uapi/linux/net_tstamp.h +2 −1
  3. net/ethtool/common.c +1 −0
  4. net/ipv4/tcp.c +7 −2
  5. net/socket.c +8 −2
Documentation/networking/timestamping.rst+17−0
@@ -267,6 +267,23 @@ SOF_TIMESTAMPING_OPT_TX_SWHW: · 266 unmodified lines
267 two separate messages will be looped to the socket's error queue,267 two separate messages will be looped to the socket's error queue,
268 each containing just one timestamp.268 each containing just one timestamp.
269 269
270SOF_TIMESTAMPING_OPT_RX_FILTER:
271 Filter out spurious receive timestamps: report a receive timestamp
272 only if the matching timestamp generation flag is enabled.
273
274 Receive timestamps are generated early in the ingress path, before a
275 packet's destination socket is known. If any socket enables receive
276 timestamps, packets for all socket will receive timestamped packets.
277 Including those that request timestamp reporting with
278 SOF_TIMESTAMPING_SOFTWARE and/or SOF_TIMESTAMPING_RAW_HARDWARE, but
279 do not request receive timestamp generation. This can happen when
280 requesting transmit timestamps only.
281
282 Receiving spurious timestamps is generally benign. A process can
283 ignore the unexpected non-zero value. But it makes behavior subtly
284 dependent on other sockets. This flag isolates the socket for more
285 deterministic behavior.
286
270New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to287New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
271disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate288disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
272regardless of the setting of sysctl net.core.tstamp_allow_data.289regardless of the setting of sysctl net.core.tstamp_allow_data.
include/uapi/linux/net_tstamp.h+2−1
@@ -32,8 +32,9 @@ enum { · 31 unmodified lines
32 SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),32 SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
33 SOF_TIMESTAMPING_BIND_PHC = (1 << 15),33 SOF_TIMESTAMPING_BIND_PHC = (1 << 15),
34 SOF_TIMESTAMPING_OPT_ID_TCP = (1 << 16),34 SOF_TIMESTAMPING_OPT_ID_TCP = (1 << 16),
35 SOF_TIMESTAMPING_OPT_RX_FILTER = (1 << 17),
35 36
36 SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_ID_TCP,37 SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_RX_FILTER,
37 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |38 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
38 SOF_TIMESTAMPING_LAST39 SOF_TIMESTAMPING_LAST
39};40};
net/ethtool/common.c+1−0
@@ -427,6 +427,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { · 426 unmodified lines
427 [const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw",427 [const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw",
428 [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc",428 [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc",
429 [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp",429 [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp",
430 [const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter",
430};431};
431static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);432static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);
432 433
net/ipv4/tcp.c+7−2
@@ -2235,6 +2235,7 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, · 2234 unmodified lines
2235 struct scm_timestamping_internal *tss)2235 struct scm_timestamping_internal *tss)
2236{2236{
2237 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);2237 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
2238 u32 tsflags = READ_ONCE(sk->sk_tsflags);
2238 bool has_timestamping = false;2239 bool has_timestamping = false;
2239 2240
2240 if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {2241 if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) {
@@ -2274,14 +2275,18 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, · 33 unmodified lines
2274 }2275 }
2275 }2276 }
2276 2277
2277 if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE)2278 if (tsflags & SOF_TIMESTAMPING_SOFTWARE &&
2279 (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE ||
2280 !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER)))
2278 has_timestamping = true;2281 has_timestamping = true;
2279 else2282 else
2280 tss->ts[0] = (struct timespec64) {0};2283 tss->ts[0] = (struct timespec64) {0};
2281 }2284 }
2282 2285
2283 if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) {2286 if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) {
2284 if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_RAW_HARDWARE)2287 if (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE &&
2288 (tsflags & SOF_TIMESTAMPING_RX_HARDWARE ||
2289 !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER)))
2285 has_timestamping = true;2290 has_timestamping = true;
2286 else2291 else
2287 tss->ts[2] = (struct timespec64) {0};2292 tss->ts[2] = (struct timespec64) {0};
net/socket.c+8−2
@@ -946,11 +946,17 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, · 945 unmodified lines
946 946
947 memset(&tss, 0, sizeof(tss));947 memset(&tss, 0, sizeof(tss));
948 tsflags = READ_ONCE(sk->sk_tsflags);948 tsflags = READ_ONCE(sk->sk_tsflags);
949 if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) &&949 if ((tsflags & SOF_TIMESTAMPING_SOFTWARE &&
950 (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE ||
951 skb_is_err_queue(skb) ||
952 !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) &&
950 ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))953 ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
951 empty = 0;954 empty = 0;
952 if (shhwtstamps &&955 if (shhwtstamps &&
953 (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&956 (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE &&
957 (tsflags & SOF_TIMESTAMPING_RX_HARDWARE ||
958 skb_is_err_queue(skb) ||
959 !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) &&
954 !skb_is_swtx_tstamp(skb, false_tstamp)) {960 !skb_is_swtx_tstamp(skb, false_tstamp)) {
955 if_index = 0;961 if_index = 0;
956 if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)962 if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)