aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2011-02-25 18:42:52 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-03-13 16:35:17 -0400
commit672d99e19a12b703c9e2d71ead8fb8b8a85a3886 (patch)
treecca078684f8adee7450cadcb565176f0a8b111ff /net/tipc/node.c
parentf831c963b5c20bec230edce89e25f369996be5db (diff)
tipc: Convert node object array to a hash table
Replaces the dynamically allocated array of pointers to the cluster's node objects with a static hash table. Hash collisions are resolved using chaining, with a typical hash chain having only a single node, to avoid degrading performance during processing of incoming packets. The conversion to a hash table reduces the memory requirements for TIPC's node table to approximately the same size it had prior to the previous commit. In addition to the hash table itself, TIPC now also maintains a linked list for the node objects, sorted by ascending network address. This list allows TIPC to continue sending responses to user space applications that request node and link information in sorted order. The list also improves performance when name table update messages are sent by making it easier to identify the nodes that must be notified. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 64976f2e3c66..22aeb2b7ad00 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -44,9 +44,31 @@ static void node_established_contact(struct tipc_node *n_ptr);
44 44
45static DEFINE_SPINLOCK(node_create_lock); 45static DEFINE_SPINLOCK(node_create_lock);
46 46
47static struct hlist_head node_htable[NODE_HTABLE_SIZE];
48LIST_HEAD(tipc_node_list);
49static u32 tipc_num_nodes;
47u32 tipc_own_tag; 50u32 tipc_own_tag;
48 51
49/** 52/**
53 * tipc_node_find - locate specified node object, if it exists
54 */
55
56struct tipc_node *tipc_node_find(u32 addr)
57{
58 struct tipc_node *node;
59 struct hlist_node *pos;
60
61 if (unlikely(!in_own_cluster(addr)))
62 return NULL;
63
64 hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
65 if (node->addr == addr)
66 return node;
67 }
68 return NULL;
69}
70
71/**
50 * tipc_node_create - create neighboring node 72 * tipc_node_create - create neighboring node
51 * 73 *
52 * Currently, this routine is called by neighbor discovery code, which holds 74 * Currently, this routine is called by neighbor discovery code, which holds
@@ -58,8 +80,7 @@ u32 tipc_own_tag;
58 80
59struct tipc_node *tipc_node_create(u32 addr) 81struct tipc_node *tipc_node_create(u32 addr)
60{ 82{
61 struct tipc_node *n_ptr; 83 struct tipc_node *n_ptr, *temp_node;
62 u32 n_num;
63 84
64 spin_lock_bh(&node_create_lock); 85 spin_lock_bh(&node_create_lock);
65 86
@@ -78,12 +99,19 @@ struct tipc_node *tipc_node_create(u32 addr)
78 99
79 n_ptr->addr = addr; 100 n_ptr->addr = addr;
80 spin_lock_init(&n_ptr->lock); 101 spin_lock_init(&n_ptr->lock);
102 INIT_HLIST_NODE(&n_ptr->hash);
103 INIT_LIST_HEAD(&n_ptr->list);
81 INIT_LIST_HEAD(&n_ptr->nsub); 104 INIT_LIST_HEAD(&n_ptr->nsub);
82 105
83 n_num = tipc_node(addr); 106 hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);
84 tipc_nodes[n_num] = n_ptr; 107
85 if (n_num > tipc_highest_node) 108 list_for_each_entry(temp_node, &tipc_node_list, list) {
86 tipc_highest_node = n_num; 109 if (n_ptr->addr < temp_node->addr)
110 break;
111 }
112 list_add_tail(&n_ptr->list, &temp_node->list);
113
114 tipc_num_nodes++;
87 115
88 spin_unlock_bh(&node_create_lock); 116 spin_unlock_bh(&node_create_lock);
89 return n_ptr; 117 return n_ptr;
@@ -91,18 +119,11 @@ struct tipc_node *tipc_node_create(u32 addr)
91 119
92void tipc_node_delete(struct tipc_node *n_ptr) 120void tipc_node_delete(struct tipc_node *n_ptr)
93{ 121{
94 u32 n_num; 122 list_del(&n_ptr->list);
95 123 hlist_del(&n_ptr->hash);
96 if (!n_ptr)
97 return;
98
99 n_num = tipc_node(n_ptr->addr);
100 tipc_nodes[n_num] = NULL;
101 kfree(n_ptr); 124 kfree(n_ptr);
102 125
103 while (!tipc_nodes[tipc_highest_node]) 126 tipc_num_nodes--;
104 if (--tipc_highest_node == 0)
105 break;
106} 127}
107 128
108 129
@@ -379,7 +400,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
379 struct tipc_node *n_ptr; 400 struct tipc_node *n_ptr;
380 struct tipc_node_info node_info; 401 struct tipc_node_info node_info;
381 u32 payload_size; 402 u32 payload_size;
382 u32 n_num;
383 403
384 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 404 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
385 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 405 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -390,15 +410,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
390 " (network address)"); 410 " (network address)");
391 411
392 read_lock_bh(&tipc_net_lock); 412 read_lock_bh(&tipc_net_lock);
393 if (!tipc_nodes) { 413 if (!tipc_num_nodes) {
394 read_unlock_bh(&tipc_net_lock); 414 read_unlock_bh(&tipc_net_lock);
395 return tipc_cfg_reply_none(); 415 return tipc_cfg_reply_none();
396 } 416 }
397 417
398 /* For now, get space for all other nodes */ 418 /* For now, get space for all other nodes */
399 419
400 payload_size = TLV_SPACE(sizeof(node_info)) * 420 payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
401 (tipc_highest_node - 1);
402 if (payload_size > 32768u) { 421 if (payload_size > 32768u) {
403 read_unlock_bh(&tipc_net_lock); 422 read_unlock_bh(&tipc_net_lock);
404 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 423 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
@@ -412,9 +431,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
412 431
413 /* Add TLVs for all nodes in scope */ 432 /* Add TLVs for all nodes in scope */
414 433
415 for (n_num = 1; n_num <= tipc_highest_node; n_num++) { 434 list_for_each_entry(n_ptr, &tipc_node_list, list) {
416 n_ptr = tipc_nodes[n_num]; 435 if (!tipc_in_scope(domain, n_ptr->addr))
417 if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
418 continue; 436 continue;
419 node_info.addr = htonl(n_ptr->addr); 437 node_info.addr = htonl(n_ptr->addr);
420 node_info.up = htonl(tipc_node_is_up(n_ptr)); 438 node_info.up = htonl(tipc_node_is_up(n_ptr));
@@ -433,7 +451,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
433 struct tipc_node *n_ptr; 451 struct tipc_node *n_ptr;
434 struct tipc_link_info link_info; 452 struct tipc_link_info link_info;
435 u32 payload_size; 453 u32 payload_size;
436 u32 n_num;
437 454
438 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 455 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
439 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 456 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -472,11 +489,10 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
472 489
473 /* Add TLVs for any other links in scope */ 490 /* Add TLVs for any other links in scope */
474 491
475 for (n_num = 1; n_num <= tipc_highest_node; n_num++) { 492 list_for_each_entry(n_ptr, &tipc_node_list, list) {
476 u32 i; 493 u32 i;
477 494
478 n_ptr = tipc_nodes[n_num]; 495 if (!tipc_in_scope(domain, n_ptr->addr))
479 if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
480 continue; 496 continue;
481 tipc_node_lock(n_ptr); 497 tipc_node_lock(n_ptr);
482 for (i = 0; i < MAX_BEARERS; i++) { 498 for (i = 0; i < MAX_BEARERS; i++) {