diff options
Diffstat (limited to 'net/tipc/bcast.c')
-rw-r--r-- | net/tipc/bcast.c | 95 |
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) | |||
62 | static void tipc_bclink_unlock(struct net *net) | 62 | static 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 | ||
82 | void tipc_bclink_input(struct net *net) | 69 | void 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 | ||
94 | void 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 | |||
101 | static u32 bcbuf_acks(struct sk_buff *buf) | 81 | static 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) | |||
210 | void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) | 190 | void 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 | ||
595 | unlock: | 571 | unlock: |
596 | tipc_node_unlock(node); | 572 | tipc_node_unlock(node); |
573 | tipc_node_put(node); | ||
597 | exit: | 574 | exit: |
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); |