diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/net/socket.c b/net/socket.c index 320f51b22b19..3c176a12fe48 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -670,7 +670,7 @@ static bool skb_is_err_queue(const struct sk_buff *skb) | |||
670 | * before the software timestamp is received, a hardware TX timestamp may be | 670 | * before the software timestamp is received, a hardware TX timestamp may be |
671 | * returned only if there is no software TX timestamp. Ignore false software | 671 | * returned only if there is no software TX timestamp. Ignore false software |
672 | * timestamps, which may be made in the __sock_recv_timestamp() call when the | 672 | * timestamps, which may be made in the __sock_recv_timestamp() call when the |
673 | * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a | 673 | * option SO_TIMESTAMP_OLD(NS) is enabled on the socket, even when the skb has a |
674 | * hardware timestamp. | 674 | * hardware timestamp. |
675 | */ | 675 | */ |
676 | static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) | 676 | static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) |
@@ -706,7 +706,9 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
706 | struct sk_buff *skb) | 706 | struct sk_buff *skb) |
707 | { | 707 | { |
708 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); | 708 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
709 | struct scm_timestamping tss; | 709 | int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); |
710 | struct scm_timestamping_internal tss; | ||
711 | |||
710 | int empty = 1, false_tstamp = 0; | 712 | int empty = 1, false_tstamp = 0; |
711 | struct skb_shared_hwtstamps *shhwtstamps = | 713 | struct skb_shared_hwtstamps *shhwtstamps = |
712 | skb_hwtstamps(skb); | 714 | skb_hwtstamps(skb); |
@@ -720,34 +722,54 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
720 | 722 | ||
721 | if (need_software_tstamp) { | 723 | if (need_software_tstamp) { |
722 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { | 724 | if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { |
723 | struct timeval tv; | 725 | if (new_tstamp) { |
724 | skb_get_timestamp(skb, &tv); | 726 | struct __kernel_sock_timeval tv; |
725 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, | 727 | |
726 | sizeof(tv), &tv); | 728 | skb_get_new_timestamp(skb, &tv); |
729 | put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW, | ||
730 | sizeof(tv), &tv); | ||
731 | } else { | ||
732 | struct __kernel_old_timeval tv; | ||
733 | |||
734 | skb_get_timestamp(skb, &tv); | ||
735 | put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, | ||
736 | sizeof(tv), &tv); | ||
737 | } | ||
727 | } else { | 738 | } else { |
728 | struct timespec ts; | 739 | if (new_tstamp) { |
729 | skb_get_timestampns(skb, &ts); | 740 | struct __kernel_timespec ts; |
730 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | 741 | |
731 | sizeof(ts), &ts); | 742 | skb_get_new_timestampns(skb, &ts); |
743 | put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW, | ||
744 | sizeof(ts), &ts); | ||
745 | } else { | ||
746 | struct timespec ts; | ||
747 | |||
748 | skb_get_timestampns(skb, &ts); | ||
749 | put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD, | ||
750 | sizeof(ts), &ts); | ||
751 | } | ||
732 | } | 752 | } |
733 | } | 753 | } |
734 | 754 | ||
735 | memset(&tss, 0, sizeof(tss)); | 755 | memset(&tss, 0, sizeof(tss)); |
736 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && | 756 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && |
737 | ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) | 757 | ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) |
738 | empty = 0; | 758 | empty = 0; |
739 | if (shhwtstamps && | 759 | if (shhwtstamps && |
740 | (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && | 760 | (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && |
741 | !skb_is_swtx_tstamp(skb, false_tstamp) && | 761 | !skb_is_swtx_tstamp(skb, false_tstamp) && |
742 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { | 762 | ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { |
743 | empty = 0; | 763 | empty = 0; |
744 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && | 764 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && |
745 | !skb_is_err_queue(skb)) | 765 | !skb_is_err_queue(skb)) |
746 | put_ts_pktinfo(msg, skb); | 766 | put_ts_pktinfo(msg, skb); |
747 | } | 767 | } |
748 | if (!empty) { | 768 | if (!empty) { |
749 | put_cmsg(msg, SOL_SOCKET, | 769 | if (sock_flag(sk, SOCK_TSTAMP_NEW)) |
750 | SCM_TIMESTAMPING, sizeof(tss), &tss); | 770 | put_cmsg_scm_timestamping64(msg, &tss); |
771 | else | ||
772 | put_cmsg_scm_timestamping(msg, &tss); | ||
751 | 773 | ||
752 | if (skb_is_err_queue(skb) && skb->len && | 774 | if (skb_is_err_queue(skb) && skb->len && |
753 | SKB_EXT_ERR(skb)->opt_stats) | 775 | SKB_EXT_ERR(skb)->opt_stats) |