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.c111
1 files changed, 52 insertions, 59 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 759b318b5ffb..28908f54459e 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -39,6 +39,7 @@
39#include "link.h" 39#include "link.h"
40#include "port.h" 40#include "port.h"
41#include "bcast.h" 41#include "bcast.h"
42#include "name_distr.h"
42 43
43#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ 44#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
44 45
@@ -298,14 +299,9 @@ static void bclink_send_nack(struct tipc_node *n_ptr)
298 msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); 299 msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
299 msg_set_bcast_tag(msg, tipc_own_tag); 300 msg_set_bcast_tag(msg, tipc_own_tag);
300 301
301 if (tipc_bearer_send(&bcbearer->bearer, buf, NULL)) { 302 tipc_bearer_send(&bcbearer->bearer, buf, NULL);
302 bcl->stats.sent_nacks++; 303 bcl->stats.sent_nacks++;
303 buf_discard(buf); 304 buf_discard(buf);
304 } else {
305 tipc_bearer_schedule(bcl->b_ptr, bcl);
306 bcl->proto_msg_queue = buf;
307 bcl->stats.bearer_congs++;
308 }
309 305
310 /* 306 /*
311 * Ensure we doesn't send another NACK msg to the node 307 * Ensure we doesn't send another NACK msg to the node
@@ -426,20 +422,28 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
426void tipc_bclink_recv_pkt(struct sk_buff *buf) 422void tipc_bclink_recv_pkt(struct sk_buff *buf)
427{ 423{
428 struct tipc_msg *msg = buf_msg(buf); 424 struct tipc_msg *msg = buf_msg(buf);
429 struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); 425 struct tipc_node *node;
430 u32 next_in; 426 u32 next_in;
431 u32 seqno; 427 u32 seqno;
432 struct sk_buff *deferred; 428 struct sk_buff *deferred;
433 429
434 if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || 430 /* Screen out unwanted broadcast messages */
435 (msg_mc_netid(msg) != tipc_net_id))) { 431
436 buf_discard(buf); 432 if (msg_mc_netid(msg) != tipc_net_id)
437 return; 433 goto exit;
438 } 434
435 node = tipc_node_find(msg_prevnode(msg));
436 if (unlikely(!node))
437 goto exit;
438
439 tipc_node_lock(node);
440 if (unlikely(!node->bclink.supported))
441 goto unlock;
439 442
440 if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { 443 if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
444 if (msg_type(msg) != STATE_MSG)
445 goto unlock;
441 if (msg_destnode(msg) == tipc_own_addr) { 446 if (msg_destnode(msg) == tipc_own_addr) {
442 tipc_node_lock(node);
443 tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); 447 tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
444 tipc_node_unlock(node); 448 tipc_node_unlock(node);
445 spin_lock_bh(&bc_lock); 449 spin_lock_bh(&bc_lock);
@@ -449,18 +453,18 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
449 msg_bcgap_to(msg)); 453 msg_bcgap_to(msg));
450 spin_unlock_bh(&bc_lock); 454 spin_unlock_bh(&bc_lock);
451 } else { 455 } else {
456 tipc_node_unlock(node);
452 tipc_bclink_peek_nack(msg_destnode(msg), 457 tipc_bclink_peek_nack(msg_destnode(msg),
453 msg_bcast_tag(msg), 458 msg_bcast_tag(msg),
454 msg_bcgap_after(msg), 459 msg_bcgap_after(msg),
455 msg_bcgap_to(msg)); 460 msg_bcgap_to(msg));
456 } 461 }
457 buf_discard(buf); 462 goto exit;
458 return;
459 } 463 }
460 464
461 tipc_node_lock(node); 465 /* Handle in-sequence broadcast message */
466
462receive: 467receive:
463 deferred = node->bclink.deferred_head;
464 next_in = mod(node->bclink.last_in + 1); 468 next_in = mod(node->bclink.last_in + 1);
465 seqno = msg_seqno(msg); 469 seqno = msg_seqno(msg);
466 470
@@ -474,7 +478,10 @@ receive:
474 } 478 }
475 if (likely(msg_isdata(msg))) { 479 if (likely(msg_isdata(msg))) {
476 tipc_node_unlock(node); 480 tipc_node_unlock(node);
477 tipc_port_recv_mcast(buf, NULL); 481 if (likely(msg_mcast(msg)))
482 tipc_port_recv_mcast(buf, NULL);
483 else
484 buf_discard(buf);
478 } else if (msg_user(msg) == MSG_BUNDLER) { 485 } else if (msg_user(msg) == MSG_BUNDLER) {
479 bcl->stats.recv_bundles++; 486 bcl->stats.recv_bundles++;
480 bcl->stats.recv_bundled += msg_msgcnt(msg); 487 bcl->stats.recv_bundled += msg_msgcnt(msg);
@@ -487,18 +494,22 @@ receive:
487 bcl->stats.recv_fragmented++; 494 bcl->stats.recv_fragmented++;
488 tipc_node_unlock(node); 495 tipc_node_unlock(node);
489 tipc_net_route_msg(buf); 496 tipc_net_route_msg(buf);
497 } else if (msg_user(msg) == NAME_DISTRIBUTOR) {
498 tipc_node_unlock(node);
499 tipc_named_recv(buf);
490 } else { 500 } else {
491 tipc_node_unlock(node); 501 tipc_node_unlock(node);
492 tipc_net_route_msg(buf); 502 buf_discard(buf);
493 } 503 }
504 buf = NULL;
505 tipc_node_lock(node);
506 deferred = node->bclink.deferred_head;
494 if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { 507 if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
495 tipc_node_lock(node);
496 buf = deferred; 508 buf = deferred;
497 msg = buf_msg(buf); 509 msg = buf_msg(buf);
498 node->bclink.deferred_head = deferred->next; 510 node->bclink.deferred_head = deferred->next;
499 goto receive; 511 goto receive;
500 } 512 }
501 return;
502 } else if (less(next_in, seqno)) { 513 } else if (less(next_in, seqno)) {
503 u32 gap_after = node->bclink.gap_after; 514 u32 gap_after = node->bclink.gap_after;
504 u32 gap_to = node->bclink.gap_to; 515 u32 gap_to = node->bclink.gap_to;
@@ -513,6 +524,7 @@ receive:
513 else if (less(gap_after, seqno) && less(seqno, gap_to)) 524 else if (less(gap_after, seqno) && less(seqno, gap_to))
514 node->bclink.gap_to = seqno; 525 node->bclink.gap_to = seqno;
515 } 526 }
527 buf = NULL;
516 if (bclink_ack_allowed(node->bclink.nack_sync)) { 528 if (bclink_ack_allowed(node->bclink.nack_sync)) {
517 if (gap_to != gap_after) 529 if (gap_to != gap_after)
518 bclink_send_nack(node); 530 bclink_send_nack(node);
@@ -520,9 +532,11 @@ receive:
520 } 532 }
521 } else { 533 } else {
522 bcl->stats.duplicates++; 534 bcl->stats.duplicates++;
523 buf_discard(buf);
524 } 535 }
536unlock:
525 tipc_node_unlock(node); 537 tipc_node_unlock(node);
538exit:
539 buf_discard(buf);
526} 540}
527 541
528u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) 542u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
@@ -535,10 +549,11 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
535/** 549/**
536 * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer 550 * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer
537 * 551 *
538 * Send through as many bearers as necessary to reach all nodes 552 * Send packet over as many bearers as necessary to reach all nodes
539 * that support TIPC multicasting. 553 * that have joined the broadcast link.
540 * 554 *
541 * Returns 0 if packet sent successfully, non-zero if not 555 * Returns 0 (packet sent successfully) under all circumstances,
556 * since the broadcast link's pseudo-bearer never blocks
542 */ 557 */
543 558
544static int tipc_bcbearer_send(struct sk_buff *buf, 559static int tipc_bcbearer_send(struct sk_buff *buf,
@@ -547,7 +562,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
547{ 562{
548 int bp_index; 563 int bp_index;
549 564
550 /* Prepare buffer for broadcasting (if first time trying to send it) */ 565 /*
566 * Prepare broadcast link message for reliable transmission,
567 * if first time trying to send it;
568 * preparation is skipped for broadcast link protocol messages
569 * since they are sent in an unreliable manner and don't need it
570 */
551 571
552 if (likely(!msg_non_seq(buf_msg(buf)))) { 572 if (likely(!msg_non_seq(buf_msg(buf)))) {
553 struct tipc_msg *msg; 573 struct tipc_msg *msg;
@@ -596,18 +616,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
596 } 616 }
597 617
598 if (bcbearer->remains_new.count == 0) 618 if (bcbearer->remains_new.count == 0)
599 return 0; 619 break; /* all targets reached */
600 620
601 bcbearer->remains = bcbearer->remains_new; 621 bcbearer->remains = bcbearer->remains_new;
602 } 622 }
603 623
604 /* 624 return 0;
605 * Unable to reach all targets (indicate success, since currently
606 * there isn't code in place to properly block & unblock the
607 * pseudo-bearer used by the broadcast link)
608 */
609
610 return TIPC_OK;
611} 625}
612 626
613/** 627/**
@@ -667,27 +681,6 @@ void tipc_bcbearer_sort(void)
667 spin_unlock_bh(&bc_lock); 681 spin_unlock_bh(&bc_lock);
668} 682}
669 683
670/**
671 * tipc_bcbearer_push - resolve bearer congestion
672 *
673 * Forces bclink to push out any unsent packets, until all packets are gone
674 * or congestion reoccurs.
675 * No locks set when function called
676 */
677
678void tipc_bcbearer_push(void)
679{
680 struct tipc_bearer *b_ptr;
681
682 spin_lock_bh(&bc_lock);
683 b_ptr = &bcbearer->bearer;
684 if (b_ptr->blocked) {
685 b_ptr->blocked = 0;
686 tipc_bearer_lock_push(b_ptr);
687 }
688 spin_unlock_bh(&bc_lock);
689}
690
691 684
692int tipc_bclink_stats(char *buf, const u32 buf_size) 685int tipc_bclink_stats(char *buf, const u32 buf_size)
693{ 686{
@@ -764,7 +757,7 @@ int tipc_bclink_init(void)
764 bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); 757 bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC);
765 bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC); 758 bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC);
766 if (!bcbearer || !bclink) { 759 if (!bcbearer || !bclink) {
767 warn("Multicast link creation failed, no memory\n"); 760 warn("Broadcast link creation failed, no memory\n");
768 kfree(bcbearer); 761 kfree(bcbearer);
769 bcbearer = NULL; 762 bcbearer = NULL;
770 kfree(bclink); 763 kfree(bclink);
@@ -775,7 +768,7 @@ int tipc_bclink_init(void)
775 INIT_LIST_HEAD(&bcbearer->bearer.cong_links); 768 INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
776 bcbearer->bearer.media = &bcbearer->media; 769 bcbearer->bearer.media = &bcbearer->media;
777 bcbearer->media.send_msg = tipc_bcbearer_send; 770 bcbearer->media.send_msg = tipc_bcbearer_send;
778 sprintf(bcbearer->media.name, "tipc-multicast"); 771 sprintf(bcbearer->media.name, "tipc-broadcast");
779 772
780 bcl = &bclink->link; 773 bcl = &bclink->link;
781 INIT_LIST_HEAD(&bcl->waiting_ports); 774 INIT_LIST_HEAD(&bcl->waiting_ports);