net-timestamp: move timestamp flags out of sk_flags

sk_flags is reaching its limit. New timestamping options will not fit.
Move all of them into a new field sk->sk_tsflags.

Added benefit is that this removes boilerplate code to convert between
SOF_TIMESTAMPING_.. and SOCK_TIMESTAMPING_.. in getsockopt/setsockopt.

SOCK_TIMESTAMPING_RX_SOFTWARE is also used to toggle the receive
timestamp logic (netstamp_needed). That can be simplified and this
last key removed, but will leave that for a separate patch.

Signed-off-by: Willem de Bruijn <willemb@google.com>

----

The u16 in sock can be moved into a 16-bit hole below sk_gso_max_segs,
though that scatters tstamp fields throughout the struct.
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Willem de Bruijn 2014-08-04 22:11:46 -04:00 committed by David S. Miller
parent f24b9be595
commit b9f40e21ef
3 changed files with 17 additions and 45 deletions

View File

@ -67,6 +67,7 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <linux/net_tstamp.h>
struct cgroup; struct cgroup;
struct cgroup_subsys; struct cgroup_subsys;
@ -278,6 +279,7 @@ struct cg_proto;
* @sk_protinfo: private area, net family specific, when not using slab * @sk_protinfo: private area, net family specific, when not using slab
* @sk_timer: sock cleanup timer * @sk_timer: sock cleanup timer
* @sk_stamp: time stamp of last packet received * @sk_stamp: time stamp of last packet received
* @sk_tsflags: SO_TIMESTAMPING socket options
* @sk_socket: Identd and reporting IO signals * @sk_socket: Identd and reporting IO signals
* @sk_user_data: RPC layer private data * @sk_user_data: RPC layer private data
* @sk_frag: cached page frag * @sk_frag: cached page frag
@ -411,6 +413,7 @@ struct sock {
void *sk_protinfo; void *sk_protinfo;
struct timer_list sk_timer; struct timer_list sk_timer;
ktime_t sk_stamp; ktime_t sk_stamp;
u16 sk_tsflags;
struct socket *sk_socket; struct socket *sk_socket;
void *sk_user_data; void *sk_user_data;
struct page_frag sk_frag; struct page_frag sk_frag;
@ -701,12 +704,7 @@ enum sock_flags {
SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
SOCK_MEMALLOC, /* VM depends on this socket for swapping */ SOCK_MEMALLOC, /* VM depends on this socket for swapping */
SOCK_TIMESTAMPING_TX_HARDWARE, /* %SOF_TIMESTAMPING_TX_HARDWARE */
SOCK_TIMESTAMPING_TX_SOFTWARE, /* %SOF_TIMESTAMPING_TX_SOFTWARE */
SOCK_TIMESTAMPING_RX_HARDWARE, /* %SOF_TIMESTAMPING_RX_HARDWARE */
SOCK_TIMESTAMPING_RX_SOFTWARE, /* %SOF_TIMESTAMPING_RX_SOFTWARE */ SOCK_TIMESTAMPING_RX_SOFTWARE, /* %SOF_TIMESTAMPING_RX_SOFTWARE */
SOCK_TIMESTAMPING_SOFTWARE, /* %SOF_TIMESTAMPING_SOFTWARE */
SOCK_TIMESTAMPING_RAW_HARDWARE, /* %SOF_TIMESTAMPING_RAW_HARDWARE */
SOCK_FASYNC, /* fasync() active */ SOCK_FASYNC, /* fasync() active */
SOCK_RXQ_OVFL, SOCK_RXQ_OVFL,
SOCK_ZEROCOPY, /* buffers from userspace */ SOCK_ZEROCOPY, /* buffers from userspace */
@ -2160,20 +2158,17 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
/* /*
* generate control messages if * generate control messages if
* - receive time stamping in software requested (SOCK_RCVTSTAMP * - receive time stamping in software requested
* or SOCK_TIMESTAMPING_RX_SOFTWARE)
* - software time stamp available and wanted * - software time stamp available and wanted
* (SOCK_TIMESTAMPING_SOFTWARE)
* - hardware time stamps available and wanted * - hardware time stamps available and wanted
* SOCK_TIMESTAMPING_RAW_HARDWARE
*/ */
if (sock_flag(sk, SOCK_RCVTSTAMP) || if (sock_flag(sk, SOCK_RCVTSTAMP) ||
sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE) || (sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
(kt.tv64 && (kt.tv64 &&
(sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) || (sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP)) || skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP)) ||
(hwtstamps->hwtstamp.tv64 && (hwtstamps->hwtstamp.tv64 &&
sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE))) (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
__sock_recv_timestamp(msg, sk, skb); __sock_recv_timestamp(msg, sk, skb);
else else
sk->sk_stamp = kt; sk->sk_stamp = kt;
@ -2189,11 +2184,11 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb) struct sk_buff *skb)
{ {
#define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL) | \ #define FLAGS_TS_OR_DROPS ((1UL << SOCK_RXQ_OVFL) | \
(1UL << SOCK_RCVTSTAMP) | \ (1UL << SOCK_RCVTSTAMP))
(1UL << SOCK_TIMESTAMPING_SOFTWARE) | \ #define TSFLAGS_ANY (SOF_TIMESTAMPING_SOFTWARE | \
(1UL << SOCK_TIMESTAMPING_RAW_HARDWARE)) SOF_TIMESTAMPING_RAW_HARDWARE)
if (sk->sk_flags & FLAGS_TS_OR_DROPS) if (sk->sk_flags & FLAGS_TS_OR_DROPS || sk->sk_tsflags & TSFLAGS_ANY)
__sock_recv_ts_and_drops(msg, sk, skb); __sock_recv_ts_and_drops(msg, sk, skb);
else else
sk->sk_stamp = skb->tstamp; sk->sk_stamp = skb->tstamp;
@ -2203,8 +2198,6 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
* sock_tx_timestamp - checks whether the outgoing packet is to be time stamped * sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
* @sk: socket sending this packet * @sk: socket sending this packet
* @tx_flags: filled with instructions for time stamping * @tx_flags: filled with instructions for time stamping
*
* Currently only depends on SOCK_TIMESTAMPING* flags.
*/ */
void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags); void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);

View File

@ -848,22 +848,13 @@ set_rcvbuf:
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, sk->sk_tsflags = val;
val & SOF_TIMESTAMPING_TX_HARDWARE);
sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE,
val & SOF_TIMESTAMPING_TX_SOFTWARE);
sock_valbool_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE,
val & SOF_TIMESTAMPING_RX_HARDWARE);
if (val & SOF_TIMESTAMPING_RX_SOFTWARE) if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
sock_enable_timestamp(sk, sock_enable_timestamp(sk,
SOCK_TIMESTAMPING_RX_SOFTWARE); SOCK_TIMESTAMPING_RX_SOFTWARE);
else else
sock_disable_timestamp(sk, sock_disable_timestamp(sk,
(1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE));
sock_valbool_flag(sk, SOCK_TIMESTAMPING_SOFTWARE,
val & SOF_TIMESTAMPING_SOFTWARE);
sock_valbool_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE,
val & SOF_TIMESTAMPING_RAW_HARDWARE);
break; break;
case SO_RCVLOWAT: case SO_RCVLOWAT:
@ -1089,19 +1080,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break; break;
case SO_TIMESTAMPING: case SO_TIMESTAMPING:
v.val = 0; v.val = sk->sk_tsflags;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE))
v.val |= SOF_TIMESTAMPING_TX_HARDWARE;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
v.val |= SOF_TIMESTAMPING_TX_SOFTWARE;
if (sock_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE))
v.val |= SOF_TIMESTAMPING_RX_HARDWARE;
if (sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE))
v.val |= SOF_TIMESTAMPING_RX_SOFTWARE;
if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE))
v.val |= SOF_TIMESTAMPING_SOFTWARE;
if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE))
v.val |= SOF_TIMESTAMPING_RAW_HARDWARE;
break; break;
case SO_RCVTIMEO: case SO_RCVTIMEO:

View File

@ -613,9 +613,9 @@ EXPORT_SYMBOL(sock_release);
void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
{ {
*tx_flags = 0; *tx_flags = 0;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE)
*tx_flags |= SKBTX_HW_TSTAMP; *tx_flags |= SKBTX_HW_TSTAMP;
if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE)
*tx_flags |= SKBTX_SW_TSTAMP; *tx_flags |= SKBTX_SW_TSTAMP;
if (sock_flag(sk, SOCK_WIFI_STATUS)) if (sock_flag(sk, SOCK_WIFI_STATUS))
*tx_flags |= SKBTX_WIFI_STATUS; *tx_flags |= SKBTX_WIFI_STATUS;
@ -723,12 +723,12 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
} }
memset(&tss, 0, sizeof(tss)); memset(&tss, 0, sizeof(tss));
if ((sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) || if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) && skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) &&
ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
empty = 0; empty = 0;
if (shhwtstamps && if (shhwtstamps &&
sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2))
empty = 0; empty = 0;
if (!empty) if (!empty)