aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/tipc/node.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c180
1 files changed, 115 insertions, 65 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 48f39dd3eae..2d106ef4fa4 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/node.c: TIPC node management routines 2 * net/tipc/node.c: TIPC node management routines
3 * 3 *
4 * Copyright (c) 2000-2006, 2012 Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -39,8 +39,6 @@
39#include "node.h" 39#include "node.h"
40#include "name_distr.h" 40#include "name_distr.h"
41 41
42#define NODE_HTABLE_SIZE 512
43
44static void node_lost_contact(struct tipc_node *n_ptr); 42static void node_lost_contact(struct tipc_node *n_ptr);
45static void node_established_contact(struct tipc_node *n_ptr); 43static void node_established_contact(struct tipc_node *n_ptr);
46 44
@@ -51,27 +49,18 @@ LIST_HEAD(tipc_node_list);
51static u32 tipc_num_nodes; 49static u32 tipc_num_nodes;
52 50
53static atomic_t tipc_num_links = ATOMIC_INIT(0); 51static atomic_t tipc_num_links = ATOMIC_INIT(0);
52u32 tipc_own_tag;
54 53
55/* 54/**
56 * A trivial power-of-two bitmask technique is used for speed, since this
57 * operation is done for every incoming TIPC packet. The number of hash table
58 * entries has been chosen so that no hash chain exceeds 8 nodes and will
59 * usually be much smaller (typically only a single node).
60 */
61static unsigned int tipc_hashfn(u32 addr)
62{
63 return addr & (NODE_HTABLE_SIZE - 1);
64}
65
66/*
67 * tipc_node_find - locate specified node object, if it exists 55 * tipc_node_find - locate specified node object, if it exists
68 */ 56 */
57
69struct tipc_node *tipc_node_find(u32 addr) 58struct tipc_node *tipc_node_find(u32 addr)
70{ 59{
71 struct tipc_node *node; 60 struct tipc_node *node;
72 struct hlist_node *pos; 61 struct hlist_node *pos;
73 62
74 if (unlikely(!in_own_cluster_exact(addr))) 63 if (unlikely(!in_own_cluster(addr)))
75 return NULL; 64 return NULL;
76 65
77 hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { 66 hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
@@ -90,6 +79,7 @@ struct tipc_node *tipc_node_find(u32 addr)
90 * time. (It would be preferable to switch to holding net_lock in write mode, 79 * time. (It would be preferable to switch to holding net_lock in write mode,
91 * but this is a non-trivial change.) 80 * but this is a non-trivial change.)
92 */ 81 */
82
93struct tipc_node *tipc_node_create(u32 addr) 83struct tipc_node *tipc_node_create(u32 addr)
94{ 84{
95 struct tipc_node *n_ptr, *temp_node; 85 struct tipc_node *n_ptr, *temp_node;
@@ -105,7 +95,7 @@ struct tipc_node *tipc_node_create(u32 addr)
105 n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); 95 n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
106 if (!n_ptr) { 96 if (!n_ptr) {
107 spin_unlock_bh(&node_create_lock); 97 spin_unlock_bh(&node_create_lock);
108 pr_warn("Node creation failed, no memory\n"); 98 warn("Node creation failed, no memory\n");
109 return NULL; 99 return NULL;
110 } 100 }
111 101
@@ -122,8 +112,6 @@ struct tipc_node *tipc_node_create(u32 addr)
122 break; 112 break;
123 } 113 }
124 list_add_tail(&n_ptr->list, &temp_node->list); 114 list_add_tail(&n_ptr->list, &temp_node->list);
125 n_ptr->block_setup = WAIT_PEER_DOWN;
126 n_ptr->signature = INVALID_NODE_SIG;
127 115
128 tipc_num_nodes++; 116 tipc_num_nodes++;
129 117
@@ -140,19 +128,21 @@ void tipc_node_delete(struct tipc_node *n_ptr)
140 tipc_num_nodes--; 128 tipc_num_nodes--;
141} 129}
142 130
131
143/** 132/**
144 * tipc_node_link_up - handle addition of link 133 * tipc_node_link_up - handle addition of link
145 * 134 *
146 * Link becomes active (alone or shared) or standby, depending on its priority. 135 * Link becomes active (alone or shared) or standby, depending on its priority.
147 */ 136 */
148void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 137
138void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr)
149{ 139{
150 struct tipc_link **active = &n_ptr->active_links[0]; 140 struct link **active = &n_ptr->active_links[0];
151 141
152 n_ptr->working_links++; 142 n_ptr->working_links++;
153 143
154 pr_info("Established link <%s> on network plane %c\n", 144 info("Established link <%s> on network plane %c\n",
155 l_ptr->name, l_ptr->b_ptr->net_plane); 145 l_ptr->name, l_ptr->b_ptr->net_plane);
156 146
157 if (!active[0]) { 147 if (!active[0]) {
158 active[0] = active[1] = l_ptr; 148 active[0] = active[1] = l_ptr;
@@ -160,7 +150,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
160 return; 150 return;
161 } 151 }
162 if (l_ptr->priority < active[0]->priority) { 152 if (l_ptr->priority < active[0]->priority) {
163 pr_info("New link <%s> becomes standby\n", l_ptr->name); 153 info("New link <%s> becomes standby\n", l_ptr->name);
164 return; 154 return;
165 } 155 }
166 tipc_link_send_duplicate(active[0], l_ptr); 156 tipc_link_send_duplicate(active[0], l_ptr);
@@ -168,25 +158,26 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
168 active[0] = l_ptr; 158 active[0] = l_ptr;
169 return; 159 return;
170 } 160 }
171 pr_info("Old link <%s> becomes standby\n", active[0]->name); 161 info("Old link <%s> becomes standby\n", active[0]->name);
172 if (active[1] != active[0]) 162 if (active[1] != active[0])
173 pr_info("Old link <%s> becomes standby\n", active[1]->name); 163 info("Old link <%s> becomes standby\n", active[1]->name);
174 active[0] = active[1] = l_ptr; 164 active[0] = active[1] = l_ptr;
175} 165}
176 166
177/** 167/**
178 * node_select_active_links - select active link 168 * node_select_active_links - select active link
179 */ 169 */
170
180static void node_select_active_links(struct tipc_node *n_ptr) 171static void node_select_active_links(struct tipc_node *n_ptr)
181{ 172{
182 struct tipc_link **active = &n_ptr->active_links[0]; 173 struct link **active = &n_ptr->active_links[0];
183 u32 i; 174 u32 i;
184 u32 highest_prio = 0; 175 u32 highest_prio = 0;
185 176
186 active[0] = active[1] = NULL; 177 active[0] = active[1] = NULL;
187 178
188 for (i = 0; i < MAX_BEARERS; i++) { 179 for (i = 0; i < MAX_BEARERS; i++) {
189 struct tipc_link *l_ptr = n_ptr->links[i]; 180 struct link *l_ptr = n_ptr->links[i];
190 181
191 if (!l_ptr || !tipc_link_is_up(l_ptr) || 182 if (!l_ptr || !tipc_link_is_up(l_ptr) ||
192 (l_ptr->priority < highest_prio)) 183 (l_ptr->priority < highest_prio))
@@ -204,18 +195,19 @@ static void node_select_active_links(struct tipc_node *n_ptr)
204/** 195/**
205 * tipc_node_link_down - handle loss of link 196 * tipc_node_link_down - handle loss of link
206 */ 197 */
207void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 198
199void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
208{ 200{
209 struct tipc_link **active; 201 struct link **active;
210 202
211 n_ptr->working_links--; 203 n_ptr->working_links--;
212 204
213 if (!tipc_link_is_active(l_ptr)) { 205 if (!tipc_link_is_active(l_ptr)) {
214 pr_info("Lost standby link <%s> on network plane %c\n", 206 info("Lost standby link <%s> on network plane %c\n",
215 l_ptr->name, l_ptr->b_ptr->net_plane); 207 l_ptr->name, l_ptr->b_ptr->net_plane);
216 return; 208 return;
217 } 209 }
218 pr_info("Lost link <%s> on network plane %c\n", 210 info("Lost link <%s> on network plane %c\n",
219 l_ptr->name, l_ptr->b_ptr->net_plane); 211 l_ptr->name, l_ptr->b_ptr->net_plane);
220 212
221 active = &n_ptr->active_links[0]; 213 active = &n_ptr->active_links[0];
@@ -246,29 +238,81 @@ int tipc_node_is_up(struct tipc_node *n_ptr)
246 return tipc_node_active_links(n_ptr); 238 return tipc_node_active_links(n_ptr);
247} 239}
248 240
249void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 241void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)
250{ 242{
251 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; 243 n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;
252 atomic_inc(&tipc_num_links); 244 atomic_inc(&tipc_num_links);
253 n_ptr->link_cnt++; 245 n_ptr->link_cnt++;
254} 246}
255 247
256void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 248void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
257{ 249{
258 n_ptr->links[l_ptr->b_ptr->identity] = NULL; 250 n_ptr->links[l_ptr->b_ptr->identity] = NULL;
259 atomic_dec(&tipc_num_links); 251 atomic_dec(&tipc_num_links);
260 n_ptr->link_cnt--; 252 n_ptr->link_cnt--;
261} 253}
262 254
255/*
256 * Routing table management - five cases to handle:
257 *
258 * 1: A link towards a zone/cluster external node comes up.
259 * => Send a multicast message updating routing tables of all
260 * system nodes within own cluster that the new destination
261 * can be reached via this node.
262 * (node.establishedContact()=>cluster.multicastNewRoute())
263 *
264 * 2: A link towards a slave node comes up.
265 * => Send a multicast message updating routing tables of all
266 * system nodes within own cluster that the new destination
267 * can be reached via this node.
268 * (node.establishedContact()=>cluster.multicastNewRoute())
269 * => Send a message to the slave node about existence
270 * of all system nodes within cluster:
271 * (node.establishedContact()=>cluster.sendLocalRoutes())
272 *
273 * 3: A new cluster local system node becomes available.
274 * => Send message(s) to this particular node containing
275 * information about all cluster external and slave
276 * nodes which can be reached via this node.
277 * (node.establishedContact()==>network.sendExternalRoutes())
278 * (node.establishedContact()==>network.sendSlaveRoutes())
279 * => Send messages to all directly connected slave nodes
280 * containing information about the existence of the new node
281 * (node.establishedContact()=>cluster.multicastNewRoute())
282 *
283 * 4: The link towards a zone/cluster external node or slave
284 * node goes down.
285 * => Send a multcast message updating routing tables of all
286 * nodes within cluster that the new destination can not any
287 * longer be reached via this node.
288 * (node.lostAllLinks()=>cluster.bcastLostRoute())
289 *
290 * 5: A cluster local system node becomes unavailable.
291 * => Remove all references to this node from the local
292 * routing tables. Note: This is a completely node
293 * local operation.
294 * (node.lostAllLinks()=>network.removeAsRouter())
295 * => Send messages to all directly connected slave nodes
296 * containing information about loss of the node
297 * (node.establishedContact()=>cluster.multicastLostRoute())
298 *
299 */
300
263static void node_established_contact(struct tipc_node *n_ptr) 301static void node_established_contact(struct tipc_node *n_ptr)
264{ 302{
265 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); 303 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
266 n_ptr->bclink.oos_state = 0; 304
305 /* Syncronize broadcast acks */
267 n_ptr->bclink.acked = tipc_bclink_get_last_sent(); 306 n_ptr->bclink.acked = tipc_bclink_get_last_sent();
268 tipc_bclink_add_node(n_ptr->addr); 307
308 if (n_ptr->bclink.supported) {
309 tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr);
310 if (n_ptr->addr < tipc_own_addr)
311 tipc_own_tag++;
312 }
269} 313}
270 314
271static void node_name_purge_complete(unsigned long node_addr) 315static void node_cleanup_finished(unsigned long node_addr)
272{ 316{
273 struct tipc_node *n_ptr; 317 struct tipc_node *n_ptr;
274 318
@@ -276,7 +320,7 @@ static void node_name_purge_complete(unsigned long node_addr)
276 n_ptr = tipc_node_find(node_addr); 320 n_ptr = tipc_node_find(node_addr);
277 if (n_ptr) { 321 if (n_ptr) {
278 tipc_node_lock(n_ptr); 322 tipc_node_lock(n_ptr);
279 n_ptr->block_setup &= ~WAIT_NAMES_GONE; 323 n_ptr->cleanup_required = 0;
280 tipc_node_unlock(n_ptr); 324 tipc_node_unlock(n_ptr);
281 } 325 }
282 read_unlock_bh(&tipc_net_lock); 326 read_unlock_bh(&tipc_net_lock);
@@ -287,32 +331,32 @@ static void node_lost_contact(struct tipc_node *n_ptr)
287 char addr_string[16]; 331 char addr_string[16];
288 u32 i; 332 u32 i;
289 333
290 pr_info("Lost contact with %s\n", 334 /* Clean up broadcast reception remains */
291 tipc_addr_string_fill(addr_string, n_ptr->addr)); 335 n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
292 336 while (n_ptr->bclink.deferred_head) {
293 /* Flush broadcast link info associated with lost node */ 337 struct sk_buff *buf = n_ptr->bclink.deferred_head;
294 if (n_ptr->bclink.recv_permitted) { 338 n_ptr->bclink.deferred_head = buf->next;
295 while (n_ptr->bclink.deferred_head) { 339 buf_discard(buf);
296 struct sk_buff *buf = n_ptr->bclink.deferred_head; 340 }
297 n_ptr->bclink.deferred_head = buf->next; 341 if (n_ptr->bclink.defragm) {
298 kfree_skb(buf); 342 buf_discard(n_ptr->bclink.defragm);
299 } 343 n_ptr->bclink.defragm = NULL;
300 n_ptr->bclink.deferred_size = 0; 344 }
301
302 if (n_ptr->bclink.defragm) {
303 kfree_skb(n_ptr->bclink.defragm);
304 n_ptr->bclink.defragm = NULL;
305 }
306
307 tipc_bclink_remove_node(n_ptr->addr);
308 tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
309 345
310 n_ptr->bclink.recv_permitted = false; 346 if (n_ptr->bclink.supported) {
347 tipc_bclink_acknowledge(n_ptr,
348 mod(n_ptr->bclink.acked + 10000));
349 tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr);
350 if (n_ptr->addr < tipc_own_addr)
351 tipc_own_tag--;
311 } 352 }
312 353
354 info("Lost contact with %s\n",
355 tipc_addr_string_fill(addr_string, n_ptr->addr));
356
313 /* Abort link changeover */ 357 /* Abort link changeover */
314 for (i = 0; i < MAX_BEARERS; i++) { 358 for (i = 0; i < MAX_BEARERS; i++) {
315 struct tipc_link *l_ptr = n_ptr->links[i]; 359 struct link *l_ptr = n_ptr->links[i];
316 if (!l_ptr) 360 if (!l_ptr)
317 continue; 361 continue;
318 l_ptr->reset_checkpoint = l_ptr->next_in_no; 362 l_ptr->reset_checkpoint = l_ptr->next_in_no;
@@ -323,9 +367,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
323 /* Notify subscribers */ 367 /* Notify subscribers */
324 tipc_nodesub_notify(n_ptr); 368 tipc_nodesub_notify(n_ptr);
325 369
326 /* Prevent re-contact with node until cleanup is done */ 370 /* Prevent re-contact with node until all cleanup is done */
327 n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE; 371
328 tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); 372 n_ptr->cleanup_required = 1;
373 tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
329} 374}
330 375
331struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) 376struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
@@ -351,6 +396,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
351 } 396 }
352 397
353 /* For now, get space for all other nodes */ 398 /* For now, get space for all other nodes */
399
354 payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; 400 payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
355 if (payload_size > 32768u) { 401 if (payload_size > 32768u) {
356 read_unlock_bh(&tipc_net_lock); 402 read_unlock_bh(&tipc_net_lock);
@@ -364,6 +410,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
364 } 410 }
365 411
366 /* Add TLVs for all nodes in scope */ 412 /* Add TLVs for all nodes in scope */
413
367 list_for_each_entry(n_ptr, &tipc_node_list, list) { 414 list_for_each_entry(n_ptr, &tipc_node_list, list) {
368 if (!tipc_in_scope(domain, n_ptr->addr)) 415 if (!tipc_in_scope(domain, n_ptr->addr))
369 continue; 416 continue;
@@ -393,12 +440,13 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
393 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 440 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
394 " (network address)"); 441 " (network address)");
395 442
396 if (!tipc_own_addr) 443 if (tipc_mode != TIPC_NET_MODE)
397 return tipc_cfg_reply_none(); 444 return tipc_cfg_reply_none();
398 445
399 read_lock_bh(&tipc_net_lock); 446 read_lock_bh(&tipc_net_lock);
400 447
401 /* Get space for all unicast links + broadcast link */ 448 /* Get space for all unicast links + multicast link */
449
402 payload_size = TLV_SPACE(sizeof(link_info)) * 450 payload_size = TLV_SPACE(sizeof(link_info)) *
403 (atomic_read(&tipc_num_links) + 1); 451 (atomic_read(&tipc_num_links) + 1);
404 if (payload_size > 32768u) { 452 if (payload_size > 32768u) {
@@ -413,12 +461,14 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
413 } 461 }
414 462
415 /* Add TLV for broadcast link */ 463 /* Add TLV for broadcast link */
464
416 link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); 465 link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
417 link_info.up = htonl(1); 466 link_info.up = htonl(1);
418 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); 467 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
419 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); 468 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
420 469
421 /* Add TLVs for any other links in scope */ 470 /* Add TLVs for any other links in scope */
471
422 list_for_each_entry(n_ptr, &tipc_node_list, list) { 472 list_for_each_entry(n_ptr, &tipc_node_list, list) {
423 u32 i; 473 u32 i;
424 474