aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-02-05 08:36:43 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-05 19:00:03 -0500
commit3c724acdd5049907555a831f814bfd5927c3350c (patch)
treeccf441eecb318238d03e8fa86a7f803d6e3914c7 /net/tipc
parent708ac32cb5e1305cf3670e147eedcc699d110ed0 (diff)
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')
-rw-r--r--net/tipc/bcast.c49
-rw-r--r--net/tipc/bcast.h24
-rw-r--r--net/tipc/name_table.c44
-rw-r--r--net/tipc/name_table.h18
-rw-r--r--net/tipc/socket.c48
-rw-r--r--net/tipc/socket.h2
6 files changed, 84 insertions, 101 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 2dfaf272928a..3eaa931e2e8c 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/bcast.c: TIPC broadcast code 2 * net/tipc/bcast.c: TIPC broadcast code
3 * 3 *
4 * Copyright (c) 2004-2006, 2014, Ericsson AB 4 * Copyright (c) 2004-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2004, Intel Corporation. 5 * Copyright (c) 2004, Intel Corporation.
6 * Copyright (c) 2005, 2010-2011, Wind River Systems 6 * Copyright (c) 2005, 2010-2011, Wind River Systems
7 * All rights reserved. 7 * All rights reserved.
@@ -1037,50 +1037,3 @@ static void tipc_nmap_diff(struct tipc_node_map *nm_a,
1037 } 1037 }
1038 } 1038 }
1039} 1039}
1040
1041/**
1042 * tipc_port_list_add - add a port to a port list, ensuring no duplicates
1043 */
1044void tipc_port_list_add(struct tipc_port_list *pl_ptr, u32 port)
1045{
1046 struct tipc_port_list *item = pl_ptr;
1047 int i;
1048 int item_sz = PLSIZE;
1049 int cnt = pl_ptr->count;
1050
1051 for (; ; cnt -= item_sz, item = item->next) {
1052 if (cnt < PLSIZE)
1053 item_sz = cnt;
1054 for (i = 0; i < item_sz; i++)
1055 if (item->ports[i] == port)
1056 return;
1057 if (i < PLSIZE) {
1058 item->ports[i] = port;
1059 pl_ptr->count++;
1060 return;
1061 }
1062 if (!item->next) {
1063 item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
1064 if (!item->next) {
1065 pr_warn("Incomplete multicast delivery, no memory\n");
1066 return;
1067 }
1068 item->next->next = NULL;
1069 }
1070 }
1071}
1072
1073/**
1074 * tipc_port_list_free - free dynamically created entries in port_list chain
1075 *
1076 */
1077void tipc_port_list_free(struct tipc_port_list *pl_ptr)
1078{
1079 struct tipc_port_list *item;
1080 struct tipc_port_list *next;
1081
1082 for (item = pl_ptr->next; item; item = next) {
1083 next = item->next;
1084 kfree(item);
1085 }
1086}
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 6ea190dccfe1..8f4d4dc38e11 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/bcast.h: Include file for TIPC broadcast code 2 * net/tipc/bcast.h: Include file for TIPC broadcast code
3 * 3 *
4 * Copyright (c) 2003-2006, 2014, Ericsson AB 4 * Copyright (c) 2003-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2005, 2010-2011, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -41,22 +41,6 @@
41#include "link.h" 41#include "link.h"
42#include "node.h" 42#include "node.h"
43 43
44#define TIPC_BCLINK_RESET 1
45#define PLSIZE 32
46#define BCBEARER MAX_BEARERS
47
48/**
49 * struct tipc_port_list - set of node local destination ports
50 * @count: # of ports in set (only valid for first entry in list)
51 * @next: pointer to next entry in list
52 * @ports: array of port references
53 */
54struct tipc_port_list {
55 int count;
56 struct tipc_port_list *next;
57 u32 ports[PLSIZE];
58};
59
60/** 44/**
61 * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link 45 * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link
62 * @primary: pointer to primary bearer 46 * @primary: pointer to primary bearer
@@ -71,6 +55,9 @@ struct tipc_bcbearer_pair {
71 struct tipc_bearer *secondary; 55 struct tipc_bearer *secondary;
72}; 56};
73 57
58#define TIPC_BCLINK_RESET 1
59#define BCBEARER MAX_BEARERS
60
74/** 61/**
75 * struct tipc_bcbearer - bearer used by broadcast link 62 * struct tipc_bcbearer - bearer used by broadcast link
76 * @bearer: (non-standard) broadcast bearer structure 63 * @bearer: (non-standard) broadcast bearer structure
@@ -126,9 +113,6 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a,
126 return !memcmp(nm_a, nm_b, sizeof(*nm_a)); 113 return !memcmp(nm_a, nm_b, sizeof(*nm_a));
127} 114}
128 115
129void tipc_port_list_add(struct tipc_port_list *pl_ptr, u32 port);
130void tipc_port_list_free(struct tipc_port_list *pl_ptr);
131
132int tipc_bclink_init(struct net *net); 116int tipc_bclink_init(struct net *net);
133void tipc_bclink_stop(struct net *net); 117void tipc_bclink_stop(struct net *net);
134void tipc_bclink_set_flags(struct net *tn, unsigned int flags); 118void tipc_bclink_set_flags(struct net *tn, unsigned int flags);
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index ce09b863528c..18a3d44238bc 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/name_table.c: TIPC name table code 2 * net/tipc/name_table.c: TIPC name table code
3 * 3 *
4 * Copyright (c) 2000-2006, 2014, Ericsson AB 4 * Copyright (c) 2000-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2014, Wind River Systems 5 * Copyright (c) 2004-2008, 2010-2014, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -618,7 +618,7 @@ not_found:
618 * Returns non-zero if any off-node ports overlap 618 * Returns non-zero if any off-node ports overlap
619 */ 619 */
620int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, 620int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
621 u32 limit, struct tipc_port_list *dports) 621 u32 limit, struct tipc_plist *dports)
622{ 622{
623 struct name_seq *seq; 623 struct name_seq *seq;
624 struct sub_seq *sseq; 624 struct sub_seq *sseq;
@@ -643,7 +643,7 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
643 info = sseq->info; 643 info = sseq->info;
644 list_for_each_entry(publ, &info->node_list, node_list) { 644 list_for_each_entry(publ, &info->node_list, node_list) {
645 if (publ->scope <= limit) 645 if (publ->scope <= limit)
646 tipc_port_list_add(dports, publ->ref); 646 tipc_plist_push(dports, publ->ref);
647 } 647 }
648 648
649 if (info->cluster_list_size != info->node_list_size) 649 if (info->cluster_list_size != info->node_list_size)
@@ -1212,3 +1212,41 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
1212 1212
1213 return skb->len; 1213 return skb->len;
1214} 1214}
1215
1216void tipc_plist_push(struct tipc_plist *pl, u32 port)
1217{
1218 struct tipc_plist *nl;
1219
1220 if (likely(!pl->port)) {
1221 pl->port = port;
1222 return;
1223 }
1224 if (pl->port == port)
1225 return;
1226 list_for_each_entry(nl, &pl->list, list) {
1227 if (nl->port == port)
1228 return;
1229 }
1230 nl = kmalloc(sizeof(*nl), GFP_ATOMIC);
1231 if (nl) {
1232 nl->port = port;
1233 list_add(&nl->list, &pl->list);
1234 }
1235}
1236
1237u32 tipc_plist_pop(struct tipc_plist *pl)
1238{
1239 struct tipc_plist *nl;
1240 u32 port = 0;
1241
1242 if (likely(list_empty(&pl->list))) {
1243 port = pl->port;
1244 pl->port = 0;
1245 return port;
1246 }
1247 nl = list_first_entry(&pl->list, typeof(*nl), list);
1248 port = nl->port;
1249 list_del(&nl->list);
1250 kfree(nl);
1251 return port;
1252}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index f67b3d8d4b2f..52501fdaafa5 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -38,7 +38,7 @@
38#define _TIPC_NAME_TABLE_H 38#define _TIPC_NAME_TABLE_H
39 39
40struct tipc_subscription; 40struct tipc_subscription;
41struct tipc_port_list; 41struct tipc_plist;
42 42
43/* 43/*
44 * TIPC name types reserved for internal TIPC use (both current and planned) 44 * TIPC name types reserved for internal TIPC use (both current and planned)
@@ -101,7 +101,7 @@ struct sk_buff *tipc_nametbl_get(struct net *net, const void *req_tlv_area,
101 int req_tlv_space); 101 int req_tlv_space);
102u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node); 102u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node);
103int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper, 103int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
104 u32 limit, struct tipc_port_list *dports); 104 u32 limit, struct tipc_plist *dports);
105struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, 105struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
106 u32 upper, u32 scope, u32 port_ref, 106 u32 upper, u32 scope, u32 port_ref,
107 u32 key); 107 u32 key);
@@ -118,4 +118,18 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
118int tipc_nametbl_init(struct net *net); 118int tipc_nametbl_init(struct net *net);
119void tipc_nametbl_stop(struct net *net); 119void tipc_nametbl_stop(struct net *net);
120 120
121struct tipc_plist {
122 struct list_head list;
123 u32 port;
124};
125
126static inline void tipc_plist_init(struct tipc_plist *pl)
127{
128 INIT_LIST_HEAD(&pl->list);
129 pl->port = 0;
130}
131
132void tipc_plist_push(struct tipc_plist *pl, u32 port);
133u32 tipc_plist_pop(struct tipc_plist *pl);
134
121#endif 135#endif
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 @@
1/* 1/*
2 * net/tipc/socket.c: TIPC socket API 2 * net/tipc/socket.c: TIPC socket API
3 * 3 *
4 * Copyright (c) 2001-2007, 2012-2014, Ericsson AB 4 * Copyright (c) 2001-2007, 2012-2015, Ericsson AB
5 * Copyright (c) 2004-2008, 2010-2013, Wind River Systems 5 * Copyright (c) 2004-2008, 2010-2013, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -778,48 +778,42 @@ new_mtu:
778 778
779/* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets 779/* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets
780 */ 780 */
781void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf) 781void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *skb)
782{ 782{
783 struct tipc_msg *msg = buf_msg(buf); 783 struct tipc_msg *msg = buf_msg(skb);
784 struct tipc_port_list dports = {0, NULL, }; 784 struct tipc_plist dports;
785 struct tipc_port_list *item; 785 struct sk_buff *cskb;
786 struct sk_buff *b; 786 u32 portid;
787 uint i, last, dst = 0;
788 u32 scope = TIPC_CLUSTER_SCOPE; 787 u32 scope = TIPC_CLUSTER_SCOPE;
789 struct sk_buff_head msgs; 788 struct sk_buff_head msgq;
789 uint hsz = skb_headroom(skb) + msg_hdr_sz(msg);
790
791 skb_queue_head_init(&msgq);
792 tipc_plist_init(&dports);
790 793
791 if (in_own_node(net, msg_orignode(msg))) 794 if (in_own_node(net, msg_orignode(msg)))
792 scope = TIPC_NODE_SCOPE; 795 scope = TIPC_NODE_SCOPE;
793 796
794 if (unlikely(!msg_mcast(msg))) { 797 if (unlikely(!msg_mcast(msg))) {
795 pr_warn("Received non-multicast msg in multicast\n"); 798 pr_warn("Received non-multicast msg in multicast\n");
796 kfree_skb(buf);
797 goto exit; 799 goto exit;
798 } 800 }
799 /* Create destination port list: */ 801 /* Create destination port list: */
800 tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg), 802 tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg),
801 msg_nameupper(msg), scope, &dports); 803 msg_nameupper(msg), scope, &dports);
802 last = dports.count; 804 portid = tipc_plist_pop(&dports);
803 if (!last) { 805 for (; portid; portid = tipc_plist_pop(&dports)) {
804 kfree_skb(buf); 806 cskb = __pskb_copy(skb, hsz, GFP_ATOMIC);
805 return; 807 if (!cskb) {
806 } 808 pr_warn("Failed do clone mcast rcv buffer\n");
807 809 continue;
808 for (item = &dports; item; item = item->next) {
809 for (i = 0; i < PLSIZE && ++dst <= last; i++) {
810 b = (dst != last) ? skb_clone(buf, GFP_ATOMIC) : buf;
811 if (!b) {
812 pr_warn("Failed do clone mcast rcv buffer\n");
813 continue;
814 }
815 msg_set_destport(msg, item->ports[i]);
816 skb_queue_head_init(&msgs);
817 skb_queue_tail(&msgs, b);
818 tipc_sk_rcv(net, &msgs);
819 } 810 }
811 msg_set_destport(buf_msg(cskb), portid);
812 skb_queue_tail(&msgq, cskb);
820 } 813 }
814 tipc_sk_rcv(net, &msgq);
821exit: 815exit:
822 tipc_port_list_free(&dports); 816 kfree_skb(skb);
823} 817}
824 818
825/** 819/**
diff --git a/net/tipc/socket.h b/net/tipc/socket.h
index e3dbdc0e1be7..95b015909ac1 100644
--- a/net/tipc/socket.h
+++ b/net/tipc/socket.h
@@ -1,6 +1,6 @@
1/* net/tipc/socket.h: Include file for TIPC socket code 1/* net/tipc/socket.h: Include file for TIPC socket code
2 * 2 *
3 * Copyright (c) 2014, Ericsson AB 3 * Copyright (c) 2014-2015, Ericsson AB
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without