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.
Unified · Split
| @@ -267,6 +267,23 @@ SOF_TIMESTAMPING_OPT_TX_SWHW: · 266 unmodified lines | ||
| 267 | 267 | two separate messages will be looped to the socket's error queue, |
| 268 | 268 | each containing just one timestamp. |
| 269 | 269 | |
| 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 | + | |
| 270 | 287 | New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to |
| 271 | 288 | disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate |
| 272 | 289 | regardless of the setting of sysctl net.core.tstamp_allow_data. |
| @@ -32,8 +32,9 @@ enum { · 31 unmodified lines | ||
| 32 | 32 | SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14), |
| 33 | 33 | SOF_TIMESTAMPING_BIND_PHC = (1 << 15), |
| 34 | 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 | 38 | SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | |
| 38 | 39 | SOF_TIMESTAMPING_LAST |
| 39 | 40 | }; |
| @@ -427,6 +427,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { · 426 unmodified lines | ||
| 427 | 427 | [const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw", |
| 428 | 428 | [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc", |
| 429 | 429 | [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp", |
| 430 | + [const_ilog2(SOF_TIMESTAMPING_OPT_RX_FILTER)] = "option-rx-filter", | |
| 430 | 431 | }; |
| 431 | 432 | static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT); |
| 432 | 433 | |
| @@ -2235,6 +2235,7 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, · 2234 unmodified lines | ||
| 2235 | 2235 | struct scm_timestamping_internal *tss) |
| 2236 | 2236 | { |
| 2237 | 2237 | int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); |
| 2238 | + u32 tsflags = READ_ONCE(sk->sk_tsflags); | |
| 2238 | 2239 | bool has_timestamping = false; |
| 2239 | 2240 | |
| 2240 | 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 | 2281 | has_timestamping = true; |
| 2279 | 2282 | else |
| 2280 | 2283 | tss->ts[0] = (struct timespec64) {0}; |
| 2281 | 2284 | } |
| 2282 | 2285 | |
| 2283 | 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 | 2290 | has_timestamping = true; |
| 2286 | 2291 | else |
| 2287 | 2292 | tss->ts[2] = (struct timespec64) {0}; |
| @@ -946,11 +946,17 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, · 945 unmodified lines | ||
| 946 | 946 | |
| 947 | 947 | memset(&tss, 0, sizeof(tss)); |
| 948 | 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 | 953 | ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) |
| 951 | 954 | empty = 0; |
| 952 | 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 | 960 | !skb_is_swtx_tstamp(skb, false_tstamp)) { |
| 955 | 961 | if_index = 0; |
| 956 | 962 | if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV) |