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
267267 two separate messages will be looped to the socket's error queue,
268268 each containing just one timestamp.
269269
270+SOF_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+
270287 New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
271288 disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
272289 regardless 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
3232 SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
3333 SOF_TIMESTAMPING_BIND_PHC = (1 << 15),
3434 SOF_TIMESTAMPING_OPT_ID_TCP = (1 << 16),
35+ SOF_TIMESTAMPING_OPT_RX_FILTER = (1 << 17),
3536
36− SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_ID_TCP,
37+ SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_RX_FILTER,
3738 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
3839 SOF_TIMESTAMPING_LAST
3940 };
net/ethtool/common.c+1−0
@@ -427,6 +427,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { · 426 unmodified lines
427427 [const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw",
428428 [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc",
429429 [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp",
430+ [const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter",
430431 };
431432 static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT);
432433
net/ipv4/tcp.c+7−2
@@ -2235,6 +2235,7 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, · 2234 unmodified lines
22352235 struct scm_timestamping_internal *tss)
22362236 {
22372237 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
2238+ u32 tsflags = READ_ONCE(sk->sk_tsflags);
22382239 bool has_timestamping = false;
22392240
22402241 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
22742275 }
22752276 }
22762277
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)))
22782281 has_timestamping = true;
22792282 else
22802283 tss->ts[0] = (struct timespec64) {0};
22812284 }
22822285
22832286 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)))
22852290 has_timestamping = true;
22862291 else
22872292 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
946946
947947 memset(&tss, 0, sizeof(tss));
948948 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))) &&
950953 ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
951954 empty = 0;
952955 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))) &&
954960 !skb_is_swtx_tstamp(skb, false_tstamp)) {
955961 if_index = 0;
956962 if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)