diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 362 |
1 files changed, 73 insertions, 289 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index b4d87eb2dc5d..2d106ef4fa4c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -2,7 +2,7 @@ | |||
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, Ericsson AB | 4 | * Copyright (c) 2000-2006, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -37,25 +37,38 @@ | |||
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 | /* sorted list of nodes within cluster */ | ||
54 | static struct tipc_node *tipc_nodes = NULL; | ||
55 | |||
56 | static DEFINE_SPINLOCK(node_create_lock); | 45 | static DEFINE_SPINLOCK(node_create_lock); |
57 | 46 | ||
58 | u32 tipc_own_tag = 0; | 47 | static struct hlist_head node_htable[NODE_HTABLE_SIZE]; |
48 | LIST_HEAD(tipc_node_list); | ||
49 | static u32 tipc_num_nodes; | ||
50 | |||
51 | static atomic_t tipc_num_links = ATOMIC_INIT(0); | ||
52 | u32 tipc_own_tag; | ||
53 | |||
54 | /** | ||
55 | * tipc_node_find - locate specified node object, if it exists | ||
56 | */ | ||
57 | |||
58 | struct tipc_node *tipc_node_find(u32 addr) | ||
59 | { | ||
60 | struct tipc_node *node; | ||
61 | struct hlist_node *pos; | ||
62 | |||
63 | if (unlikely(!in_own_cluster(addr))) | ||
64 | return NULL; | ||
65 | |||
66 | hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) { | ||
67 | if (node->addr == addr) | ||
68 | return node; | ||
69 | } | ||
70 | return NULL; | ||
71 | } | ||
59 | 72 | ||
60 | /** | 73 | /** |
61 | * tipc_node_create - create neighboring node | 74 | * tipc_node_create - create neighboring node |
@@ -69,65 +82,50 @@ u32 tipc_own_tag = 0; | |||
69 | 82 | ||
70 | struct tipc_node *tipc_node_create(u32 addr) | 83 | struct tipc_node *tipc_node_create(u32 addr) |
71 | { | 84 | { |
72 | struct cluster *c_ptr; | 85 | struct tipc_node *n_ptr, *temp_node; |
73 | struct tipc_node *n_ptr; | ||
74 | struct tipc_node **curr_node; | ||
75 | 86 | ||
76 | spin_lock_bh(&node_create_lock); | 87 | spin_lock_bh(&node_create_lock); |
77 | 88 | ||
78 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 89 | n_ptr = tipc_node_find(addr); |
79 | if (addr < n_ptr->addr) | 90 | if (n_ptr) { |
80 | break; | 91 | spin_unlock_bh(&node_create_lock); |
81 | if (addr == n_ptr->addr) { | 92 | return n_ptr; |
82 | spin_unlock_bh(&node_create_lock); | ||
83 | return n_ptr; | ||
84 | } | ||
85 | } | 93 | } |
86 | 94 | ||
87 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); | 95 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); |
88 | if (!n_ptr) { | 96 | if (!n_ptr) { |
89 | spin_unlock_bh(&node_create_lock); | 97 | spin_unlock_bh(&node_create_lock); |
90 | warn("Node creation failed, no memory\n"); | 98 | warn("Node creation failed, no memory\n"); |
91 | return NULL; | 99 | return NULL; |
92 | } | 100 | } |
93 | 101 | ||
94 | c_ptr = tipc_cltr_find(addr); | ||
95 | if (!c_ptr) { | ||
96 | c_ptr = tipc_cltr_create(addr); | ||
97 | } | ||
98 | if (!c_ptr) { | ||
99 | spin_unlock_bh(&node_create_lock); | ||
100 | kfree(n_ptr); | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | n_ptr->addr = addr; | 102 | n_ptr->addr = addr; |
105 | spin_lock_init(&n_ptr->lock); | 103 | spin_lock_init(&n_ptr->lock); |
104 | INIT_HLIST_NODE(&n_ptr->hash); | ||
105 | INIT_LIST_HEAD(&n_ptr->list); | ||
106 | INIT_LIST_HEAD(&n_ptr->nsub); | 106 | INIT_LIST_HEAD(&n_ptr->nsub); |
107 | n_ptr->owner = c_ptr; | 107 | |
108 | tipc_cltr_attach_node(c_ptr, n_ptr); | 108 | hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
109 | n_ptr->last_router = -1; | 109 | |
110 | 110 | list_for_each_entry(temp_node, &tipc_node_list, list) { | |
111 | /* Insert node into ordered list */ | 111 | if (n_ptr->addr < temp_node->addr) |
112 | for (curr_node = &tipc_nodes; *curr_node; | ||
113 | curr_node = &(*curr_node)->next) { | ||
114 | if (addr < (*curr_node)->addr) { | ||
115 | n_ptr->next = *curr_node; | ||
116 | break; | 112 | break; |
117 | } | ||
118 | } | 113 | } |
119 | (*curr_node) = n_ptr; | 114 | list_add_tail(&n_ptr->list, &temp_node->list); |
115 | |||
116 | tipc_num_nodes++; | ||
117 | |||
120 | spin_unlock_bh(&node_create_lock); | 118 | spin_unlock_bh(&node_create_lock); |
121 | return n_ptr; | 119 | return n_ptr; |
122 | } | 120 | } |
123 | 121 | ||
124 | void tipc_node_delete(struct tipc_node *n_ptr) | 122 | void tipc_node_delete(struct tipc_node *n_ptr) |
125 | { | 123 | { |
126 | if (!n_ptr) | 124 | list_del(&n_ptr->list); |
127 | return; | 125 | hlist_del(&n_ptr->hash); |
128 | |||
129 | dbg("node %x deleted\n", n_ptr->addr); | ||
130 | kfree(n_ptr); | 126 | kfree(n_ptr); |
127 | |||
128 | tipc_num_nodes--; | ||
131 | } | 129 | } |
132 | 130 | ||
133 | 131 | ||
@@ -147,7 +145,6 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr) | |||
147 | l_ptr->name, l_ptr->b_ptr->net_plane); | 145 | l_ptr->name, l_ptr->b_ptr->net_plane); |
148 | 146 | ||
149 | if (!active[0]) { | 147 | if (!active[0]) { |
150 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
151 | active[0] = active[1] = l_ptr; | 148 | active[0] = active[1] = l_ptr; |
152 | node_established_contact(n_ptr); | 149 | node_established_contact(n_ptr); |
153 | return; | 150 | return; |
@@ -226,59 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) | |||
226 | node_lost_contact(n_ptr); | 223 | node_lost_contact(n_ptr); |
227 | } | 224 | } |
228 | 225 | ||
229 | int tipc_node_has_active_links(struct tipc_node *n_ptr) | 226 | int tipc_node_active_links(struct tipc_node *n_ptr) |
230 | { | 227 | { |
231 | return n_ptr->active_links[0] != NULL; | 228 | return n_ptr->active_links[0] != NULL; |
232 | } | 229 | } |
233 | 230 | ||
234 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr) | 231 | int tipc_node_redundant_links(struct tipc_node *n_ptr) |
235 | { | 232 | { |
236 | return n_ptr->working_links > 1; | 233 | return n_ptr->working_links > 1; |
237 | } | 234 | } |
238 | 235 | ||
239 | static int tipc_node_has_active_routes(struct tipc_node *n_ptr) | ||
240 | { | ||
241 | return n_ptr && (n_ptr->last_router >= 0); | ||
242 | } | ||
243 | |||
244 | int tipc_node_is_up(struct tipc_node *n_ptr) | 236 | int tipc_node_is_up(struct tipc_node *n_ptr) |
245 | { | 237 | { |
246 | return tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr); | 238 | return tipc_node_active_links(n_ptr); |
247 | } | 239 | } |
248 | 240 | ||
249 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | 241 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr) |
250 | { | 242 | { |
251 | struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); | 243 | n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; |
252 | 244 | atomic_inc(&tipc_num_links); | |
253 | if (!n_ptr) | 245 | n_ptr->link_cnt++; |
254 | n_ptr = tipc_node_create(l_ptr->addr); | ||
255 | if (n_ptr) { | ||
256 | u32 bearer_id = l_ptr->b_ptr->identity; | ||
257 | char addr_string[16]; | ||
258 | |||
259 | if (n_ptr->link_cnt >= 2) { | ||
260 | err("Attempt to create third link to %s\n", | ||
261 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | ||
262 | return NULL; | ||
263 | } | ||
264 | |||
265 | if (!n_ptr->links[bearer_id]) { | ||
266 | n_ptr->links[bearer_id] = l_ptr; | ||
267 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; | ||
268 | n_ptr->link_cnt++; | ||
269 | return n_ptr; | ||
270 | } | ||
271 | err("Attempt to establish second link on <%s> to %s\n", | ||
272 | l_ptr->b_ptr->publ.name, | ||
273 | tipc_addr_string_fill(addr_string, l_ptr->addr)); | ||
274 | } | ||
275 | return NULL; | ||
276 | } | 246 | } |
277 | 247 | ||
278 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | 248 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) |
279 | { | 249 | { |
280 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; | 250 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; |
281 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; | 251 | atomic_dec(&tipc_num_links); |
282 | n_ptr->link_cnt--; | 252 | n_ptr->link_cnt--; |
283 | } | 253 | } |
284 | 254 | ||
@@ -330,48 +300,16 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | |||
330 | 300 | ||
331 | static void node_established_contact(struct tipc_node *n_ptr) | 301 | static void node_established_contact(struct tipc_node *n_ptr) |
332 | { | 302 | { |
333 | struct cluster *c_ptr; | 303 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); |
334 | |||
335 | dbg("node_established_contact:-> %x\n", n_ptr->addr); | ||
336 | if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { | ||
337 | tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); | ||
338 | } | ||
339 | 304 | ||
340 | /* Syncronize broadcast acks */ | 305 | /* Syncronize broadcast acks */ |
341 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); | 306 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); |
342 | 307 | ||
343 | if (is_slave(tipc_own_addr)) | ||
344 | return; | ||
345 | if (!in_own_cluster(n_ptr->addr)) { | ||
346 | /* Usage case 1 (see above) */ | ||
347 | c_ptr = tipc_cltr_find(tipc_own_addr); | ||
348 | if (!c_ptr) | ||
349 | c_ptr = tipc_cltr_create(tipc_own_addr); | ||
350 | if (c_ptr) | ||
351 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, | ||
352 | tipc_max_nodes); | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | c_ptr = n_ptr->owner; | ||
357 | if (is_slave(n_ptr->addr)) { | ||
358 | /* Usage case 2 (see above) */ | ||
359 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); | ||
360 | tipc_cltr_send_local_routes(c_ptr, n_ptr->addr); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | if (n_ptr->bclink.supported) { | 308 | if (n_ptr->bclink.supported) { |
365 | tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); | 309 | tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); |
366 | if (n_ptr->addr < tipc_own_addr) | 310 | if (n_ptr->addr < tipc_own_addr) |
367 | tipc_own_tag++; | 311 | tipc_own_tag++; |
368 | } | 312 | } |
369 | |||
370 | /* Case 3 (see above) */ | ||
371 | tipc_net_send_external_routes(n_ptr->addr); | ||
372 | tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); | ||
373 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, | ||
374 | tipc_highest_allowed_slave); | ||
375 | } | 313 | } |
376 | 314 | ||
377 | static void node_cleanup_finished(unsigned long node_addr) | 315 | static void node_cleanup_finished(unsigned long node_addr) |
@@ -390,15 +328,13 @@ static void node_cleanup_finished(unsigned long node_addr) | |||
390 | 328 | ||
391 | static void node_lost_contact(struct tipc_node *n_ptr) | 329 | static void node_lost_contact(struct tipc_node *n_ptr) |
392 | { | 330 | { |
393 | struct cluster *c_ptr; | ||
394 | struct tipc_node_subscr *ns, *tns; | ||
395 | char addr_string[16]; | 331 | char addr_string[16]; |
396 | u32 i; | 332 | u32 i; |
397 | 333 | ||
398 | /* Clean up broadcast reception remains */ | 334 | /* Clean up broadcast reception remains */ |
399 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | 335 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; |
400 | while (n_ptr->bclink.deferred_head) { | 336 | while (n_ptr->bclink.deferred_head) { |
401 | struct sk_buff* buf = n_ptr->bclink.deferred_head; | 337 | struct sk_buff *buf = n_ptr->bclink.deferred_head; |
402 | n_ptr->bclink.deferred_head = buf->next; | 338 | n_ptr->bclink.deferred_head = buf->next; |
403 | buf_discard(buf); | 339 | buf_discard(buf); |
404 | } | 340 | } |
@@ -406,41 +342,14 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
406 | buf_discard(n_ptr->bclink.defragm); | 342 | buf_discard(n_ptr->bclink.defragm); |
407 | n_ptr->bclink.defragm = NULL; | 343 | n_ptr->bclink.defragm = NULL; |
408 | } | 344 | } |
409 | if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { | ||
410 | tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); | ||
411 | } | ||
412 | 345 | ||
413 | /* Update routing tables */ | 346 | if (n_ptr->bclink.supported) { |
414 | if (is_slave(tipc_own_addr)) { | 347 | tipc_bclink_acknowledge(n_ptr, |
415 | tipc_net_remove_as_router(n_ptr->addr); | 348 | mod(n_ptr->bclink.acked + 10000)); |
416 | } else { | 349 | tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr); |
417 | if (!in_own_cluster(n_ptr->addr)) { | 350 | if (n_ptr->addr < tipc_own_addr) |
418 | /* Case 4 (see above) */ | 351 | tipc_own_tag--; |
419 | c_ptr = tipc_cltr_find(tipc_own_addr); | ||
420 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
421 | tipc_max_nodes); | ||
422 | } else { | ||
423 | /* Case 5 (see above) */ | ||
424 | c_ptr = tipc_cltr_find(n_ptr->addr); | ||
425 | if (is_slave(n_ptr->addr)) { | ||
426 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
427 | tipc_max_nodes); | ||
428 | } else { | ||
429 | if (n_ptr->bclink.supported) { | ||
430 | tipc_nmap_remove(&tipc_cltr_bcast_nodes, | ||
431 | n_ptr->addr); | ||
432 | if (n_ptr->addr < tipc_own_addr) | ||
433 | tipc_own_tag--; | ||
434 | } | ||
435 | tipc_net_remove_as_router(n_ptr->addr); | ||
436 | tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, | ||
437 | LOWEST_SLAVE, | ||
438 | tipc_highest_allowed_slave); | ||
439 | } | ||
440 | } | ||
441 | } | 352 | } |
442 | if (tipc_node_has_active_routes(n_ptr)) | ||
443 | return; | ||
444 | 353 | ||
445 | info("Lost contact with %s\n", | 354 | info("Lost contact with %s\n", |
446 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | 355 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
@@ -456,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
456 | } | 365 | } |
457 | 366 | ||
458 | /* Notify subscribers */ | 367 | /* Notify subscribers */ |
459 | list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { | 368 | tipc_nodesub_notify(n_ptr); |
460 | ns->node = NULL; | ||
461 | list_del_init(&ns->nodesub_list); | ||
462 | tipc_k_signal((Handler)ns->handle_node_down, | ||
463 | (unsigned long)ns->usr_handle); | ||
464 | } | ||
465 | 369 | ||
466 | /* Prevent re-contact with node until all cleanup is done */ | 370 | /* Prevent re-contact with node until all cleanup is done */ |
467 | 371 | ||
@@ -469,125 +373,6 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
469 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); | 373 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); |
470 | } | 374 | } |
471 | 375 | ||
472 | /** | ||
473 | * tipc_node_select_next_hop - find the next-hop node for a message | ||
474 | * | ||
475 | * Called by when cluster local lookup has failed. | ||
476 | */ | ||
477 | |||
478 | struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector) | ||
479 | { | ||
480 | struct tipc_node *n_ptr; | ||
481 | u32 router_addr; | ||
482 | |||
483 | if (!tipc_addr_domain_valid(addr)) | ||
484 | return NULL; | ||
485 | |||
486 | /* Look for direct link to destination processsor */ | ||
487 | n_ptr = tipc_node_find(addr); | ||
488 | if (n_ptr && tipc_node_has_active_links(n_ptr)) | ||
489 | return n_ptr; | ||
490 | |||
491 | /* Cluster local system nodes *must* have direct links */ | ||
492 | if (!is_slave(addr) && in_own_cluster(addr)) | ||
493 | return NULL; | ||
494 | |||
495 | /* Look for cluster local router with direct link to node */ | ||
496 | router_addr = tipc_node_select_router(n_ptr, selector); | ||
497 | if (router_addr) | ||
498 | return tipc_node_select(router_addr, selector); | ||
499 | |||
500 | /* Slave nodes can only be accessed within own cluster via a | ||
501 | known router with direct link -- if no router was found,give up */ | ||
502 | if (is_slave(addr)) | ||
503 | return NULL; | ||
504 | |||
505 | /* Inter zone/cluster -- find any direct link to remote cluster */ | ||
506 | addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
507 | n_ptr = tipc_net_select_remote_node(addr, selector); | ||
508 | if (n_ptr && tipc_node_has_active_links(n_ptr)) | ||
509 | return n_ptr; | ||
510 | |||
511 | /* Last resort -- look for any router to anywhere in remote zone */ | ||
512 | router_addr = tipc_net_select_router(addr, selector); | ||
513 | if (router_addr) | ||
514 | return tipc_node_select(router_addr, selector); | ||
515 | |||
516 | return NULL; | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * tipc_node_select_router - select router to reach specified node | ||
521 | * | ||
522 | * Uses a deterministic and fair algorithm for selecting router node. | ||
523 | */ | ||
524 | |||
525 | u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref) | ||
526 | { | ||
527 | u32 ulim; | ||
528 | u32 mask; | ||
529 | u32 start; | ||
530 | u32 r; | ||
531 | |||
532 | if (!n_ptr) | ||
533 | return 0; | ||
534 | |||
535 | if (n_ptr->last_router < 0) | ||
536 | return 0; | ||
537 | ulim = ((n_ptr->last_router + 1) * 32) - 1; | ||
538 | |||
539 | /* Start entry must be random */ | ||
540 | mask = tipc_max_nodes; | ||
541 | while (mask > ulim) | ||
542 | mask >>= 1; | ||
543 | start = ref & mask; | ||
544 | r = start; | ||
545 | |||
546 | /* Lookup upwards with wrap-around */ | ||
547 | do { | ||
548 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
549 | break; | ||
550 | } while (++r <= ulim); | ||
551 | if (r > ulim) { | ||
552 | r = 1; | ||
553 | do { | ||
554 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
555 | break; | ||
556 | } while (++r < start); | ||
557 | assert(r != start); | ||
558 | } | ||
559 | assert(r && (r <= ulim)); | ||
560 | return tipc_addr(own_zone(), own_cluster(), r); | ||
561 | } | ||
562 | |||
563 | void tipc_node_add_router(struct tipc_node *n_ptr, u32 router) | ||
564 | { | ||
565 | u32 r_num = tipc_node(router); | ||
566 | |||
567 | n_ptr->routers[r_num / 32] = | ||
568 | ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); | ||
569 | n_ptr->last_router = tipc_max_nodes / 32; | ||
570 | while ((--n_ptr->last_router >= 0) && | ||
571 | !n_ptr->routers[n_ptr->last_router]); | ||
572 | } | ||
573 | |||
574 | void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router) | ||
575 | { | ||
576 | u32 r_num = tipc_node(router); | ||
577 | |||
578 | if (n_ptr->last_router < 0) | ||
579 | return; /* No routes */ | ||
580 | |||
581 | n_ptr->routers[r_num / 32] = | ||
582 | ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); | ||
583 | n_ptr->last_router = tipc_max_nodes / 32; | ||
584 | while ((--n_ptr->last_router >= 0) && | ||
585 | !n_ptr->routers[n_ptr->last_router]); | ||
586 | |||
587 | if (!tipc_node_is_up(n_ptr)) | ||
588 | node_lost_contact(n_ptr); | ||
589 | } | ||
590 | |||
591 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | 376 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) |
592 | { | 377 | { |
593 | u32 domain; | 378 | u32 domain; |
@@ -605,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
605 | " (network address)"); | 390 | " (network address)"); |
606 | 391 | ||
607 | read_lock_bh(&tipc_net_lock); | 392 | read_lock_bh(&tipc_net_lock); |
608 | if (!tipc_nodes) { | 393 | if (!tipc_num_nodes) { |
609 | read_unlock_bh(&tipc_net_lock); | 394 | read_unlock_bh(&tipc_net_lock); |
610 | return tipc_cfg_reply_none(); | 395 | return tipc_cfg_reply_none(); |
611 | } | 396 | } |
612 | 397 | ||
613 | /* For now, get space for all other nodes | 398 | /* For now, get space for all other nodes */ |
614 | (will need to modify this when slave nodes are supported */ | ||
615 | 399 | ||
616 | payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); | 400 | payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; |
617 | if (payload_size > 32768u) { | 401 | if (payload_size > 32768u) { |
618 | read_unlock_bh(&tipc_net_lock); | 402 | read_unlock_bh(&tipc_net_lock); |
619 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 403 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -627,7 +411,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
627 | 411 | ||
628 | /* Add TLVs for all nodes in scope */ | 412 | /* Add TLVs for all nodes in scope */ |
629 | 413 | ||
630 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 414 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
631 | if (!tipc_in_scope(domain, n_ptr->addr)) | 415 | if (!tipc_in_scope(domain, n_ptr->addr)) |
632 | continue; | 416 | continue; |
633 | node_info.addr = htonl(n_ptr->addr); | 417 | node_info.addr = htonl(n_ptr->addr); |
@@ -664,7 +448,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
664 | /* Get space for all unicast links + multicast link */ | 448 | /* Get space for all unicast links + multicast link */ |
665 | 449 | ||
666 | payload_size = TLV_SPACE(sizeof(link_info)) * | 450 | payload_size = TLV_SPACE(sizeof(link_info)) * |
667 | (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); | 451 | (atomic_read(&tipc_num_links) + 1); |
668 | if (payload_size > 32768u) { | 452 | if (payload_size > 32768u) { |
669 | read_unlock_bh(&tipc_net_lock); | 453 | read_unlock_bh(&tipc_net_lock); |
670 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 454 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -678,14 +462,14 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
678 | 462 | ||
679 | /* Add TLV for broadcast link */ | 463 | /* Add TLV for broadcast link */ |
680 | 464 | ||
681 | link_info.dest = htonl(tipc_own_addr & 0xfffff00); | 465 | link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); |
682 | link_info.up = htonl(1); | 466 | link_info.up = htonl(1); |
683 | strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); | 467 | strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); |
684 | 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)); |
685 | 469 | ||
686 | /* Add TLVs for any other links in scope */ | 470 | /* Add TLVs for any other links in scope */ |
687 | 471 | ||
688 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 472 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
689 | u32 i; | 473 | u32 i; |
690 | 474 | ||
691 | if (!tipc_in_scope(domain, n_ptr->addr)) | 475 | if (!tipc_in_scope(domain, n_ptr->addr)) |