aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/bcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/bcast.c')
-rw-r--r--net/tipc/bcast.c95
1 files changed, 36 insertions, 59 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 3e41704832de..c5cbdcb1f0b5 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -62,21 +62,8 @@ static void tipc_bclink_lock(struct net *net)
62static void tipc_bclink_unlock(struct net *net) 62static void tipc_bclink_unlock(struct net *net)
63{ 63{
64 struct tipc_net *tn = net_generic(net, tipc_net_id); 64 struct tipc_net *tn = net_generic(net, tipc_net_id);
65 struct tipc_node *node = NULL;
66 65
67 if (likely(!tn->bclink->flags)) {
68 spin_unlock_bh(&tn->bclink->lock);
69 return;
70 }
71
72 if (tn->bclink->flags & TIPC_BCLINK_RESET) {
73 tn->bclink->flags &= ~TIPC_BCLINK_RESET;
74 node = tipc_bclink_retransmit_to(net);
75 }
76 spin_unlock_bh(&tn->bclink->lock); 66 spin_unlock_bh(&tn->bclink->lock);
77
78 if (node)
79 tipc_link_reset_all(node);
80} 67}
81 68
82void tipc_bclink_input(struct net *net) 69void tipc_bclink_input(struct net *net)
@@ -91,13 +78,6 @@ uint tipc_bclink_get_mtu(void)
91 return MAX_PKT_DEFAULT_MCAST; 78 return MAX_PKT_DEFAULT_MCAST;
92} 79}
93 80
94void tipc_bclink_set_flags(struct net *net, unsigned int flags)
95{
96 struct tipc_net *tn = net_generic(net, tipc_net_id);
97
98 tn->bclink->flags |= flags;
99}
100
101static u32 bcbuf_acks(struct sk_buff *buf) 81static u32 bcbuf_acks(struct sk_buff *buf)
102{ 82{
103 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle; 83 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
@@ -135,9 +115,10 @@ static void bclink_set_last_sent(struct net *net)
135{ 115{
136 struct tipc_net *tn = net_generic(net, tipc_net_id); 116 struct tipc_net *tn = net_generic(net, tipc_net_id);
137 struct tipc_link *bcl = tn->bcl; 117 struct tipc_link *bcl = tn->bcl;
118 struct sk_buff *skb = skb_peek(&bcl->backlogq);
138 119
139 if (bcl->next_out) 120 if (skb)
140 bcl->fsm_msg_cnt = mod(buf_seqno(bcl->next_out) - 1); 121 bcl->fsm_msg_cnt = mod(buf_seqno(skb) - 1);
141 else 122 else
142 bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1); 123 bcl->fsm_msg_cnt = mod(bcl->next_out_no - 1);
143} 124}
@@ -155,7 +136,6 @@ static void bclink_update_last_sent(struct tipc_node *node, u32 seqno)
155 seqno : node->bclink.last_sent; 136 seqno : node->bclink.last_sent;
156} 137}
157 138
158
159/** 139/**
160 * tipc_bclink_retransmit_to - get most recent node to request retransmission 140 * tipc_bclink_retransmit_to - get most recent node to request retransmission
161 * 141 *
@@ -180,7 +160,7 @@ static void bclink_retransmit_pkt(struct tipc_net *tn, u32 after, u32 to)
180 struct sk_buff *skb; 160 struct sk_buff *skb;
181 struct tipc_link *bcl = tn->bcl; 161 struct tipc_link *bcl = tn->bcl;
182 162
183 skb_queue_walk(&bcl->outqueue, skb) { 163 skb_queue_walk(&bcl->transmq, skb) {
184 if (more(buf_seqno(skb), after)) { 164 if (more(buf_seqno(skb), after)) {
185 tipc_link_retransmit(bcl, skb, mod(to - after)); 165 tipc_link_retransmit(bcl, skb, mod(to - after));
186 break; 166 break;
@@ -210,14 +190,17 @@ void tipc_bclink_wakeup_users(struct net *net)
210void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) 190void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
211{ 191{
212 struct sk_buff *skb, *tmp; 192 struct sk_buff *skb, *tmp;
213 struct sk_buff *next;
214 unsigned int released = 0; 193 unsigned int released = 0;
215 struct net *net = n_ptr->net; 194 struct net *net = n_ptr->net;
216 struct tipc_net *tn = net_generic(net, tipc_net_id); 195 struct tipc_net *tn = net_generic(net, tipc_net_id);
217 196
197 if (unlikely(!n_ptr->bclink.recv_permitted))
198 return;
199
218 tipc_bclink_lock(net); 200 tipc_bclink_lock(net);
201
219 /* Bail out if tx queue is empty (no clean up is required) */ 202 /* Bail out if tx queue is empty (no clean up is required) */
220 skb = skb_peek(&tn->bcl->outqueue); 203 skb = skb_peek(&tn->bcl->transmq);
221 if (!skb) 204 if (!skb)
222 goto exit; 205 goto exit;
223 206
@@ -244,27 +227,19 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
244 } 227 }
245 228
246 /* Skip over packets that node has previously acknowledged */ 229 /* Skip over packets that node has previously acknowledged */
247 skb_queue_walk(&tn->bcl->outqueue, skb) { 230 skb_queue_walk(&tn->bcl->transmq, skb) {
248 if (more(buf_seqno(skb), n_ptr->bclink.acked)) 231 if (more(buf_seqno(skb), n_ptr->bclink.acked))
249 break; 232 break;
250 } 233 }
251 234
252 /* Update packets that node is now acknowledging */ 235 /* Update packets that node is now acknowledging */
253 skb_queue_walk_from_safe(&tn->bcl->outqueue, skb, tmp) { 236 skb_queue_walk_from_safe(&tn->bcl->transmq, skb, tmp) {
254 if (more(buf_seqno(skb), acked)) 237 if (more(buf_seqno(skb), acked))
255 break; 238 break;
256 239 bcbuf_decr_acks(skb);
257 next = tipc_skb_queue_next(&tn->bcl->outqueue, skb); 240 bclink_set_last_sent(net);
258 if (skb != tn->bcl->next_out) {
259 bcbuf_decr_acks(skb);
260 } else {
261 bcbuf_set_acks(skb, 0);
262 tn->bcl->next_out = next;
263 bclink_set_last_sent(net);
264 }
265
266 if (bcbuf_acks(skb) == 0) { 241 if (bcbuf_acks(skb) == 0) {
267 __skb_unlink(skb, &tn->bcl->outqueue); 242 __skb_unlink(skb, &tn->bcl->transmq);
268 kfree_skb(skb); 243 kfree_skb(skb);
269 released = 1; 244 released = 1;
270 } 245 }
@@ -272,7 +247,7 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
272 n_ptr->bclink.acked = acked; 247 n_ptr->bclink.acked = acked;
273 248
274 /* Try resolving broadcast link congestion, if necessary */ 249 /* Try resolving broadcast link congestion, if necessary */
275 if (unlikely(tn->bcl->next_out)) { 250 if (unlikely(skb_peek(&tn->bcl->backlogq))) {
276 tipc_link_push_packets(tn->bcl); 251 tipc_link_push_packets(tn->bcl);
277 bclink_set_last_sent(net); 252 bclink_set_last_sent(net);
278 } 253 }
@@ -319,7 +294,7 @@ void tipc_bclink_update_link_state(struct tipc_node *n_ptr,
319 buf = tipc_buf_acquire(INT_H_SIZE); 294 buf = tipc_buf_acquire(INT_H_SIZE);
320 if (buf) { 295 if (buf) {
321 struct tipc_msg *msg = buf_msg(buf); 296 struct tipc_msg *msg = buf_msg(buf);
322 struct sk_buff *skb = skb_peek(&n_ptr->bclink.deferred_queue); 297 struct sk_buff *skb = skb_peek(&n_ptr->bclink.deferdq);
323 u32 to = skb ? buf_seqno(skb) - 1 : n_ptr->bclink.last_sent; 298 u32 to = skb ? buf_seqno(skb) - 1 : n_ptr->bclink.last_sent;
324 299
325 tipc_msg_init(tn->own_addr, msg, BCAST_PROTOCOL, STATE_MSG, 300 tipc_msg_init(tn->own_addr, msg, BCAST_PROTOCOL, STATE_MSG,
@@ -354,13 +329,12 @@ static void bclink_peek_nack(struct net *net, struct tipc_msg *msg)
354 return; 329 return;
355 330
356 tipc_node_lock(n_ptr); 331 tipc_node_lock(n_ptr);
357
358 if (n_ptr->bclink.recv_permitted && 332 if (n_ptr->bclink.recv_permitted &&
359 (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) && 333 (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) &&
360 (n_ptr->bclink.last_in == msg_bcgap_after(msg))) 334 (n_ptr->bclink.last_in == msg_bcgap_after(msg)))
361 n_ptr->bclink.oos_state = 2; 335 n_ptr->bclink.oos_state = 2;
362
363 tipc_node_unlock(n_ptr); 336 tipc_node_unlock(n_ptr);
337 tipc_node_put(n_ptr);
364} 338}
365 339
366/* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster 340/* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster
@@ -387,14 +361,13 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
387 __skb_queue_purge(list); 361 __skb_queue_purge(list);
388 return -EHOSTUNREACH; 362 return -EHOSTUNREACH;
389 } 363 }
390
391 /* Broadcast to all nodes */ 364 /* Broadcast to all nodes */
392 if (likely(bclink)) { 365 if (likely(bclink)) {
393 tipc_bclink_lock(net); 366 tipc_bclink_lock(net);
394 if (likely(bclink->bcast_nodes.count)) { 367 if (likely(bclink->bcast_nodes.count)) {
395 rc = __tipc_link_xmit(net, bcl, list); 368 rc = __tipc_link_xmit(net, bcl, list);
396 if (likely(!rc)) { 369 if (likely(!rc)) {
397 u32 len = skb_queue_len(&bcl->outqueue); 370 u32 len = skb_queue_len(&bcl->transmq);
398 371
399 bclink_set_last_sent(net); 372 bclink_set_last_sent(net);
400 bcl->stats.queue_sz_counts++; 373 bcl->stats.queue_sz_counts++;
@@ -440,7 +413,7 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno)
440 */ 413 */
441 if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) { 414 if (((seqno - tn->own_addr) % TIPC_MIN_LINK_WIN) == 0) {
442 tipc_link_proto_xmit(node->active_links[node->addr & 1], 415 tipc_link_proto_xmit(node->active_links[node->addr & 1],
443 STATE_MSG, 0, 0, 0, 0, 0); 416 STATE_MSG, 0, 0, 0, 0);
444 tn->bcl->stats.sent_acks++; 417 tn->bcl->stats.sent_acks++;
445 } 418 }
446} 419}
@@ -481,17 +454,18 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf)
481 goto unlock; 454 goto unlock;
482 if (msg_destnode(msg) == tn->own_addr) { 455 if (msg_destnode(msg) == tn->own_addr) {
483 tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); 456 tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
484 tipc_node_unlock(node);
485 tipc_bclink_lock(net); 457 tipc_bclink_lock(net);
486 bcl->stats.recv_nacks++; 458 bcl->stats.recv_nacks++;
487 tn->bclink->retransmit_to = node; 459 tn->bclink->retransmit_to = node;
488 bclink_retransmit_pkt(tn, msg_bcgap_after(msg), 460 bclink_retransmit_pkt(tn, msg_bcgap_after(msg),
489 msg_bcgap_to(msg)); 461 msg_bcgap_to(msg));
490 tipc_bclink_unlock(net); 462 tipc_bclink_unlock(net);
463 tipc_node_unlock(node);
491 } else { 464 } else {
492 tipc_node_unlock(node); 465 tipc_node_unlock(node);
493 bclink_peek_nack(net, msg); 466 bclink_peek_nack(net, msg);
494 } 467 }
468 tipc_node_put(node);
495 goto exit; 469 goto exit;
496 } 470 }
497 471
@@ -528,11 +502,13 @@ receive:
528 tipc_bclink_unlock(net); 502 tipc_bclink_unlock(net);
529 tipc_node_unlock(node); 503 tipc_node_unlock(node);
530 } else if (msg_user(msg) == MSG_FRAGMENTER) { 504 } else if (msg_user(msg) == MSG_FRAGMENTER) {
531 tipc_buf_append(&node->bclink.reasm_buf, &buf);
532 if (unlikely(!buf && !node->bclink.reasm_buf))
533 goto unlock;
534 tipc_bclink_lock(net); 505 tipc_bclink_lock(net);
535 bclink_accept_pkt(node, seqno); 506 bclink_accept_pkt(node, seqno);
507 tipc_buf_append(&node->bclink.reasm_buf, &buf);
508 if (unlikely(!buf && !node->bclink.reasm_buf)) {
509 tipc_bclink_unlock(net);
510 goto unlock;
511 }
536 bcl->stats.recv_fragments++; 512 bcl->stats.recv_fragments++;
537 if (buf) { 513 if (buf) {
538 bcl->stats.recv_fragmented++; 514 bcl->stats.recv_fragmented++;
@@ -559,25 +535,25 @@ receive:
559 if (node->bclink.last_in == node->bclink.last_sent) 535 if (node->bclink.last_in == node->bclink.last_sent)
560 goto unlock; 536 goto unlock;
561 537
562 if (skb_queue_empty(&node->bclink.deferred_queue)) { 538 if (skb_queue_empty(&node->bclink.deferdq)) {
563 node->bclink.oos_state = 1; 539 node->bclink.oos_state = 1;
564 goto unlock; 540 goto unlock;
565 } 541 }
566 542
567 msg = buf_msg(skb_peek(&node->bclink.deferred_queue)); 543 msg = buf_msg(skb_peek(&node->bclink.deferdq));
568 seqno = msg_seqno(msg); 544 seqno = msg_seqno(msg);
569 next_in = mod(next_in + 1); 545 next_in = mod(next_in + 1);
570 if (seqno != next_in) 546 if (seqno != next_in)
571 goto unlock; 547 goto unlock;
572 548
573 /* Take in-sequence message from deferred queue & deliver it */ 549 /* Take in-sequence message from deferred queue & deliver it */
574 buf = __skb_dequeue(&node->bclink.deferred_queue); 550 buf = __skb_dequeue(&node->bclink.deferdq);
575 goto receive; 551 goto receive;
576 } 552 }
577 553
578 /* Handle out-of-sequence broadcast message */ 554 /* Handle out-of-sequence broadcast message */
579 if (less(next_in, seqno)) { 555 if (less(next_in, seqno)) {
580 deferred = tipc_link_defer_pkt(&node->bclink.deferred_queue, 556 deferred = tipc_link_defer_pkt(&node->bclink.deferdq,
581 buf); 557 buf);
582 bclink_update_last_sent(node, seqno); 558 bclink_update_last_sent(node, seqno);
583 buf = NULL; 559 buf = NULL;
@@ -594,6 +570,7 @@ receive:
594 570
595unlock: 571unlock:
596 tipc_node_unlock(node); 572 tipc_node_unlock(node);
573 tipc_node_put(node);
597exit: 574exit:
598 kfree_skb(buf); 575 kfree_skb(buf);
599} 576}
@@ -634,7 +611,6 @@ static int tipc_bcbearer_send(struct net *net, struct sk_buff *buf,
634 msg_set_non_seq(msg, 1); 611 msg_set_non_seq(msg, 1);
635 msg_set_mc_netid(msg, tn->net_id); 612 msg_set_mc_netid(msg, tn->net_id);
636 tn->bcl->stats.sent_info++; 613 tn->bcl->stats.sent_info++;
637
638 if (WARN_ON(!bclink->bcast_nodes.count)) { 614 if (WARN_ON(!bclink->bcast_nodes.count)) {
639 dump_stack(); 615 dump_stack();
640 return 0; 616 return 0;
@@ -835,7 +811,7 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
835 prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP); 811 prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
836 if (!prop) 812 if (!prop)
837 goto attr_msg_full; 813 goto attr_msg_full;
838 if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->queue_limit[0])) 814 if (nla_put_u32(msg->skb, TIPC_NLA_PROP_WIN, bcl->window))
839 goto prop_msg_full; 815 goto prop_msg_full;
840 nla_nest_end(msg->skb, prop); 816 nla_nest_end(msg->skb, prop);
841 817
@@ -913,8 +889,9 @@ int tipc_bclink_init(struct net *net)
913 sprintf(bcbearer->media.name, "tipc-broadcast"); 889 sprintf(bcbearer->media.name, "tipc-broadcast");
914 890
915 spin_lock_init(&bclink->lock); 891 spin_lock_init(&bclink->lock);
916 __skb_queue_head_init(&bcl->outqueue); 892 __skb_queue_head_init(&bcl->transmq);
917 __skb_queue_head_init(&bcl->deferred_queue); 893 __skb_queue_head_init(&bcl->backlogq);
894 __skb_queue_head_init(&bcl->deferdq);
918 skb_queue_head_init(&bcl->wakeupq); 895 skb_queue_head_init(&bcl->wakeupq);
919 bcl->next_out_no = 1; 896 bcl->next_out_no = 1;
920 spin_lock_init(&bclink->node.lock); 897 spin_lock_init(&bclink->node.lock);
@@ -922,7 +899,7 @@ int tipc_bclink_init(struct net *net)
922 skb_queue_head_init(&bclink->inputq); 899 skb_queue_head_init(&bclink->inputq);
923 bcl->owner = &bclink->node; 900 bcl->owner = &bclink->node;
924 bcl->owner->net = net; 901 bcl->owner->net = net;
925 bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; 902 bcl->mtu = MAX_PKT_DEFAULT_MCAST;
926 tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); 903 tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
927 bcl->bearer_id = MAX_BEARERS; 904 bcl->bearer_id = MAX_BEARERS;
928 rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer); 905 rcu_assign_pointer(tn->bearer_list[MAX_BEARERS], &bcbearer->bearer);