|
@@ -44,8 +44,32 @@ static void node_established_contact(struct tipc_node *n_ptr);
|
|
|
|
|
|
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;
|
|
|
+
|
|
|
+static atomic_t tipc_num_links = ATOMIC_INIT(0);
|
|
|
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
|
|
|
*
|
|
@@ -58,8 +82,7 @@ u32 tipc_own_tag;
|
|
|
|
|
|
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);
|
|
|
|
|
@@ -78,12 +101,19 @@ struct tipc_node *tipc_node_create(u32 addr)
|
|
|
|
|
|
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_net.nodes[n_num] = n_ptr;
|
|
|
- if (n_num > tipc_net.highest_node)
|
|
|
- tipc_net.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;
|
|
@@ -91,18 +121,11 @@ struct tipc_node *tipc_node_create(u32 addr)
|
|
|
|
|
|
void tipc_node_delete(struct tipc_node *n_ptr)
|
|
|
{
|
|
|
- u32 n_num;
|
|
|
-
|
|
|
- if (!n_ptr)
|
|
|
- return;
|
|
|
-
|
|
|
- n_num = tipc_node(n_ptr->addr);
|
|
|
- tipc_net.nodes[n_num] = NULL;
|
|
|
+ list_del(&n_ptr->list);
|
|
|
+ hlist_del(&n_ptr->hash);
|
|
|
kfree(n_ptr);
|
|
|
|
|
|
- while (!tipc_net.nodes[tipc_net.highest_node])
|
|
|
- if (--tipc_net.highest_node == 0)
|
|
|
- break;
|
|
|
+ tipc_num_nodes--;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -200,54 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
|
|
|
node_lost_contact(n_ptr);
|
|
|
}
|
|
|
|
|
|
-int tipc_node_has_active_links(struct tipc_node *n_ptr)
|
|
|
+int tipc_node_active_links(struct tipc_node *n_ptr)
|
|
|
{
|
|
|
return n_ptr->active_links[0] != NULL;
|
|
|
}
|
|
|
|
|
|
-int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
|
|
|
+int tipc_node_redundant_links(struct tipc_node *n_ptr)
|
|
|
{
|
|
|
return n_ptr->working_links > 1;
|
|
|
}
|
|
|
|
|
|
int tipc_node_is_up(struct tipc_node *n_ptr)
|
|
|
{
|
|
|
- return tipc_node_has_active_links(n_ptr);
|
|
|
+ return tipc_node_active_links(n_ptr);
|
|
|
}
|
|
|
|
|
|
-struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
|
|
|
+void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)
|
|
|
{
|
|
|
- struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr);
|
|
|
-
|
|
|
- if (!n_ptr)
|
|
|
- n_ptr = tipc_node_create(l_ptr->addr);
|
|
|
- if (n_ptr) {
|
|
|
- u32 bearer_id = l_ptr->b_ptr->identity;
|
|
|
- char addr_string[16];
|
|
|
-
|
|
|
- if (n_ptr->link_cnt >= 2) {
|
|
|
- err("Attempt to create third link to %s\n",
|
|
|
- tipc_addr_string_fill(addr_string, n_ptr->addr));
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- if (!n_ptr->links[bearer_id]) {
|
|
|
- n_ptr->links[bearer_id] = l_ptr;
|
|
|
- tipc_net.links++;
|
|
|
- n_ptr->link_cnt++;
|
|
|
- return n_ptr;
|
|
|
- }
|
|
|
- err("Attempt to establish second link on <%s> to %s\n",
|
|
|
- l_ptr->b_ptr->name,
|
|
|
- tipc_addr_string_fill(addr_string, l_ptr->addr));
|
|
|
- }
|
|
|
- return NULL;
|
|
|
+ n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;
|
|
|
+ atomic_inc(&tipc_num_links);
|
|
|
+ n_ptr->link_cnt++;
|
|
|
}
|
|
|
|
|
|
void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
|
|
|
{
|
|
|
n_ptr->links[l_ptr->b_ptr->identity] = NULL;
|
|
|
- tipc_net.links--;
|
|
|
+ atomic_dec(&tipc_num_links);
|
|
|
n_ptr->link_cnt--;
|
|
|
}
|
|
|
|
|
@@ -327,7 +328,6 @@ static void node_cleanup_finished(unsigned long node_addr)
|
|
|
|
|
|
static void node_lost_contact(struct tipc_node *n_ptr)
|
|
|
{
|
|
|
- struct tipc_node_subscr *ns, *tns;
|
|
|
char addr_string[16];
|
|
|
u32 i;
|
|
|
|
|
@@ -365,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
|
|
|
}
|
|
|
|
|
|
/* Notify subscribers */
|
|
|
- list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
|
|
|
- ns->node = NULL;
|
|
|
- list_del_init(&ns->nodesub_list);
|
|
|
- tipc_k_signal((Handler)ns->handle_node_down,
|
|
|
- (unsigned long)ns->usr_handle);
|
|
|
- }
|
|
|
+ tipc_nodesub_notify(n_ptr);
|
|
|
|
|
|
/* Prevent re-contact with node until all cleanup is done */
|
|
|
|
|
@@ -385,7 +380,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
|
|
|
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);
|
|
@@ -396,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
|
|
|
" (network address)");
|
|
|
|
|
|
read_lock_bh(&tipc_net_lock);
|
|
|
- if (!tipc_net.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_net.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
|
|
@@ -418,9 +411,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
|
|
|
|
|
|
/* Add TLVs for all nodes in scope */
|
|
|
|
|
|
- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {
|
|
|
- n_ptr = tipc_net.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));
|
|
@@ -439,7 +431,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
|
|
|
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);
|
|
@@ -456,7 +447,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
|
|
|
|
|
|
/* Get space for all unicast links + multicast link */
|
|
|
|
|
|
- payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1);
|
|
|
+ payload_size = TLV_SPACE(sizeof(link_info)) *
|
|
|
+ (atomic_read(&tipc_num_links) + 1);
|
|
|
if (payload_size > 32768u) {
|
|
|
read_unlock_bh(&tipc_net_lock);
|
|
|
return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
|
|
@@ -470,18 +462,17 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
|
|
|
|
|
|
/* Add TLV for broadcast link */
|
|
|
|
|
|
- link_info.dest = htonl(tipc_own_addr & 0xfffff00);
|
|
|
+ link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
|
|
|
link_info.up = htonl(1);
|
|
|
strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
|
|
|
tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
|
|
|
|
|
|
/* Add TLVs for any other links in scope */
|
|
|
|
|
|
- for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {
|
|
|
+ list_for_each_entry(n_ptr, &tipc_node_list, list) {
|
|
|
u32 i;
|
|
|
|
|
|
- n_ptr = tipc_net.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++) {
|