node.c 19.7 KB
Newer Older
P
Per Liden 已提交
1 2 3
/*
 * net/tipc/node.c: TIPC node management routines
 * 
P
Per Liden 已提交
4
 * Copyright (c) 2000-2006, Ericsson AB
P
Per Liden 已提交
5 6 7
 * Copyright (c) 2005, Wind River Systems
 * All rights reserved.
 *
P
Per Liden 已提交
8
 * Redistribution and use in source and binary forms, with or without
P
Per Liden 已提交
9 10
 * modification, are permitted provided that the following conditions are met:
 *
P
Per Liden 已提交
11 12 13 14 15 16 17 18
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
P
Per Liden 已提交
19
 *
P
Per Liden 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
P
Per Liden 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "core.h"
#include "config.h"
#include "node.h"
#include "cluster.h"
#include "net.h"
#include "addr.h"
#include "node_subscr.h"
#include "link.h"
#include "port.h"
#include "bearer.h"
#include "name_distr.h"

void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
static void node_lost_contact(struct node *n_ptr);
static void node_established_contact(struct node *n_ptr);

53
struct node *tipc_nodes = NULL;	/* sorted list of nodes within cluster */
P
Per Liden 已提交
54 55 56

u32 tipc_own_tag = 0;

57
struct node *tipc_node_create(u32 addr)
P
Per Liden 已提交
58 59 60 61 62 63 64 65 66 67 68 69
{
	struct cluster *c_ptr;
	struct node *n_ptr;
        struct node **curr_node;

	n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
        if (n_ptr != NULL) {
                memset(n_ptr, 0, sizeof(*n_ptr));
                n_ptr->addr = addr;
                n_ptr->lock =  SPIN_LOCK_UNLOCKED;	
                INIT_LIST_HEAD(&n_ptr->nsub);
	
70
		c_ptr = tipc_cltr_find(addr);
P
Per Liden 已提交
71
                if (c_ptr == NULL)
72
                        c_ptr = tipc_cltr_create(addr);
P
Per Liden 已提交
73 74
                if (c_ptr != NULL) {
                        n_ptr->owner = c_ptr;
75
                        tipc_cltr_attach_node(c_ptr, n_ptr);
P
Per Liden 已提交
76 77 78
                        n_ptr->last_router = -1;

                        /* Insert node into ordered list */
79
                        for (curr_node = &tipc_nodes; *curr_node; 
P
Per Liden 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
			     curr_node = &(*curr_node)->next) {
                                if (addr < (*curr_node)->addr) {
                                        n_ptr->next = *curr_node;
                                        break;
                                }
                        }
                        (*curr_node) = n_ptr;
                } else {
                        kfree(n_ptr);
                        n_ptr = NULL;
                }
        }
	return n_ptr;
}

95
void tipc_node_delete(struct node *n_ptr)
P
Per Liden 已提交
96 97 98 99 100
{
	if (!n_ptr)
		return;

#if 0
101
	/* Not needed because links are already deleted via tipc_bearer_stop() */
P
Per Liden 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115

	u32 l_num;

	for (l_num = 0; l_num < MAX_BEARERS; l_num++) {
		link_delete(n_ptr->links[l_num]);
	}
#endif

	dbg("node %x deleted\n", n_ptr->addr);
	kfree(n_ptr);
}


/**
116
 * tipc_node_link_up - handle addition of link
P
Per Liden 已提交
117 118 119 120
 * 
 * Link becomes active (alone or shared) or standby, depending on its priority.
 */

121
void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
P
Per Liden 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
{
	struct link **active = &n_ptr->active_links[0];

	info("Established link <%s> on network plane %c\n",
	     l_ptr->name, l_ptr->b_ptr->net_plane);
	
	if (!active[0]) {
		dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]);
		active[0] = active[1] = l_ptr;
		node_established_contact(n_ptr);
		return;
	}
	if (l_ptr->priority < active[0]->priority) { 
		info("Link is standby\n");
		return;
	}
138
	tipc_link_send_duplicate(active[0], l_ptr);
P
Per Liden 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	if (l_ptr->priority == active[0]->priority) { 
		active[0] = l_ptr;
		return;
	}
	info("Link <%s> on network plane %c becomes standby\n",
	     active[0]->name, active[0]->b_ptr->net_plane);
	active[0] = active[1] = l_ptr;
}

/**
 * node_select_active_links - select active link
 */

static void node_select_active_links(struct node *n_ptr)
{
	struct link **active = &n_ptr->active_links[0];
	u32 i;
	u32 highest_prio = 0;

158
        active[0] = active[1] = NULL;
P
Per Liden 已提交
159 160 161 162

	for (i = 0; i < MAX_BEARERS; i++) {
                struct link *l_ptr = n_ptr->links[i];

163
		if (!l_ptr || !tipc_link_is_up(l_ptr) ||
P
Per Liden 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176
		    (l_ptr->priority < highest_prio))
			continue;

		if (l_ptr->priority > highest_prio) {
                        highest_prio = l_ptr->priority;
			active[0] = active[1] = l_ptr;
		} else {
			active[1] = l_ptr;
		}
	}
}

/**
177
 * tipc_node_link_down - handle loss of link
P
Per Liden 已提交
178 179
 */

180
void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
P
Per Liden 已提交
181 182 183
{
	struct link **active;

184
	if (!tipc_link_is_active(l_ptr)) {
P
Per Liden 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198
		info("Lost standby link <%s> on network plane %c\n",
		     l_ptr->name, l_ptr->b_ptr->net_plane);
		return;
	}
	info("Lost link <%s> on network plane %c\n",
		l_ptr->name, l_ptr->b_ptr->net_plane);

	active = &n_ptr->active_links[0];
	if (active[0] == l_ptr)
		active[0] = active[1];
	if (active[1] == l_ptr)
		active[1] = active[0];
	if (active[0] == l_ptr)
		node_select_active_links(n_ptr);
199 200
	if (tipc_node_is_up(n_ptr)) 
		tipc_link_changeover(l_ptr);
P
Per Liden 已提交
201 202 203 204
	else 
		node_lost_contact(n_ptr);
}

205
int tipc_node_has_active_links(struct node *n_ptr)
P
Per Liden 已提交
206 207 208 209 210
{
	return (n_ptr && 
		((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
}

211
int tipc_node_has_redundant_links(struct node *n_ptr)
P
Per Liden 已提交
212
{
213
	return (tipc_node_has_active_links(n_ptr) &&
P
Per Liden 已提交
214 215 216
		(n_ptr->active_links[0] != n_ptr->active_links[1]));
}

A
Adrian Bunk 已提交
217
static int tipc_node_has_active_routes(struct node *n_ptr)
P
Per Liden 已提交
218 219 220 221
{
	return (n_ptr && (n_ptr->last_router >= 0));
}

222
int tipc_node_is_up(struct node *n_ptr)
P
Per Liden 已提交
223
{
224
	return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
P
Per Liden 已提交
225 226
}

227
struct node *tipc_node_attach_link(struct link *l_ptr)
P
Per Liden 已提交
228
{
229
	struct node *n_ptr = tipc_node_find(l_ptr->addr);
P
Per Liden 已提交
230 231

	if (!n_ptr)
232
		n_ptr = tipc_node_create(l_ptr->addr);
P
Per Liden 已提交
233 234 235 236 237 238 239 240 241 242
        if (n_ptr) {
		u32 bearer_id = l_ptr->b_ptr->identity;
		char addr_string[16];

                assert(bearer_id < MAX_BEARERS);
                if (n_ptr->link_cnt >= 2) {
			char addr_string[16];

                        err("Attempt to create third link to %s\n",
			    addr_string_fill(addr_string, n_ptr->addr));
243
                        return NULL;
P
Per Liden 已提交
244 245 246 247
                }

                if (!n_ptr->links[bearer_id]) {
                        n_ptr->links[bearer_id] = l_ptr;
248
                        tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
P
Per Liden 已提交
249 250 251 252 253 254 255
                        n_ptr->link_cnt++;
                        return n_ptr;
                }
                err("Attempt to establish second link on <%s> to <%s> \n",
                    l_ptr->b_ptr->publ.name, 
		    addr_string_fill(addr_string, l_ptr->addr));
        }
256
	return NULL;
P
Per Liden 已提交
257 258
}

259
void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
P
Per Liden 已提交
260
{
261
	n_ptr->links[l_ptr->b_ptr->identity] = NULL;
262
	tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
P
Per Liden 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	n_ptr->link_cnt--;
}

/*
 * Routing table management - five cases to handle:
 *
 * 1: A link towards a zone/cluster external node comes up.
 *    => Send a multicast message updating routing tables of all 
 *    system nodes within own cluster that the new destination 
 *    can be reached via this node. 
 *    (node.establishedContact()=>cluster.multicastNewRoute())
 *
 * 2: A link towards a slave node comes up.
 *    => Send a multicast message updating routing tables of all 
 *    system nodes within own cluster that the new destination 
 *    can be reached via this node. 
 *    (node.establishedContact()=>cluster.multicastNewRoute())
 *    => Send a  message to the slave node about existence 
 *    of all system nodes within cluster:
 *    (node.establishedContact()=>cluster.sendLocalRoutes())
 *
 * 3: A new cluster local system node becomes available.
 *    => Send message(s) to this particular node containing
 *    information about all cluster external and slave
 *     nodes which can be reached via this node.
 *    (node.establishedContact()==>network.sendExternalRoutes())
 *    (node.establishedContact()==>network.sendSlaveRoutes())
 *    => Send messages to all directly connected slave nodes 
 *    containing information about the existence of the new node
 *    (node.establishedContact()=>cluster.multicastNewRoute())
 *    
 * 4: The link towards a zone/cluster external node or slave
 *    node goes down.
 *    => Send a multcast message updating routing tables of all 
 *    nodes within cluster that the new destination can not any
 *    longer be reached via this node.
 *    (node.lostAllLinks()=>cluster.bcastLostRoute())
 *
 * 5: A cluster local system node becomes unavailable.
 *    => Remove all references to this node from the local
 *    routing tables. Note: This is a completely node
 *    local operation.
 *    (node.lostAllLinks()=>network.removeAsRouter())
 *    => Send messages to all directly connected slave nodes 
 *    containing information about loss of the node
 *    (node.establishedContact()=>cluster.multicastLostRoute())
 *
 */

static void node_established_contact(struct node *n_ptr)
{
	struct cluster *c_ptr;

	dbg("node_established_contact:-> %x\n", n_ptr->addr);
317 318
	if (!tipc_node_has_active_routes(n_ptr)) { 
		tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
P
Per Liden 已提交
319 320 321
	}

        /* Syncronize broadcast acks */
322
        n_ptr->bclink.acked = tipc_bclink_get_last_sent();
P
Per Liden 已提交
323 324 325 326 327

	if (is_slave(tipc_own_addr))
		return;
	if (!in_own_cluster(n_ptr->addr)) {
		/* Usage case 1 (see above) */
328
		c_ptr = tipc_cltr_find(tipc_own_addr);
P
Per Liden 已提交
329
		if (!c_ptr)
330
			c_ptr = tipc_cltr_create(tipc_own_addr);
P
Per Liden 已提交
331
                if (c_ptr)
332 333
                        tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, 
						  tipc_max_nodes);
P
Per Liden 已提交
334 335 336 337 338 339
		return;
	} 

	c_ptr = n_ptr->owner;
	if (is_slave(n_ptr->addr)) {
		/* Usage case 2 (see above) */
340 341
		tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
		tipc_cltr_send_local_routes(c_ptr, n_ptr->addr);
P
Per Liden 已提交
342 343 344 345
		return;
	}

	if (n_ptr->bclink.supported) {
346
		tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr);
P
Per Liden 已提交
347 348 349 350 351
		if (n_ptr->addr < tipc_own_addr)
			tipc_own_tag++;
	}

	/* Case 3 (see above) */
352 353 354 355
	tipc_net_send_external_routes(n_ptr->addr);
	tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr);
	tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
				  tipc_highest_allowed_slave);
P
Per Liden 已提交
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
}

static void node_lost_contact(struct node *n_ptr)
{
	struct cluster *c_ptr;
	struct node_subscr *ns, *tns;
	char addr_string[16];
	u32 i;

        /* Clean up broadcast reception remains */
        n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
        while (n_ptr->bclink.deferred_head) {
                struct sk_buff* buf = n_ptr->bclink.deferred_head;
                n_ptr->bclink.deferred_head = buf->next;
                buf_discard(buf);
        }
        if (n_ptr->bclink.defragm) {
                buf_discard(n_ptr->bclink.defragm);  
                n_ptr->bclink.defragm = NULL;
        }            
        if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { 
377
                tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
P
Per Liden 已提交
378 379 380 381
        }

        /* Update routing tables */
	if (is_slave(tipc_own_addr)) {
382
		tipc_net_remove_as_router(n_ptr->addr);
P
Per Liden 已提交
383 384 385
	} else {
		if (!in_own_cluster(n_ptr->addr)) { 
			/* Case 4 (see above) */
386 387 388
			c_ptr = tipc_cltr_find(tipc_own_addr);
			tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
						   tipc_max_nodes);
P
Per Liden 已提交
389 390
		} else {
			/* Case 5 (see above) */
391
			c_ptr = tipc_cltr_find(n_ptr->addr);
P
Per Liden 已提交
392
			if (is_slave(n_ptr->addr)) {
393 394
				tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
							   tipc_max_nodes);
P
Per Liden 已提交
395 396
			} else {
				if (n_ptr->bclink.supported) {
397 398
					tipc_nmap_remove(&tipc_cltr_bcast_nodes, 
							 n_ptr->addr);
P
Per Liden 已提交
399 400 401
					if (n_ptr->addr < tipc_own_addr)
						tipc_own_tag--;
				}
402 403 404 405
				tipc_net_remove_as_router(n_ptr->addr);
				tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr,
							   LOWEST_SLAVE,
							   tipc_highest_allowed_slave);
P
Per Liden 已提交
406 407 408
			}
		}
	}
409
	if (tipc_node_has_active_routes(n_ptr))
P
Per Liden 已提交
410 411 412 413 414 415 416 417 418 419 420 421
		return;

	info("Lost contact with %s\n", 
	     addr_string_fill(addr_string, n_ptr->addr));

	/* Abort link changeover */
	for (i = 0; i < MAX_BEARERS; i++) {
		struct link *l_ptr = n_ptr->links[i];
		if (!l_ptr) 
			continue;
		l_ptr->reset_checkpoint = l_ptr->next_in_no;
		l_ptr->exp_msg_count = 0;
422
		tipc_link_reset_fragments(l_ptr);
P
Per Liden 已提交
423 424 425 426
	}

	/* Notify subscribers */
	list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
427
                ns->node = NULL;
P
Per Liden 已提交
428
		list_del_init(&ns->nodesub_list);
429 430
		tipc_k_signal((Handler)ns->handle_node_down,
			      (unsigned long)ns->usr_handle);
P
Per Liden 已提交
431 432 433 434
	}
}

/**
435
 * tipc_node_select_next_hop - find the next-hop node for a message
P
Per Liden 已提交
436 437 438 439
 * 
 * Called by when cluster local lookup has failed.
 */

440
struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
P
Per Liden 已提交
441 442 443 444
{
	struct node *n_ptr;
	u32 router_addr;

445
        if (!tipc_addr_domain_valid(addr))
446
                return NULL;
P
Per Liden 已提交
447 448

	/* Look for direct link to destination processsor */
449 450
	n_ptr = tipc_node_find(addr);
	if (n_ptr && tipc_node_has_active_links(n_ptr))
P
Per Liden 已提交
451 452 453 454
                return n_ptr;

	/* Cluster local system nodes *must* have direct links */
	if (!is_slave(addr) && in_own_cluster(addr))
455
		return NULL;
P
Per Liden 已提交
456 457

	/* Look for cluster local router with direct link to node */
458
	router_addr = tipc_node_select_router(n_ptr, selector);
P
Per Liden 已提交
459
	if (router_addr) 
460
                return tipc_node_select(router_addr, selector);
P
Per Liden 已提交
461 462 463 464

	/* Slave nodes can only be accessed within own cluster via a 
	   known router with direct link -- if no router was found,give up */
	if (is_slave(addr))
465
		return NULL;
P
Per Liden 已提交
466 467 468

	/* Inter zone/cluster -- find any direct link to remote cluster */
	addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
469 470
	n_ptr = tipc_net_select_remote_node(addr, selector);
	if (n_ptr && tipc_node_has_active_links(n_ptr))
P
Per Liden 已提交
471 472 473
                return n_ptr;

	/* Last resort -- look for any router to anywhere in remote zone */
474
	router_addr =  tipc_net_select_router(addr, selector);
P
Per Liden 已提交
475
	if (router_addr) 
476
                return tipc_node_select(router_addr, selector);
P
Per Liden 已提交
477

478
        return NULL;
P
Per Liden 已提交
479 480 481
}

/**
482
 * tipc_node_select_router - select router to reach specified node
P
Per Liden 已提交
483 484 485 486
 * 
 * Uses a deterministic and fair algorithm for selecting router node. 
 */

487
u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
P
Per Liden 已提交
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
{
	u32 ulim;
	u32 mask;
	u32 start;
	u32 r;

        if (!n_ptr)
                return 0;

	if (n_ptr->last_router < 0)
		return 0;
	ulim = ((n_ptr->last_router + 1) * 32) - 1;

	/* Start entry must be random */
	mask = tipc_max_nodes;
	while (mask > ulim)
		mask >>= 1;
	start = ref & mask;
	r = start;

	/* Lookup upwards with wrap-around */
	do {
		if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
			break;
	} while (++r <= ulim);
	if (r > ulim) {
		r = 1;
		do {
			if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
				break;
		} while (++r < start);
		assert(r != start);
	}
	assert(r && (r <= ulim));
	return tipc_addr(own_zone(), own_cluster(), r);
}

525
void tipc_node_add_router(struct node *n_ptr, u32 router)
P
Per Liden 已提交
526 527 528 529 530 531 532 533 534 535
{
	u32 r_num = tipc_node(router);

	n_ptr->routers[r_num / 32] = 
		((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
	n_ptr->last_router = tipc_max_nodes / 32;
	while ((--n_ptr->last_router >= 0) && 
	       !n_ptr->routers[n_ptr->last_router]);
}

536
void tipc_node_remove_router(struct node *n_ptr, u32 router)
P
Per Liden 已提交
537 538 539 540 541 542 543 544 545 546 547 548
{
	u32 r_num = tipc_node(router);

	if (n_ptr->last_router < 0)
		return;		/* No routes */

	n_ptr->routers[r_num / 32] =
		((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
	n_ptr->last_router = tipc_max_nodes / 32;
	while ((--n_ptr->last_router >= 0) && 
	       !n_ptr->routers[n_ptr->last_router]);

549
	if (!tipc_node_is_up(n_ptr))
P
Per Liden 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
		node_lost_contact(n_ptr);
}

#if 0
void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
{
	u32 i;

	tipc_printf(buf, "\n\n%s", str);
	for (i = 0; i < MAX_BEARERS; i++) {
		if (!n_ptr->links[i]) 
			continue;
		tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
	}
	tipc_printf(buf, "Active links: [%x,%x]\n",
		    n_ptr->active_links[0], n_ptr->active_links[1]);
}
#endif

u32 tipc_available_nodes(const u32 domain)
{
	struct node *n_ptr;
	u32 cnt = 0;

574
	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
P
Per Liden 已提交
575 576
		if (!in_scope(domain, n_ptr->addr))
			continue;
577
		if (tipc_node_is_up(n_ptr))
P
Per Liden 已提交
578 579 580 581 582
			cnt++;
	}
	return cnt;
}

583
struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
P
Per Liden 已提交
584 585 586 587 588 589 590
{
	u32 domain;
	struct sk_buff *buf;
	struct node *n_ptr;
        struct tipc_node_info node_info;

	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
591
		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
P
Per Liden 已提交
592 593 594

	domain = *(u32 *)TLV_DATA(req_tlv_area);
	domain = ntohl(domain);
595 596 597
	if (!tipc_addr_domain_valid(domain))
		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
						   " (network address)");
P
Per Liden 已提交
598

599 600
        if (!tipc_nodes)
                return tipc_cfg_reply_none();
P
Per Liden 已提交
601 602 603 604

	/* For now, get space for all other nodes 
	   (will need to modify this when slave nodes are supported */

605 606
	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
				   (tipc_max_nodes - 1));
P
Per Liden 已提交
607 608 609 610 611
	if (!buf)
		return NULL;

	/* Add TLVs for all nodes in scope */

612
	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
P
Per Liden 已提交
613 614 615
		if (!in_scope(domain, n_ptr->addr))
			continue;
                node_info.addr = htonl(n_ptr->addr);
616 617 618
                node_info.up = htonl(tipc_node_is_up(n_ptr));
		tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, 
				    &node_info, sizeof(node_info));
P
Per Liden 已提交
619 620 621 622 623
	}

	return buf;
}

624
struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
P
Per Liden 已提交
625 626 627 628 629 630 631
{
	u32 domain;
	struct sk_buff *buf;
	struct node *n_ptr;
        struct tipc_link_info link_info;

	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
632
		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
P
Per Liden 已提交
633 634 635

	domain = *(u32 *)TLV_DATA(req_tlv_area);
	domain = ntohl(domain);
636 637 638
	if (!tipc_addr_domain_valid(domain))
		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
						   " (network address)");
P
Per Liden 已提交
639

640 641
        if (!tipc_nodes)
                return tipc_cfg_reply_none();
P
Per Liden 已提交
642 643 644 645

	/* For now, get space for 2 links to all other nodes + bcast link 
	   (will need to modify this when slave nodes are supported */

646 647
	buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
				   (2 * (tipc_max_nodes - 1) + 1));
P
Per Liden 已提交
648 649 650 651 652 653 654 655
	if (!buf)
		return NULL;

	/* Add TLV for broadcast link */

        link_info.dest = tipc_own_addr & 0xfffff00;
	link_info.dest = htonl(link_info.dest);
        link_info.up = htonl(1);
656 657
        sprintf(link_info.str, tipc_bclink_name);
	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
P
Per Liden 已提交
658 659 660

	/* Add TLVs for any other links in scope */

661
	for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
P
Per Liden 已提交
662 663 664 665 666 667 668 669
                u32 i;

		if (!in_scope(domain, n_ptr->addr))
			continue;
                for (i = 0; i < MAX_BEARERS; i++) {
                        if (!n_ptr->links[i]) 
                                continue;
                        link_info.dest = htonl(n_ptr->addr);
670
                        link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
P
Per Liden 已提交
671
                        strcpy(link_info.str, n_ptr->links[i]->name);
672 673
			tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, 
					    &link_info, sizeof(link_info));
P
Per Liden 已提交
674 675 676 677 678
                }
	}

	return buf;
}