summaryrefslogtreecommitdiff
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-02-05 13:36:43 (GMT)
committerDavid S. Miller <davem@davemloft.net>2015-02-06 00:00:03 (GMT)
commit3c724acdd5049907555a831f814bfd5927c3350c (patch)
treeccf441eecb318238d03e8fa86a7f803d6e3914c7 /net/tipc/socket.c
parent708ac32cb5e1305cf3670e147eedcc699d110ed0 (diff)
downloadlinux-3c724acdd5049907555a831f814bfd5927c3350c.tar.xz
tipc: simplify socket multicast reception
The structure 'tipc_port_list' is used to collect port numbers representing multicast destination socket on a receiving node. The list is not based on a standard linked list, and is in reality optimized for the uncommon case that there are more than one multicast destinations per node. This makes the list handling unecessarily complex, and as a consequence, even the socket multicast reception becomes more complex. In this commit, we replace 'tipc_port_list' with a new 'struct tipc_plist', which is based on a standard list. We give the new list stack (push/pop) semantics, someting that simplifies the implementation of the function tipc_sk_mcast_rcv(). Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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 c1a4611..26aec84 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);
}
/**