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

net: Add a new socket option for a future transmit time.

This patch introduces SO_TXTIME. User space enables this option in
order to pass a desired future transmit time in a CMSG when calling
sendmsg(2). The argument to this socket option is a 8-bytes long struct
provided by the uapi header net_tstamp.h defined as:

struct sock_txtime {
clockid_t clockid;
u32 flags;
};

Note that new fields were added to struct sock by filling a 2-bytes
hole found in the struct. For that reason, neither the struct size or
number of cachelines were altered.

Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Richard Cochran and committed by
David S. Miller
80b14dee c47d8c2f

+84
+3
arch/alpha/include/uapi/asm/socket.h
··· 112 112 113 113 #define SO_ZEROCOPY 60 114 114 115 + #define SO_TXTIME 61 116 + #define SCM_TXTIME SO_TXTIME 117 + 115 118 #endif /* _UAPI_ASM_SOCKET_H */
+3
arch/ia64/include/uapi/asm/socket.h
··· 114 114 115 115 #define SO_ZEROCOPY 60 116 116 117 + #define SO_TXTIME 61 118 + #define SCM_TXTIME SO_TXTIME 119 + 117 120 #endif /* _ASM_IA64_SOCKET_H */
+3
arch/mips/include/uapi/asm/socket.h
··· 123 123 124 124 #define SO_ZEROCOPY 60 125 125 126 + #define SO_TXTIME 61 127 + #define SCM_TXTIME SO_TXTIME 128 + 126 129 #endif /* _UAPI_ASM_SOCKET_H */
+3
arch/parisc/include/uapi/asm/socket.h
··· 104 104 105 105 #define SO_ZEROCOPY 0x4035 106 106 107 + #define SO_TXTIME 0x4036 108 + #define SCM_TXTIME SO_TXTIME 109 + 107 110 #endif /* _UAPI_ASM_SOCKET_H */
+3
arch/s390/include/uapi/asm/socket.h
··· 111 111 112 112 #define SO_ZEROCOPY 60 113 113 114 + #define SO_TXTIME 61 115 + #define SCM_TXTIME SO_TXTIME 116 + 114 117 #endif /* _ASM_SOCKET_H */
+3
arch/sparc/include/uapi/asm/socket.h
··· 101 101 102 102 #define SO_ZEROCOPY 0x003e 103 103 104 + #define SO_TXTIME 0x003f 105 + #define SCM_TXTIME SO_TXTIME 106 + 104 107 /* Security levels - as per NRL IPv6 - don't actually do anything */ 105 108 #define SO_SECURITY_AUTHENTICATION 0x5001 106 109 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
+3
arch/xtensa/include/uapi/asm/socket.h
··· 116 116 117 117 #define SO_ZEROCOPY 60 118 118 119 + #define SO_TXTIME 61 120 + #define SCM_TXTIME SO_TXTIME 121 + 119 122 #endif /* _XTENSA_SOCKET_H */
+10
include/net/sock.h
··· 319 319 * @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0 320 320 * @sk_reuseport_cb: reuseport group container 321 321 * @sk_rcu: used during RCU grace period 322 + * @sk_clockid: clockid used by time-based scheduling (SO_TXTIME) 323 + * @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME 324 + * @sk_txtime_unused: unused txtime flags 322 325 */ 323 326 struct sock { 324 327 /* ··· 478 475 u8 sk_shutdown; 479 476 u32 sk_tskey; 480 477 atomic_t sk_zckey; 478 + 479 + u8 sk_clockid; 480 + u8 sk_txtime_deadline_mode : 1, 481 + sk_txtime_unused : 7; 482 + 481 483 struct socket *sk_socket; 482 484 void *sk_user_data; 483 485 #ifdef CONFIG_SECURITY ··· 798 790 SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */ 799 791 SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */ 800 792 SOCK_RCU_FREE, /* wait rcu grace period in sk_destruct() */ 793 + SOCK_TXTIME, 801 794 }; 802 795 803 796 #define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)) ··· 1594 1585 void sk_send_sigurg(struct sock *sk); 1595 1586 1596 1587 struct sockcm_cookie { 1588 + u64 transmit_time; 1597 1589 u32 mark; 1598 1590 u16 tsflags; 1599 1591 };
+3
include/uapi/asm-generic/socket.h
··· 107 107 108 108 #define SO_ZEROCOPY 60 109 109 110 + #define SO_TXTIME 61 111 + #define SCM_TXTIME SO_TXTIME 112 + 110 113 #endif /* __ASM_GENERIC_SOCKET_H */
+15
include/uapi/linux/net_tstamp.h
··· 141 141 __u32 reserved[2]; 142 142 }; 143 143 144 + /* 145 + * SO_TXTIME gets a struct sock_txtime with flags being an integer bit 146 + * field comprised of these values. 147 + */ 148 + enum txtime_flags { 149 + SOF_TXTIME_DEADLINE_MODE = (1 << 0), 150 + 151 + SOF_TXTIME_FLAGS_MASK = (SOF_TXTIME_DEADLINE_MODE) 152 + }; 153 + 154 + struct sock_txtime { 155 + clockid_t clockid; /* reference clockid */ 156 + u32 flags; /* flags defined by enum txtime_flags */ 157 + }; 158 + 144 159 #endif /* _NET_TIMESTAMPING_H */
+35
net/core/sock.c
··· 91 91 92 92 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 93 93 94 + #include <asm/unaligned.h> 94 95 #include <linux/capability.h> 95 96 #include <linux/errno.h> 96 97 #include <linux/errqueue.h> ··· 698 697 int sock_setsockopt(struct socket *sock, int level, int optname, 699 698 char __user *optval, unsigned int optlen) 700 699 { 700 + struct sock_txtime sk_txtime; 701 701 struct sock *sk = sock->sk; 702 702 int val; 703 703 int valbool; ··· 1072 1070 } 1073 1071 break; 1074 1072 1073 + case SO_TXTIME: 1074 + if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { 1075 + ret = -EPERM; 1076 + } else if (optlen != sizeof(struct sock_txtime)) { 1077 + ret = -EINVAL; 1078 + } else if (copy_from_user(&sk_txtime, optval, 1079 + sizeof(struct sock_txtime))) { 1080 + ret = -EFAULT; 1081 + } else if (sk_txtime.flags & ~SOF_TXTIME_FLAGS_MASK) { 1082 + ret = -EINVAL; 1083 + } else { 1084 + sock_valbool_flag(sk, SOCK_TXTIME, true); 1085 + sk->sk_clockid = sk_txtime.clockid; 1086 + sk->sk_txtime_deadline_mode = 1087 + !!(sk_txtime.flags & SOF_TXTIME_DEADLINE_MODE); 1088 + } 1089 + break; 1090 + 1075 1091 default: 1076 1092 ret = -ENOPROTOOPT; 1077 1093 break; ··· 1135 1115 u64 val64; 1136 1116 struct linger ling; 1137 1117 struct timeval tm; 1118 + struct sock_txtime txtime; 1138 1119 } v; 1139 1120 1140 1121 int lv = sizeof(int); ··· 1422 1401 1423 1402 case SO_ZEROCOPY: 1424 1403 v.val = sock_flag(sk, SOCK_ZEROCOPY); 1404 + break; 1405 + 1406 + case SO_TXTIME: 1407 + lv = sizeof(v.txtime); 1408 + v.txtime.clockid = sk->sk_clockid; 1409 + v.txtime.flags |= sk->sk_txtime_deadline_mode ? 1410 + SOF_TXTIME_DEADLINE_MODE : 0; 1425 1411 break; 1426 1412 1427 1413 default: ··· 2164 2136 2165 2137 sockc->tsflags &= ~SOF_TIMESTAMPING_TX_RECORD_MASK; 2166 2138 sockc->tsflags |= tsflags; 2139 + break; 2140 + case SCM_TXTIME: 2141 + if (!sock_flag(sk, SOCK_TXTIME)) 2142 + return -EINVAL; 2143 + if (cmsg->cmsg_len != CMSG_LEN(sizeof(u64))) 2144 + return -EINVAL; 2145 + sockc->transmit_time = get_unaligned((u64 *)CMSG_DATA(cmsg)); 2167 2146 break; 2168 2147 /* SCM_RIGHTS and SCM_CREDENTIALS are semantically in SOL_UNIX. */ 2169 2148 case SCM_RIGHTS: