Skip to content

Commit 2a06b89

Browse files
edumazetdavem330
authored andcommitted
net: reorder 'struct net' fields to avoid false sharing
Intel test robot reported a ~7% regression on TCP_CRR tests that they bisected to the cited commit. Indeed, every time a new TCP socket is created or deleted, the atomic counter net->count is touched (via get_net(net) and put_net(net) calls) So cpus might have to reload a contended cache line in net_hash_mix(net) calls. We need to reorder 'struct net' fields to move @hash_mix in a read mostly cache line. We move in the first cache line fields that can be dirtied often. We probably will have to address in a followup patch the __randomize_layout that was added in linux-4.13, since this might break our placement choices. Fixes: 355b985 ("netns: provide pure entropy for net_hash_mix()") Signed-off-by: Eric Dumazet <[email protected]> Reported-by: kernel test robot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 50c7d2b commit 2a06b89

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

include/net/net_namespace.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ struct bpf_prog;
5252
#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
5353

5454
struct net {
55+
/* First cache line can be often dirtied.
56+
* Do not place here read-mostly fields.
57+
*/
5558
refcount_t passive; /* To decide when the network
5659
* namespace should be freed.
5760
*/
@@ -60,7 +63,13 @@ struct net {
6063
*/
6164
spinlock_t rules_mod_lock;
6265

63-
u32 hash_mix;
66+
unsigned int dev_unreg_count;
67+
68+
unsigned int dev_base_seq; /* protected by rtnl_mutex */
69+
int ifindex;
70+
71+
spinlock_t nsid_lock;
72+
atomic_t fnhe_genid;
6473

6574
struct list_head list; /* list of network namespaces */
6675
struct list_head exit_list; /* To linked to call pernet exit
@@ -76,11 +85,11 @@ struct net {
7685
#endif
7786
struct user_namespace *user_ns; /* Owning user namespace */
7887
struct ucounts *ucounts;
79-
spinlock_t nsid_lock;
8088
struct idr netns_ids;
8189

8290
struct ns_common ns;
8391

92+
struct list_head dev_base_head;
8493
struct proc_dir_entry *proc_net;
8594
struct proc_dir_entry *proc_net_stat;
8695

@@ -93,17 +102,18 @@ struct net {
93102

94103
struct uevent_sock *uevent_sock; /* uevent socket */
95104

96-
struct list_head dev_base_head;
97105
struct hlist_head *dev_name_head;
98106
struct hlist_head *dev_index_head;
99-
unsigned int dev_base_seq; /* protected by rtnl_mutex */
100-
int ifindex;
101-
unsigned int dev_unreg_count;
107+
/* Note that @hash_mix can be read millions times per second,
108+
* it is critical that it is on a read_mostly cache line.
109+
*/
110+
u32 hash_mix;
111+
112+
struct net_device *loopback_dev; /* The loopback */
102113

103114
/* core fib_rules */
104115
struct list_head rules_ops;
105116

106-
struct net_device *loopback_dev; /* The loopback */
107117
struct netns_core core;
108118
struct netns_mib mib;
109119
struct netns_packet packet;
@@ -171,7 +181,6 @@ struct net {
171181
struct sock *crypto_nlsk;
172182
#endif
173183
struct sock *diag_nlsk;
174-
atomic_t fnhe_genid;
175184
} __randomize_layout;
176185

177186
#include <linux/seq_file_net.h>

0 commit comments

Comments
 (0)