summaryrefslogtreecommitdiffstats
path: root/net/tipc/bcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/bcast.c')
-rw-r--r--net/tipc/bcast.c105
1 files changed, 82 insertions, 23 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 412d3351abb7..672e6ef93cab 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -70,7 +70,7 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net)
70 70
71int tipc_bcast_get_mtu(struct net *net) 71int tipc_bcast_get_mtu(struct net *net)
72{ 72{
73 return tipc_link_mtu(tipc_bc_sndlink(net)); 73 return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE;
74} 74}
75 75
76/* tipc_bcbase_select_primary(): find a bearer with links to all destinations, 76/* tipc_bcbase_select_primary(): find a bearer with links to all destinations,
@@ -175,42 +175,101 @@ static void tipc_bcbase_xmit(struct net *net, struct sk_buff_head *xmitq)
175 __skb_queue_purge(&_xmitq); 175 __skb_queue_purge(&_xmitq);
176} 176}
177 177
178/* tipc_bcast_xmit - deliver buffer chain to all nodes in cluster 178/* tipc_bcast_xmit - broadcast the buffer chain to all external nodes
179 * and to identified node local sockets
180 * @net: the applicable net namespace 179 * @net: the applicable net namespace
181 * @list: chain of buffers containing message 180 * @pkts: chain of buffers containing message
181 * @cong_link_cnt: set to 1 if broadcast link is congested, otherwise 0
182 * Consumes the buffer chain. 182 * Consumes the buffer chain.
183 * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE 183 * Returns 0 if success, otherwise errno: -EHOSTUNREACH,-EMSGSIZE
184 */ 184 */
185int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list) 185static int tipc_bcast_xmit(struct net *net, struct sk_buff_head *pkts,
186 u16 *cong_link_cnt)
186{ 187{
187 struct tipc_link *l = tipc_bc_sndlink(net); 188 struct tipc_link *l = tipc_bc_sndlink(net);
188 struct sk_buff_head xmitq, inputq, rcvq; 189 struct sk_buff_head xmitq;
189 int rc = 0; 190 int rc = 0;
190 191
191 __skb_queue_head_init(&rcvq);
192 __skb_queue_head_init(&xmitq); 192 __skb_queue_head_init(&xmitq);
193 skb_queue_head_init(&inputq);
194
195 /* Prepare message clone for local node */
196 if (unlikely(!tipc_msg_reassemble(list, &rcvq)))
197 return -EHOSTUNREACH;
198
199 tipc_bcast_lock(net); 193 tipc_bcast_lock(net);
200 if (tipc_link_bc_peers(l)) 194 if (tipc_link_bc_peers(l))
201 rc = tipc_link_xmit(l, list, &xmitq); 195 rc = tipc_link_xmit(l, pkts, &xmitq);
202 tipc_bcast_unlock(net); 196 tipc_bcast_unlock(net);
197 tipc_bcbase_xmit(net, &xmitq);
198 __skb_queue_purge(pkts);
199 if (rc == -ELINKCONG) {
200 *cong_link_cnt = 1;
201 rc = 0;
202 }
203 return rc;
204}
203 205
204 /* Don't send to local node if adding to link failed */ 206/* tipc_rcast_xmit - replicate and send a message to given destination nodes
205 if (unlikely(rc && (rc != -ELINKCONG))) { 207 * @net: the applicable net namespace
206 __skb_queue_purge(&rcvq); 208 * @pkts: chain of buffers containing message
207 return rc; 209 * @dests: list of destination nodes
210 * @cong_link_cnt: returns number of congested links
211 * @cong_links: returns identities of congested links
212 * Returns 0 if success, otherwise errno
213 */
214static int tipc_rcast_xmit(struct net *net, struct sk_buff_head *pkts,
215 struct tipc_nlist *dests, u16 *cong_link_cnt)
216{
217 struct sk_buff_head _pkts;
218 struct u32_item *n, *tmp;
219 u32 dst, selector;
220
221 selector = msg_link_selector(buf_msg(skb_peek(pkts)));
222 __skb_queue_head_init(&_pkts);
223
224 list_for_each_entry_safe(n, tmp, &dests->list, list) {
225 dst = n->value;
226 if (!tipc_msg_pskb_copy(dst, pkts, &_pkts))
227 return -ENOMEM;
228
229 /* Any other return value than -ELINKCONG is ignored */
230 if (tipc_node_xmit(net, &_pkts, dst, selector) == -ELINKCONG)
231 (*cong_link_cnt)++;
208 } 232 }
233 return 0;
234}
209 235
210 /* Broadcast to all nodes, inluding local node */ 236/* tipc_mcast_xmit - deliver message to indicated destination nodes
211 tipc_bcbase_xmit(net, &xmitq); 237 * and to identified node local sockets
212 tipc_sk_mcast_rcv(net, &rcvq, &inputq); 238 * @net: the applicable net namespace
213 __skb_queue_purge(list); 239 * @pkts: chain of buffers containing message
240 * @dests: destination nodes for message. Not consumed.
241 * @cong_link_cnt: returns number of encountered congested destination links
242 * @cong_links: returns identities of congested links
243 * Consumes buffer chain.
244 * Returns 0 if success, otherwise errno
245 */
246int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts,
247 struct tipc_nlist *dests, u16 *cong_link_cnt)
248{
249 struct tipc_bc_base *bb = tipc_bc_base(net);
250 struct sk_buff_head inputq, localq;
251 int rc = 0;
252
253 skb_queue_head_init(&inputq);
254 skb_queue_head_init(&localq);
255
256 /* Clone packets before they are consumed by next call */
257 if (dests->local && !tipc_msg_reassemble(pkts, &localq)) {
258 rc = -ENOMEM;
259 goto exit;
260 }
261
262 if (dests->remote) {
263 if (!bb->bcast_support)
264 rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt);
265 else
266 rc = tipc_bcast_xmit(net, pkts, cong_link_cnt);
267 }
268
269 if (dests->local)
270 tipc_sk_mcast_rcv(net, &localq, &inputq);
271exit:
272 __skb_queue_purge(pkts);
214 return rc; 273 return rc;
215} 274}
216 275