1 /* 2 * net/tipc/node.c: TIPC node management routines 3 * 4 * Copyright (c) 2000-2006, Ericsson AB 5 * Copyright (c) 2005-2006, Wind River Systems 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the names of the copyright holders nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * Alternatively, this software may be distributed under the terms of the 21 * GNU General Public License ("GPL") version 2 as published by the Free 22 * Software Foundation. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include "core.h" 38 #include "config.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" 48 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); 51 static void node_established_contact(struct tipc_node *n_ptr); 52 53 struct tipc_node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ 54 55 static DEFINE_SPINLOCK(node_create_lock); 56 57 u32 tipc_own_tag = 0; 58 59 /** 60 * tipc_node_create - create neighboring node 61 * 62 * Currently, this routine is called by neighbor discovery code, which holds 63 * net_lock for reading only. We must take node_create_lock to ensure a node 64 * isn't created twice if two different bearers discover the node at the same 65 * time. (It would be preferable to switch to holding net_lock in write mode, 66 * but this is a non-trivial change.) 67 */ 68 69 struct tipc_node *tipc_node_create(u32 addr) 70 { 71 struct cluster *c_ptr; 72 struct tipc_node *n_ptr; 73 struct tipc_node **curr_node; 74 75 spin_lock_bh(&node_create_lock); 76 77 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 78 if (addr < n_ptr->addr) 79 break; 80 if (addr == n_ptr->addr) { 81 spin_unlock_bh(&node_create_lock); 82 return n_ptr; 83 } 84 } 85 86 n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); 87 if (!n_ptr) { 88 spin_unlock_bh(&node_create_lock); 89 warn("Node creation failed, no memory\n"); 90 return NULL; 91 } 92 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; 104 spin_lock_init(&n_ptr->lock); 105 INIT_LIST_HEAD(&n_ptr->nsub); 106 n_ptr->owner = c_ptr; 107 tipc_cltr_attach_node(c_ptr, n_ptr); 108 n_ptr->last_router = -1; 109 110 /* Insert node into ordered list */ 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; 116 } 117 } 118 (*curr_node) = n_ptr; 119 spin_unlock_bh(&node_create_lock); 120 return n_ptr; 121 } 122 123 void tipc_node_delete(struct tipc_node *n_ptr) 124 { 125 if (!n_ptr) 126 return; 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); 140 } 141 142 143 /** 144 * tipc_node_link_up - handle addition of link 145 * 146 * Link becomes active (alone or shared) or standby, depending on its priority. 147 */ 148 149 void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr) 150 { 151 struct link **active = &n_ptr->active_links[0]; 152 153 n_ptr->working_links++; 154 155 info("Established link <%s> on network plane %c\n", 156 l_ptr->name, l_ptr->b_ptr->net_plane); 157 158 if (!active[0]) { 159 dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); 160 active[0] = active[1] = l_ptr; 161 node_established_contact(n_ptr); 162 return; 163 } 164 if (l_ptr->priority < active[0]->priority) { 165 info("New link <%s> becomes standby\n", l_ptr->name); 166 return; 167 } 168 tipc_link_send_duplicate(active[0], l_ptr); 169 if (l_ptr->priority == active[0]->priority) { 170 active[0] = l_ptr; 171 return; 172 } 173 info("Old link <%s> becomes standby\n", active[0]->name); 174 if (active[1] != active[0]) 175 info("Old link <%s> becomes standby\n", active[1]->name); 176 active[0] = active[1] = l_ptr; 177 } 178 179 /** 180 * node_select_active_links - select active link 181 */ 182 183 static void node_select_active_links(struct tipc_node *n_ptr) 184 { 185 struct link **active = &n_ptr->active_links[0]; 186 u32 i; 187 u32 highest_prio = 0; 188 189 active[0] = active[1] = NULL; 190 191 for (i = 0; i < MAX_BEARERS; i++) { 192 struct link *l_ptr = n_ptr->links[i]; 193 194 if (!l_ptr || !tipc_link_is_up(l_ptr) || 195 (l_ptr->priority < highest_prio)) 196 continue; 197 198 if (l_ptr->priority > highest_prio) { 199 highest_prio = l_ptr->priority; 200 active[0] = active[1] = l_ptr; 201 } else { 202 active[1] = l_ptr; 203 } 204 } 205 } 206 207 /** 208 * tipc_node_link_down - handle loss of link 209 */ 210 211 void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr) 212 { 213 struct link **active; 214 215 n_ptr->working_links--; 216 217 if (!tipc_link_is_active(l_ptr)) { 218 info("Lost standby link <%s> on network plane %c\n", 219 l_ptr->name, l_ptr->b_ptr->net_plane); 220 return; 221 } 222 info("Lost link <%s> on network plane %c\n", 223 l_ptr->name, l_ptr->b_ptr->net_plane); 224 225 active = &n_ptr->active_links[0]; 226 if (active[0] == l_ptr) 227 active[0] = active[1]; 228 if (active[1] == l_ptr) 229 active[1] = active[0]; 230 if (active[0] == l_ptr) 231 node_select_active_links(n_ptr); 232 if (tipc_node_is_up(n_ptr)) 233 tipc_link_changeover(l_ptr); 234 else 235 node_lost_contact(n_ptr); 236 } 237 238 int tipc_node_has_active_links(struct tipc_node *n_ptr) 239 { 240 return n_ptr->active_links[0] != NULL; 241 } 242 243 int tipc_node_has_redundant_links(struct tipc_node *n_ptr) 244 { 245 return (n_ptr->working_links > 1); 246 } 247 248 static int tipc_node_has_active_routes(struct tipc_node *n_ptr) 249 { 250 return (n_ptr && (n_ptr->last_router >= 0)); 251 } 252 253 int tipc_node_is_up(struct tipc_node *n_ptr) 254 { 255 return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr)); 256 } 257 258 struct tipc_node *tipc_node_attach_link(struct link *l_ptr) 259 { 260 struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr); 261 262 if (!n_ptr) 263 n_ptr = tipc_node_create(l_ptr->addr); 264 if (n_ptr) { 265 u32 bearer_id = l_ptr->b_ptr->identity; 266 char addr_string[16]; 267 268 if (n_ptr->link_cnt >= 2) { 269 err("Attempt to create third link to %s\n", 270 tipc_addr_string_fill(addr_string, n_ptr->addr)); 271 return NULL; 272 } 273 274 if (!n_ptr->links[bearer_id]) { 275 n_ptr->links[bearer_id] = l_ptr; 276 tipc_net.zones[tipc_zone(l_ptr->addr)]->links++; 277 n_ptr->link_cnt++; 278 return n_ptr; 279 } 280 err("Attempt to establish second link on <%s> to %s\n", 281 l_ptr->b_ptr->publ.name, 282 tipc_addr_string_fill(addr_string, l_ptr->addr)); 283 } 284 return NULL; 285 } 286 287 void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr) 288 { 289 n_ptr->links[l_ptr->b_ptr->identity] = NULL; 290 tipc_net.zones[tipc_zone(l_ptr->addr)]->links--; 291 n_ptr->link_cnt--; 292 } 293 294 /* 295 * Routing table management - five cases to handle: 296 * 297 * 1: A link towards a zone/cluster external node comes up. 298 * => Send a multicast message updating routing tables of all 299 * system nodes within own cluster that the new destination 300 * can be reached via this node. 301 * (node.establishedContact()=>cluster.multicastNewRoute()) 302 * 303 * 2: A link towards a slave node comes up. 304 * => Send a multicast message updating routing tables of all 305 * system nodes within own cluster that the new destination 306 * can be reached via this node. 307 * (node.establishedContact()=>cluster.multicastNewRoute()) 308 * => Send a message to the slave node about existence 309 * of all system nodes within cluster: 310 * (node.establishedContact()=>cluster.sendLocalRoutes()) 311 * 312 * 3: A new cluster local system node becomes available. 313 * => Send message(s) to this particular node containing 314 * information about all cluster external and slave 315 * nodes which can be reached via this node. 316 * (node.establishedContact()==>network.sendExternalRoutes()) 317 * (node.establishedContact()==>network.sendSlaveRoutes()) 318 * => Send messages to all directly connected slave nodes 319 * containing information about the existence of the new node 320 * (node.establishedContact()=>cluster.multicastNewRoute()) 321 * 322 * 4: The link towards a zone/cluster external node or slave 323 * node goes down. 324 * => Send a multcast message updating routing tables of all 325 * nodes within cluster that the new destination can not any 326 * longer be reached via this node. 327 * (node.lostAllLinks()=>cluster.bcastLostRoute()) 328 * 329 * 5: A cluster local system node becomes unavailable. 330 * => Remove all references to this node from the local 331 * routing tables. Note: This is a completely node 332 * local operation. 333 * (node.lostAllLinks()=>network.removeAsRouter()) 334 * => Send messages to all directly connected slave nodes 335 * containing information about loss of the node 336 * (node.establishedContact()=>cluster.multicastLostRoute()) 337 * 338 */ 339 340 static void node_established_contact(struct tipc_node *n_ptr) 341 { 342 struct cluster *c_ptr; 343 344 dbg("node_established_contact:-> %x\n", n_ptr->addr); 345 if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { 346 tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); 347 } 348 349 /* Syncronize broadcast acks */ 350 n_ptr->bclink.acked = tipc_bclink_get_last_sent(); 351 352 if (is_slave(tipc_own_addr)) 353 return; 354 if (!in_own_cluster(n_ptr->addr)) { 355 /* Usage case 1 (see above) */ 356 c_ptr = tipc_cltr_find(tipc_own_addr); 357 if (!c_ptr) 358 c_ptr = tipc_cltr_create(tipc_own_addr); 359 if (c_ptr) 360 tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, 361 tipc_max_nodes); 362 return; 363 } 364 365 c_ptr = n_ptr->owner; 366 if (is_slave(n_ptr->addr)) { 367 /* Usage case 2 (see above) */ 368 tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); 369 tipc_cltr_send_local_routes(c_ptr, n_ptr->addr); 370 return; 371 } 372 373 if (n_ptr->bclink.supported) { 374 tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr); 375 if (n_ptr->addr < tipc_own_addr) 376 tipc_own_tag++; 377 } 378 379 /* Case 3 (see above) */ 380 tipc_net_send_external_routes(n_ptr->addr); 381 tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr); 382 tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, 383 tipc_highest_allowed_slave); 384 } 385 386 static void node_cleanup_finished(unsigned long node_addr) 387 { 388 struct tipc_node *n_ptr; 389 390 read_lock_bh(&tipc_net_lock); 391 n_ptr = tipc_node_find(node_addr); 392 if (n_ptr) { 393 tipc_node_lock(n_ptr); 394 n_ptr->cleanup_required = 0; 395 tipc_node_unlock(n_ptr); 396 } 397 read_unlock_bh(&tipc_net_lock); 398 } 399 400 static void node_lost_contact(struct tipc_node *n_ptr) 401 { 402 struct cluster *c_ptr; 403 struct tipc_node_subscr *ns, *tns; 404 char addr_string[16]; 405 u32 i; 406 407 /* Clean up broadcast reception remains */ 408 n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; 409 while (n_ptr->bclink.deferred_head) { 410 struct sk_buff* buf = n_ptr->bclink.deferred_head; 411 n_ptr->bclink.deferred_head = buf->next; 412 buf_discard(buf); 413 } 414 if (n_ptr->bclink.defragm) { 415 buf_discard(n_ptr->bclink.defragm); 416 n_ptr->bclink.defragm = NULL; 417 } 418 if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { 419 tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); 420 } 421 422 /* Update routing tables */ 423 if (is_slave(tipc_own_addr)) { 424 tipc_net_remove_as_router(n_ptr->addr); 425 } else { 426 if (!in_own_cluster(n_ptr->addr)) { 427 /* Case 4 (see above) */ 428 c_ptr = tipc_cltr_find(tipc_own_addr); 429 tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, 430 tipc_max_nodes); 431 } else { 432 /* Case 5 (see above) */ 433 c_ptr = tipc_cltr_find(n_ptr->addr); 434 if (is_slave(n_ptr->addr)) { 435 tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1, 436 tipc_max_nodes); 437 } else { 438 if (n_ptr->bclink.supported) { 439 tipc_nmap_remove(&tipc_cltr_bcast_nodes, 440 n_ptr->addr); 441 if (n_ptr->addr < tipc_own_addr) 442 tipc_own_tag--; 443 } 444 tipc_net_remove_as_router(n_ptr->addr); 445 tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 446 LOWEST_SLAVE, 447 tipc_highest_allowed_slave); 448 } 449 } 450 } 451 if (tipc_node_has_active_routes(n_ptr)) 452 return; 453 454 info("Lost contact with %s\n", 455 tipc_addr_string_fill(addr_string, n_ptr->addr)); 456 457 /* Abort link changeover */ 458 for (i = 0; i < MAX_BEARERS; i++) { 459 struct link *l_ptr = n_ptr->links[i]; 460 if (!l_ptr) 461 continue; 462 l_ptr->reset_checkpoint = l_ptr->next_in_no; 463 l_ptr->exp_msg_count = 0; 464 tipc_link_reset_fragments(l_ptr); 465 } 466 467 /* Notify subscribers */ 468 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { 469 ns->node = NULL; 470 list_del_init(&ns->nodesub_list); 471 tipc_k_signal((Handler)ns->handle_node_down, 472 (unsigned long)ns->usr_handle); 473 } 474 475 /* Prevent re-contact with node until all cleanup is done */ 476 477 n_ptr->cleanup_required = 1; 478 tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); 479 } 480 481 /** 482 * tipc_node_select_next_hop - find the next-hop node for a message 483 * 484 * Called by when cluster local lookup has failed. 485 */ 486 487 struct tipc_node *tipc_node_select_next_hop(u32 addr, u32 selector) 488 { 489 struct tipc_node *n_ptr; 490 u32 router_addr; 491 492 if (!tipc_addr_domain_valid(addr)) 493 return NULL; 494 495 /* Look for direct link to destination processsor */ 496 n_ptr = tipc_node_find(addr); 497 if (n_ptr && tipc_node_has_active_links(n_ptr)) 498 return n_ptr; 499 500 /* Cluster local system nodes *must* have direct links */ 501 if (!is_slave(addr) && in_own_cluster(addr)) 502 return NULL; 503 504 /* Look for cluster local router with direct link to node */ 505 router_addr = tipc_node_select_router(n_ptr, selector); 506 if (router_addr) 507 return tipc_node_select(router_addr, selector); 508 509 /* Slave nodes can only be accessed within own cluster via a 510 known router with direct link -- if no router was found,give up */ 511 if (is_slave(addr)) 512 return NULL; 513 514 /* Inter zone/cluster -- find any direct link to remote cluster */ 515 addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); 516 n_ptr = tipc_net_select_remote_node(addr, selector); 517 if (n_ptr && tipc_node_has_active_links(n_ptr)) 518 return n_ptr; 519 520 /* Last resort -- look for any router to anywhere in remote zone */ 521 router_addr = tipc_net_select_router(addr, selector); 522 if (router_addr) 523 return tipc_node_select(router_addr, selector); 524 525 return NULL; 526 } 527 528 /** 529 * tipc_node_select_router - select router to reach specified node 530 * 531 * Uses a deterministic and fair algorithm for selecting router node. 532 */ 533 534 u32 tipc_node_select_router(struct tipc_node *n_ptr, u32 ref) 535 { 536 u32 ulim; 537 u32 mask; 538 u32 start; 539 u32 r; 540 541 if (!n_ptr) 542 return 0; 543 544 if (n_ptr->last_router < 0) 545 return 0; 546 ulim = ((n_ptr->last_router + 1) * 32) - 1; 547 548 /* Start entry must be random */ 549 mask = tipc_max_nodes; 550 while (mask > ulim) 551 mask >>= 1; 552 start = ref & mask; 553 r = start; 554 555 /* Lookup upwards with wrap-around */ 556 do { 557 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) 558 break; 559 } while (++r <= ulim); 560 if (r > ulim) { 561 r = 1; 562 do { 563 if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) 564 break; 565 } while (++r < start); 566 assert(r != start); 567 } 568 assert(r && (r <= ulim)); 569 return tipc_addr(own_zone(), own_cluster(), r); 570 } 571 572 void tipc_node_add_router(struct tipc_node *n_ptr, u32 router) 573 { 574 u32 r_num = tipc_node(router); 575 576 n_ptr->routers[r_num / 32] = 577 ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); 578 n_ptr->last_router = tipc_max_nodes / 32; 579 while ((--n_ptr->last_router >= 0) && 580 !n_ptr->routers[n_ptr->last_router]); 581 } 582 583 void tipc_node_remove_router(struct tipc_node *n_ptr, u32 router) 584 { 585 u32 r_num = tipc_node(router); 586 587 if (n_ptr->last_router < 0) 588 return; /* No routes */ 589 590 n_ptr->routers[r_num / 32] = 591 ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); 592 n_ptr->last_router = tipc_max_nodes / 32; 593 while ((--n_ptr->last_router >= 0) && 594 !n_ptr->routers[n_ptr->last_router]); 595 596 if (!tipc_node_is_up(n_ptr)) 597 node_lost_contact(n_ptr); 598 } 599 600 #if 0 601 void node_print(struct print_buf *buf, struct tipc_node *n_ptr, char *str) 602 { 603 u32 i; 604 605 tipc_printf(buf, "\n\n%s", str); 606 for (i = 0; i < MAX_BEARERS; i++) { 607 if (!n_ptr->links[i]) 608 continue; 609 tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); 610 } 611 tipc_printf(buf, "Active links: [%x,%x]\n", 612 n_ptr->active_links[0], n_ptr->active_links[1]); 613 } 614 #endif 615 616 u32 tipc_available_nodes(const u32 domain) 617 { 618 struct tipc_node *n_ptr; 619 u32 cnt = 0; 620 621 read_lock_bh(&tipc_net_lock); 622 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 623 if (!tipc_in_scope(domain, n_ptr->addr)) 624 continue; 625 if (tipc_node_is_up(n_ptr)) 626 cnt++; 627 } 628 read_unlock_bh(&tipc_net_lock); 629 return cnt; 630 } 631 632 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) 633 { 634 u32 domain; 635 struct sk_buff *buf; 636 struct tipc_node *n_ptr; 637 struct tipc_node_info node_info; 638 u32 payload_size; 639 640 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 641 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 642 643 domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); 644 if (!tipc_addr_domain_valid(domain)) 645 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 646 " (network address)"); 647 648 read_lock_bh(&tipc_net_lock); 649 if (!tipc_nodes) { 650 read_unlock_bh(&tipc_net_lock); 651 return tipc_cfg_reply_none(); 652 } 653 654 /* For now, get space for all other nodes 655 (will need to modify this when slave nodes are supported */ 656 657 payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); 658 if (payload_size > 32768u) { 659 read_unlock_bh(&tipc_net_lock); 660 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 661 " (too many nodes)"); 662 } 663 buf = tipc_cfg_reply_alloc(payload_size); 664 if (!buf) { 665 read_unlock_bh(&tipc_net_lock); 666 return NULL; 667 } 668 669 /* Add TLVs for all nodes in scope */ 670 671 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 672 if (!tipc_in_scope(domain, n_ptr->addr)) 673 continue; 674 node_info.addr = htonl(n_ptr->addr); 675 node_info.up = htonl(tipc_node_is_up(n_ptr)); 676 tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, 677 &node_info, sizeof(node_info)); 678 } 679 680 read_unlock_bh(&tipc_net_lock); 681 return buf; 682 } 683 684 struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) 685 { 686 u32 domain; 687 struct sk_buff *buf; 688 struct tipc_node *n_ptr; 689 struct tipc_link_info link_info; 690 u32 payload_size; 691 692 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 693 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 694 695 domain = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); 696 if (!tipc_addr_domain_valid(domain)) 697 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 698 " (network address)"); 699 700 if (tipc_mode != TIPC_NET_MODE) 701 return tipc_cfg_reply_none(); 702 703 read_lock_bh(&tipc_net_lock); 704 705 /* Get space for all unicast links + multicast link */ 706 707 payload_size = TLV_SPACE(sizeof(link_info)) * 708 (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); 709 if (payload_size > 32768u) { 710 read_unlock_bh(&tipc_net_lock); 711 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 712 " (too many links)"); 713 } 714 buf = tipc_cfg_reply_alloc(payload_size); 715 if (!buf) { 716 read_unlock_bh(&tipc_net_lock); 717 return NULL; 718 } 719 720 /* Add TLV for broadcast link */ 721 722 link_info.dest = htonl(tipc_own_addr & 0xfffff00); 723 link_info.up = htonl(1); 724 strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME); 725 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); 726 727 /* Add TLVs for any other links in scope */ 728 729 for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) { 730 u32 i; 731 732 if (!tipc_in_scope(domain, n_ptr->addr)) 733 continue; 734 tipc_node_lock(n_ptr); 735 for (i = 0; i < MAX_BEARERS; i++) { 736 if (!n_ptr->links[i]) 737 continue; 738 link_info.dest = htonl(n_ptr->addr); 739 link_info.up = htonl(tipc_link_is_up(n_ptr->links[i])); 740 strcpy(link_info.str, n_ptr->links[i]->name); 741 tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 742 &link_info, sizeof(link_info)); 743 } 744 tipc_node_unlock(n_ptr); 745 } 746 747 read_unlock_bh(&tipc_net_lock); 748 return buf; 749 } 750