diff options
author | Ying Xue <ying.xue@windriver.com> | 2015-01-09 02:27:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-12 16:24:33 -0500 |
commit | e05b31f4bf8994d49322e9afb004ad479a129db0 (patch) | |
tree | 7d413a68ee6fdc5ca81b2eec93323433e61753a8 | |
parent | 1da465683a93142488a54a9038155f23d6349441 (diff) |
tipc: make tipc socket support net namespace
Now tipc socket table is statically allocated as a global variable.
Through it, we can look up one socket instance with port ID, insert
a new socket instance to the table, and delete a socket from the
table. But when tipc supports net namespace, each namespace must own
its specific socket table. So the global variable of socket table
must be redefined in tipc_net structure. As a concequence, a new
socket table will be allocated when a new namespace is created, and
a socket table will be deallocated when namespace is destroyed.
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Tested-by: Tero Aho <Tero.Aho@coriant.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/tipc/config.c | 2 | ||||
-rw-r--r-- | net/tipc/core.c | 12 | ||||
-rw-r--r-- | net/tipc/core.h | 4 | ||||
-rw-r--r-- | net/tipc/net.c | 2 | ||||
-rw-r--r-- | net/tipc/socket.c | 48 | ||||
-rw-r--r-- | net/tipc/socket.h | 8 |
6 files changed, 43 insertions, 33 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c index ac73291d0d32..20b1c5812f00 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -257,7 +257,7 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd, | |||
257 | rep_tlv_buf = tipc_media_get_names(); | 257 | rep_tlv_buf = tipc_media_get_names(); |
258 | break; | 258 | break; |
259 | case TIPC_CMD_SHOW_PORTS: | 259 | case TIPC_CMD_SHOW_PORTS: |
260 | rep_tlv_buf = tipc_sk_socks_show(); | 260 | rep_tlv_buf = tipc_sk_socks_show(net); |
261 | break; | 261 | break; |
262 | case TIPC_CMD_SHOW_STATS: | 262 | case TIPC_CMD_SHOW_STATS: |
263 | rep_tlv_buf = tipc_show_stats(); | 263 | rep_tlv_buf = tipc_show_stats(); |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 7b8443938caf..23ff3caa1ce6 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -55,17 +55,20 @@ int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ | |||
55 | static int __net_init tipc_init_net(struct net *net) | 55 | static int __net_init tipc_init_net(struct net *net) |
56 | { | 56 | { |
57 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 57 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
58 | int err; | ||
58 | 59 | ||
59 | tn->net_id = 4711; | 60 | tn->net_id = 4711; |
60 | INIT_LIST_HEAD(&tn->node_list); | 61 | INIT_LIST_HEAD(&tn->node_list); |
61 | spin_lock_init(&tn->node_list_lock); | 62 | spin_lock_init(&tn->node_list_lock); |
62 | 63 | ||
63 | return 0; | 64 | err = tipc_sk_rht_init(net); |
65 | return err; | ||
64 | } | 66 | } |
65 | 67 | ||
66 | static void __net_exit tipc_exit_net(struct net *net) | 68 | static void __net_exit tipc_exit_net(struct net *net) |
67 | { | 69 | { |
68 | tipc_net_stop(net); | 70 | tipc_net_stop(net); |
71 | tipc_sk_rht_destroy(net); | ||
69 | } | 72 | } |
70 | 73 | ||
71 | static struct pernet_operations tipc_net_ops = { | 74 | static struct pernet_operations tipc_net_ops = { |
@@ -95,10 +98,6 @@ static int __init tipc_init(void) | |||
95 | if (err) | 98 | if (err) |
96 | goto out_pernet; | 99 | goto out_pernet; |
97 | 100 | ||
98 | err = tipc_sk_rht_init(); | ||
99 | if (err) | ||
100 | goto out_reftbl; | ||
101 | |||
102 | err = tipc_nametbl_init(); | 101 | err = tipc_nametbl_init(); |
103 | if (err) | 102 | if (err) |
104 | goto out_nametbl; | 103 | goto out_nametbl; |
@@ -136,8 +135,6 @@ out_socket: | |||
136 | out_netlink: | 135 | out_netlink: |
137 | tipc_nametbl_stop(); | 136 | tipc_nametbl_stop(); |
138 | out_nametbl: | 137 | out_nametbl: |
139 | tipc_sk_rht_destroy(); | ||
140 | out_reftbl: | ||
141 | unregister_pernet_subsys(&tipc_net_ops); | 138 | unregister_pernet_subsys(&tipc_net_ops); |
142 | out_pernet: | 139 | out_pernet: |
143 | pr_err("Unable to start in single node mode\n"); | 140 | pr_err("Unable to start in single node mode\n"); |
@@ -153,7 +150,6 @@ static void __exit tipc_exit(void) | |||
153 | tipc_nametbl_stop(); | 150 | tipc_nametbl_stop(); |
154 | tipc_socket_stop(); | 151 | tipc_socket_stop(); |
155 | tipc_unregister_sysctl(); | 152 | tipc_unregister_sysctl(); |
156 | tipc_sk_rht_destroy(); | ||
157 | 153 | ||
158 | pr_info("Deactivated\n"); | 154 | pr_info("Deactivated\n"); |
159 | } | 155 | } |
diff --git a/net/tipc/core.h b/net/tipc/core.h index 3f6f9e07da99..1a7f81643668 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/rtnetlink.h> | 58 | #include <linux/rtnetlink.h> |
59 | #include <linux/etherdevice.h> | 59 | #include <linux/etherdevice.h> |
60 | #include <net/netns/generic.h> | 60 | #include <net/netns/generic.h> |
61 | #include <linux/rhashtable.h> | ||
61 | 62 | ||
62 | #include "node.h" | 63 | #include "node.h" |
63 | #include "bearer.h" | 64 | #include "bearer.h" |
@@ -101,6 +102,9 @@ struct tipc_net { | |||
101 | struct tipc_bcbearer *bcbearer; | 102 | struct tipc_bcbearer *bcbearer; |
102 | struct tipc_bclink *bclink; | 103 | struct tipc_bclink *bclink; |
103 | struct tipc_link *bcl; | 104 | struct tipc_link *bcl; |
105 | |||
106 | /* Socket hash table */ | ||
107 | struct rhashtable sk_rht; | ||
104 | }; | 108 | }; |
105 | 109 | ||
106 | #ifdef CONFIG_SYSCTL | 110 | #ifdef CONFIG_SYSCTL |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 7548ba80d289..44ccf47c79a3 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -117,7 +117,7 @@ int tipc_net_start(struct net *net, u32 addr) | |||
117 | 117 | ||
118 | tipc_own_addr = addr; | 118 | tipc_own_addr = addr; |
119 | tipc_named_reinit(); | 119 | tipc_named_reinit(); |
120 | tipc_sk_reinit(); | 120 | tipc_sk_reinit(net); |
121 | res = tipc_bclink_init(net); | 121 | res = tipc_bclink_init(net); |
122 | if (res) | 122 | if (res) |
123 | return res; | 123 | return res; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 68831453bc0e..accb02cb3527 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -115,7 +115,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, | |||
115 | struct tipc_name_seq const *seq); | 115 | struct tipc_name_seq const *seq); |
116 | static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, | 116 | static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, |
117 | struct tipc_name_seq const *seq); | 117 | struct tipc_name_seq const *seq); |
118 | static struct tipc_sock *tipc_sk_lookup(u32 portid); | 118 | static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); |
119 | static int tipc_sk_insert(struct tipc_sock *tsk); | 119 | static int tipc_sk_insert(struct tipc_sock *tsk); |
120 | static void tipc_sk_remove(struct tipc_sock *tsk); | 120 | static void tipc_sk_remove(struct tipc_sock *tsk); |
121 | 121 | ||
@@ -179,9 +179,6 @@ static const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { | |||
179 | * - port reference | 179 | * - port reference |
180 | */ | 180 | */ |
181 | 181 | ||
182 | /* Protects tipc socket hash table mutations */ | ||
183 | static struct rhashtable tipc_sk_rht; | ||
184 | |||
185 | static u32 tsk_peer_node(struct tipc_sock *tsk) | 182 | static u32 tsk_peer_node(struct tipc_sock *tsk) |
186 | { | 183 | { |
187 | return msg_destnode(&tsk->phdr); | 184 | return msg_destnode(&tsk->phdr); |
@@ -1766,7 +1763,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) | |||
1766 | u32 dnode; | 1763 | u32 dnode; |
1767 | 1764 | ||
1768 | /* Validate destination and message */ | 1765 | /* Validate destination and message */ |
1769 | tsk = tipc_sk_lookup(dport); | 1766 | tsk = tipc_sk_lookup(net, dport); |
1770 | if (unlikely(!tsk)) { | 1767 | if (unlikely(!tsk)) { |
1771 | rc = tipc_msg_eval(skb, &dnode); | 1768 | rc = tipc_msg_eval(skb, &dnode); |
1772 | goto exit; | 1769 | goto exit; |
@@ -2245,8 +2242,9 @@ static int tipc_sk_show(struct tipc_sock *tsk, char *buf, | |||
2245 | return ret; | 2242 | return ret; |
2246 | } | 2243 | } |
2247 | 2244 | ||
2248 | struct sk_buff *tipc_sk_socks_show(void) | 2245 | struct sk_buff *tipc_sk_socks_show(struct net *net) |
2249 | { | 2246 | { |
2247 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2250 | const struct bucket_table *tbl; | 2248 | const struct bucket_table *tbl; |
2251 | struct rhash_head *pos; | 2249 | struct rhash_head *pos; |
2252 | struct sk_buff *buf; | 2250 | struct sk_buff *buf; |
@@ -2265,7 +2263,7 @@ struct sk_buff *tipc_sk_socks_show(void) | |||
2265 | pb_len = ULTRA_STRING_MAX_LEN; | 2263 | pb_len = ULTRA_STRING_MAX_LEN; |
2266 | 2264 | ||
2267 | rcu_read_lock(); | 2265 | rcu_read_lock(); |
2268 | tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); | 2266 | tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); |
2269 | for (i = 0; i < tbl->size; i++) { | 2267 | for (i = 0; i < tbl->size; i++) { |
2270 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { | 2268 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { |
2271 | spin_lock_bh(&tsk->sk.sk_lock.slock); | 2269 | spin_lock_bh(&tsk->sk.sk_lock.slock); |
@@ -2286,8 +2284,9 @@ struct sk_buff *tipc_sk_socks_show(void) | |||
2286 | /* tipc_sk_reinit: set non-zero address in all existing sockets | 2284 | /* tipc_sk_reinit: set non-zero address in all existing sockets |
2287 | * when we go from standalone to network mode. | 2285 | * when we go from standalone to network mode. |
2288 | */ | 2286 | */ |
2289 | void tipc_sk_reinit(void) | 2287 | void tipc_sk_reinit(struct net *net) |
2290 | { | 2288 | { |
2289 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2291 | const struct bucket_table *tbl; | 2290 | const struct bucket_table *tbl; |
2292 | struct rhash_head *pos; | 2291 | struct rhash_head *pos; |
2293 | struct tipc_sock *tsk; | 2292 | struct tipc_sock *tsk; |
@@ -2295,7 +2294,7 @@ void tipc_sk_reinit(void) | |||
2295 | int i; | 2294 | int i; |
2296 | 2295 | ||
2297 | rcu_read_lock(); | 2296 | rcu_read_lock(); |
2298 | tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); | 2297 | tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); |
2299 | for (i = 0; i < tbl->size; i++) { | 2298 | for (i = 0; i < tbl->size; i++) { |
2300 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { | 2299 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { |
2301 | spin_lock_bh(&tsk->sk.sk_lock.slock); | 2300 | spin_lock_bh(&tsk->sk.sk_lock.slock); |
@@ -2308,12 +2307,13 @@ void tipc_sk_reinit(void) | |||
2308 | rcu_read_unlock(); | 2307 | rcu_read_unlock(); |
2309 | } | 2308 | } |
2310 | 2309 | ||
2311 | static struct tipc_sock *tipc_sk_lookup(u32 portid) | 2310 | static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) |
2312 | { | 2311 | { |
2312 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2313 | struct tipc_sock *tsk; | 2313 | struct tipc_sock *tsk; |
2314 | 2314 | ||
2315 | rcu_read_lock(); | 2315 | rcu_read_lock(); |
2316 | tsk = rhashtable_lookup(&tipc_sk_rht, &portid); | 2316 | tsk = rhashtable_lookup(&tn->sk_rht, &portid); |
2317 | if (tsk) | 2317 | if (tsk) |
2318 | sock_hold(&tsk->sk); | 2318 | sock_hold(&tsk->sk); |
2319 | rcu_read_unlock(); | 2319 | rcu_read_unlock(); |
@@ -2323,6 +2323,9 @@ static struct tipc_sock *tipc_sk_lookup(u32 portid) | |||
2323 | 2323 | ||
2324 | static int tipc_sk_insert(struct tipc_sock *tsk) | 2324 | static int tipc_sk_insert(struct tipc_sock *tsk) |
2325 | { | 2325 | { |
2326 | struct sock *sk = &tsk->sk; | ||
2327 | struct net *net = sock_net(sk); | ||
2328 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2326 | u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1; | 2329 | u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1; |
2327 | u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT; | 2330 | u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT; |
2328 | 2331 | ||
@@ -2332,7 +2335,7 @@ static int tipc_sk_insert(struct tipc_sock *tsk) | |||
2332 | portid = TIPC_MIN_PORT; | 2335 | portid = TIPC_MIN_PORT; |
2333 | tsk->portid = portid; | 2336 | tsk->portid = portid; |
2334 | sock_hold(&tsk->sk); | 2337 | sock_hold(&tsk->sk); |
2335 | if (rhashtable_lookup_insert(&tipc_sk_rht, &tsk->node)) | 2338 | if (rhashtable_lookup_insert(&tn->sk_rht, &tsk->node)) |
2336 | return 0; | 2339 | return 0; |
2337 | sock_put(&tsk->sk); | 2340 | sock_put(&tsk->sk); |
2338 | } | 2341 | } |
@@ -2343,15 +2346,17 @@ static int tipc_sk_insert(struct tipc_sock *tsk) | |||
2343 | static void tipc_sk_remove(struct tipc_sock *tsk) | 2346 | static void tipc_sk_remove(struct tipc_sock *tsk) |
2344 | { | 2347 | { |
2345 | struct sock *sk = &tsk->sk; | 2348 | struct sock *sk = &tsk->sk; |
2349 | struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id); | ||
2346 | 2350 | ||
2347 | if (rhashtable_remove(&tipc_sk_rht, &tsk->node)) { | 2351 | if (rhashtable_remove(&tn->sk_rht, &tsk->node)) { |
2348 | WARN_ON(atomic_read(&sk->sk_refcnt) == 1); | 2352 | WARN_ON(atomic_read(&sk->sk_refcnt) == 1); |
2349 | __sock_put(sk); | 2353 | __sock_put(sk); |
2350 | } | 2354 | } |
2351 | } | 2355 | } |
2352 | 2356 | ||
2353 | int tipc_sk_rht_init(void) | 2357 | int tipc_sk_rht_init(struct net *net) |
2354 | { | 2358 | { |
2359 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2355 | struct rhashtable_params rht_params = { | 2360 | struct rhashtable_params rht_params = { |
2356 | .nelem_hint = 192, | 2361 | .nelem_hint = 192, |
2357 | .head_offset = offsetof(struct tipc_sock, node), | 2362 | .head_offset = offsetof(struct tipc_sock, node), |
@@ -2364,15 +2369,17 @@ int tipc_sk_rht_init(void) | |||
2364 | .shrink_decision = rht_shrink_below_30, | 2369 | .shrink_decision = rht_shrink_below_30, |
2365 | }; | 2370 | }; |
2366 | 2371 | ||
2367 | return rhashtable_init(&tipc_sk_rht, &rht_params); | 2372 | return rhashtable_init(&tn->sk_rht, &rht_params); |
2368 | } | 2373 | } |
2369 | 2374 | ||
2370 | void tipc_sk_rht_destroy(void) | 2375 | void tipc_sk_rht_destroy(struct net *net) |
2371 | { | 2376 | { |
2377 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2378 | |||
2372 | /* Wait for socket readers to complete */ | 2379 | /* Wait for socket readers to complete */ |
2373 | synchronize_net(); | 2380 | synchronize_net(); |
2374 | 2381 | ||
2375 | rhashtable_destroy(&tipc_sk_rht); | 2382 | rhashtable_destroy(&tn->sk_rht); |
2376 | } | 2383 | } |
2377 | 2384 | ||
2378 | /** | 2385 | /** |
@@ -2730,10 +2737,12 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2730 | struct rhash_head *pos; | 2737 | struct rhash_head *pos; |
2731 | u32 prev_portid = cb->args[0]; | 2738 | u32 prev_portid = cb->args[0]; |
2732 | u32 portid = prev_portid; | 2739 | u32 portid = prev_portid; |
2740 | struct net *net = sock_net(skb->sk); | ||
2741 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
2733 | int i; | 2742 | int i; |
2734 | 2743 | ||
2735 | rcu_read_lock(); | 2744 | rcu_read_lock(); |
2736 | tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); | 2745 | tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); |
2737 | for (i = 0; i < tbl->size; i++) { | 2746 | for (i = 0; i < tbl->size; i++) { |
2738 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { | 2747 | rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { |
2739 | spin_lock_bh(&tsk->sk.sk_lock.slock); | 2748 | spin_lock_bh(&tsk->sk.sk_lock.slock); |
@@ -2839,6 +2848,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2839 | u32 tsk_portid = cb->args[0]; | 2848 | u32 tsk_portid = cb->args[0]; |
2840 | u32 last_publ = cb->args[1]; | 2849 | u32 last_publ = cb->args[1]; |
2841 | u32 done = cb->args[2]; | 2850 | u32 done = cb->args[2]; |
2851 | struct net *net = sock_net(skb->sk); | ||
2842 | struct tipc_sock *tsk; | 2852 | struct tipc_sock *tsk; |
2843 | 2853 | ||
2844 | if (!tsk_portid) { | 2854 | if (!tsk_portid) { |
@@ -2864,7 +2874,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2864 | if (done) | 2874 | if (done) |
2865 | return 0; | 2875 | return 0; |
2866 | 2876 | ||
2867 | tsk = tipc_sk_lookup(tsk_portid); | 2877 | tsk = tipc_sk_lookup(net, tsk_portid); |
2868 | if (!tsk) | 2878 | if (!tsk) |
2869 | return -EINVAL; | 2879 | return -EINVAL; |
2870 | 2880 | ||
diff --git a/net/tipc/socket.h b/net/tipc/socket.h index eb15c3107920..c15c4e121fe3 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h | |||
@@ -50,11 +50,11 @@ void tipc_sock_release_local(struct socket *sock); | |||
50 | int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, | 50 | int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, |
51 | int flags); | 51 | int flags); |
52 | int tipc_sk_rcv(struct net *net, struct sk_buff *buf); | 52 | int tipc_sk_rcv(struct net *net, struct sk_buff *buf); |
53 | struct sk_buff *tipc_sk_socks_show(void); | 53 | struct sk_buff *tipc_sk_socks_show(struct net *net); |
54 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf); | 54 | void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf); |
55 | void tipc_sk_reinit(void); | 55 | void tipc_sk_reinit(struct net *net); |
56 | int tipc_sk_rht_init(void); | 56 | int tipc_sk_rht_init(struct net *net); |
57 | void tipc_sk_rht_destroy(void); | 57 | void tipc_sk_rht_destroy(struct net *net); |
58 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); | 58 | int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); |
59 | int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb); | 59 | int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb); |
60 | 60 | ||