diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-01-13 01:06:28 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-13 01:06:28 -0500 |
commit | f43dc23d5ea91fca257be02138a255f02d98e806 (patch) | |
tree | b29722f6e965316e90ac97abf79923ced250dc21 /net/tipc/node.c | |
parent | f8e53553f452dcbf67cb89c8cba63a1cd6eb4cc0 (diff) | |
parent | 4162cf64973df51fc885825bc9ca4d055891c49f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into common/serial-rework
Conflicts:
arch/sh/kernel/cpu/sh2/setup-sh7619.c
arch/sh/kernel/cpu/sh2a/setup-mxg.c
arch/sh/kernel/cpu/sh2a/setup-sh7201.c
arch/sh/kernel/cpu/sh2a/setup-sh7203.c
arch/sh/kernel/cpu/sh2a/setup-sh7206.c
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sh/kernel/cpu/sh3/setup-sh7710.c
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4/setup-sh4-202.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4a/setup-sh7343.c
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7770.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/cpu/sh4a/setup-shx3.c
arch/sh/kernel/cpu/sh5/setup-sh5.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
include/linux/serial_sci.h
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 368 |
1 files changed, 69 insertions, 299 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2c24e7d6d950..3af53e327f49 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -37,24 +37,14 @@ | |||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "config.h" | 38 | #include "config.h" |
39 | #include "node.h" | 39 | #include "node.h" |
40 | #include "cluster.h" | ||
41 | #include "net.h" | ||
42 | #include "addr.h" | ||
43 | #include "node_subscr.h" | ||
44 | #include "link.h" | ||
45 | #include "port.h" | ||
46 | #include "bearer.h" | ||
47 | #include "name_distr.h" | 40 | #include "name_distr.h" |
48 | 41 | ||
49 | void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str); | ||
50 | static void node_lost_contact(struct tipc_node *n_ptr); | 42 | static void node_lost_contact(struct tipc_node *n_ptr); |
51 | static void node_established_contact(struct tipc_node *n_ptr); | 43 | static void node_established_contact(struct tipc_node *n_ptr); |
52 | 44 | ||
53 | struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ | ||
54 | |||
55 | static DEFINE_SPINLOCK(node_create_lock); | 45 | static DEFINE_SPINLOCK(node_create_lock); |
56 | 46 | ||
57 | u32 tipc_own_tag = 0; | 47 | u32 tipc_own_tag; |
58 | 48 | ||
59 | /** | 49 | /** |
60 | * tipc_node_create - create neighboring node | 50 | * tipc_node_create - create neighboring node |
@@ -68,75 +58,51 @@ u32 tipc_own_tag = 0; | |||
68 | 58 | ||
69 | struct tipc_node *tipc_node_create(u32 addr) | 59 | struct tipc_node *tipc_node_create(u32 addr) |
70 | { | 60 | { |
71 | struct cluster *c_ptr; | ||
72 | struct tipc_node *n_ptr; | 61 | struct tipc_node *n_ptr; |
73 | struct tipc_node **curr_node; | 62 | u32 n_num; |
74 | 63 | ||
75 | spin_lock_bh(&node_create_lock); | 64 | spin_lock_bh(&node_create_lock); |
76 | 65 | ||
77 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 66 | n_ptr = tipc_node_find(addr); |
78 | if (addr < n_ptr->addr) | 67 | if (n_ptr) { |
79 | break; | 68 | spin_unlock_bh(&node_create_lock); |
80 | if (addr == n_ptr->addr) { | 69 | return n_ptr; |
81 | spin_unlock_bh(&node_create_lock); | ||
82 | return n_ptr; | ||
83 | } | ||
84 | } | 70 | } |
85 | 71 | ||
86 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); | 72 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); |
87 | if (!n_ptr) { | 73 | if (!n_ptr) { |
88 | spin_unlock_bh(&node_create_lock); | 74 | spin_unlock_bh(&node_create_lock); |
89 | warn("Node creation failed, no memory\n"); | 75 | warn("Node creation failed, no memory\n"); |
90 | return NULL; | 76 | return NULL; |
91 | } | 77 | } |
92 | 78 | ||
93 | c_ptr = tipc_cltr_find(addr); | ||
94 | if (!c_ptr) { | ||
95 | c_ptr = tipc_cltr_create(addr); | ||
96 | } | ||
97 | if (!c_ptr) { | ||
98 | spin_unlock_bh(&node_create_lock); | ||
99 | kfree(n_ptr); | ||
100 | return NULL; | ||
101 | } | ||
102 | |||
103 | n_ptr->addr = addr; | 79 | n_ptr->addr = addr; |
104 | spin_lock_init(&n_ptr->lock); | 80 | spin_lock_init(&n_ptr->lock); |
105 | INIT_LIST_HEAD(&n_ptr->nsub); | 81 | INIT_LIST_HEAD(&n_ptr->nsub); |
106 | n_ptr->owner = c_ptr; | 82 | |
107 | tipc_cltr_attach_node(c_ptr, n_ptr); | 83 | n_num = tipc_node(addr); |
108 | n_ptr->last_router = -1; | 84 | tipc_net.nodes[n_num] = n_ptr; |
109 | 85 | if (n_num > tipc_net.highest_node) | |
110 | /* Insert node into ordered list */ | 86 | tipc_net.highest_node = n_num; |
111 | for (curr_node = &tipc_nodes; *curr_node; | 87 | |
112 | curr_node = &(*curr_node)->next) { | ||
113 | if (addr < (*curr_node)->addr) { | ||
114 | n_ptr->next = *curr_node; | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | (*curr_node) = n_ptr; | ||
119 | spin_unlock_bh(&node_create_lock); | 88 | spin_unlock_bh(&node_create_lock); |
120 | return n_ptr; | 89 | return n_ptr; |
121 | } | 90 | } |
122 | 91 | ||
123 | void tipc_node_delete(struct tipc_node *n_ptr) | 92 | void tipc_node_delete(struct tipc_node *n_ptr) |
124 | { | 93 | { |
94 | u32 n_num; | ||
95 | |||
125 | if (!n_ptr) | 96 | if (!n_ptr) |
126 | return; | 97 | return; |
127 | 98 | ||
128 | #if 0 | 99 | n_num = tipc_node(n_ptr->addr); |
129 | /* Not needed because links are already deleted via tipc_bearer_stop() */ | 100 | tipc_net.nodes[n_num] = NULL; |
130 | |||
131 | u32 l_num; | ||
132 | |||
133 | for (l_num = 0; l_num < MAX_BEARERS; l_num++) { | ||
134 | link_delete(n_ptr->links[l_num]); | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | dbg("node %x deleted\n", n_ptr->addr); | ||
139 | kfree(n_ptr); | 101 | kfree(n_ptr); |
102 | |||
103 | while (!tipc_net.nodes[tipc_net.highest_node]) | ||
104 | if (--tipc_net.highest_node == 0) | ||
105 | break; | ||
140 | } | 106 | } |
141 | 107 | ||
142 | 108 | ||
@@ -156,7 +122,6 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr) | |||
156 | l_ptr->name, l_ptr->b_ptr->net_plane); | 122 | l_ptr->name, l_ptr->b_ptr->net_plane); |
157 | 123 | ||
158 | if (!active[0]) { | 124 | if (!active[0]) { |
159 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
160 | active[0] = active[1] = l_ptr; | 125 | active[0] = active[1] = l_ptr; |
161 | node_established_contact(n_ptr); | 126 | node_established_contact(n_ptr); |
162 | return; | 127 | return; |
@@ -237,23 +202,17 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) | |||
237 | 202 | ||
238 | int tipc_node_has_active_links(struct tipc_node *n_ptr) | 203 | int tipc_node_has_active_links(struct tipc_node *n_ptr) |
239 | { | 204 | { |
240 | return (n_ptr && | 205 | return n_ptr->active_links[0] != NULL; |
241 | ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); | ||
242 | } | 206 | } |
243 | 207 | ||
244 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr) | 208 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr) |
245 | { | 209 | { |
246 | return (n_ptr->working_links > 1); | 210 | return n_ptr->working_links > 1; |
247 | } | ||
248 | |||
249 | static int tipc_node_has_active_routes(struct tipc_node *n_ptr) | ||
250 | { | ||
251 | return (n_ptr && (n_ptr->last_router >= 0)); | ||
252 | } | 211 | } |
253 | 212 | ||
254 | int tipc_node_is_up(struct tipc_node *n_ptr) | 213 | int tipc_node_is_up(struct tipc_node *n_ptr) |
255 | { | 214 | { |
256 | return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr)); | 215 | return tipc_node_has_active_links(n_ptr); |
257 | } | 216 | } |
258 | 217 | ||
259 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | 218 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) |
@@ -268,19 +227,19 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
268 | 227 | ||
269 | if (n_ptr->link_cnt >= 2) { | 228 | if (n_ptr->link_cnt >= 2) { |
270 | err("Attempt to create third link to %s\n", | 229 | err("Attempt to create third link to %s\n", |
271 | addr_string_fill(addr_string, n_ptr->addr)); | 230 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
272 | return NULL; | 231 | return NULL; |
273 | } | 232 | } |
274 | 233 | ||
275 | if (!n_ptr->links[bearer_id]) { | 234 | if (!n_ptr->links[bearer_id]) { |
276 | n_ptr->links[bearer_id] = l_ptr; | 235 | n_ptr->links[bearer_id] = l_ptr; |
277 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; | 236 | tipc_net.links++; |
278 | n_ptr->link_cnt++; | 237 | n_ptr->link_cnt++; |
279 | return n_ptr; | 238 | return n_ptr; |
280 | } | 239 | } |
281 | err("Attempt to establish second link on <%s> to %s \n", | 240 | err("Attempt to establish second link on <%s> to %s\n", |
282 | l_ptr->b_ptr->publ.name, | 241 | l_ptr->b_ptr->publ.name, |
283 | addr_string_fill(addr_string, l_ptr->addr)); | 242 | tipc_addr_string_fill(addr_string, l_ptr->addr)); |
284 | } | 243 | } |
285 | return NULL; | 244 | return NULL; |
286 | } | 245 | } |
@@ -288,7 +247,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
288 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | 247 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) |
289 | { | 248 | { |
290 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; | 249 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; |
291 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; | 250 | tipc_net.links--; |
292 | n_ptr->link_cnt--; | 251 | n_ptr->link_cnt--; |
293 | } | 252 | } |
294 | 253 | ||
@@ -340,53 +299,34 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | |||
340 | 299 | ||
341 | static void node_established_contact(struct tipc_node *n_ptr) | 300 | static void node_established_contact(struct tipc_node *n_ptr) |
342 | { | 301 | { |
343 | struct cluster *c_ptr; | 302 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); |
344 | |||
345 | dbg("node_established_contact:-> %x\n", n_ptr->addr); | ||
346 | if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { | ||
347 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); | ||
348 | } | ||
349 | 303 | ||
350 | /* Syncronize broadcast acks */ | 304 | /* Syncronize broadcast acks */ |
351 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); | 305 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); |
352 | 306 | ||
353 | if (is_slave(tipc_own_addr)) | ||
354 | return; | ||
355 | if (!in_own_cluster(n_ptr->addr)) { | ||
356 | /* Usage case 1 (see above) */ | ||
357 | c_ptr = tipc_cltr_find(tipc_own_addr); | ||
358 | if (!c_ptr) | ||
359 | c_ptr = tipc_cltr_create(tipc_own_addr); | ||
360 | if (c_ptr) | ||
361 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, | ||
362 | tipc_max_nodes); | ||
363 | return; | ||
364 | } | ||
365 | |||
366 | c_ptr = n_ptr->owner; | ||
367 | if (is_slave(n_ptr->addr)) { | ||
368 | /* Usage case 2 (see above) */ | ||
369 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); | ||
370 | tipc_cltr_send_local_routes(c_ptr, n_ptr->addr); | ||
371 | return; | ||
372 | } | ||
373 | |||
374 | if (n_ptr->bclink.supported) { | 307 | if (n_ptr->bclink.supported) { |
375 | tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); | 308 | tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); |
376 | if (n_ptr->addr < tipc_own_addr) | 309 | if (n_ptr->addr < tipc_own_addr) |
377 | tipc_own_tag++; | 310 | tipc_own_tag++; |
378 | } | 311 | } |
312 | } | ||
379 | 313 | ||
380 | /* Case 3 (see above) */ | 314 | static void node_cleanup_finished(unsigned long node_addr) |
381 | tipc_net_send_external_routes(n_ptr->addr); | 315 | { |
382 | tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); | 316 | struct tipc_node *n_ptr; |
383 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, | 317 | |
384 | tipc_highest_allowed_slave); | 318 | read_lock_bh(&tipc_net_lock); |
319 | n_ptr = tipc_node_find(node_addr); | ||
320 | if (n_ptr) { | ||
321 | tipc_node_lock(n_ptr); | ||
322 | n_ptr->cleanup_required = 0; | ||
323 | tipc_node_unlock(n_ptr); | ||
324 | } | ||
325 | read_unlock_bh(&tipc_net_lock); | ||
385 | } | 326 | } |
386 | 327 | ||
387 | static void node_lost_contact(struct tipc_node *n_ptr) | 328 | static void node_lost_contact(struct tipc_node *n_ptr) |
388 | { | 329 | { |
389 | struct cluster *c_ptr; | ||
390 | struct tipc_node_subscr *ns, *tns; | 330 | struct tipc_node_subscr *ns, *tns; |
391 | char addr_string[16]; | 331 | char addr_string[16]; |
392 | u32 i; | 332 | u32 i; |
@@ -394,7 +334,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
394 | /* Clean up broadcast reception remains */ | 334 | /* Clean up broadcast reception remains */ |
395 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | 335 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; |
396 | while (n_ptr->bclink.deferred_head) { | 336 | while (n_ptr->bclink.deferred_head) { |
397 | struct sk_buff* buf = n_ptr->bclink.deferred_head; | 337 | struct sk_buff *buf = n_ptr->bclink.deferred_head; |
398 | n_ptr->bclink.deferred_head = buf->next; | 338 | n_ptr->bclink.deferred_head = buf->next; |
399 | buf_discard(buf); | 339 | buf_discard(buf); |
400 | } | 340 | } |
@@ -402,44 +342,17 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
402 | buf_discard(n_ptr->bclink.defragm); | 342 | buf_discard(n_ptr->bclink.defragm); |
403 | n_ptr->bclink.defragm = NULL; | 343 | n_ptr->bclink.defragm = NULL; |
404 | } | 344 | } |
405 | if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { | ||
406 | tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); | ||
407 | } | ||
408 | 345 | ||
409 | /* Update routing tables */ | 346 | if (n_ptr->bclink.supported) { |
410 | if (is_slave(tipc_own_addr)) { | 347 | tipc_bclink_acknowledge(n_ptr, |
411 | tipc_net_remove_as_router(n_ptr->addr); | 348 | mod(n_ptr->bclink.acked + 10000)); |
412 | } else { | 349 | tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr); |
413 | if (!in_own_cluster(n_ptr->addr)) { | 350 | if (n_ptr->addr < tipc_own_addr) |
414 | /* Case 4 (see above) */ | 351 | tipc_own_tag--; |
415 | c_ptr = tipc_cltr_find(tipc_own_addr); | ||
416 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
417 | tipc_max_nodes); | ||
418 | } else { | ||
419 | /* Case 5 (see above) */ | ||
420 | c_ptr = tipc_cltr_find(n_ptr->addr); | ||
421 | if (is_slave(n_ptr->addr)) { | ||
422 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
423 | tipc_max_nodes); | ||
424 | } else { | ||
425 | if (n_ptr->bclink.supported) { | ||
426 | tipc_nmap_remove(&tipc_cltr_bcast_nodes, | ||
427 | n_ptr->addr); | ||
428 | if (n_ptr->addr < tipc_own_addr) | ||
429 | tipc_own_tag--; | ||
430 | } | ||
431 | tipc_net_remove_as_router(n_ptr->addr); | ||
432 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, | ||
433 | LOWEST_SLAVE, | ||
434 | tipc_highest_allowed_slave); | ||
435 | } | ||
436 | } | ||
437 | } | 352 | } |
438 | if (tipc_node_has_active_routes(n_ptr)) | ||
439 | return; | ||
440 | 353 | ||
441 | info("Lost contact with %s\n", | 354 | info("Lost contact with %s\n", |
442 | addr_string_fill(addr_string, n_ptr->addr)); | 355 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
443 | 356 | ||
444 | /* Abort link changeover */ | 357 | /* Abort link changeover */ |
445 | for (i = 0; i < MAX_BEARERS; i++) { | 358 | for (i = 0; i < MAX_BEARERS; i++) { |
@@ -458,157 +371,11 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
458 | tipc_k_signal((Handler)ns->handle_node_down, | 371 | tipc_k_signal((Handler)ns->handle_node_down, |
459 | (unsigned long)ns->usr_handle); | 372 | (unsigned long)ns->usr_handle); |
460 | } | 373 | } |
461 | } | ||
462 | 374 | ||
463 | /** | 375 | /* Prevent re-contact with node until all cleanup is done */ |
464 | * tipc_node_select_next_hop - find the next-hop node for a message | ||
465 | * | ||
466 | * Called by when cluster local lookup has failed. | ||
467 | */ | ||
468 | 376 | ||
469 | struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector) | 377 | n_ptr->cleanup_required = 1; |
470 | { | 378 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); |
471 | struct tipc_node *n_ptr; | ||
472 | u32 router_addr; | ||
473 | |||
474 | if (!tipc_addr_domain_valid(addr)) | ||
475 | return NULL; | ||
476 | |||
477 | /* Look for direct link to destination processsor */ | ||
478 | n_ptr = tipc_node_find(addr); | ||
479 | if (n_ptr && tipc_node_has_active_links(n_ptr)) | ||
480 | return n_ptr; | ||
481 | |||
482 | /* Cluster local system nodes *must* have direct links */ | ||
483 | if (!is_slave(addr) && in_own_cluster(addr)) | ||
484 | return NULL; | ||
485 | |||
486 | /* Look for cluster local router with direct link to node */ | ||
487 | router_addr = tipc_node_select_router(n_ptr, selector); | ||
488 | if (router_addr) | ||
489 | return tipc_node_select(router_addr, selector); | ||
490 | |||
491 | /* Slave nodes can only be accessed within own cluster via a | ||
492 | known router with direct link -- if no router was found,give up */ | ||
493 | if (is_slave(addr)) | ||
494 | return NULL; | ||
495 | |||
496 | /* Inter zone/cluster -- find any direct link to remote cluster */ | ||
497 | addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
498 | n_ptr = tipc_net_select_remote_node(addr, selector); | ||
499 | if (n_ptr && tipc_node_has_active_links(n_ptr)) | ||
500 | return n_ptr; | ||
501 | |||
502 | /* Last resort -- look for any router to anywhere in remote zone */ | ||
503 | router_addr = tipc_net_select_router(addr, selector); | ||
504 | if (router_addr) | ||
505 | return tipc_node_select(router_addr, selector); | ||
506 | |||
507 | return NULL; | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * tipc_node_select_router - select router to reach specified node | ||
512 | * | ||
513 | * Uses a deterministic and fair algorithm for selecting router node. | ||
514 | */ | ||
515 | |||
516 | u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref) | ||
517 | { | ||
518 | u32 ulim; | ||
519 | u32 mask; | ||
520 | u32 start; | ||
521 | u32 r; | ||
522 | |||
523 | if (!n_ptr) | ||
524 | return 0; | ||
525 | |||
526 | if (n_ptr->last_router < 0) | ||
527 | return 0; | ||
528 | ulim = ((n_ptr->last_router + 1) * 32) - 1; | ||
529 | |||
530 | /* Start entry must be random */ | ||
531 | mask = tipc_max_nodes; | ||
532 | while (mask > ulim) | ||
533 | mask >>= 1; | ||
534 | start = ref & mask; | ||
535 | r = start; | ||
536 | |||
537 | /* Lookup upwards with wrap-around */ | ||
538 | do { | ||
539 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
540 | break; | ||
541 | } while (++r <= ulim); | ||
542 | if (r > ulim) { | ||
543 | r = 1; | ||
544 | do { | ||
545 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
546 | break; | ||
547 | } while (++r < start); | ||
548 | assert(r != start); | ||
549 | } | ||
550 | assert(r && (r <= ulim)); | ||
551 | return tipc_addr(own_zone(), own_cluster(), r); | ||
552 | } | ||
553 | |||
554 | void tipc_node_add_router(struct tipc_node *n_ptr, u32 router) | ||
555 | { | ||
556 | u32 r_num = tipc_node(router); | ||
557 | |||
558 | n_ptr->routers[r_num / 32] = | ||
559 | ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); | ||
560 | n_ptr->last_router = tipc_max_nodes / 32; | ||
561 | while ((--n_ptr->last_router >= 0) && | ||
562 | !n_ptr->routers[n_ptr->last_router]); | ||
563 | } | ||
564 | |||
565 | void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router) | ||
566 | { | ||
567 | u32 r_num = tipc_node(router); | ||
568 | |||
569 | if (n_ptr->last_router < 0) | ||
570 | return; /* No routes */ | ||
571 | |||
572 | n_ptr->routers[r_num / 32] = | ||
573 | ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); | ||
574 | n_ptr->last_router = tipc_max_nodes / 32; | ||
575 | while ((--n_ptr->last_router >= 0) && | ||
576 | !n_ptr->routers[n_ptr->last_router]); | ||
577 | |||
578 | if (!tipc_node_is_up(n_ptr)) | ||
579 | node_lost_contact(n_ptr); | ||
580 | } | ||
581 | |||
582 | #if 0 | ||
583 | void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str) | ||
584 | { | ||
585 | u32 i; | ||
586 | |||
587 | tipc_printf(buf, "\n\n%s", str); | ||
588 | for (i = 0; i < MAX_BEARERS; i++) { | ||
589 | if (!n_ptr->links[i]) | ||
590 | continue; | ||
591 | tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); | ||
592 | } | ||
593 | tipc_printf(buf, "Active links: [%x,%x]\n", | ||
594 | n_ptr->active_links[0], n_ptr->active_links[1]); | ||
595 | } | ||
596 | #endif | ||
597 | |||
598 | u32 tipc_available_nodes(const u32 domain) | ||
599 | { | ||
600 | struct tipc_node *n_ptr; | ||
601 | u32 cnt = 0; | ||
602 | |||
603 | read_lock_bh(&tipc_net_lock); | ||
604 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | ||
605 | if (!in_scope(domain, n_ptr->addr)) | ||
606 | continue; | ||
607 | if (tipc_node_is_up(n_ptr)) | ||
608 | cnt++; | ||
609 | } | ||
610 | read_unlock_bh(&tipc_net_lock); | ||
611 | return cnt; | ||
612 | } | 379 | } |
613 | 380 | ||
614 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | 381 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) |
@@ -618,6 +385,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
618 | struct tipc_node *n_ptr; | 385 | struct tipc_node *n_ptr; |
619 | struct tipc_node_info node_info; | 386 | struct tipc_node_info node_info; |
620 | u32 payload_size; | 387 | u32 payload_size; |
388 | u32 n_num; | ||
621 | 389 | ||
622 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | 390 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
623 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 391 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
@@ -628,15 +396,15 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
628 | " (network address)"); | 396 | " (network address)"); |
629 | 397 | ||
630 | read_lock_bh(&tipc_net_lock); | 398 | read_lock_bh(&tipc_net_lock); |
631 | if (!tipc_nodes) { | 399 | if (!tipc_net.nodes) { |
632 | read_unlock_bh(&tipc_net_lock); | 400 | read_unlock_bh(&tipc_net_lock); |
633 | return tipc_cfg_reply_none(); | 401 | return tipc_cfg_reply_none(); |
634 | } | 402 | } |
635 | 403 | ||
636 | /* For now, get space for all other nodes | 404 | /* For now, get space for all other nodes */ |
637 | (will need to modify this when slave nodes are supported */ | ||
638 | 405 | ||
639 | payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); | 406 | payload_size = TLV_SPACE(sizeof(node_info)) * |
407 | (tipc_net.highest_node - 1); | ||
640 | if (payload_size > 32768u) { | 408 | if (payload_size > 32768u) { |
641 | read_unlock_bh(&tipc_net_lock); | 409 | read_unlock_bh(&tipc_net_lock); |
642 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 410 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -650,8 +418,9 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
650 | 418 | ||
651 | /* Add TLVs for all nodes in scope */ | 419 | /* Add TLVs for all nodes in scope */ |
652 | 420 | ||
653 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 421 | for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { |
654 | if (!in_scope(domain, n_ptr->addr)) | 422 | n_ptr = tipc_net.nodes[n_num]; |
423 | if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) | ||
655 | continue; | 424 | continue; |
656 | node_info.addr = htonl(n_ptr->addr); | 425 | node_info.addr = htonl(n_ptr->addr); |
657 | node_info.up = htonl(tipc_node_is_up(n_ptr)); | 426 | node_info.up = htonl(tipc_node_is_up(n_ptr)); |
@@ -670,6 +439,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
670 | struct tipc_node *n_ptr; | 439 | struct tipc_node *n_ptr; |
671 | struct tipc_link_info link_info; | 440 | struct tipc_link_info link_info; |
672 | u32 payload_size; | 441 | u32 payload_size; |
442 | u32 n_num; | ||
673 | 443 | ||
674 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | 444 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
675 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 445 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
@@ -686,8 +456,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
686 | 456 | ||
687 | /* Get space for all unicast links + multicast link */ | 457 | /* Get space for all unicast links + multicast link */ |
688 | 458 | ||
689 | payload_size = TLV_SPACE(sizeof(link_info)) * | 459 | payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1); |
690 | (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); | ||
691 | if (payload_size > 32768u) { | 460 | if (payload_size > 32768u) { |
692 | read_unlock_bh(&tipc_net_lock); | 461 | read_unlock_bh(&tipc_net_lock); |
693 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 462 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -708,10 +477,11 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
708 | 477 | ||
709 | /* Add TLVs for any other links in scope */ | 478 | /* Add TLVs for any other links in scope */ |
710 | 479 | ||
711 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 480 | for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) { |
712 | u32 i; | 481 | u32 i; |
713 | 482 | ||
714 | if (!in_scope(domain, n_ptr->addr)) | 483 | n_ptr = tipc_net.nodes[n_num]; |
484 | if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr)) | ||
715 | continue; | 485 | continue; |
716 | tipc_node_lock(n_ptr); | 486 | tipc_node_lock(n_ptr); |
717 | for (i = 0; i < MAX_BEARERS; i++) { | 487 | for (i = 0; i < MAX_BEARERS; i++) { |