diff options
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r-- | net/tipc/node.c | 301 |
1 files changed, 47 insertions, 254 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c index b4d87eb2dc5d..3af53e327f49 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -37,25 +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 | /* 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 | u32 tipc_own_tag; |
59 | 48 | ||
60 | /** | 49 | /** |
61 | * tipc_node_create - create neighboring node | 50 | * tipc_node_create - create neighboring node |
@@ -69,65 +58,51 @@ u32 tipc_own_tag = 0; | |||
69 | 58 | ||
70 | struct tipc_node *tipc_node_create(u32 addr) | 59 | struct tipc_node *tipc_node_create(u32 addr) |
71 | { | 60 | { |
72 | struct cluster *c_ptr; | ||
73 | struct tipc_node *n_ptr; | 61 | struct tipc_node *n_ptr; |
74 | struct tipc_node **curr_node; | 62 | u32 n_num; |
75 | 63 | ||
76 | spin_lock_bh(&node_create_lock); | 64 | spin_lock_bh(&node_create_lock); |
77 | 65 | ||
78 | for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { | 66 | n_ptr = tipc_node_find(addr); |
79 | if (addr < n_ptr->addr) | 67 | if (n_ptr) { |
80 | break; | 68 | spin_unlock_bh(&node_create_lock); |
81 | if (addr == n_ptr->addr) { | 69 | return n_ptr; |
82 | spin_unlock_bh(&node_create_lock); | ||
83 | return n_ptr; | ||
84 | } | ||
85 | } | 70 | } |
86 | 71 | ||
87 | n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); | 72 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); |
88 | if (!n_ptr) { | 73 | if (!n_ptr) { |
89 | spin_unlock_bh(&node_create_lock); | 74 | spin_unlock_bh(&node_create_lock); |
90 | warn("Node creation failed, no memory\n"); | 75 | warn("Node creation failed, no memory\n"); |
91 | return NULL; | 76 | return NULL; |
92 | } | 77 | } |
93 | 78 | ||
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; | 79 | n_ptr->addr = addr; |
105 | spin_lock_init(&n_ptr->lock); | 80 | spin_lock_init(&n_ptr->lock); |
106 | INIT_LIST_HEAD(&n_ptr->nsub); | 81 | INIT_LIST_HEAD(&n_ptr->nsub); |
107 | n_ptr->owner = c_ptr; | 82 | |
108 | tipc_cltr_attach_node(c_ptr, n_ptr); | 83 | n_num = tipc_node(addr); |
109 | n_ptr->last_router = -1; | 84 | tipc_net.nodes[n_num] = n_ptr; |
110 | 85 | if (n_num > tipc_net.highest_node) | |
111 | /* Insert node into ordered list */ | 86 | tipc_net.highest_node = n_num; |
112 | for (curr_node = &tipc_nodes; *curr_node; | 87 | |
113 | curr_node = &(*curr_node)->next) { | ||
114 | if (addr < (*curr_node)->addr) { | ||
115 | n_ptr->next = *curr_node; | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | (*curr_node) = n_ptr; | ||
120 | spin_unlock_bh(&node_create_lock); | 88 | spin_unlock_bh(&node_create_lock); |
121 | return n_ptr; | 89 | return n_ptr; |
122 | } | 90 | } |
123 | 91 | ||
124 | void tipc_node_delete(struct tipc_node *n_ptr) | 92 | void tipc_node_delete(struct tipc_node *n_ptr) |
125 | { | 93 | { |
94 | u32 n_num; | ||
95 | |||
126 | if (!n_ptr) | 96 | if (!n_ptr) |
127 | return; | 97 | return; |
128 | 98 | ||
129 | dbg("node %x deleted\n", n_ptr->addr); | 99 | n_num = tipc_node(n_ptr->addr); |
100 | tipc_net.nodes[n_num] = NULL; | ||
130 | 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; | ||
131 | } | 106 | } |
132 | 107 | ||
133 | 108 | ||
@@ -147,7 +122,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); | 122 | l_ptr->name, l_ptr->b_ptr->net_plane); |
148 | 123 | ||
149 | if (!active[0]) { | 124 | if (!active[0]) { |
150 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
151 | active[0] = active[1] = l_ptr; | 125 | active[0] = active[1] = l_ptr; |
152 | node_established_contact(n_ptr); | 126 | node_established_contact(n_ptr); |
153 | return; | 127 | return; |
@@ -236,14 +210,9 @@ int tipc_node_has_redundant_links(struct tipc_node *n_ptr) | |||
236 | return n_ptr->working_links > 1; | 210 | return n_ptr->working_links > 1; |
237 | } | 211 | } |
238 | 212 | ||
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) | 213 | int tipc_node_is_up(struct tipc_node *n_ptr) |
245 | { | 214 | { |
246 | return tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr); | 215 | return tipc_node_has_active_links(n_ptr); |
247 | } | 216 | } |
248 | 217 | ||
249 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | 218 | struct tipc_node *tipc_node_attach_link(struct link *l_ptr) |
@@ -264,7 +233,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
264 | 233 | ||
265 | if (!n_ptr->links[bearer_id]) { | 234 | if (!n_ptr->links[bearer_id]) { |
266 | n_ptr->links[bearer_id] = l_ptr; | 235 | n_ptr->links[bearer_id] = l_ptr; |
267 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; | 236 | tipc_net.links++; |
268 | n_ptr->link_cnt++; | 237 | n_ptr->link_cnt++; |
269 | return n_ptr; | 238 | return n_ptr; |
270 | } | 239 | } |
@@ -278,7 +247,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
278 | 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) |
279 | { | 248 | { |
280 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; | 249 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; |
281 | tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; | 250 | tipc_net.links--; |
282 | n_ptr->link_cnt--; | 251 | n_ptr->link_cnt--; |
283 | } | 252 | } |
284 | 253 | ||
@@ -330,48 +299,16 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) | |||
330 | 299 | ||
331 | static void node_established_contact(struct tipc_node *n_ptr) | 300 | static void node_established_contact(struct tipc_node *n_ptr) |
332 | { | 301 | { |
333 | struct cluster *c_ptr; | 302 | 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 | 303 | ||
340 | /* Syncronize broadcast acks */ | 304 | /* Syncronize broadcast acks */ |
341 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); | 305 | n_ptr->bclink.acked = tipc_bclink_get_last_sent(); |
342 | 306 | ||
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) { | 307 | if (n_ptr->bclink.supported) { |
365 | tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); | 308 | tipc_nmap_add(&tipc_bcast_nmap, n_ptr->addr); |
366 | if (n_ptr->addr < tipc_own_addr) | 309 | if (n_ptr->addr < tipc_own_addr) |
367 | tipc_own_tag++; | 310 | tipc_own_tag++; |
368 | } | 311 | } |
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 | } | 312 | } |
376 | 313 | ||
377 | static void node_cleanup_finished(unsigned long node_addr) | 314 | static void node_cleanup_finished(unsigned long node_addr) |
@@ -390,7 +327,6 @@ static void node_cleanup_finished(unsigned long node_addr) | |||
390 | 327 | ||
391 | static void node_lost_contact(struct tipc_node *n_ptr) | 328 | static void node_lost_contact(struct tipc_node *n_ptr) |
392 | { | 329 | { |
393 | struct cluster *c_ptr; | ||
394 | struct tipc_node_subscr *ns, *tns; | 330 | struct tipc_node_subscr *ns, *tns; |
395 | char addr_string[16]; | 331 | char addr_string[16]; |
396 | u32 i; | 332 | u32 i; |
@@ -398,7 +334,7 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
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)); |
@@ -469,125 +378,6 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
469 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); | 378 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); |
470 | } | 379 | } |
471 | 380 | ||
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) | 381 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) |
592 | { | 382 | { |
593 | u32 domain; | 383 | u32 domain; |
@@ -595,6 +385,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
595 | struct tipc_node *n_ptr; | 385 | struct tipc_node *n_ptr; |
596 | struct tipc_node_info node_info; | 386 | struct tipc_node_info node_info; |
597 | u32 payload_size; | 387 | u32 payload_size; |
388 | u32 n_num; | ||
598 | 389 | ||
599 | 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)) |
600 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 391 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
@@ -605,15 +396,15 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
605 | " (network address)"); | 396 | " (network address)"); |
606 | 397 | ||
607 | read_lock_bh(&tipc_net_lock); | 398 | read_lock_bh(&tipc_net_lock); |
608 | if (!tipc_nodes) { | 399 | if (!tipc_net.nodes) { |
609 | read_unlock_bh(&tipc_net_lock); | 400 | read_unlock_bh(&tipc_net_lock); |
610 | return tipc_cfg_reply_none(); | 401 | return tipc_cfg_reply_none(); |
611 | } | 402 | } |
612 | 403 | ||
613 | /* For now, get space for all other nodes | 404 | /* For now, get space for all other nodes */ |
614 | (will need to modify this when slave nodes are supported */ | ||
615 | 405 | ||
616 | 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); | ||
617 | if (payload_size > 32768u) { | 408 | if (payload_size > 32768u) { |
618 | read_unlock_bh(&tipc_net_lock); | 409 | read_unlock_bh(&tipc_net_lock); |
619 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 410 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -627,8 +418,9 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
627 | 418 | ||
628 | /* Add TLVs for all nodes in scope */ | 419 | /* Add TLVs for all nodes in scope */ |
629 | 420 | ||
630 | 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++) { |
631 | if (!tipc_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)) | ||
632 | continue; | 424 | continue; |
633 | node_info.addr = htonl(n_ptr->addr); | 425 | node_info.addr = htonl(n_ptr->addr); |
634 | node_info.up = htonl(tipc_node_is_up(n_ptr)); | 426 | node_info.up = htonl(tipc_node_is_up(n_ptr)); |
@@ -647,6 +439,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
647 | struct tipc_node *n_ptr; | 439 | struct tipc_node *n_ptr; |
648 | struct tipc_link_info link_info; | 440 | struct tipc_link_info link_info; |
649 | u32 payload_size; | 441 | u32 payload_size; |
442 | u32 n_num; | ||
650 | 443 | ||
651 | 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)) |
652 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 445 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
@@ -663,8 +456,7 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
663 | 456 | ||
664 | /* Get space for all unicast links + multicast link */ | 457 | /* Get space for all unicast links + multicast link */ |
665 | 458 | ||
666 | payload_size = TLV_SPACE(sizeof(link_info)) * | 459 | payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1); |
667 | (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); | ||
668 | if (payload_size > 32768u) { | 460 | if (payload_size > 32768u) { |
669 | read_unlock_bh(&tipc_net_lock); | 461 | read_unlock_bh(&tipc_net_lock); |
670 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 462 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
@@ -685,10 +477,11 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
685 | 477 | ||
686 | /* Add TLVs for any other links in scope */ | 478 | /* Add TLVs for any other links in scope */ |
687 | 479 | ||
688 | 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++) { |
689 | u32 i; | 481 | u32 i; |
690 | 482 | ||
691 | if (!tipc_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)) | ||
692 | continue; | 485 | continue; |
693 | tipc_node_lock(n_ptr); | 486 | tipc_node_lock(n_ptr); |
694 | for (i = 0; i < MAX_BEARERS; i++) { | 487 | for (i = 0; i < MAX_BEARERS; i++) { |