aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.9/024-7-net-reorganize-struct-sock-for-better-data-locality.patch
blob: e8c1915e188c92f710a6d7b7f5247d33d45b62e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
From 9115e8cd2a0c6eaaa900c462721f12e1d45f326c Mon Sep 17 00:00:00 2001
From: Eric Dumazet <edumazet@google.com>
Date: Sat, 3 Dec 2016 11:14:56 -0800
Subject: [PATCH 07/10] net: reorganize struct sock for better data locality

Group fields used in TX path, and keep some cache lines mostly read
to permit sharing among cpus.

Gained two 4 bytes holes on 64bit arches.

Added a place holder for tcp tsq_flags, next to sk_wmem_alloc
to speed up tcp_wfree() in the following patch.

I have not added ____cacheline_aligned_in_smp, this might be done later.
I prefer doing this once inet and tcp/udp sockets reorg is also done.

Tested with both TCP and UDP.

UDP receiver performance under flood increased by ~20 % :
Accessing sk_filter/sk_wq/sk_napi_id no longer stalls because sk_drops
was moved away from a critical cache line, now mostly read and shared.

	/* --- cacheline 4 boundary (256 bytes) --- */
	unsigned int               sk_napi_id;           /* 0x100   0x4 */
	int                        sk_rcvbuf;            /* 0x104   0x4 */
	struct sk_filter *         sk_filter;            /* 0x108   0x8 */
	union {
		struct socket_wq * sk_wq;                /*         0x8 */
		struct socket_wq * sk_wq_raw;            /*         0x8 */
	};                                               /* 0x110   0x8 */
	struct xfrm_policy *       sk_policy[2];         /* 0x118  0x10 */
	struct dst_entry *         sk_rx_dst;            /* 0x128   0x8 */
	struct dst_entry *         sk_dst_cache;         /* 0x130   0x8 */
	atomic_t                   sk_omem_alloc;        /* 0x138   0x4 */
	int                        sk_sndbuf;            /* 0x13c   0x4 */
	/* --- cacheline 5 boundary (320 bytes) --- */
	int                        sk_wmem_queued;       /* 0x140   0x4 */
	atomic_t                   sk_wmem_alloc;        /* 0x144   0x4 */
	long unsigned int          sk_tsq_flags;         /* 0x148   0x8 */
	struct sk_buff *           sk_send_head;         /* 0x150   0x8 */
	struct sk_buff_head        sk_write_queue;       /* 0x158  0x18 */
	__s32                      sk_peek_off;          /* 0x170   0x4 */
	int                        sk_write_pending;     /* 0x174   0x4 */
	long int                   sk_sndtimeo;          /* 0x178   0x8 */

Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/sock.h | 51 +++++++++++++++++++++++++++------------------------
 1 file changed, 27 insertions(+), 24 deletions(-)

--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -343,6 +343,9 @@ struct sock {
 #define sk_rxhash		__sk_common.skc_rxhash
 
 	socket_lock_t		sk_lock;
+	atomic_t		sk_drops;
+	int			sk_rcvlowat;
+	struct sk_buff_head	sk_error_queue;
 	struct sk_buff_head	sk_receive_queue;
 	/*
 	 * The backlog queue is special, it is always used with
@@ -359,14 +362,13 @@ struct sock {
 		struct sk_buff	*tail;
 	} sk_backlog;
 #define sk_rmem_alloc sk_backlog.rmem_alloc
-	int			sk_forward_alloc;
 
-	__u32			sk_txhash;
+	int			sk_forward_alloc;
 #ifdef CONFIG_NET_RX_BUSY_POLL
-	unsigned int		sk_napi_id;
 	unsigned int		sk_ll_usec;
+	/* ===== mostly read cache line ===== */
+	unsigned int		sk_napi_id;
 #endif
-	atomic_t		sk_drops;
 	int			sk_rcvbuf;
 
 	struct sk_filter __rcu	*sk_filter;
@@ -379,11 +381,30 @@ struct sock {
 #endif
 	struct dst_entry	*sk_rx_dst;
 	struct dst_entry __rcu	*sk_dst_cache;
-	/* Note: 32bit hole on 64bit arches */
-	atomic_t		sk_wmem_alloc;
 	atomic_t		sk_omem_alloc;
 	int			sk_sndbuf;
+
+	/* ===== cache line for TX ===== */
+	int			sk_wmem_queued;
+	atomic_t		sk_wmem_alloc;
+	unsigned long		sk_tsq_flags;
+	struct sk_buff		*sk_send_head;
 	struct sk_buff_head	sk_write_queue;
+	__s32			sk_peek_off;
+	int			sk_write_pending;
+	long			sk_sndtimeo;
+	struct timer_list	sk_timer;
+	__u32			sk_priority;
+	__u32			sk_mark;
+	u32			sk_pacing_rate; /* bytes per second */
+	u32			sk_max_pacing_rate;
+	struct page_frag	sk_frag;
+	netdev_features_t	sk_route_caps;
+	netdev_features_t	sk_route_nocaps;
+	int			sk_gso_type;
+	unsigned int		sk_gso_max_size;
+	gfp_t			sk_allocation;
+	__u32			sk_txhash;
 
 	/*
 	 * Because of non atomicity rules, all
@@ -399,41 +420,23 @@ struct sock {
 #define SK_PROTOCOL_MAX U8_MAX
 	kmemcheck_bitfield_end(flags);
 
-	int			sk_wmem_queued;
-	gfp_t			sk_allocation;
-	u32			sk_pacing_rate; /* bytes per second */
-	u32			sk_max_pacing_rate;
-	netdev_features_t	sk_route_caps;
-	netdev_features_t	sk_route_nocaps;
-	int			sk_gso_type;
-	unsigned int		sk_gso_max_size;
 	u16			sk_gso_max_segs;
-	int			sk_rcvlowat;
 	unsigned long	        sk_lingertime;
-	struct sk_buff_head	sk_error_queue;
 	struct proto		*sk_prot_creator;
 	rwlock_t		sk_callback_lock;
 	int			sk_err,
 				sk_err_soft;
 	u32			sk_ack_backlog;
 	u32			sk_max_ack_backlog;
-	__u32			sk_priority;
-	__u32			sk_mark;
 	struct pid		*sk_peer_pid;
 	const struct cred	*sk_peer_cred;
 	long			sk_rcvtimeo;
-	long			sk_sndtimeo;
-	struct timer_list	sk_timer;
 	ktime_t			sk_stamp;
 	u16			sk_tsflags;
 	u8			sk_shutdown;
 	u32			sk_tskey;
 	struct socket		*sk_socket;
 	void			*sk_user_data;
-	struct page_frag	sk_frag;
-	struct sk_buff		*sk_send_head;
-	__s32			sk_peek_off;
-	int			sk_write_pending;
 #ifdef CONFIG_SECURITY
 	void			*sk_security;
 #endif
string prompt "Target name" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "arm-unknown-linux-gnu" if arm default "armeb-unknown-linux-gnu" if armeb default "i486-unknown-linux-gnu" if i386 default "mips-unknown-linux-gnu" if mips default "mipsel-unknown-linux-gnu" if mipsel default "powerpc-unknown-linux-gnu" if powerpc default "x86_64-unknown-linux-gnu" if x86_64 config TOOLCHAIN_PREFIX string prompt "Toolchain prefix" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "arm-unknown-linux-gnu-" if arm default "armeb-unknown-linux-gnu-" if armeb default "i486-unknown-linux-gnu-" if i386 default "mips-unknown-linux-gnu-" if mips default "mipsel-unknown-linux-gnu-" if mipsel default "powerpc-unknown-linux-gnu-" if powerpc default "x86_64-unknown-linux-gnu-" if x86_64 config TOOLCHAIN_ROOT string prompt "Toolchain root" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "/opt/cross/arm-unknown-linux-gnu" if arm default "/opt/cross/armeb-unknown-linux-gnu" if armeb default "/opt/cross/i486-unknown-linux-gnu" if i386 default "/opt/cross/mips-unknown-linux-gnu" if mips default "/opt/cross/mipsel-unknown-linux-gnu" if mipsel default "/opt/cross/powerpc-unknown-linux-gnu" if powerpc default "/opt/cross/x86_64-unknown-linux-gnu" if x86_64 config TOOLCHAIN_LIBC string prompt "Toolchain libc" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "uclibc" help Specify the libc type used by the external toolchain. The given value us passed as -m flag to all gcc and g++ invocations. This is mainly intended for multilib toolchains which support glibc and uclibc at the same time. If no value is specified, no -m flag is passed. config TOOLCHAIN_BIN_PATH string prompt "Toolchain program path" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "./usr/bin ./bin" help Specify additional directories searched for toolchain binaries (override PATH) Use ./DIR for directories relative to the root above config TOOLCHAIN_INC_PATH string prompt "Toolchain include path" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "./usr/include ./include" help Specify additional directories searched for header files (override CPPFLAGS) Use ./DIR for directories relative to the root above config TOOLCHAIN_LIB_PATH string prompt "Toolchain library path" if DEVEL depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "./usr/lib ./lib" help Specify additional directories searched for libraries (override LDFLAGS) Use ./DIR for directories relative to the root above config NEED_TOOLCHAIN bool depends on DEVEL default y if !EXTERNAL_TOOLCHAIN menuconfig TOOLCHAINOPTS bool "Toolchain Options" if DEVEL depends on NEED_TOOLCHAIN menuconfig EXTRA_TARGET_ARCH bool prompt "Enable an extra toolchain target architecture" if TOOLCHAINOPTS depends on !sparc default y if powerpc64 default n help Some builds may require a 'biarch' toolchain. This option allows you to specify an additional target arch. Most people will answer N here. config EXTRA_TARGET_ARCH_NAME string default "powerpc64" if powerpc64 prompt "Extra architecture name" if EXTRA_TARGET_ARCH help Specify the cpu name (eg powerpc64 or x86_64) of the additional target architecture. config EXTRA_TARGET_ARCH_OPTS string default "-m64" if powerpc64 prompt "Extra architecture compiler options" if EXTRA_TARGET_ARCH help If you're specifying an addition target architecture, you'll probably need to also provide options to make the compiler use this alternate arch. For example, if you're building a compiler that can build both powerpc and powerpc64 binaries, you'll need to specify -m64 here. choice prompt "MIPS64 user-land ABI" if TOOLCHAINOPTS && (mips64 || mips64el) default MIPS64_ABI_N64 help MIPS64 supports 3 different user-land ABIs: o32 (legacy), n32 and n64. config MIPS64_ABI_N64 bool "n64" config MIPS64_ABI_N32 bool "n32" config MIPS64_ABI_O32 bool "o32" endchoice comment "Binary tools" depends on TOOLCHAINOPTS source "toolchain/binutils/Config.in" comment "Compiler" depends on TOOLCHAINOPTS source "toolchain/gcc/Config.in" comment "C Library" depends on TOOLCHAINOPTS choice prompt "C Library implementation" if TOOLCHAINOPTS default LIBC_USE_UCLIBC help Select the C library implementation. config LIBC_USE_EGLIBC bool "Use eglibc" select USE_EGLIBC depends on !avr32 config LIBC_USE_UCLIBC select USE_UCLIBC bool "Use uClibc" config LIBC_USE_MUSL bool "Use musl" select USE_MUSL depends on !(mips64 || mips64el) endchoice source "toolchain/eglibc/Config.in" source "toolchain/uClibc/Config.in" source "toolchain/musl/Config.in" comment "Debuggers" depends on TOOLCHAINOPTS config GDB bool depends on !avr32 prompt "Build gdb" if TOOLCHAINOPTS default y if !EXTERNAL_TOOLCHAIN help Enable if you want to build the gdb config INSIGHT bool prompt "Build insight-gdb" if TOOLCHAINOPTS select GDB default n help Enable if you want to build insight-gdb config USE_EGLIBC bool config USE_UCLIBC bool default y if !TOOLCHAINOPTS && !EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN config USE_MUSL bool config USE_EXTERNAL_LIBC bool default y if EXTERNAL_TOOLCHAIN || NATIVE_TOOLCHAIN source "toolchain/gcc/Config.version" source "toolchain/eglibc/Config.version" source "toolchain/uClibc/Config.version" source "toolchain/musl/Config.version" config LIBC string default "eglibc" if USE_EGLIBC default "uClibc" if USE_UCLIBC default "musl" if USE_MUSL config LIBC_VERSION string default EGLIBC_VERSION if USE_EGLIBC default UCLIBC_VERSION if USE_UCLIBC default MUSL_VERSION if USE_MUSL config TARGET_SUFFIX string default "gnueabi" if USE_EGLIBC && (arm || armeb) default "gnu" if USE_EGLIBC && !(arm || armeb) default "uclibcgnueabi" if USE_UCLIBC && (arm || armeb) default "uclibc" if USE_UCLIBC && !(arm || armeb) default "muslgnueabi" if USE_MUSL && (arm || armeb) default "musl" if USE_MUSL && !(arm || armeb) config MIPS64_ABI depends on mips64 || mips64el string default "64" if MIPS64_ABI_N64 default "n32" if MIPS64_ABI_N32 default "32" if MIPS64_ABI_O32 default "64"