diff options
Diffstat (limited to 'net/tipc/bcast.c')
-rw-r--r-- | net/tipc/bcast.c | 62 |
1 files changed, 56 insertions, 6 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); |