static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, struct tipc_media_addr *unused2) { int bp_index; /* * Prepare broadcast link message for reliable transmission, * if first time trying to send it; * preparation is skipped for broadcast link protocol messages * since they are sent in an unreliable manner and don't need it */ if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; bcbuf_set_acks(buf, bclink->bcast_nodes.count); msg = buf_msg(buf); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); bcl->stats.sent_info++; if (WARN_ON(!bclink->bcast_nodes.count)) { dump_stack(); return 0; } } /* Send buffer over bearers until all targets reached */ bcbearer->remains = bclink->bcast_nodes; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; if (!p) break; /* no more bearers to try */ tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new); if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* bearer pair doesn't add anything */ if (p->blocked || p->media->send_msg(buf, p, &p->media->bcast_addr)) { /* unable to send on primary bearer */ if (!s || s->blocked || s->media->send_msg(buf, s, &s->media->bcast_addr)) { /* unable to send on either bearer */ continue; } } if (s) { bcbearer->bpairs[bp_index].primary = s; bcbearer->bpairs[bp_index].secondary = p; } if (bcbearer->remains_new.count == 0) break; /* all targets reached */ bcbearer->remains = bcbearer->remains_new; } return 0; }
/** * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer * * Send packet over as many bearers as necessary to reach all nodes * that have joined the broadcast link. * * Returns 0 (packet sent successfully) under all circumstances, * since the broadcast link's pseudo-bearer never blocks */ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, struct tipc_media_addr *unused2) { int bp_index; /* Prepare broadcast link message for reliable transmission, * if first time trying to send it; * preparation is skipped for broadcast link protocol messages * since they are sent in an unreliable manner and don't need it */ if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; bcbuf_set_acks(buf, bclink->bcast_nodes.count); msg = buf_msg(buf); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); bcl->stats.sent_info++; if (WARN_ON(!bclink->bcast_nodes.count)) { dump_stack(); return 0; } } /* Send buffer over bearers until all targets reached */ bcbearer->remains = bclink->bcast_nodes; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; struct tipc_bearer *b = p; struct sk_buff *tbuf; if (!p) break; /* No more bearers to try */ if (tipc_bearer_blocked(p)) { if (!s || tipc_bearer_blocked(s)) continue; /* Can't use either bearer */ b = s; } tipc_nmap_diff(&bcbearer->remains, &b->nodes, &bcbearer->remains_new); if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* Nothing added by bearer pair */ if (bp_index == 0) { /* Use original buffer for first bearer */ tipc_bearer_send(b, buf, &b->bcast_addr); } else { /* Avoid concurrent buffer access */ tbuf = pskb_copy(buf, GFP_ATOMIC); if (!tbuf) break; tipc_bearer_send(b, tbuf, &b->bcast_addr); kfree_skb(tbuf); /* Bearer keeps a clone */ } /* Swap bearers for next packet */ if (s) { bcbearer->bpairs[bp_index].primary = s; bcbearer->bpairs[bp_index].secondary = p; } if (bcbearer->remains_new.count == 0) break; /* All targets reached */ bcbearer->remains = bcbearer->remains_new; } return 0; }
static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, struct tipc_media_addr *unused2) { static int send_count = 0; int bp_index; int swap_time; /* Prepare buffer for broadcasting (if first time trying to send it) */ if (likely(!msg_non_seq(buf_msg(buf)))) { struct tipc_msg *msg; assert(tipc_cltr_bcast_nodes.count != 0); bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count); msg = buf_msg(buf); msg_set_non_seq(msg, 1); msg_set_mc_netid(msg, tipc_net_id); } /* Determine if bearer pairs should be swapped following this attempt */ if ((swap_time = (++send_count >= 10))) send_count = 0; /* Send buffer over bearers until all targets reached */ bcbearer->remains = tipc_cltr_bcast_nodes; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct bearer *p = bcbearer->bpairs[bp_index].primary; struct bearer *s = bcbearer->bpairs[bp_index].secondary; if (!p) break; /* no more bearers to try */ tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new); if (bcbearer->remains_new.count == bcbearer->remains.count) continue; /* bearer pair doesn't add anything */ if (!p->publ.blocked && !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { if (swap_time && s && !s->publ.blocked) goto swap; else goto update; } if (!s || s->publ.blocked || s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) continue; /* unable to send using bearer pair */ swap: bcbearer->bpairs[bp_index].primary = s; bcbearer->bpairs[bp_index].secondary = p; update: if (bcbearer->remains_new.count == 0) return 0; bcbearer->remains = bcbearer->remains_new; } /* Unable to reach all targets */ bcbearer->bearer.publ.blocked = 1; bcl->stats.bearer_congs++; return 1; }