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