summaryrefslogtreecommitdiff
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index c1a4611649ab..26aec8414ac1 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,7 +1,7 @@
/*
* net/tipc/socket.c: TIPC socket API
*
- * Copyright (c) 2001-2007, 2012-2014, Ericsson AB
+ * Copyright (c) 2001-2007, 2012-2015, Ericsson AB
* Copyright (c) 2004-2008, 2010-2013, Wind River Systems
* All rights reserved.
*
@@ -778,48 +778,42 @@ new_mtu:
/* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets
*/
-void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf)
+void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *skb)
{
- struct tipc_msg *msg = buf_msg(buf);
- struct tipc_port_list dports = {0, NULL, };
- struct tipc_port_list *item;
- struct sk_buff *b;
- uint i, last, dst = 0;
+ struct tipc_msg *msg = buf_msg(skb);
+ struct tipc_plist dports;
+ struct sk_buff *cskb;
+ u32 portid;
u32 scope = TIPC_CLUSTER_SCOPE;
- struct sk_buff_head msgs;
+ struct sk_buff_head msgq;
+ uint hsz = skb_headroom(skb) + msg_hdr_sz(msg);
+
+ skb_queue_head_init(&msgq);
+ tipc_plist_init(&dports);
if (in_own_node(net, msg_orignode(msg)))
scope = TIPC_NODE_SCOPE;
if (unlikely(!msg_mcast(msg))) {
pr_warn("Received non-multicast msg in multicast\n");
- kfree_skb(buf);
goto exit;
}
/* Create destination port list: */
tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg),
msg_nameupper(msg), scope, &dports);
- last = dports.count;
- if (!last) {
- kfree_skb(buf);
- return;
- }
-
- for (item = &dports; item; item = item->next) {
- for (i = 0; i < PLSIZE && ++dst <= last; i++) {
- b = (dst != last) ? skb_clone(buf, GFP_ATOMIC) : buf;
- if (!b) {
- pr_warn("Failed do clone mcast rcv buffer\n");
- continue;
- }
- msg_set_destport(msg, item->ports[i]);
- skb_queue_head_init(&msgs);
- skb_queue_tail(&msgs, b);
- tipc_sk_rcv(net, &msgs);
+ portid = tipc_plist_pop(&dports);
+ for (; portid; portid = tipc_plist_pop(&dports)) {
+ cskb = __pskb_copy(skb, hsz, GFP_ATOMIC);
+ if (!cskb) {
+ pr_warn("Failed do clone mcast rcv buffer\n");
+ continue;
}
+ msg_set_destport(buf_msg(cskb), portid);
+ skb_queue_tail(&msgq, cskb);
}
+ tipc_sk_rcv(net, &msgq);
exit:
- tipc_port_list_free(&dports);
+ kfree_skb(skb);
}
/**