Message ID | 20240830153751.86895-2-kerneljasonxing@gmail.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net-timestamp: introduce a flag to filter out rx software report | expand |
Jason Xing wrote: > From: Jason Xing <kernelxing@tencent.com> > > introduce a new flag SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER in the > receive path. User can set it with SOF_TIMESTAMPING_SOFTWARE to filter > out rx 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. > > In this way, we have two kinds of combination: > 1. setting SOF_TIMESTAMPING_SOFTWARE|SOF_TIMESTAMPING_RX_SOFTWARE, it > will surely allow users to get the rx timestamp report. > 2. setting SOF_TIMESTAMPING_SOFTWARE|SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER > while the skb is timestamped, it will stop reporting the rx timestamp. The one point this commit does not explain is 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. > 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. Good find on skb_is_err_queue rather than open-coding PACKET_OUTGOING. > Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com> > Signed-off-by: Jason Xing <kernelxing@tencent.com> Reviewed-by: Willem de Bruijn <willemb@google.com> > --- > 1. Willem suggested this alternative way to solve the issue, so I > added his Suggested-by tag here. Thanks! > --- > Documentation/networking/timestamping.rst | 12 ++++++++++++ > include/uapi/linux/net_tstamp.h | 3 ++- > net/core/sock.c | 4 ++++ > net/ethtool/common.c | 1 + > net/ipv4/tcp.c | 7 +++++-- > net/socket.c | 5 ++++- > 6 files changed, 28 insertions(+), 4 deletions(-) > > diff --git a/Documentation/networking/timestamping.rst b/Documentation/networking/timestamping.rst > index 5e93cd71f99f..ef2a334d373e 100644 > --- a/Documentation/networking/timestamping.rst > +++ b/Documentation/networking/timestamping.rst > @@ -266,6 +266,18 @@ SOF_TIMESTAMPING_OPT_TX_SWHW: > two separate messages will be looped to the socket's error queue, > each containing just one timestamp. > > +SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER: > + Used in the receive software timestamp. Enabling the flag along with > + SOF_TIMESTAMPING_SOFTWARE will not report the rx timestamp to the > + userspace so that it can filter out the case where one process starts > + first which turns on netstamp_needed_key through setting generation > + flags like SOF_TIMESTAMPING_RX_SOFTWARE, then another one only passing > + SOF_TIMESTAMPING_SOFTWARE report flag could also get the rx timestamp. > + > + SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER prevents the application from > + being influenced by others and let the application finally choose > + whether to report the timestamp in the receive path or not. > + nit, so no need to revise, but for next time: Documentation should describe the current state, not a history of changes (log), so wording like "finally" does not belong.
On Sat, Aug 31, 2024 at 10:50 PM Willem de Bruijn <willemdebruijn.kernel@gmail.com> wrote: > > Jason Xing wrote: > > From: Jason Xing <kernelxing@tencent.com> > > > > introduce a new flag SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER in the > > receive path. User can set it with SOF_TIMESTAMPING_SOFTWARE to filter > > out rx 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. > > > > In this way, we have two kinds of combination: > > 1. setting SOF_TIMESTAMPING_SOFTWARE|SOF_TIMESTAMPING_RX_SOFTWARE, it > > will surely allow users to get the rx timestamp report. > > 2. setting SOF_TIMESTAMPING_SOFTWARE|SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER > > while the skb is timestamped, it will stop reporting the rx timestamp. > > The one point this commit does not explain is 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. Yes, you're right. > > > 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. > > Good find on skb_is_err_queue rather than open-coding PACKET_OUTGOING. > > > Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com> > > Signed-off-by: Jason Xing <kernelxing@tencent.com> > > Reviewed-by: Willem de Bruijn <willemb@google.com> Thanks for your review:) > > > --- > > 1. Willem suggested this alternative way to solve the issue, so I > > added his Suggested-by tag here. Thanks! > > --- > > Documentation/networking/timestamping.rst | 12 ++++++++++++ > > include/uapi/linux/net_tstamp.h | 3 ++- > > net/core/sock.c | 4 ++++ > > net/ethtool/common.c | 1 + > > net/ipv4/tcp.c | 7 +++++-- > > net/socket.c | 5 ++++- > > 6 files changed, 28 insertions(+), 4 deletions(-) > > > > diff --git a/Documentation/networking/timestamping.rst b/Documentation/networking/timestamping.rst > > index 5e93cd71f99f..ef2a334d373e 100644 > > --- a/Documentation/networking/timestamping.rst > > +++ b/Documentation/networking/timestamping.rst > > @@ -266,6 +266,18 @@ SOF_TIMESTAMPING_OPT_TX_SWHW: > > two separate messages will be looped to the socket's error queue, > > each containing just one timestamp. > > > > +SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER: > > + Used in the receive software timestamp. Enabling the flag along with > > + SOF_TIMESTAMPING_SOFTWARE will not report the rx timestamp to the > > + userspace so that it can filter out the case where one process starts > > + first which turns on netstamp_needed_key through setting generation > > + flags like SOF_TIMESTAMPING_RX_SOFTWARE, then another one only passing > > + SOF_TIMESTAMPING_SOFTWARE report flag could also get the rx timestamp. > > + > > + SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER prevents the application from > > + being influenced by others and let the application finally choose > > + whether to report the timestamp in the receive path or not. > > + > > nit, so no need to revise, but for next time: > > Documentation should describe the current state, not a history of > changes (log), so wording like "finally" does not belong. I learned it, and will bear it in my mind:) Thanks, Jason
On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > + return -EINVAL; > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > has_timestamping = true; > else > tss->ts[0] = (struct timespec64) {0}; > } > memset(&tss, 0, sizeof(tss)); > tsflags = READ_ONCE(sk->sk_tsflags); > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > + skb_is_err_queue(skb) || > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && Willem, do you prefer to keep the: tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) conditions?IIUC we prevent both from being set at once. So !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) is sufficient (and, subjectively, more intuitive). Question #2 -- why are we only doing this for SW stamps? HW stamps for TCP are also all or nothing.
Jakub Kicinski wrote: > On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > + return -EINVAL; > > > > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > > has_timestamping = true; > > else > > tss->ts[0] = (struct timespec64) {0}; > > } > > > memset(&tss, 0, sizeof(tss)); > > tsflags = READ_ONCE(sk->sk_tsflags); > > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > + skb_is_err_queue(skb) || > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && > > Willem, do you prefer to keep the: > > tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > conditions?IIUC we prevent both from being set at once. So > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > is sufficient (and, subjectively, more intuitive). Good point. Yes, let's definitely simplify. > Question #2 -- why are we only doing this for SW stamps? > HW stamps for TCP are also all or nothing. Fair. Else we'll inevitably add a SOF_TIMESTAMPING_OPT_RX_HARDWARE_FILTER at some point. There probably is no real use to filter one, but not the other. So SOF_TIMESTAMPING_OPT_RX_FILTER then, and also apply to the branch below: if (shhwtstamps && (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && !skb_is_swtx_tstamp(skb, false_tstamp)) { and same for tcp_recv_timestamp.
On Wed, Sep 4, 2024 at 6:13 AM Willem de Bruijn <willemdebruijn.kernel@gmail.com> wrote: > > Jakub Kicinski wrote: > > On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > > > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > > > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > + return -EINVAL; > > > > > > > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > > > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > > > has_timestamping = true; > > > else > > > tss->ts[0] = (struct timespec64) {0}; > > > } > > > > > memset(&tss, 0, sizeof(tss)); > > > tsflags = READ_ONCE(sk->sk_tsflags); > > > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > > > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > + skb_is_err_queue(skb) || > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && > > > > Willem, do you prefer to keep the: > > > > tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > conditions?IIUC we prevent both from being set at once. So > > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > is sufficient (and, subjectively, more intuitive). > > Good point. Yes, let's definitely simplify. Will do it. > > > Question #2 -- why are we only doing this for SW stamps? > > HW stamps for TCP are also all or nothing. > > Fair. Else we'll inevitably add a > SOF_TIMESTAMPING_OPT_RX_HARDWARE_FILTER at some point. > > There probably is no real use to filter one, but not the other. > > So SOF_TIMESTAMPING_OPT_RX_FILTER then, and also apply > to the branch below: > > if (shhwtstamps && > (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && > !skb_is_swtx_tstamp(skb, false_tstamp)) { > > and same for tcp_recv_timestamp. IIUC, I'm going to replace it with SOF_TIMESTAMPING_OPT_RX_FILTER and update the test statements accordingly. Thanks, Jason
On Wed, Sep 4, 2024 at 6:13 AM Willem de Bruijn <willemdebruijn.kernel@gmail.com> wrote: > > Jakub Kicinski wrote: > > On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > > > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > > > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > + return -EINVAL; > > > > > > > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > > > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > > > has_timestamping = true; > > > else > > > tss->ts[0] = (struct timespec64) {0}; > > > } > > > > > memset(&tss, 0, sizeof(tss)); > > > tsflags = READ_ONCE(sk->sk_tsflags); > > > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > > > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > + skb_is_err_queue(skb) || > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && > > > > Willem, do you prefer to keep the: > > > > tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > conditions?IIUC we prevent both from being set at once. So > > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > is sufficient (and, subjectively, more intuitive). > > Good point. Yes, let's definitely simplify. > > > Question #2 -- why are we only doing this for SW stamps? > > HW stamps for TCP are also all or nothing. > > Fair. Else we'll inevitably add a > SOF_TIMESTAMPING_OPT_RX_HARDWARE_FILTER at some point. > > There probably is no real use to filter one, but not the other. > > So SOF_TIMESTAMPING_OPT_RX_FILTER then, and also apply > to the branch below: > > if (shhwtstamps && > (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && > !skb_is_swtx_tstamp(skb, false_tstamp)) { > > and same for tcp_recv_timestamp. When I'm looking at this part, I noticed that RAW_HARDWARE is actually a tx report flag instead of rx, please also see the kdoc you wrote a long time ago: SOF_TIMESTAMPING_RAW_HARDWARE: Report hardware timestamps as generated by SOF_TIMESTAMPING_TX_HARDWARE when available. If so, OPT_RX_FILTER doesn't fit for the name of tx timestamp. I wonder if I can only revise the series with the code simplified as Jakub suggested and then repost it? I think we need to choose a new name for this tx hardware report case, like SOF_TIMESTAMPING_OPT_TX_HARDWARE_FILTER? Since it belongs to the tx path, can I put it into another series or a new patch in the current series where I will explicitly explain why we also need to introduce this new flag? Thanks, Jason
Jason Xing wrote: > On Wed, Sep 4, 2024 at 6:13 AM Willem de Bruijn > <willemdebruijn.kernel@gmail.com> wrote: > > > > Jakub Kicinski wrote: > > > On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > > > > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > > > > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > + return -EINVAL; > > > > > > > > > > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > > > > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > > > > has_timestamping = true; > > > > else > > > > tss->ts[0] = (struct timespec64) {0}; > > > > } > > > > > > > memset(&tss, 0, sizeof(tss)); > > > > tsflags = READ_ONCE(sk->sk_tsflags); > > > > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > > > > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > > + skb_is_err_queue(skb) || > > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && > > > > > > Willem, do you prefer to keep the: > > > > > > tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > > > conditions?IIUC we prevent both from being set at once. So > > > > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > > > is sufficient (and, subjectively, more intuitive). > > > > Good point. Yes, let's definitely simplify. > > > > > Question #2 -- why are we only doing this for SW stamps? > > > HW stamps for TCP are also all or nothing. > > > > Fair. Else we'll inevitably add a > > SOF_TIMESTAMPING_OPT_RX_HARDWARE_FILTER at some point. > > > > There probably is no real use to filter one, but not the other. > > > > So SOF_TIMESTAMPING_OPT_RX_FILTER then, and also apply > > to the branch below: > > > > if (shhwtstamps && > > (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && > > !skb_is_swtx_tstamp(skb, false_tstamp)) { > > > > and same for tcp_recv_timestamp. > > When I'm looking at this part, I noticed that RAW_HARDWARE is actually > a tx report flag instead of rx, please also see the kdoc you wrote a > long time ago: > > SOF_TIMESTAMPING_RAW_HARDWARE: > Report hardware timestamps as generated by > SOF_TIMESTAMPING_TX_HARDWARE when available. Right, this is analogous to the software part that you modify: if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) empty = 0; The idea is to also add for hardware timestamps your suggested condition that the socket also sets the timestamp generation flag SOF_TIMESTAMPING_RX_HARDWARE or that the new OPT_RX_FILTER flag is not set. > If so, OPT_RX_FILTER doesn't fit for the name of tx timestamp. > > I wonder if I can only revise the series with the code simplified as > Jakub suggested and then repost it? I think we need to choose a new > name for this tx hardware report case, like > SOF_TIMESTAMPING_OPT_TX_HARDWARE_FILTER? > > Since it belongs to the tx path, can I put it into another series or a > new patch in the current series where I will explicitly explain why we > also need to introduce this new flag? I think the confusion here comes from that comment that SOF_TIMESTAMPING_RAW_HARDWARE only reports SOF_TIMESTAMPING_TX_HARDWARE generated timestamps. This statement is incorrect and should be revised. It also reports SOF_TIMESTAMPING_RX_HARDWARE. Unless I'm missing something. But I think the author of that statement is the one who made the mistake. Who is.. also me.
On Thu, Sep 5, 2024 at 4:25 AM Willem de Bruijn <willemdebruijn.kernel@gmail.com> wrote: > > Jason Xing wrote: > > On Wed, Sep 4, 2024 at 6:13 AM Willem de Bruijn > > <willemdebruijn.kernel@gmail.com> wrote: > > > > > > Jakub Kicinski wrote: > > > > On Fri, 30 Aug 2024 23:37:50 +0800 Jason Xing wrote: > > > > > + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && > > > > > + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > > + return -EINVAL; > > > > > > > > > > > > > - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) > > > > > + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) > > > > > has_timestamping = true; > > > > > else > > > > > tss->ts[0] = (struct timespec64) {0}; > > > > > } > > > > > > > > > memset(&tss, 0, sizeof(tss)); > > > > > tsflags = READ_ONCE(sk->sk_tsflags); > > > > > - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > > > > > + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && > > > > > + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > > > + skb_is_err_queue(skb) || > > > > > + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && > > > > > > > > Willem, do you prefer to keep the: > > > > > > > > tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || > > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > > > > > conditions?IIUC we prevent both from being set at once. So > > > > > > > > !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) > > > > > > > > is sufficient (and, subjectively, more intuitive). > > > > > > Good point. Yes, let's definitely simplify. > > > > > > > Question #2 -- why are we only doing this for SW stamps? > > > > HW stamps for TCP are also all or nothing. > > > > > > Fair. Else we'll inevitably add a > > > SOF_TIMESTAMPING_OPT_RX_HARDWARE_FILTER at some point. > > > > > > There probably is no real use to filter one, but not the other. > > > > > > So SOF_TIMESTAMPING_OPT_RX_FILTER then, and also apply > > > to the branch below: > > > > > > if (shhwtstamps && > > > (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && > > > !skb_is_swtx_tstamp(skb, false_tstamp)) { > > > > > > and same for tcp_recv_timestamp. > > > > When I'm looking at this part, I noticed that RAW_HARDWARE is actually > > a tx report flag instead of rx, please also see the kdoc you wrote a > > long time ago: > > > > SOF_TIMESTAMPING_RAW_HARDWARE: > > Report hardware timestamps as generated by > > SOF_TIMESTAMPING_TX_HARDWARE when available. > > Right, this is analogous to the software part that you modify: > > if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && > ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) > empty = 0; > > The idea is to also add for hardware timestamps your suggested > condition that the socket also sets the timestamp generation flag > SOF_TIMESTAMPING_RX_HARDWARE or that the new OPT_RX_FILTER flag > is not set. > > > > If so, OPT_RX_FILTER doesn't fit for the name of tx timestamp. > > > > I wonder if I can only revise the series with the code simplified as > > Jakub suggested and then repost it? I think we need to choose a new > > name for this tx hardware report case, like > > SOF_TIMESTAMPING_OPT_TX_HARDWARE_FILTER? > > > > Since it belongs to the tx path, can I put it into another series or a > > new patch in the current series where I will explicitly explain why we > > also need to introduce this new flag? > > I think the confusion here comes from that comment that > SOF_TIMESTAMPING_RAW_HARDWARE only reports > SOF_TIMESTAMPING_TX_HARDWARE generated timestamps. This statement is > incorrect and should be revised. It also reports > SOF_TIMESTAMPING_RX_HARDWARE. > > Unless I'm missing something. But I think the author of that statement > is the one who made the mistake. Who is.. also me. That's all right :) Then, the OPT_RX_FILTER is fine under this circumstance. Let me also revise the documentation first in the series and put it into a separate patch because the rule of writing the patch is to keep one patch doing only one thing at one time. Similar action will be done to the "rx hardware" part because I think mixing the long description for both of them (software & hardware) can be a little bit messy to readers. Let me try a better organization of the series: keep each patch clear, small, atomic and easy to review. Thanks for your help!
diff --git a/Documentation/networking/timestamping.rst b/Documentation/networking/timestamping.rst index 5e93cd71f99f..ef2a334d373e 100644 --- a/Documentation/networking/timestamping.rst +++ b/Documentation/networking/timestamping.rst @@ -266,6 +266,18 @@ SOF_TIMESTAMPING_OPT_TX_SWHW: two separate messages will be looped to the socket's error queue, each containing just one timestamp. +SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER: + Used in the receive software timestamp. Enabling the flag along with + SOF_TIMESTAMPING_SOFTWARE will not report the rx timestamp to the + userspace so that it can filter out the case where one process starts + first which turns on netstamp_needed_key through setting generation + flags like SOF_TIMESTAMPING_RX_SOFTWARE, then another one only passing + SOF_TIMESTAMPING_SOFTWARE report flag could also get the rx timestamp. + + SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER prevents the application from + being influenced by others and let the application finally choose + whether to report the timestamp in the receive path or not. + New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate regardless of the setting of sysctl net.core.tstamp_allow_data. diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h index a2c66b3d7f0f..0042e91fa213 100644 --- a/include/uapi/linux/net_tstamp.h +++ b/include/uapi/linux/net_tstamp.h @@ -32,8 +32,9 @@ enum { SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14), SOF_TIMESTAMPING_BIND_PHC = (1 << 15), SOF_TIMESTAMPING_OPT_ID_TCP = (1 << 16), + SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER = (1 << 17), - SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_ID_TCP, + SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER, SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) | SOF_TIMESTAMPING_LAST }; diff --git a/net/core/sock.c b/net/core/sock.c index 468b1239606c..c4488f6a3ce8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -908,6 +908,10 @@ int sock_set_timestamping(struct sock *sk, int optname, !(val & SOF_TIMESTAMPING_OPT_ID)) return -EINVAL; + if (val & SOF_TIMESTAMPING_RX_SOFTWARE && + val & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER) + return -EINVAL; + if (val & SOF_TIMESTAMPING_OPT_ID && !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { if (sk_is_tcp(sk)) { diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 7257ae272296..6fde55a904b0 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -430,6 +430,7 @@ const char sof_timestamping_names[][ETH_GSTRING_LEN] = { [const_ilog2(SOF_TIMESTAMPING_OPT_TX_SWHW)] = "option-tx-swhw", [const_ilog2(SOF_TIMESTAMPING_BIND_PHC)] = "bind-phc", [const_ilog2(SOF_TIMESTAMPING_OPT_ID_TCP)] = "option-id-tcp", + [const_ilog2(SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER)] = "option-rx-software-filter", }; static_assert(ARRAY_SIZE(sof_timestamping_names) == __SOF_TIMESTAMPING_CNT); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8514257f4ecd..863cc6b8a208 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2235,6 +2235,7 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, struct scm_timestamping_internal *tss) { int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); + u32 tsflags = READ_ONCE(sk->sk_tsflags); bool has_timestamping = false; if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) { @@ -2274,14 +2275,16 @@ void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, } } - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_SOFTWARE) + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) has_timestamping = true; else tss->ts[0] = (struct timespec64) {0}; } if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) { - if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_RAW_HARDWARE) + if (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) has_timestamping = true; else tss->ts[2] = (struct timespec64) {0}; diff --git a/net/socket.c b/net/socket.c index fcbdd5bc47ac..5ede4146198c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -946,7 +946,10 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, memset(&tss, 0, sizeof(tss)); tsflags = READ_ONCE(sk->sk_tsflags); - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE) && + if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || + skb_is_err_queue(skb) || + !(tsflags & SOF_TIMESTAMPING_OPT_RX_SOFTWARE_FILTER))) && ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) empty = 0; if (shhwtstamps &&