diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 62 | ||||
-rw-r--r-- | net/tipc/bcast.h | 17 | ||||
-rw-r--r-- | net/tipc/link.c | 4 | ||||
-rw-r--r-- | net/tipc/node.h | 4 | ||||
-rw-r--r-- | net/tipc/socket.c | 36 |
5 files changed, 108 insertions, 15 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 672e6ef93cab..7d99029df342 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -54,6 +54,9 @@ const char tipc_bclink_name[] = "broadcast-link"; | |||
54 | * @dest: array keeping number of reachable destinations per bearer | 54 | * @dest: array keeping number of reachable destinations per bearer |
55 | * @primary_bearer: a bearer having links to all broadcast destinations, if any | 55 | * @primary_bearer: a bearer having links to all broadcast destinations, if any |
56 | * @bcast_support: indicates if primary bearer, if any, supports broadcast | 56 | * @bcast_support: indicates if primary bearer, if any, supports broadcast |
57 | * @rcast_support: indicates if all peer nodes support replicast | ||
58 | * @rc_ratio: dest count as percentage of cluster size where send method changes | ||
59 | * @bc_threshold: calculated drom rc_ratio; if dests > threshold use broadcast | ||
57 | */ | 60 | */ |
58 | struct tipc_bc_base { | 61 | struct tipc_bc_base { |
59 | struct tipc_link *link; | 62 | struct tipc_link *link; |
@@ -61,6 +64,9 @@ struct tipc_bc_base { | |||
61 | int dests[MAX_BEARERS]; | 64 | int dests[MAX_BEARERS]; |
62 | int primary_bearer; | 65 | int primary_bearer; |
63 | bool bcast_support; | 66 | bool bcast_support; |
67 | bool rcast_support; | ||
68 | int rc_ratio; | ||
69 | int bc_threshold; | ||
64 | }; | 70 | }; |
65 | 71 | ||
66 | static struct tipc_bc_base *tipc_bc_base(struct net *net) | 72 | static struct tipc_bc_base *tipc_bc_base(struct net *net) |
@@ -73,6 +79,19 @@ int tipc_bcast_get_mtu(struct net *net) | |||
73 | return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE; | 79 | return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE; |
74 | } | 80 | } |
75 | 81 | ||
82 | void tipc_bcast_disable_rcast(struct net *net) | ||
83 | { | ||
84 | tipc_bc_base(net)->rcast_support = false; | ||
85 | } | ||
86 | |||
87 | static void tipc_bcbase_calc_bc_threshold(struct net *net) | ||
88 | { | ||
89 | struct tipc_bc_base *bb = tipc_bc_base(net); | ||
90 | int cluster_size = tipc_link_bc_peers(tipc_bc_sndlink(net)); | ||
91 | |||
92 | bb->bc_threshold = 1 + (cluster_size * bb->rc_ratio / 100); | ||
93 | } | ||
94 | |||
76 | /* tipc_bcbase_select_primary(): find a bearer with links to all destinations, | 95 | /* tipc_bcbase_select_primary(): find a bearer with links to all destinations, |
77 | * if any, and make it primary bearer | 96 | * if any, and make it primary bearer |
78 | */ | 97 | */ |
@@ -175,6 +194,31 @@ static void tipc_bcbase_xmit(struct net *net, struct sk_buff_head *xmitq) | |||
175 | __skb_queue_purge(&_xmitq); | 194 | __skb_queue_purge(&_xmitq); |
176 | } | 195 | } |
177 | 196 | ||
197 | static void tipc_bcast_select_xmit_method(struct net *net, int dests, | ||
198 | struct tipc_mc_method *method) | ||
199 | { | ||
200 | struct tipc_bc_base *bb = tipc_bc_base(net); | ||
201 | unsigned long exp = method->expires; | ||
202 | |||
203 | /* Broadcast supported by used bearer/bearers? */ | ||
204 | if (!bb->bcast_support) { | ||
205 | method->rcast = true; | ||
206 | return; | ||
207 | } | ||
208 | /* Any destinations which don't support replicast ? */ | ||
209 | if (!bb->rcast_support) { | ||
210 | method->rcast = false; | ||
211 | return; | ||
212 | } | ||
213 | /* Can current method be changed ? */ | ||
214 | method->expires = jiffies + TIPC_METHOD_EXPIRE; | ||
215 | if (method->mandatory || time_before(jiffies, exp)) | ||
216 | return; | ||
217 | |||
218 | /* Determine method to use now */ | ||
219 | method->rcast = dests <= bb->bc_threshold; | ||
220 | } | ||
221 | |||
178 | /* tipc_bcast_xmit - broadcast the buffer chain to all external nodes | 222 | /* tipc_bcast_xmit - broadcast the buffer chain to all external nodes |
179 | * @net: the applicable net namespace | 223 | * @net: the applicable net namespace |
180 | * @pkts: chain of buffers containing message | 224 | * @pkts: chain of buffers containing message |
@@ -237,16 +281,16 @@ static int tipc_rcast_xmit(struct net *net, struct sk_buff_head *pkts, | |||
237 | * and to identified node local sockets | 281 | * and to identified node local sockets |
238 | * @net: the applicable net namespace | 282 | * @net: the applicable net namespace |
239 | * @pkts: chain of buffers containing message | 283 | * @pkts: chain of buffers containing message |
240 | * @dests: destination nodes for message. Not consumed. | 284 | * @method: send method to be used |
285 | * @dests: destination nodes for message. | ||
241 | * @cong_link_cnt: returns number of encountered congested destination links | 286 | * @cong_link_cnt: returns number of encountered congested destination links |
242 | * @cong_links: returns identities of congested links | ||
243 | * Consumes buffer chain. | 287 | * Consumes buffer chain. |
244 | * Returns 0 if success, otherwise errno | 288 | * Returns 0 if success, otherwise errno |
245 | */ | 289 | */ |
246 | int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, | 290 | int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, |
247 | struct tipc_nlist *dests, u16 *cong_link_cnt) | 291 | struct tipc_mc_method *method, struct tipc_nlist *dests, |
292 | u16 *cong_link_cnt) | ||
248 | { | 293 | { |
249 | struct tipc_bc_base *bb = tipc_bc_base(net); | ||
250 | struct sk_buff_head inputq, localq; | 294 | struct sk_buff_head inputq, localq; |
251 | int rc = 0; | 295 | int rc = 0; |
252 | 296 | ||
@@ -258,9 +302,10 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, | |||
258 | rc = -ENOMEM; | 302 | rc = -ENOMEM; |
259 | goto exit; | 303 | goto exit; |
260 | } | 304 | } |
261 | 305 | /* Send according to determined transmit method */ | |
262 | if (dests->remote) { | 306 | if (dests->remote) { |
263 | if (!bb->bcast_support) | 307 | tipc_bcast_select_xmit_method(net, dests->remote, method); |
308 | if (method->rcast) | ||
264 | rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt); | 309 | rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt); |
265 | else | 310 | else |
266 | rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); | 311 | rc = tipc_bcast_xmit(net, pkts, cong_link_cnt); |
@@ -269,6 +314,7 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, | |||
269 | if (dests->local) | 314 | if (dests->local) |
270 | tipc_sk_mcast_rcv(net, &localq, &inputq); | 315 | tipc_sk_mcast_rcv(net, &localq, &inputq); |
271 | exit: | 316 | exit: |
317 | /* This queue should normally be empty by now */ | ||
272 | __skb_queue_purge(pkts); | 318 | __skb_queue_purge(pkts); |
273 | return rc; | 319 | return rc; |
274 | } | 320 | } |
@@ -377,6 +423,7 @@ void tipc_bcast_add_peer(struct net *net, struct tipc_link *uc_l, | |||
377 | tipc_bcast_lock(net); | 423 | tipc_bcast_lock(net); |
378 | tipc_link_add_bc_peer(snd_l, uc_l, xmitq); | 424 | tipc_link_add_bc_peer(snd_l, uc_l, xmitq); |
379 | tipc_bcbase_select_primary(net); | 425 | tipc_bcbase_select_primary(net); |
426 | tipc_bcbase_calc_bc_threshold(net); | ||
380 | tipc_bcast_unlock(net); | 427 | tipc_bcast_unlock(net); |
381 | } | 428 | } |
382 | 429 | ||
@@ -395,6 +442,7 @@ void tipc_bcast_remove_peer(struct net *net, struct tipc_link *rcv_l) | |||
395 | tipc_bcast_lock(net); | 442 | tipc_bcast_lock(net); |
396 | tipc_link_remove_bc_peer(snd_l, rcv_l, &xmitq); | 443 | tipc_link_remove_bc_peer(snd_l, rcv_l, &xmitq); |
397 | tipc_bcbase_select_primary(net); | 444 | tipc_bcbase_select_primary(net); |
445 | tipc_bcbase_calc_bc_threshold(net); | ||
398 | tipc_bcast_unlock(net); | 446 | tipc_bcast_unlock(net); |
399 | 447 | ||
400 | tipc_bcbase_xmit(net, &xmitq); | 448 | tipc_bcbase_xmit(net, &xmitq); |
@@ -477,6 +525,8 @@ int tipc_bcast_init(struct net *net) | |||
477 | goto enomem; | 525 | goto enomem; |
478 | bb->link = l; | 526 | bb->link = l; |
479 | tn->bcl = l; | 527 | tn->bcl = l; |
528 | bb->rc_ratio = 25; | ||
529 | bb->rcast_support = true; | ||
480 | return 0; | 530 | return 0; |
481 | enomem: | 531 | enomem: |
482 | kfree(bb); | 532 | kfree(bb); |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index dd772e6f6fa4..751530ab0c49 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -46,6 +46,8 @@ struct tipc_nlist; | |||
46 | struct tipc_nitem; | 46 | struct tipc_nitem; |
47 | extern const char tipc_bclink_name[]; | 47 | extern const char tipc_bclink_name[]; |
48 | 48 | ||
49 | #define TIPC_METHOD_EXPIRE msecs_to_jiffies(5000) | ||
50 | |||
49 | struct tipc_nlist { | 51 | struct tipc_nlist { |
50 | struct list_head list; | 52 | struct list_head list; |
51 | u32 self; | 53 | u32 self; |
@@ -58,6 +60,17 @@ void tipc_nlist_purge(struct tipc_nlist *nl); | |||
58 | void tipc_nlist_add(struct tipc_nlist *nl, u32 node); | 60 | void tipc_nlist_add(struct tipc_nlist *nl, u32 node); |
59 | void tipc_nlist_del(struct tipc_nlist *nl, u32 node); | 61 | void tipc_nlist_del(struct tipc_nlist *nl, u32 node); |
60 | 62 | ||
63 | /* Cookie to be used between socket and broadcast layer | ||
64 | * @rcast: replicast (instead of broadcast) was used at previous xmit | ||
65 | * @mandatory: broadcast/replicast indication was set by user | ||
66 | * @expires: re-evaluate non-mandatory transmit method if we are past this | ||
67 | */ | ||
68 | struct tipc_mc_method { | ||
69 | bool rcast; | ||
70 | bool mandatory; | ||
71 | unsigned long expires; | ||
72 | }; | ||
73 | |||
61 | int tipc_bcast_init(struct net *net); | 74 | int tipc_bcast_init(struct net *net); |
62 | void tipc_bcast_stop(struct net *net); | 75 | void tipc_bcast_stop(struct net *net); |
63 | void tipc_bcast_add_peer(struct net *net, struct tipc_link *l, | 76 | void tipc_bcast_add_peer(struct net *net, struct tipc_link *l, |
@@ -66,8 +79,10 @@ void tipc_bcast_remove_peer(struct net *net, struct tipc_link *rcv_bcl); | |||
66 | void tipc_bcast_inc_bearer_dst_cnt(struct net *net, int bearer_id); | 79 | void tipc_bcast_inc_bearer_dst_cnt(struct net *net, int bearer_id); |
67 | void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int bearer_id); | 80 | void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int bearer_id); |
68 | int tipc_bcast_get_mtu(struct net *net); | 81 | int tipc_bcast_get_mtu(struct net *net); |
82 | void tipc_bcast_disable_rcast(struct net *net); | ||
69 | int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, | 83 | int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, |
70 | struct tipc_nlist *dests, u16 *cong_link_cnt); | 84 | struct tipc_mc_method *method, struct tipc_nlist *dests, |
85 | u16 *cong_link_cnt); | ||
71 | int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb); | 86 | int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb); |
72 | void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, | 87 | void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, |
73 | struct tipc_msg *hdr); | 88 | struct tipc_msg *hdr); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index b17b9e155469..ddd2dd6f77aa 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -515,6 +515,10 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, | |||
515 | if (link_is_bc_sndlink(l)) | 515 | if (link_is_bc_sndlink(l)) |
516 | l->state = LINK_ESTABLISHED; | 516 | l->state = LINK_ESTABLISHED; |
517 | 517 | ||
518 | /* Disable replicast if even a single peer doesn't support it */ | ||
519 | if (link_is_bc_rcvlink(l) && !(peer_caps & TIPC_BCAST_RCAST)) | ||
520 | tipc_bcast_disable_rcast(net); | ||
521 | |||
518 | return true; | 522 | return true; |
519 | } | 523 | } |
520 | 524 | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h index 39ef54c1f2ad..898c22916984 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -47,11 +47,13 @@ | |||
47 | enum { | 47 | enum { |
48 | TIPC_BCAST_SYNCH = (1 << 1), | 48 | TIPC_BCAST_SYNCH = (1 << 1), |
49 | TIPC_BCAST_STATE_NACK = (1 << 2), | 49 | TIPC_BCAST_STATE_NACK = (1 << 2), |
50 | TIPC_BLOCK_FLOWCTL = (1 << 3) | 50 | TIPC_BLOCK_FLOWCTL = (1 << 3), |
51 | TIPC_BCAST_RCAST = (1 << 4) | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | #define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \ | 54 | #define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \ |
54 | TIPC_BCAST_STATE_NACK | \ | 55 | TIPC_BCAST_STATE_NACK | \ |
56 | TIPC_BCAST_RCAST | \ | ||
55 | TIPC_BLOCK_FLOWCTL) | 57 | TIPC_BLOCK_FLOWCTL) |
56 | #define INVALID_BEARER_ID -1 | 58 | #define INVALID_BEARER_ID -1 |
57 | 59 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 93b6ae3154c9..5bec8aac5008 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -79,6 +79,7 @@ enum { | |||
79 | * @rcv_unacked: # messages read by user, but not yet acked back to peer | 79 | * @rcv_unacked: # messages read by user, but not yet acked back to peer |
80 | * @peer: 'connected' peer for dgram/rdm | 80 | * @peer: 'connected' peer for dgram/rdm |
81 | * @node: hash table node | 81 | * @node: hash table node |
82 | * @mc_method: cookie for use between socket and broadcast layer | ||
82 | * @rcu: rcu struct for tipc_sock | 83 | * @rcu: rcu struct for tipc_sock |
83 | */ | 84 | */ |
84 | struct tipc_sock { | 85 | struct tipc_sock { |
@@ -103,6 +104,7 @@ struct tipc_sock { | |||
103 | u16 rcv_win; | 104 | u16 rcv_win; |
104 | struct sockaddr_tipc peer; | 105 | struct sockaddr_tipc peer; |
105 | struct rhash_head node; | 106 | struct rhash_head node; |
107 | struct tipc_mc_method mc_method; | ||
106 | struct rcu_head rcu; | 108 | struct rcu_head rcu; |
107 | }; | 109 | }; |
108 | 110 | ||
@@ -740,6 +742,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
740 | struct tipc_msg *hdr = &tsk->phdr; | 742 | struct tipc_msg *hdr = &tsk->phdr; |
741 | struct net *net = sock_net(sk); | 743 | struct net *net = sock_net(sk); |
742 | int mtu = tipc_bcast_get_mtu(net); | 744 | int mtu = tipc_bcast_get_mtu(net); |
745 | struct tipc_mc_method *method = &tsk->mc_method; | ||
743 | u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE); | 746 | u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE); |
744 | struct sk_buff_head pkts; | 747 | struct sk_buff_head pkts; |
745 | struct tipc_nlist dsts; | 748 | struct tipc_nlist dsts; |
@@ -773,7 +776,7 @@ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | |||
773 | 776 | ||
774 | /* Send message if build was successful */ | 777 | /* Send message if build was successful */ |
775 | if (unlikely(rc == dlen)) | 778 | if (unlikely(rc == dlen)) |
776 | rc = tipc_mcast_xmit(net, &pkts, &dsts, | 779 | rc = tipc_mcast_xmit(net, &pkts, method, &dsts, |
777 | &tsk->cong_link_cnt); | 780 | &tsk->cong_link_cnt); |
778 | 781 | ||
779 | tipc_nlist_purge(&dsts); | 782 | tipc_nlist_purge(&dsts); |
@@ -2344,18 +2347,29 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | |||
2344 | { | 2347 | { |
2345 | struct sock *sk = sock->sk; | 2348 | struct sock *sk = sock->sk; |
2346 | struct tipc_sock *tsk = tipc_sk(sk); | 2349 | struct tipc_sock *tsk = tipc_sk(sk); |
2347 | u32 value; | 2350 | u32 value = 0; |
2348 | int res; | 2351 | int res; |
2349 | 2352 | ||
2350 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) | 2353 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) |
2351 | return 0; | 2354 | return 0; |
2352 | if (lvl != SOL_TIPC) | 2355 | if (lvl != SOL_TIPC) |
2353 | return -ENOPROTOOPT; | 2356 | return -ENOPROTOOPT; |
2354 | if (ol < sizeof(value)) | 2357 | |
2355 | return -EINVAL; | 2358 | switch (opt) { |
2356 | res = get_user(value, (u32 __user *)ov); | 2359 | case TIPC_IMPORTANCE: |
2357 | if (res) | 2360 | case TIPC_SRC_DROPPABLE: |
2358 | return res; | 2361 | case TIPC_DEST_DROPPABLE: |
2362 | case TIPC_CONN_TIMEOUT: | ||
2363 | if (ol < sizeof(value)) | ||
2364 | return -EINVAL; | ||
2365 | res = get_user(value, (u32 __user *)ov); | ||
2366 | if (res) | ||
2367 | return res; | ||
2368 | break; | ||
2369 | default: | ||
2370 | if (ov || ol) | ||
2371 | return -EINVAL; | ||
2372 | } | ||
2359 | 2373 | ||
2360 | lock_sock(sk); | 2374 | lock_sock(sk); |
2361 | 2375 | ||
@@ -2376,6 +2390,14 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | |||
2376 | tipc_sk(sk)->conn_timeout = value; | 2390 | tipc_sk(sk)->conn_timeout = value; |
2377 | /* no need to set "res", since already 0 at this point */ | 2391 | /* no need to set "res", since already 0 at this point */ |
2378 | break; | 2392 | break; |
2393 | case TIPC_MCAST_BROADCAST: | ||
2394 | tsk->mc_method.rcast = false; | ||
2395 | tsk->mc_method.mandatory = true; | ||
2396 | break; | ||
2397 | case TIPC_MCAST_REPLICAST: | ||
2398 | tsk->mc_method.rcast = true; | ||
2399 | tsk->mc_method.mandatory = true; | ||
2400 | break; | ||
2379 | default: | 2401 | default: |
2380 | res = -EINVAL; | 2402 | res = -EINVAL; |
2381 | } | 2403 | } |