diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 421 |
1 files changed, 91 insertions, 330 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index b634942caba5..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,24 +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 | 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 | 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 | } | ||
58 | 72 | ||
59 | /** | 73 | /** |
60 | * tipc_node_create - create neighboring node | 74 | * tipc_node_create - create neighboring node |
@@ -68,75 +82,50 @@ u32 tipc_own_tag = 0; | |||
68 | 82 | ||
69 | struct tipc_node *tipc_node_create(u32 addr) | 83 | struct tipc_node *tipc_node_create(u32 addr) |
70 | { | 84 | { |
71 | struct cluster *c_ptr; | 85 | struct tipc_node *n_ptr, *temp_node; |
72 | struct tipc_node *n_ptr; | ||
73 | struct tipc_node **curr_node; | ||
74 | 86 | ||
75 | spin_lock_bh(&node_create_lock); | 87 | spin_lock_bh(&node_create_lock); |
76 | 88 | ||
77 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 89 | n_ptr = tipc_node_find(addr); |
78 | if (addr < n_ptr->addr) | 90 | if (n_ptr) { |
79 | break; | 91 | spin_unlock_bh(&node_create_lock); |
80 | if (addr == n_ptr->addr) { | 92 | return n_ptr; |
81 | spin_unlock_bh(&node_create_lock); | ||
82 | return n_ptr; | ||
83 | } | ||
84 | } | 93 | } |
85 | 94 | ||
86 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); | 95 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); |
87 | if (!n_ptr) { | 96 | if (!n_ptr) { |
88 | spin_unlock_bh(&node_create_lock); | 97 | spin_unlock_bh(&node_create_lock); |
89 | warn("Node creation failed, no memory\n"); | 98 | warn("Node creation failed, no memory\n"); |
90 | return NULL; | 99 | return NULL; |
91 | } | 100 | } |
92 | 101 | ||
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; | 102 | n_ptr->addr = addr; |
104 | 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); | ||
105 | INIT_LIST_HEAD(&n_ptr->nsub); | 106 | INIT_LIST_HEAD(&n_ptr->nsub); |
106 | n_ptr->owner = c_ptr; | 107 | |
107 | tipc_cltr_attach_node(c_ptr, n_ptr); | 108 | hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
108 | n_ptr->last_router = -1; | 109 | |
109 | 110 | list_for_each_entry(temp_node, &tipc_node_list, list) { | |
110 | /* Insert node into ordered list */ | 111 | if (n_ptr->addr < temp_node->addr) |
111 | for (curr_node = &tipc_nodes; *curr_node; | ||
112 | curr_node = &(*curr_node)->next) { | ||
113 | if (addr < (*curr_node)->addr) { | ||
114 | n_ptr->next = *curr_node; | ||
115 | break; | 112 | break; |
116 | } | ||
117 | } | 113 | } |
118 | (*curr_node) = n_ptr; | 114 | list_add_tail(&n_ptr->list, &temp_node->list); |
115 | |||
116 | tipc_num_nodes++; | ||
117 | |||
119 | spin_unlock_bh(&node_create_lock); | 118 | spin_unlock_bh(&node_create_lock); |
120 | return n_ptr; | 119 | return n_ptr; |
121 | } | 120 | } |
122 | 121 | ||
123 | void tipc_node_delete(struct tipc_node *n_ptr) | 122 | void tipc_node_delete(struct tipc_node *n_ptr) |
124 | { | 123 | { |
125 | if (!n_ptr) | 124 | list_del(&n_ptr->list); |
126 | return; | 125 | hlist_del(&n_ptr->hash); |
127 | |||
128 | #if 0 | ||
129 | /* Not needed because links are already deleted via tipc_bearer_stop() */ | ||
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); | 126 | kfree(n_ptr); |
127 | |||
128 | tipc_num_nodes--; | ||
140 | } | 129 | } |
141 | 130 | ||
142 | 131 | ||
@@ -156,7 +145,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); | 145 | l_ptr->name, l_ptr->b_ptr->net_plane); |
157 | 146 | ||
158 | if (!active[0]) { | 147 | if (!active[0]) { |
159 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
160 | active[0] = active[1] = l_ptr; | 148 | active[0] = active[1] = l_ptr; |
161 | node_established_contact(n_ptr); | 149 | node_established_contact(n_ptr); |
162 | return; | 150 | return; |
@@ -235,60 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) | |||
235 | node_lost_contact(n_ptr); | 223 | node_lost_contact(n_ptr); |
236 | } | 224 | } |
237 | 225 | ||
238 | int tipc_node_has_active_links(struct tipc_node *n_ptr) | 226 | int tipc_node_active_links(struct tipc_node *n_ptr) |
239 | { | 227 | { |
240 | return (n_ptr && | 228 | return n_ptr->active_links[0] != NULL; |
241 | ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); | ||
242 | } | 229 | } |
243 | 230 | ||
244 | int tipc_node_has_redundant_links(struct tipc_node *n_ptr) | 231 | int tipc_node_redundant_links(struct tipc_node *n_ptr) |
245 | { | 232 | { |
246 | return (n_ptr->working_links > 1); | 233 | 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 | } | 234 | } |
253 | 235 | ||
254 | int tipc_node_is_up(struct tipc_node *n_ptr) | 236 | int tipc_node_is_up(struct tipc_node *n_ptr) |
255 | { | 237 | { |
256 | return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr)); | 238 | return tipc_node_active_links(n_ptr); |
257 | } | 239 | } |
258 | 240 | ||
259 | 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) |
260 | { | 242 | { |
261 | struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); | 243 | n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; |
262 | 244 | atomic_inc(&tipc_num_links); | |
263 | if (!n_ptr) | 245 | n_ptr->link_cnt++; |
264 | n_ptr = tipc_node_create(l_ptr->addr); | ||
265 | if (n_ptr) { | ||
266 | u32 bearer_id = l_ptr->b_ptr->identity; | ||
267 | char addr_string[16]; | ||
268 | |||
269 | if (n_ptr->link_cnt >= 2) { | ||
270 | err("Attempt to create third link to %s\n", | ||
271 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | ||
272 | return NULL; | ||
273 | } | ||
274 | |||
275 | if (!n_ptr->links[bearer_id]) { | ||
276 | n_ptr->links[bearer_id] = l_ptr; | ||
277 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; | ||
278 | n_ptr->link_cnt++; | ||
279 | return n_ptr; | ||
280 | } | ||
281 | err("Attempt to establish second link on <%s> to %s\n", | ||
282 | l_ptr->b_ptr->publ.name, | ||
283 | tipc_addr_string_fill(addr_string, l_ptr->addr)); | ||
284 | } | ||
285 | return NULL; | ||
286 | } | 246 | } |
287 | 247 | ||
288 | 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) |
289 | { | 249 | { |
290 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; | 250 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; |
291 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; | 251 | atomic_dec(&tipc_num_links); |
292 | n_ptr->link_cnt--; | 252 | n_ptr->link_cnt--; |
293 | } | 253 | } |
294 | 254 | ||
@@ -340,61 +300,41 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | |||
340 | 300 | ||
341 | static void node_established_contact(struct tipc_node *n_ptr) | 301 | static void node_established_contact(struct tipc_node *n_ptr) |
342 | { | 302 | { |
343 | struct cluster *c_ptr; | 303 | 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 | 304 | ||
350 | /* Syncronize broadcast acks */ | 305 | /* Syncronize broadcast acks */ |
351 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); | 306 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); |
352 | 307 | ||
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) { | 308 | if (n_ptr->bclink.supported) { |
375 | tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); | 309 | tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); |
376 | if (n_ptr->addr < tipc_own_addr) | 310 | if (n_ptr->addr < tipc_own_addr) |
377 | tipc_own_tag++; | 311 | tipc_own_tag++; |
378 | } | 312 | } |
313 | } | ||
314 | |||
315 | static void node_cleanup_finished(unsigned long node_addr) | ||
316 | { | ||
317 | struct tipc_node *n_ptr; | ||
379 | 318 | ||
380 | /* Case 3 (see above) */ | 319 | read_lock_bh(&tipc_net_lock); |
381 | tipc_net_send_external_routes(n_ptr->addr); | 320 | n_ptr = tipc_node_find(node_addr); |
382 | tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); | 321 | if (n_ptr) { |
383 | tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, | 322 | tipc_node_lock(n_ptr); |
384 | tipc_highest_allowed_slave); | 323 | n_ptr->cleanup_required = 0; |
324 | tipc_node_unlock(n_ptr); | ||
325 | } | ||
326 | read_unlock_bh(&tipc_net_lock); | ||
385 | } | 327 | } |
386 | 328 | ||
387 | static void node_lost_contact(struct tipc_node *n_ptr) | 329 | static void node_lost_contact(struct tipc_node *n_ptr) |
388 | { | 330 | { |
389 | struct cluster *c_ptr; | ||
390 | struct tipc_node_subscr *ns, *tns; | ||
391 | char addr_string[16]; | 331 | char addr_string[16]; |
392 | u32 i; | 332 | u32 i; |
393 | 333 | ||
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,41 +342,14 @@ 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 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | 355 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
@@ -452,163 +365,12 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
452 | } | 365 | } |
453 | 366 | ||
454 | /* Notify subscribers */ | 367 | /* Notify subscribers */ |
455 | list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { | 368 | tipc_nodesub_notify(n_ptr); |
456 | ns->node = NULL; | ||
457 | list_del_init(&ns->nodesub_list); | ||
458 | tipc_k_signal((Handler)ns->handle_node_down, | ||
459 | (unsigned long)ns->usr_handle); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | /** | ||
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 | |||
469 | struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector) | ||
470 | { | ||
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 | 369 | ||
558 | n_ptr->routers[r_num / 32] = | 370 | /* Prevent re-contact with node until all cleanup is done */ |
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 | 371 | ||
582 | #if 0 | 372 | n_ptr->cleanup_required = 1; |
583 | void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str) | 373 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); |
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 (!tipc_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 | } | 374 | } |
613 | 375 | ||
614 | 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) |
@@ -628,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
628 | " (network address)"); | 390 | " (network address)"); |
629 | 391 | ||
630 | read_lock_bh(&tipc_net_lock); | 392 | read_lock_bh(&tipc_net_lock); |
631 | if (!tipc_nodes) { | 393 | if (!tipc_num_nodes) { |
632 | read_unlock_bh(&tipc_net_lock); | 394 | read_unlock_bh(&tipc_net_lock); |
633 | return tipc_cfg_reply_none(); | 395 | return tipc_cfg_reply_none(); |
634 | } | 396 | } |
635 | 397 | ||
636 | /* For now, get space for all other nodes | 398 | /* For now, get space for all other nodes */ |
637 | (will need to modify this when slave nodes are supported */ | ||
638 | 399 | ||
639 | payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); | 400 | payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; |
640 | if (payload_size > 32768u) { | 401 | if (payload_size > 32768u) { |
641 | read_unlock_bh(&tipc_net_lock); | 402 | read_unlock_bh(&tipc_net_lock); |
642 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 403 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -650,7 +411,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
650 | 411 | ||
651 | /* Add TLVs for all nodes in scope */ | 412 | /* Add TLVs for all nodes in scope */ |
652 | 413 | ||
653 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 414 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
654 | if (!tipc_in_scope(domain, n_ptr->addr)) | 415 | if (!tipc_in_scope(domain, n_ptr->addr)) |
655 | continue; | 416 | continue; |
656 | node_info.addr = htonl(n_ptr->addr); | 417 | node_info.addr = htonl(n_ptr->addr); |
@@ -687,7 +448,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
687 | /* Get space for all unicast links + multicast link */ | 448 | /* Get space for all unicast links + multicast link */ |
688 | 449 | ||
689 | payload_size = TLV_SPACE(sizeof(link_info)) * | 450 | payload_size = TLV_SPACE(sizeof(link_info)) * |
690 | (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); | 451 | (atomic_read(&tipc_num_links) + 1); |
691 | if (payload_size > 32768u) { | 452 | if (payload_size > 32768u) { |
692 | read_unlock_bh(&tipc_net_lock); | 453 | read_unlock_bh(&tipc_net_lock); |
693 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 454 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -701,14 +462,14 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
701 | 462 | ||
702 | /* Add TLV for broadcast link */ | 463 | /* Add TLV for broadcast link */ |
703 | 464 | ||
704 | link_info.dest = htonl(tipc_own_addr & 0xfffff00); | 465 | link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); |
705 | link_info.up = htonl(1); | 466 | link_info.up = htonl(1); |
706 | strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); | 467 | strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); |
707 | 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)); |
708 | 469 | ||
709 | /* Add TLVs for any other links in scope */ | 470 | /* Add TLVs for any other links in scope */ |
710 | 471 | ||
711 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 472 | list_for_each_entry(n_ptr, &tipc_node_list, list) { |
712 | u32 i; | 473 | u32 i; |
713 | 474 | ||
714 | if (!tipc_in_scope(domain, n_ptr->addr)) | 475 | if (!tipc_in_scope(domain, n_ptr->addr)) |