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); | 
