aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
authorMiroslav Lichvar <mlichvar@redhat.com>2017-05-19 11:52:40 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-21 13:37:32 -0400
commitb50a5c70ffa4fd6b6da324ab54c84adf48fb17d9 (patch)
tree02554df34f5ee85dd91f228e45b8d17a066b1e48 /net/socket.c
parent67953d47bb24e63d209705f745a0de411a4c6578 (diff)
net: allow simultaneous SW and HW transmit timestamping
Add SOF_TIMESTAMPING_OPT_TX_SWHW option to allow an outgoing packet to be looped to the socket's error queue with a software timestamp even when a hardware transmit timestamp is expected to be provided by the driver. Applications using this option will receive two separate messages from the error queue, one with a software timestamp and the other with a hardware timestamp. As the hardware timestamp is saved to the shared skb info, which may happen before the first message with software timestamp is received by the application, the hardware timestamp is copied to the SCM_TIMESTAMPING control message only when the skb has no software timestamp or it is an incoming packet. While changing sw_tx_timestamp(), inline it in skb_tx_timestamp() as there are no other users. CC: Richard Cochran <richardcochran@gmail.com> CC: Willem de Bruijn <willemb@google.com> Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/net/socket.c b/net/socket.c
index 67db7d8a3b81..cb355a7ef135 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -662,6 +662,19 @@ static bool skb_is_err_queue(const struct sk_buff *skb)
662 return skb->pkt_type == PACKET_OUTGOING; 662 return skb->pkt_type == PACKET_OUTGOING;
663} 663}
664 664
665/* On transmit, software and hardware timestamps are returned independently.
666 * As the two skb clones share the hardware timestamp, which may be updated
667 * before the software timestamp is received, a hardware TX timestamp may be
668 * returned only if there is no software TX timestamp. Ignore false software
669 * timestamps, which may be made in the __sock_recv_timestamp() call when the
670 * option SO_TIMESTAMP(NS) is enabled on the socket, even when the skb has a
671 * hardware timestamp.
672 */
673static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp)
674{
675 return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
676}
677
665static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) 678static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
666{ 679{
667 struct scm_ts_pktinfo ts_pktinfo; 680 struct scm_ts_pktinfo ts_pktinfo;
@@ -691,14 +704,16 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
691{ 704{
692 int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 705 int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
693 struct scm_timestamping tss; 706 struct scm_timestamping tss;
694 int empty = 1; 707 int empty = 1, false_tstamp = 0;
695 struct skb_shared_hwtstamps *shhwtstamps = 708 struct skb_shared_hwtstamps *shhwtstamps =
696 skb_hwtstamps(skb); 709 skb_hwtstamps(skb);
697 710
698 /* Race occurred between timestamp enabling and packet 711 /* Race occurred between timestamp enabling and packet
699 receiving. Fill in the current time for now. */ 712 receiving. Fill in the current time for now. */
700 if (need_software_tstamp && skb->tstamp == 0) 713 if (need_software_tstamp && skb->tstamp == 0) {
701 __net_timestamp(skb); 714 __net_timestamp(skb);
715 false_tstamp = 1;
716 }
702 717
703 if (need_software_tstamp) { 718 if (need_software_tstamp) {
704 if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { 719 if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
@@ -720,6 +735,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
720 empty = 0; 735 empty = 0;
721 if (shhwtstamps && 736 if (shhwtstamps &&
722 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && 737 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
738 !skb_is_swtx_tstamp(skb, false_tstamp) &&
723 ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) { 739 ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
724 empty = 0; 740 empty = 0;
725 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 741 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&