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.c79
1 files changed, 46 insertions, 33 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 2c4ecbe50082..54128040a124 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -49,13 +49,19 @@
49#include "name_table.h" 49#include "name_table.h"
50#include "bcast.h" 50#include "bcast.h"
51 51
52
53#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ 52#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
54 53
55#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ 54#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
56 55
57#define BCLINK_LOG_BUF_SIZE 0 56#define BCLINK_LOG_BUF_SIZE 0
58 57
58/*
59 * Loss rate for incoming broadcast frames; used to test retransmission code.
60 * Set to N to cause every N'th frame to be discarded; 0 => don't discard any.
61 */
62
63#define TIPC_BCAST_LOSS_RATE 0
64
59/** 65/**
60 * struct bcbearer_pair - a pair of bearers used by broadcast link 66 * struct bcbearer_pair - a pair of bearers used by broadcast link
61 * @primary: pointer to primary bearer 67 * @primary: pointer to primary bearer
@@ -75,7 +81,14 @@ struct bcbearer_pair {
75 * @bearer: (non-standard) broadcast bearer structure 81 * @bearer: (non-standard) broadcast bearer structure
76 * @media: (non-standard) broadcast media structure 82 * @media: (non-standard) broadcast media structure
77 * @bpairs: array of bearer pairs 83 * @bpairs: array of bearer pairs
78 * @bpairs_temp: array of bearer pairs used during creation of "bpairs" 84 * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort()
85 * @remains: temporary node map used by tipc_bcbearer_send()
86 * @remains_new: temporary node map used tipc_bcbearer_send()
87 *
88 * Note: The fields labelled "temporary" are incorporated into the bearer
89 * to avoid consuming potentially limited stack space through the use of
90 * large local variables within multicast routines. Concurrent access is
91 * prevented through use of the spinlock "bc_lock".
79 */ 92 */
80 93
81struct bcbearer { 94struct bcbearer {
@@ -83,6 +96,8 @@ struct bcbearer {
83 struct media media; 96 struct media media;
84 struct bcbearer_pair bpairs[MAX_BEARERS]; 97 struct bcbearer_pair bpairs[MAX_BEARERS];
85 struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; 98 struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
99 struct node_map remains;
100 struct node_map remains_new;
86}; 101};
87 102
88/** 103/**
@@ -165,21 +180,18 @@ static int bclink_ack_allowed(u32 n)
165 * @after: sequence number of last packet to *not* retransmit 180 * @after: sequence number of last packet to *not* retransmit
166 * @to: sequence number of last packet to retransmit 181 * @to: sequence number of last packet to retransmit
167 * 182 *
168 * Called with 'node' locked, bc_lock unlocked 183 * Called with bc_lock locked
169 */ 184 */
170 185
171static void bclink_retransmit_pkt(u32 after, u32 to) 186static void bclink_retransmit_pkt(u32 after, u32 to)
172{ 187{
173 struct sk_buff *buf; 188 struct sk_buff *buf;
174 189
175 spin_lock_bh(&bc_lock);
176 buf = bcl->first_out; 190 buf = bcl->first_out;
177 while (buf && less_eq(buf_seqno(buf), after)) { 191 while (buf && less_eq(buf_seqno(buf), after)) {
178 buf = buf->next; 192 buf = buf->next;
179 } 193 }
180 if (buf != NULL) 194 tipc_link_retransmit(bcl, buf, mod(to - after));
181 tipc_link_retransmit(bcl, buf, mod(to - after));
182 spin_unlock_bh(&bc_lock);
183} 195}
184 196
185/** 197/**
@@ -346,8 +358,10 @@ static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 g
346 for (; buf; buf = buf->next) { 358 for (; buf; buf = buf->next) {
347 u32 seqno = buf_seqno(buf); 359 u32 seqno = buf_seqno(buf);
348 360
349 if (mod(seqno - prev) != 1) 361 if (mod(seqno - prev) != 1) {
350 buf = NULL; 362 buf = NULL;
363 break;
364 }
351 if (seqno == gap_after) 365 if (seqno == gap_after)
352 break; 366 break;
353 prev = seqno; 367 prev = seqno;
@@ -399,7 +413,10 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
399 */ 413 */
400 414
401void tipc_bclink_recv_pkt(struct sk_buff *buf) 415void tipc_bclink_recv_pkt(struct sk_buff *buf)
402{ 416{
417#if (TIPC_BCAST_LOSS_RATE)
418 static int rx_count = 0;
419#endif
403 struct tipc_msg *msg = buf_msg(buf); 420 struct tipc_msg *msg = buf_msg(buf);
404 struct node* node = tipc_node_find(msg_prevnode(msg)); 421 struct node* node = tipc_node_find(msg_prevnode(msg));
405 u32 next_in; 422 u32 next_in;
@@ -420,9 +437,13 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
420 tipc_node_lock(node); 437 tipc_node_lock(node);
421 tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); 438 tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
422 tipc_node_unlock(node); 439 tipc_node_unlock(node);
440 spin_lock_bh(&bc_lock);
423 bcl->stats.recv_nacks++; 441 bcl->stats.recv_nacks++;
442 bcl->owner->next = node; /* remember requestor */
424 bclink_retransmit_pkt(msg_bcgap_after(msg), 443 bclink_retransmit_pkt(msg_bcgap_after(msg),
425 msg_bcgap_to(msg)); 444 msg_bcgap_to(msg));
445 bcl->owner->next = NULL;
446 spin_unlock_bh(&bc_lock);
426 } else { 447 } else {
427 tipc_bclink_peek_nack(msg_destnode(msg), 448 tipc_bclink_peek_nack(msg_destnode(msg),
428 msg_bcast_tag(msg), 449 msg_bcast_tag(msg),
@@ -433,6 +454,14 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
433 return; 454 return;
434 } 455 }
435 456
457#if (TIPC_BCAST_LOSS_RATE)
458 if (++rx_count == TIPC_BCAST_LOSS_RATE) {
459 rx_count = 0;
460 buf_discard(buf);
461 return;
462 }
463#endif
464
436 tipc_node_lock(node); 465 tipc_node_lock(node);
437receive: 466receive:
438 deferred = node->bclink.deferred_head; 467 deferred = node->bclink.deferred_head;
@@ -531,12 +560,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
531{ 560{
532 static int send_count = 0; 561 static int send_count = 0;
533 562
534 struct node_map *remains;
535 struct node_map *remains_new;
536 struct node_map *remains_tmp;
537 int bp_index; 563 int bp_index;
538 int swap_time; 564 int swap_time;
539 int err;
540 565
541 /* Prepare buffer for broadcasting (if first time trying to send it) */ 566 /* Prepare buffer for broadcasting (if first time trying to send it) */
542 567
@@ -557,9 +582,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
557 582
558 /* Send buffer over bearers until all targets reached */ 583 /* Send buffer over bearers until all targets reached */
559 584
560 remains = kmalloc(sizeof(struct node_map), GFP_ATOMIC); 585 bcbearer->remains = tipc_cltr_bcast_nodes;
561 remains_new = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
562 *remains = tipc_cltr_bcast_nodes;
563 586
564 for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { 587 for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
565 struct bearer *p = bcbearer->bpairs[bp_index].primary; 588 struct bearer *p = bcbearer->bpairs[bp_index].primary;
@@ -568,8 +591,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
568 if (!p) 591 if (!p)
569 break; /* no more bearers to try */ 592 break; /* no more bearers to try */
570 593
571 tipc_nmap_diff(remains, &p->nodes, remains_new); 594 tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new);
572 if (remains_new->count == remains->count) 595 if (bcbearer->remains_new.count == bcbearer->remains.count)
573 continue; /* bearer pair doesn't add anything */ 596 continue; /* bearer pair doesn't add anything */
574 597
575 if (!p->publ.blocked && 598 if (!p->publ.blocked &&
@@ -587,27 +610,17 @@ swap:
587 bcbearer->bpairs[bp_index].primary = s; 610 bcbearer->bpairs[bp_index].primary = s;
588 bcbearer->bpairs[bp_index].secondary = p; 611 bcbearer->bpairs[bp_index].secondary = p;
589update: 612update:
590 if (remains_new->count == 0) { 613 if (bcbearer->remains_new.count == 0)
591 err = TIPC_OK; 614 return TIPC_OK;
592 goto out;
593 }
594 615
595 /* swap map */ 616 bcbearer->remains = bcbearer->remains_new;
596 remains_tmp = remains;
597 remains = remains_new;
598 remains_new = remains_tmp;
599 } 617 }
600 618
601 /* Unable to reach all targets */ 619 /* Unable to reach all targets */
602 620
603 bcbearer->bearer.publ.blocked = 1; 621 bcbearer->bearer.publ.blocked = 1;
604 bcl->stats.bearer_congs++; 622 bcl->stats.bearer_congs++;
605 err = ~TIPC_OK; 623 return ~TIPC_OK;
606
607 out:
608 kfree(remains_new);
609 kfree(remains);
610 return err;
611} 624}
612 625
613/** 626/**
@@ -765,7 +778,7 @@ int tipc_bclink_init(void)
765 bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); 778 bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
766 if (!bcbearer || !bclink) { 779 if (!bcbearer || !bclink) {
767 nomem: 780 nomem:
768 warn("Memory squeeze; Failed to create multicast link\n"); 781 warn("Multicast link creation failed, no memory\n");
769 kfree(bcbearer); 782 kfree(bcbearer);
770 bcbearer = NULL; 783 bcbearer = NULL;
771 kfree(bclink); 784 kfree(bclink);