Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: use ktime_t in struct scm_timestamping_internal

Instead of using struct timespec64 in scm_timestamping_internal,
use ktime_t, saving 24 bytes in kernel stack.

This makes tcp_update_recv_tstamps() small enough to be inlined.

The ktime_t -> timespec64 conversions happen after socket lock
has been released in tcp_recvmsg(), and only if the application
requested them.

$ scripts/bloat-o-meter -t vmlinux.0 vmlinux
add/remove: 0/2 grow/shrink: 5/4 up/down: 146/-277 (-131)
Function old new delta
tcp_zerocopy_receive 2383 2425 +42
mptcp_recvmsg 1565 1607 +42
tcp_recvmsg_locked 3797 3823 +26
put_cmsg_scm_timestamping64 131 149 +18
put_cmsg_scm_timestamping 131 149 +18
__pfx_tcp_update_recv_tstamps 16 - -16
do_tcp_getsockopt 4024 4006 -18
tcp_recv_timestamp 474 430 -44
tcp_zc_handle_leftover 417 371 -46
__sock_recv_timestamp 1087 1031 -56
tcp_update_recv_tstamps 97 - -97
Total: Before=25223788, After=25223657, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Link: https://patch.msgid.link/20260304012747.881644-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
c66e0f45 39ae83b0

+51 -58
+1 -1
include/linux/socket.h
··· 415 415 struct old_timespec32; 416 416 417 417 struct scm_timestamping_internal { 418 - struct timespec64 ts[3]; 418 + ktime_t ts[3]; 419 419 }; 420 420 421 421 extern void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss);
+9 -2
include/net/tcp.h
··· 503 503 int flags); 504 504 int tcp_set_rcvlowat(struct sock *sk, int val); 505 505 int tcp_set_window_clamp(struct sock *sk, int val); 506 - void tcp_update_recv_tstamps(struct sk_buff *skb, 507 - struct scm_timestamping_internal *tss); 506 + 507 + static inline void 508 + tcp_update_recv_tstamps(struct sk_buff *skb, 509 + struct scm_timestamping_internal *tss) 510 + { 511 + tss->ts[0] = skb->tstamp; 512 + tss->ts[2] = skb_hwtstamps(skb)->hwtstamp; 513 + } 514 + 508 515 void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, 509 516 struct scm_timestamping_internal *tss); 510 517 void tcp_data_ready(struct sock *sk);
+8 -4
net/core/scm.c
··· 318 318 int i; 319 319 320 320 for (i = 0; i < ARRAY_SIZE(tss.ts); i++) { 321 - tss.ts[i].tv_sec = tss_internal->ts[i].tv_sec; 322 - tss.ts[i].tv_nsec = tss_internal->ts[i].tv_nsec; 321 + struct timespec64 tv = ktime_to_timespec64(tss_internal->ts[i]); 322 + 323 + tss.ts[i].tv_sec = tv.tv_sec; 324 + tss.ts[i].tv_nsec = tv.tv_nsec; 323 325 } 324 326 325 327 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_NEW, sizeof(tss), &tss); ··· 334 332 int i; 335 333 336 334 for (i = 0; i < ARRAY_SIZE(tss.ts); i++) { 337 - tss.ts[i].tv_sec = tss_internal->ts[i].tv_sec; 338 - tss.ts[i].tv_nsec = tss_internal->ts[i].tv_nsec; 335 + struct timespec64 tv = ktime_to_timespec64(tss_internal->ts[i]); 336 + 337 + tss.ts[i].tv_sec = tv.tv_sec; 338 + tss.ts[i].tv_nsec = tv.tv_nsec; 339 339 } 340 340 341 341 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_OLD, sizeof(tss), &tss);
+22 -39
net/ipv4/tcp.c
··· 1871 1871 } 1872 1872 EXPORT_IPV6_MOD(tcp_set_rcvlowat); 1873 1873 1874 - void tcp_update_recv_tstamps(struct sk_buff *skb, 1875 - struct scm_timestamping_internal *tss) 1876 - { 1877 - if (skb->tstamp) 1878 - tss->ts[0] = ktime_to_timespec64(skb->tstamp); 1879 - else 1880 - tss->ts[0] = (struct timespec64) {0}; 1881 - 1882 - if (skb_hwtstamps(skb)->hwtstamp) 1883 - tss->ts[2] = ktime_to_timespec64(skb_hwtstamps(skb)->hwtstamp); 1884 - else 1885 - tss->ts[2] = (struct timespec64) {0}; 1886 - } 1887 - 1888 1874 #ifdef CONFIG_MMU 1889 1875 static const struct vm_operations_struct tcp_vm_ops = { 1890 1876 }; ··· 2362 2376 { 2363 2377 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); 2364 2378 u32 tsflags = READ_ONCE(sk->sk_tsflags); 2365 - bool has_timestamping = false; 2366 2379 2367 - if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) { 2380 + if (tss->ts[0]) { 2368 2381 if (sock_flag(sk, SOCK_RCVTSTAMP)) { 2382 + struct timespec64 tv = ktime_to_timespec64(tss->ts[0]); 2383 + 2369 2384 if (sock_flag(sk, SOCK_RCVTSTAMPNS)) { 2370 2385 if (new_tstamp) { 2371 2386 struct __kernel_timespec kts = { 2372 - .tv_sec = tss->ts[0].tv_sec, 2373 - .tv_nsec = tss->ts[0].tv_nsec, 2387 + .tv_sec = tv.tv_sec, 2388 + .tv_nsec = tv.tv_nsec, 2374 2389 }; 2375 2390 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW, 2376 2391 sizeof(kts), &kts); 2377 2392 } else { 2378 2393 struct __kernel_old_timespec ts_old = { 2379 - .tv_sec = tss->ts[0].tv_sec, 2380 - .tv_nsec = tss->ts[0].tv_nsec, 2394 + .tv_sec = tv.tv_sec, 2395 + .tv_nsec = tv.tv_nsec, 2381 2396 }; 2382 2397 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD, 2383 2398 sizeof(ts_old), &ts_old); ··· 2386 2399 } else { 2387 2400 if (new_tstamp) { 2388 2401 struct __kernel_sock_timeval stv = { 2389 - .tv_sec = tss->ts[0].tv_sec, 2390 - .tv_usec = tss->ts[0].tv_nsec / 1000, 2402 + .tv_sec = tv.tv_sec, 2403 + .tv_usec = tv.tv_nsec / 1000, 2391 2404 }; 2392 2405 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW, 2393 2406 sizeof(stv), &stv); 2394 2407 } else { 2395 - struct __kernel_old_timeval tv = { 2396 - .tv_sec = tss->ts[0].tv_sec, 2397 - .tv_usec = tss->ts[0].tv_nsec / 1000, 2408 + struct __kernel_old_timeval otv = { 2409 + .tv_sec = tv.tv_sec, 2410 + .tv_usec = tv.tv_nsec / 1000, 2398 2411 }; 2399 2412 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, 2400 - sizeof(tv), &tv); 2413 + sizeof(otv), &otv); 2401 2414 } 2402 2415 } 2403 2416 } 2404 2417 2405 - if (tsflags & SOF_TIMESTAMPING_SOFTWARE && 2418 + if (!(tsflags & SOF_TIMESTAMPING_SOFTWARE && 2406 2419 (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || 2407 - !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) 2408 - has_timestamping = true; 2409 - else 2410 - tss->ts[0] = (struct timespec64) {0}; 2420 + !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER)))) 2421 + tss->ts[0] = 0; 2411 2422 } 2412 2423 2413 - if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) { 2414 - if (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE && 2424 + if (tss->ts[2]) { 2425 + if (!(tsflags & SOF_TIMESTAMPING_RAW_HARDWARE && 2415 2426 (tsflags & SOF_TIMESTAMPING_RX_HARDWARE || 2416 - !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) 2417 - has_timestamping = true; 2418 - else 2419 - tss->ts[2] = (struct timespec64) {0}; 2427 + !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER)))) 2428 + tss->ts[2] = 0; 2420 2429 } 2421 2430 2422 - if (has_timestamping) { 2423 - tss->ts[1] = (struct timespec64) {0}; 2431 + if (tss->ts[0] | tss->ts[2]) { 2432 + tss->ts[1] = 0; 2424 2433 if (sock_flag(sk, SOCK_TSTAMP_NEW)) 2425 2434 put_cmsg_scm_timestamping64(msg, tss); 2426 2435 else
+11 -12
net/socket.c
··· 912 912 { 913 913 int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); 914 914 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW); 915 - struct scm_timestamping_internal tss; 916 - int empty = 1, false_tstamp = 0; 917 915 struct skb_shared_hwtstamps *shhwtstamps = 918 916 skb_hwtstamps(skb); 919 - int if_index; 917 + struct scm_timestamping_internal tss; 918 + int if_index, false_tstamp = 0; 920 919 ktime_t hwtstamp; 921 920 u32 tsflags; 922 921 ··· 960 961 961 962 memset(&tss, 0, sizeof(tss)); 962 963 tsflags = READ_ONCE(sk->sk_tsflags); 963 - if ((tsflags & SOF_TIMESTAMPING_SOFTWARE && 964 - (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || 965 - skb_is_err_queue(skb) || 966 - !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) && 967 - ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0)) 968 - empty = 0; 964 + if (tsflags & SOF_TIMESTAMPING_SOFTWARE && 965 + (tsflags & SOF_TIMESTAMPING_RX_SOFTWARE || 966 + skb_is_err_queue(skb) || 967 + !(tsflags & SOF_TIMESTAMPING_OPT_RX_FILTER))) 968 + tss.ts[0] = skb->tstamp; 969 + 969 970 if (shhwtstamps && 970 971 (tsflags & SOF_TIMESTAMPING_RAW_HARDWARE && 971 972 (tsflags & SOF_TIMESTAMPING_RX_HARDWARE || ··· 982 983 hwtstamp = ptp_convert_timestamp(&hwtstamp, 983 984 READ_ONCE(sk->sk_bind_phc)); 984 985 985 - if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) { 986 - empty = 0; 986 + if (hwtstamp) { 987 + tss.ts[2] = hwtstamp; 987 988 988 989 if ((tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) && 989 990 !skb_is_err_queue(skb)) 990 991 put_ts_pktinfo(msg, skb, if_index); 991 992 } 992 993 } 993 - if (!empty) { 994 + if (tss.ts[0] | tss.ts[2]) { 994 995 if (sock_flag(sk, SOCK_TSTAMP_NEW)) 995 996 put_cmsg_scm_timestamping64(msg, &tss); 996 997 else