280280#include <asm/ioctls.h>
281281#include <net/busy_poll.h>
282282
283+ /* Track pending CMSGs. */
284+ enum {
285+ TCP_CMSG_INQ = 1 ,
286+ TCP_CMSG_TS = 2
287+ };
288+
283289struct percpu_counter tcp_orphan_count ;
284290EXPORT_SYMBOL_GPL (tcp_orphan_count );
285291
@@ -1739,6 +1745,20 @@ int tcp_set_rcvlowat(struct sock *sk, int val)
17391745}
17401746EXPORT_SYMBOL (tcp_set_rcvlowat );
17411747
1748+ static void tcp_update_recv_tstamps (struct sk_buff * skb ,
1749+ struct scm_timestamping_internal * tss )
1750+ {
1751+ if (skb -> tstamp )
1752+ tss -> ts [0 ] = ktime_to_timespec64 (skb -> tstamp );
1753+ else
1754+ tss -> ts [0 ] = (struct timespec64 ) {0 };
1755+
1756+ if (skb_hwtstamps (skb )-> hwtstamp )
1757+ tss -> ts [2 ] = ktime_to_timespec64 (skb_hwtstamps (skb )-> hwtstamp );
1758+ else
1759+ tss -> ts [2 ] = (struct timespec64 ) {0 };
1760+ }
1761+
17421762#ifdef CONFIG_MMU
17431763static const struct vm_operations_struct tcp_vm_ops = {
17441764};
@@ -1842,13 +1862,13 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
18421862 struct scm_timestamping_internal * tss ,
18431863 int * cmsg_flags );
18441864static int receive_fallback_to_copy (struct sock * sk ,
1845- struct tcp_zerocopy_receive * zc , int inq )
1865+ struct tcp_zerocopy_receive * zc , int inq ,
1866+ struct scm_timestamping_internal * tss )
18461867{
18471868 unsigned long copy_address = (unsigned long )zc -> copybuf_address ;
1848- struct scm_timestamping_internal tss_unused ;
1849- int err , cmsg_flags_unused ;
18501869 struct msghdr msg = {};
18511870 struct iovec iov ;
1871+ int err ;
18521872
18531873 zc -> length = 0 ;
18541874 zc -> recv_skip_hint = 0 ;
@@ -1862,7 +1882,7 @@ static int receive_fallback_to_copy(struct sock *sk,
18621882 return err ;
18631883
18641884 err = tcp_recvmsg_locked (sk , & msg , inq , /*nonblock=*/ 1 , /*flags=*/ 0 ,
1865- & tss_unused , & cmsg_flags_unused );
1885+ tss , & zc -> msg_flags );
18661886 if (err < 0 )
18671887 return err ;
18681888
@@ -1903,21 +1923,27 @@ static int tcp_copy_straggler_data(struct tcp_zerocopy_receive *zc,
19031923 return (__s32 )copylen ;
19041924}
19051925
1906- static int tcp_zerocopy_handle_leftover_data (struct tcp_zerocopy_receive * zc ,
1907- struct sock * sk ,
1908- struct sk_buff * skb ,
1909- u32 * seq ,
1910- s32 copybuf_len )
1926+ static int tcp_zc_handle_leftover (struct tcp_zerocopy_receive * zc ,
1927+ struct sock * sk ,
1928+ struct sk_buff * skb ,
1929+ u32 * seq ,
1930+ s32 copybuf_len ,
1931+ struct scm_timestamping_internal * tss )
19111932{
19121933 u32 offset , copylen = min_t (u32 , copybuf_len , zc -> recv_skip_hint );
19131934
19141935 if (!copylen )
19151936 return 0 ;
19161937 /* skb is null if inq < PAGE_SIZE. */
1917- if (skb )
1938+ if (skb ) {
19181939 offset = * seq - TCP_SKB_CB (skb )-> seq ;
1919- else
1940+ } else {
19201941 skb = tcp_recv_skb (sk , * seq , & offset );
1942+ if (TCP_SKB_CB (skb )-> has_rxtstamp ) {
1943+ tcp_update_recv_tstamps (skb , tss );
1944+ zc -> msg_flags |= TCP_CMSG_TS ;
1945+ }
1946+ }
19211947
19221948 zc -> copybuf_len = tcp_copy_straggler_data (zc , skb , copylen , & offset ,
19231949 seq );
@@ -2004,9 +2030,37 @@ static int tcp_zerocopy_vm_insert_batch(struct vm_area_struct *vma,
20042030 err );
20052031}
20062032
2033+ static void tcp_recv_timestamp (struct msghdr * msg , const struct sock * sk ,
2034+ struct scm_timestamping_internal * tss );
2035+ static void tcp_zc_finalize_rx_tstamp (struct sock * sk ,
2036+ struct tcp_zerocopy_receive * zc ,
2037+ struct scm_timestamping_internal * tss )
2038+ {
2039+ unsigned long msg_control_addr ;
2040+ struct msghdr cmsg_dummy ;
2041+
2042+ msg_control_addr = (unsigned long )zc -> msg_control ;
2043+ cmsg_dummy .msg_control = (void * )msg_control_addr ;
2044+ cmsg_dummy .msg_controllen =
2045+ (__kernel_size_t )zc -> msg_controllen ;
2046+ cmsg_dummy .msg_flags = in_compat_syscall ()
2047+ ? MSG_CMSG_COMPAT : 0 ;
2048+ zc -> msg_flags = 0 ;
2049+ if (zc -> msg_control == msg_control_addr &&
2050+ zc -> msg_controllen == cmsg_dummy .msg_controllen ) {
2051+ tcp_recv_timestamp (& cmsg_dummy , sk , tss );
2052+ zc -> msg_control = (__u64 )
2053+ ((uintptr_t )cmsg_dummy .msg_control );
2054+ zc -> msg_controllen =
2055+ (__u64 )cmsg_dummy .msg_controllen ;
2056+ zc -> msg_flags = (__u32 )cmsg_dummy .msg_flags ;
2057+ }
2058+ }
2059+
20072060#define TCP_ZEROCOPY_PAGE_BATCH_SIZE 32
20082061static int tcp_zerocopy_receive (struct sock * sk ,
2009- struct tcp_zerocopy_receive * zc )
2062+ struct tcp_zerocopy_receive * zc ,
2063+ struct scm_timestamping_internal * tss )
20102064{
20112065 u32 length = 0 , offset , vma_len , avail_len , copylen = 0 ;
20122066 unsigned long address = (unsigned long )zc -> address ;
@@ -2023,6 +2077,7 @@ static int tcp_zerocopy_receive(struct sock *sk,
20232077 int ret ;
20242078
20252079 zc -> copybuf_len = 0 ;
2080+ zc -> msg_flags = 0 ;
20262081
20272082 if (address & (PAGE_SIZE - 1 ) || address != zc -> address )
20282083 return - EINVAL ;
@@ -2033,7 +2088,7 @@ static int tcp_zerocopy_receive(struct sock *sk,
20332088 sock_rps_record_flow (sk );
20342089
20352090 if (inq && inq <= copybuf_len )
2036- return receive_fallback_to_copy (sk , zc , inq );
2091+ return receive_fallback_to_copy (sk , zc , inq , tss );
20372092
20382093 if (inq < PAGE_SIZE ) {
20392094 zc -> length = 0 ;
@@ -2078,6 +2133,11 @@ static int tcp_zerocopy_receive(struct sock *sk,
20782133 } else {
20792134 skb = tcp_recv_skb (sk , seq , & offset );
20802135 }
2136+
2137+ if (TCP_SKB_CB (skb )-> has_rxtstamp ) {
2138+ tcp_update_recv_tstamps (skb , tss );
2139+ zc -> msg_flags |= TCP_CMSG_TS ;
2140+ }
20812141 zc -> recv_skip_hint = skb -> len - offset ;
20822142 frags = skb_advance_to_frag (skb , offset , & offset_frag );
20832143 if (!frags || offset_frag )
@@ -2120,8 +2180,7 @@ static int tcp_zerocopy_receive(struct sock *sk,
21202180 mmap_read_unlock (current -> mm );
21212181 /* Try to copy straggler data. */
21222182 if (!ret )
2123- copylen = tcp_zerocopy_handle_leftover_data (zc , sk , skb , & seq ,
2124- copybuf_len );
2183+ copylen = tcp_zc_handle_leftover (zc , sk , skb , & seq , copybuf_len , tss );
21252184
21262185 if (length + copylen ) {
21272186 WRITE_ONCE (tp -> copied_seq , seq );
@@ -2142,20 +2201,6 @@ static int tcp_zerocopy_receive(struct sock *sk,
21422201}
21432202#endif
21442203
2145- static void tcp_update_recv_tstamps (struct sk_buff * skb ,
2146- struct scm_timestamping_internal * tss )
2147- {
2148- if (skb -> tstamp )
2149- tss -> ts [0 ] = ktime_to_timespec64 (skb -> tstamp );
2150- else
2151- tss -> ts [0 ] = (struct timespec64 ) {0 };
2152-
2153- if (skb_hwtstamps (skb )-> hwtstamp )
2154- tss -> ts [2 ] = ktime_to_timespec64 (skb_hwtstamps (skb )-> hwtstamp );
2155- else
2156- tss -> ts [2 ] = (struct timespec64 ) {0 };
2157- }
2158-
21592204/* Similar to __sock_recv_timestamp, but does not require an skb */
21602205static void tcp_recv_timestamp (struct msghdr * msg , const struct sock * sk ,
21612206 struct scm_timestamping_internal * tss )
@@ -2272,7 +2317,7 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
22722317 goto out ;
22732318
22742319 if (tp -> recvmsg_inq )
2275- * cmsg_flags = 1 ;
2320+ * cmsg_flags = TCP_CMSG_INQ ;
22762321 timeo = sock_rcvtimeo (sk , nonblock );
22772322
22782323 /* Urgent data needs to be handled specially. */
@@ -2453,7 +2498,7 @@ static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
24532498
24542499 if (TCP_SKB_CB (skb )-> has_rxtstamp ) {
24552500 tcp_update_recv_tstamps (skb , tss );
2456- * cmsg_flags |= 2 ;
2501+ * cmsg_flags |= TCP_CMSG_TS ;
24572502 }
24582503
24592504 if (used + offset < skb -> len )
@@ -2513,9 +2558,9 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
25132558 release_sock (sk );
25142559
25152560 if (cmsg_flags && ret >= 0 ) {
2516- if (cmsg_flags & 2 )
2561+ if (cmsg_flags & TCP_CMSG_TS )
25172562 tcp_recv_timestamp (msg , sk , & tss );
2518- if (cmsg_flags & 1 ) {
2563+ if (cmsg_flags & TCP_CMSG_INQ ) {
25192564 inq = tcp_inq_hint (sk );
25202565 put_cmsg (msg , SOL_TCP , TCP_CM_INQ , sizeof (inq ), & inq );
25212566 }
@@ -4099,6 +4144,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
40994144 }
41004145#ifdef CONFIG_MMU
41014146 case TCP_ZEROCOPY_RECEIVE : {
4147+ struct scm_timestamping_internal tss ;
41024148 struct tcp_zerocopy_receive zc = {};
41034149 int err ;
41044150
@@ -4114,11 +4160,18 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
41144160 if (copy_from_user (& zc , optval , len ))
41154161 return - EFAULT ;
41164162 lock_sock (sk );
4117- err = tcp_zerocopy_receive (sk , & zc );
4163+ err = tcp_zerocopy_receive (sk , & zc , & tss );
41184164 release_sock (sk );
4119- if (len >= offsetofend (struct tcp_zerocopy_receive , err ))
4120- goto zerocopy_rcv_sk_err ;
4165+ if (len >= offsetofend (struct tcp_zerocopy_receive , msg_flags ))
4166+ goto zerocopy_rcv_cmsg ;
41214167 switch (len ) {
4168+ case offsetofend (struct tcp_zerocopy_receive , msg_flags ):
4169+ goto zerocopy_rcv_cmsg ;
4170+ case offsetofend (struct tcp_zerocopy_receive , msg_controllen ):
4171+ case offsetofend (struct tcp_zerocopy_receive , msg_control ):
4172+ case offsetofend (struct tcp_zerocopy_receive , flags ):
4173+ case offsetofend (struct tcp_zerocopy_receive , copybuf_len ):
4174+ case offsetofend (struct tcp_zerocopy_receive , copybuf_address ):
41224175 case offsetofend (struct tcp_zerocopy_receive , err ):
41234176 goto zerocopy_rcv_sk_err ;
41244177 case offsetofend (struct tcp_zerocopy_receive , inq ):
@@ -4127,6 +4180,11 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
41274180 default :
41284181 goto zerocopy_rcv_out ;
41294182 }
4183+ zerocopy_rcv_cmsg :
4184+ if (zc .msg_flags & TCP_CMSG_TS )
4185+ tcp_zc_finalize_rx_tstamp (sk , & zc , & tss );
4186+ else
4187+ zc .msg_flags = 0 ;
41304188zerocopy_rcv_sk_err :
41314189 if (!err )
41324190 zc .err = sock_error (sk );
0 commit comments