#include "name_distr.h"
#include "subscr.h"
#include "port.h"
+#include "node.h"
#include "config.h"
/*
*/
DEFINE_RWLOCK(tipc_net_lock);
-struct tipc_node **tipc_nodes;
-u32 tipc_highest_node;
atomic_t tipc_num_links;
static int net_start(void)
{
- tipc_nodes = kcalloc(4096, sizeof(*tipc_nodes), GFP_ATOMIC);
- tipc_highest_node = 0;
atomic_set(&tipc_num_links, 0);
- return tipc_nodes ? 0 : -ENOMEM;
+ return 0;
}
static void net_stop(void)
{
- u32 n_num;
+ struct tipc_node *node, *t_node;
- for (n_num = 1; n_num <= tipc_highest_node; n_num++)
- tipc_node_delete(tipc_nodes[n_num]);
- kfree(tipc_nodes);
- tipc_nodes = NULL;
+ list_for_each_entry_safe(node, t_node, &tipc_node_list, list)
+ tipc_node_delete(node);
}
static void net_route_named_msg(struct sk_buff *buf)
static DEFINE_SPINLOCK(node_create_lock);
+static struct hlist_head node_htable[NODE_HTABLE_SIZE];
+LIST_HEAD(tipc_node_list);
+static u32 tipc_num_nodes;
u32 tipc_own_tag;
+/**
+ * tipc_node_find - locate specified node object, if it exists
+ */
+
+struct tipc_node *tipc_node_find(u32 addr)
+{
+ struct tipc_node *node;
+ struct hlist_node *pos;
+
+ if (unlikely(!in_own_cluster(addr)))
+ return NULL;
+
+ hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
+ if (node->addr == addr)
+ return node;
+ }
+ return NULL;
+}
+
/**
* tipc_node_create - create neighboring node
*
struct tipc_node *tipc_node_create(u32 addr)
{
- struct tipc_node *n_ptr;
- u32 n_num;
+ struct tipc_node *n_ptr, *temp_node;
spin_lock_bh(&node_create_lock);
n_ptr->addr = addr;
spin_lock_init(&n_ptr->lock);
+ INIT_HLIST_NODE(&n_ptr->hash);
+ INIT_LIST_HEAD(&n_ptr->list);
INIT_LIST_HEAD(&n_ptr->nsub);
- n_num = tipc_node(addr);
- tipc_nodes[n_num] = n_ptr;
- if (n_num > tipc_highest_node)
- tipc_highest_node = n_num;
+ hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);
+
+ list_for_each_entry(temp_node, &tipc_node_list, list) {
+ if (n_ptr->addr < temp_node->addr)
+ break;
+ }
+ list_add_tail(&n_ptr->list, &temp_node->list);
+
+ tipc_num_nodes++;
spin_unlock_bh(&node_create_lock);
return n_ptr;
void tipc_node_delete(struct tipc_node *n_ptr)
{
- u32 n_num;
-
- if (!n_ptr)
- return;
-
- n_num = tipc_node(n_ptr->addr);
- tipc_nodes[n_num] = NULL;
+ list_del(&n_ptr->list);
+ hlist_del(&n_ptr->hash);
kfree(n_ptr);
- while (!tipc_nodes[tipc_highest_node])
- if (--tipc_highest_node == 0)
- break;
+ tipc_num_nodes--;
}
struct tipc_node *n_ptr;
struct tipc_node_info node_info;
u32 payload_size;
- u32 n_num;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
" (network address)");
read_lock_bh(&tipc_net_lock);
- if (!tipc_nodes) {
+ if (!tipc_num_nodes) {
read_unlock_bh(&tipc_net_lock);
return tipc_cfg_reply_none();
}
/* For now, get space for all other nodes */
- payload_size = TLV_SPACE(sizeof(node_info)) *
- (tipc_highest_node - 1);
+ payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
if (payload_size > 32768u) {
read_unlock_bh(&tipc_net_lock);
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
/* Add TLVs for all nodes in scope */
- for (n_num = 1; n_num <= tipc_highest_node; n_num++) {
- n_ptr = tipc_nodes[n_num];
- if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
+ list_for_each_entry(n_ptr, &tipc_node_list, list) {
+ if (!tipc_in_scope(domain, n_ptr->addr))
continue;
node_info.addr = htonl(n_ptr->addr);
node_info.up = htonl(tipc_node_is_up(n_ptr));
struct tipc_node *n_ptr;
struct tipc_link_info link_info;
u32 payload_size;
- u32 n_num;
if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
/* Add TLVs for any other links in scope */
- for (n_num = 1; n_num <= tipc_highest_node; n_num++) {
+ list_for_each_entry(n_ptr, &tipc_node_list, list) {
u32 i;
- n_ptr = tipc_nodes[n_num];
- if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
+ if (!tipc_in_scope(domain, n_ptr->addr))
continue;
tipc_node_lock(n_ptr);
for (i = 0; i < MAX_BEARERS; i++) {
* net/tipc/node.h: Include file for TIPC node management routines
*
* Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* struct tipc_node - TIPC node structure
* @addr: network address of node
* @lock: spinlock governing access to structure
- * @next: pointer to next node in sorted list of cluster's nodes
+ * @hash: links to adjacent nodes in unsorted hash chain
+ * @list: links to adjacent nodes in sorted list of cluster's nodes
* @nsub: list of "node down" subscriptions monitoring node
* @active_links: pointers to active links to node
* @links: pointers to all links to node
struct tipc_node {
u32 addr;
spinlock_t lock;
- struct tipc_node *next;
+ struct hlist_node hash;
+ struct list_head list;
struct list_head nsub;
struct link *active_links[2];
struct link *links[MAX_BEARERS];
} bclink;
};
+#define NODE_HTABLE_SIZE 512
+extern struct list_head tipc_node_list;
+
+/*
+ * A trivial power-of-two bitmask technique is used for speed, since this
+ * operation is done for every incoming TIPC packet. The number of hash table
+ * entries has been chosen so that no hash chain exceeds 8 nodes and will
+ * usually be much smaller (typically only a single node).
+ */
+static inline unsigned int tipc_hashfn(u32 addr)
+{
+ return addr & (NODE_HTABLE_SIZE - 1);
+}
+
extern u32 tipc_own_tag;
+struct tipc_node *tipc_node_find(u32 addr);
struct tipc_node *tipc_node_create(u32 addr);
void tipc_node_delete(struct tipc_node *n_ptr);
struct tipc_node *tipc_node_attach_link(struct link *l_ptr);
struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
-static inline struct tipc_node *tipc_node_find(u32 addr)
-{
- if (likely(in_own_cluster(addr)))
- return tipc_nodes[tipc_node(addr)];
- return NULL;
-}
-
static inline void tipc_node_lock(struct tipc_node *n_ptr)
{
spin_lock_bh(&n_ptr->lock);