On Fri, Oct 9, 2020 at 6:32 AM Christian Eggers <cegg...@arri.de> wrote:
>
> The comparison of optname with SO_TIMESTAMPING_NEW is wrong way around,
> so SOCK_TSTAMP_NEW will first be set and than reset again. Additionally
> move it out of the test for SOF_TIMESTAMPING_RX_SOFTWARE as this seems
> unrelated.
>
> This problem happens on 32 bit platforms were the libc has already
> switched to struct timespec64 (from SO_TIMExxx_OLD to SO_TIMExxx_NEW
> socket options). ptp4l complains with "missing timestamp on transmitted
> peer delay request" because the wrong format is received (and
> discarded).
>
> Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW")
> Signed-off-by: Christian Eggers <cegg...@arri.de>
> ---
>  net/core/sock.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 34a8d12e38d7..3926804702c1 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1024,16 +1024,15 @@ int sock_setsockopt(struct socket *sock, int level, 
> int optname,
>                 }
>
>                 sk->sk_tsflags = val;
> +               if (optname != SO_TIMESTAMPING_NEW)
> +                       sock_reset_flag(sk, SOCK_TSTAMP_NEW);
> +
>                 if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
>                         sock_enable_timestamp(sk,
>                                               SOCK_TIMESTAMPING_RX_SOFTWARE);
> -               else {
> -                       if (optname == SO_TIMESTAMPING_NEW)
> -                               sock_reset_flag(sk, SOCK_TSTAMP_NEW);
> -

The idea is to select new vs old behavior depending on which of the
two setsockopts is called.

This suggested fix still sets and clears the flag if calling
SO_TIMESTAMPING_NEW to disable timestamping. Instead, how about

        case SO_TIMESTAMPING_NEW:
-               sock_set_flag(sk, SOCK_TSTAMP_NEW);
                fallthrough;
        case SO_TIMESTAMPING_OLD:
[..]
+               sock_valbool_flag(sk, SOCK_TSTAMP_NEW,
+                                 optname == SO_TIMESTAMPING_NEW);
+
                if (val & SOF_TIMESTAMPING_OPT_ID &&

That is a subtle behavioral change, because it now leaves
SOCK_TSTAMP_NEW set also when timestamping is turned off. But this is
harmless, as in that case the versioning does not matter. A more
pedantic version would be

+               sock_valbool_flag(sk, SOCK_TSTAMP_NEW,
+                                 optname == SO_TIMESTAMPING_NEW &&
+                                 val & SOF_TIMESTAMPING_TX_RECORD_MASK);

Reply via email to