aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.h
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2014-08-02 05:47:45 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-02 22:49:38 -0400
commite341694e3eb57fcda9f1adc7bfea42fe080d8d7a (patch)
tree12ac538a44609b3075bfaf98999ba68d9ff575cc /net/netlink/af_netlink.h
parent7e1e77636e36075ebf118298855268468f1028e8 (diff)
netlink: Convert netlink_lookup() to use RCU protected hash table
Heavy Netlink users such as Open vSwitch spend a considerable amount of time in netlink_lookup() due to the read-lock on nl_table_lock. Use of RCU relieves the lock contention. Makes use of the new resizable hash table to avoid locking on the lookup. The hash table will grow if entries exceeds 75% of table size up to a total table size of 64K. It will automatically shrink if usage falls below 30%. Also splits nl_table_lock into a separate mutex to protect hash table mutations and allow synchronize_rcu() to sleep while waiting for readers during expansion and shrinking. Before: 9.16% kpktgend_0 [openvswitch] [k] masked_flow_lookup 6.42% kpktgend_0 [pktgen] [k] mod_cur_headers 6.26% kpktgend_0 [pktgen] [k] pktgen_thread_worker 6.23% kpktgend_0 [kernel.kallsyms] [k] memset 4.79% kpktgend_0 [kernel.kallsyms] [k] netlink_lookup 4.37% kpktgend_0 [kernel.kallsyms] [k] memcpy 3.60% kpktgend_0 [openvswitch] [k] ovs_flow_extract 2.69% kpktgend_0 [kernel.kallsyms] [k] jhash2 After: 15.26% kpktgend_0 [openvswitch] [k] masked_flow_lookup 8.12% kpktgend_0 [pktgen] [k] pktgen_thread_worker 7.92% kpktgend_0 [pktgen] [k] mod_cur_headers 5.11% kpktgend_0 [kernel.kallsyms] [k] memset 4.11% kpktgend_0 [openvswitch] [k] ovs_flow_extract 4.06% kpktgend_0 [kernel.kallsyms] [k] _raw_spin_lock 3.90% kpktgend_0 [kernel.kallsyms] [k] jhash2 [...] 0.67% kpktgend_0 [kernel.kallsyms] [k] netlink_lookup Signed-off-by: Thomas Graf <tgraf@suug.ch> Reviewed-by: Nikolay Aleksandrov <nikolay@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.h')
-rw-r--r--net/netlink/af_netlink.h18
1 files changed, 4 insertions, 14 deletions
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 0b59d441f5b6..60f631fb7087 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -1,6 +1,7 @@
1#ifndef _AF_NETLINK_H 1#ifndef _AF_NETLINK_H
2#define _AF_NETLINK_H 2#define _AF_NETLINK_H
3 3
4#include <linux/rhashtable.h>
4#include <net/sock.h> 5#include <net/sock.h>
5 6
6#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) 7#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
@@ -47,6 +48,8 @@ struct netlink_sock {
47 struct netlink_ring tx_ring; 48 struct netlink_ring tx_ring;
48 atomic_t mapped; 49 atomic_t mapped;
49#endif /* CONFIG_NETLINK_MMAP */ 50#endif /* CONFIG_NETLINK_MMAP */
51
52 struct rhash_head node;
50}; 53};
51 54
52static inline struct netlink_sock *nlk_sk(struct sock *sk) 55static inline struct netlink_sock *nlk_sk(struct sock *sk)
@@ -54,21 +57,8 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk)
54 return container_of(sk, struct netlink_sock, sk); 57 return container_of(sk, struct netlink_sock, sk);
55} 58}
56 59
57struct nl_portid_hash {
58 struct hlist_head *table;
59 unsigned long rehash_time;
60
61 unsigned int mask;
62 unsigned int shift;
63
64 unsigned int entries;
65 unsigned int max_shift;
66
67 u32 rnd;
68};
69
70struct netlink_table { 60struct netlink_table {
71 struct nl_portid_hash hash; 61 struct rhashtable hash;
72 struct hlist_head mc_list; 62 struct hlist_head mc_list;
73 struct listeners __rcu *listeners; 63 struct listeners __rcu *listeners;
74 unsigned int flags; 64 unsigned int flags;