diff options
Diffstat (limited to 'net/tipc/bcast.c')
-rw-r--r-- | net/tipc/bcast.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 5200457eaeb4..bc01ca6891e4 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -426,20 +426,26 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
426 | void tipc_bclink_recv_pkt(struct sk_buff *buf) | 426 | void tipc_bclink_recv_pkt(struct sk_buff *buf) |
427 | { | 427 | { |
428 | struct tipc_msg *msg = buf_msg(buf); | 428 | struct tipc_msg *msg = buf_msg(buf); |
429 | struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); | 429 | struct tipc_node *node; |
430 | u32 next_in; | 430 | u32 next_in; |
431 | u32 seqno; | 431 | u32 seqno; |
432 | struct sk_buff *deferred; | 432 | struct sk_buff *deferred; |
433 | 433 | ||
434 | if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || | 434 | /* Screen out unwanted broadcast messages */ |
435 | (msg_mc_netid(msg) != tipc_net_id))) { | 435 | |
436 | buf_discard(buf); | 436 | if (msg_mc_netid(msg) != tipc_net_id) |
437 | return; | 437 | goto exit; |
438 | } | 438 | |
439 | node = tipc_node_find(msg_prevnode(msg)); | ||
440 | if (unlikely(!node)) | ||
441 | goto exit; | ||
442 | |||
443 | tipc_node_lock(node); | ||
444 | if (unlikely(!node->bclink.supported)) | ||
445 | goto unlock; | ||
439 | 446 | ||
440 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { | 447 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { |
441 | if (msg_destnode(msg) == tipc_own_addr) { | 448 | if (msg_destnode(msg) == tipc_own_addr) { |
442 | tipc_node_lock(node); | ||
443 | tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); | 449 | tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); |
444 | tipc_node_unlock(node); | 450 | tipc_node_unlock(node); |
445 | spin_lock_bh(&bc_lock); | 451 | spin_lock_bh(&bc_lock); |
@@ -449,16 +455,17 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
449 | msg_bcgap_to(msg)); | 455 | msg_bcgap_to(msg)); |
450 | spin_unlock_bh(&bc_lock); | 456 | spin_unlock_bh(&bc_lock); |
451 | } else { | 457 | } else { |
458 | tipc_node_unlock(node); | ||
452 | tipc_bclink_peek_nack(msg_destnode(msg), | 459 | tipc_bclink_peek_nack(msg_destnode(msg), |
453 | msg_bcast_tag(msg), | 460 | msg_bcast_tag(msg), |
454 | msg_bcgap_after(msg), | 461 | msg_bcgap_after(msg), |
455 | msg_bcgap_to(msg)); | 462 | msg_bcgap_to(msg)); |
456 | } | 463 | } |
457 | buf_discard(buf); | 464 | goto exit; |
458 | return; | ||
459 | } | 465 | } |
460 | 466 | ||
461 | tipc_node_lock(node); | 467 | /* Handle in-sequence broadcast message */ |
468 | |||
462 | receive: | 469 | receive: |
463 | deferred = node->bclink.deferred_head; | 470 | deferred = node->bclink.deferred_head; |
464 | next_in = mod(node->bclink.last_in + 1); | 471 | next_in = mod(node->bclink.last_in + 1); |
@@ -491,14 +498,14 @@ receive: | |||
491 | tipc_node_unlock(node); | 498 | tipc_node_unlock(node); |
492 | tipc_net_route_msg(buf); | 499 | tipc_net_route_msg(buf); |
493 | } | 500 | } |
501 | buf = NULL; | ||
502 | tipc_node_lock(node); | ||
494 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { | 503 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { |
495 | tipc_node_lock(node); | ||
496 | buf = deferred; | 504 | buf = deferred; |
497 | msg = buf_msg(buf); | 505 | msg = buf_msg(buf); |
498 | node->bclink.deferred_head = deferred->next; | 506 | node->bclink.deferred_head = deferred->next; |
499 | goto receive; | 507 | goto receive; |
500 | } | 508 | } |
501 | return; | ||
502 | } else if (less(next_in, seqno)) { | 509 | } else if (less(next_in, seqno)) { |
503 | u32 gap_after = node->bclink.gap_after; | 510 | u32 gap_after = node->bclink.gap_after; |
504 | u32 gap_to = node->bclink.gap_to; | 511 | u32 gap_to = node->bclink.gap_to; |
@@ -513,6 +520,7 @@ receive: | |||
513 | else if (less(gap_after, seqno) && less(seqno, gap_to)) | 520 | else if (less(gap_after, seqno) && less(seqno, gap_to)) |
514 | node->bclink.gap_to = seqno; | 521 | node->bclink.gap_to = seqno; |
515 | } | 522 | } |
523 | buf = NULL; | ||
516 | if (bclink_ack_allowed(node->bclink.nack_sync)) { | 524 | if (bclink_ack_allowed(node->bclink.nack_sync)) { |
517 | if (gap_to != gap_after) | 525 | if (gap_to != gap_after) |
518 | bclink_send_nack(node); | 526 | bclink_send_nack(node); |
@@ -520,9 +528,11 @@ receive: | |||
520 | } | 528 | } |
521 | } else { | 529 | } else { |
522 | bcl->stats.duplicates++; | 530 | bcl->stats.duplicates++; |
523 | buf_discard(buf); | ||
524 | } | 531 | } |
532 | unlock: | ||
525 | tipc_node_unlock(node); | 533 | tipc_node_unlock(node); |
534 | exit: | ||
535 | buf_discard(buf); | ||
526 | } | 536 | } |
527 | 537 | ||
528 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) | 538 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) |