1 : /*
2 : * TIPC Linux kernel implementation
3 : * Copyright (c) 2001-2003 Ericsson Research Canada
4 : * Copyright (c) 2003 OSDL, Inc.
5 : *
6 : * This file is based on the original source code done by Jon Maloy
7 : * (jon.maloy@ericsson.com) for TIPC version 0.96, available from
8 : * http://tipc.sourceforge.net
9 : ***************************************************************************
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 2 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, write to the Free Software
22 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 : ***************************************************************************
24 : * Alphabetical list of people who have worked on this file:
25 : * - Mark Haverkamp (markh@osdl.org)
26 : * - Mika Kukkonen (mika@osdl.org)
27 : * - Rusty Lynch (rusty@linux.intel.com)
28 : */
29 :
30 : #include "cluster.h"
31 : #include "link.h"
32 : #include "local.h"
33 :
34 : static void send_multicast(struct tipc_cluster *, struct sk_buff *, uint, uint);
35 : static struct sk_buff *prepare_routing_msg(uint dataSize);
36 :
37 : struct tipc_node **localnodes = 0;
38 : struct tipc_cluster *cluster_pool = 0;
39 :
40 : struct tipc_cluster *
41 : tipc_cluster_new(tipc_net_addr_t addr)
42 1 : {
43 1 : struct tipc_zone *zone;
44 1 : struct tipc_cluster *cluster;
45 1 : uint zone_id = tipc_zone_id(addr);
46 1 : uint cluster_id = tipc_cluster_id(addr);
47 :
48 : assert(zone_id < TIPC_ZONE_AMOUNT);
49 : assert(cluster_id < TIPC_CLUSTER_AMOUNT);
50 1 : zone = network.zones[zone_id];
51 1 : if (!zone) {
52 1 : int status = 0;
53 :
54 1 : status = tipc_zone_new(zone_id);
55 1 : if (status)
56 0 : return 0;
57 1 : zone = network.zones[zone_id];
58 : }
59 1 : cluster = zone->clusters[cluster_id];
60 1 : if (!cluster) {
61 2 : mem_cnew(cluster, cluster_pool, 12000);
62 1 : zone->clusters[cluster_id] = cluster;
63 1 : cluster->addr = tipc_make_addr(zone_id, cluster_id, 0);
64 1 : cluster->nodes = tipc_local_addr(addr) ? localnodes : cluster->defaultarea;
65 1 : cluster->highestDevice = TIPC_SLAVE_MIN_ID - 1;
66 1 : cluster->highestnode = 0;
67 1 : cluster->owner = zone;
68 1 : netwsub_init(&cluster->subscription, cluster,
69 : (NS_Virtual) tipc_cluster_handleavailable,
70 : (NS_Virtual) tipc_cluster_handleunavailable);
71 : }
72 1 : return cluster;
73 : }
74 :
75 : tipc_net_addr_t
76 : tipc_cluster_nextnode(struct tipc_cluster * this, tipc_net_addr_t addr)
77 0 : {
78 0 : struct tipc_node *p = 0;
79 0 : uint i = tipc_node_id(addr) + 1;
80 :
81 0 : if (!this)
82 0 : return addr;
83 : dbg("tipc_cluster_nextnode() attempting %u->%u\n", i,
84 : this->highestnode);
85 0 : for (; i <= this->highestnode; i++) {
86 0 : p = this->nodes[i];
87 0 : if (p && tipc_node_activelinks(p))
88 0 : return p->addr;
89 : }
90 : dbg("tipc_cluster_nextnode() attempting %u->%u\n", i,
91 : tipc_node_id(addr) - 1);
92 0 : for (i = 1; i < tipc_node_id(addr); i++) {
93 0 : p = this->nodes[i];
94 0 : if (p && tipc_node_activelinks(p))
95 0 : return p->addr;
96 : }
97 : dbg("tipc_cluster_nextnode() returning %x\n", addr);
98 0 : return 0;
99 : }
100 :
101 : void
102 : tipc_cluster_notifyavailable(struct tipc_cluster *this,
103 : struct net_reg * sc)
104 1 : {
105 1 : uint z = tipc_zone_id(this->addr);
106 1 : uint s = tipc_cluster_id(this->addr);
107 1 : uint tstart = 1;
108 1 : uint tstop = this->highestnode;
109 1 : uint x;
110 :
111 3 : for (x = 1; x <= 2; x++) {
112 2 : uint p;
113 :
114 21 : for (p = tstart; p <= tstop; p++) {
115 19 : struct tipc_node *node = this->nodes[p];
116 :
117 19 : if (node && tipc_node_available(node)) {
118 : dbg(" cluster_notify: calling %p->%p for node:%x,hi dev = %i \n", sc, sc->handleAvailableF, tipc_make_addr(z, s, p), this->highestDevice);
119 2 : sc->handleAvailableF(sc->object,
120 : tipc_make_addr(z, s, p));
121 : }
122 : }
123 2 : tstart = TIPC_SLAVE_MIN_ID;
124 2 : tstop = this->highestDevice;
125 : }
126 : }
127 :
128 : void
129 : tipc_cluster_reportlinks(struct tipc_cluster *this, LinkSubscription * sc)
130 0 : {
131 0 : uint tstart = 1;
132 0 : uint tstop = this->highestnode;
133 0 : uint x;
134 :
135 0 : for (x = 1; x <= 2; x++) {
136 0 : uint p;
137 :
138 0 : for (p = tstart; p <= tstop; p++) {
139 0 : struct tipc_node *node = this->nodes[p];
140 :
141 0 : if (node && tipc_node_available(node)) {
142 0 : tipc_node_reportlinks(node, sc);
143 : }
144 : }
145 0 : tstart = TIPC_SLAVE_MIN_ID;
146 0 : tstop = this->highestDevice;
147 : }
148 : }
149 :
150 : void
151 : tipc_cluster_attachnode(struct tipc_cluster *this, struct tipc_node *p)
152 2 : {
153 2 : uint pno = tipc_node_id(p->addr);
154 :
155 : assert(pno > 0);
156 : assert(pno <=
157 : ((tipc_local_addr(p->addr)) ? TIPC_SLAVE_MAX_ID :
158 : TIPC_NODE_MAX_ID));
159 : assert(this->nodes[pno] == 0);
160 2 : this->nodes[pno] = p;
161 : }
162 :
163 : void
164 : tipc_cluster_handleunavailable(struct tipc_cluster *this, tipc_net_addr_t addr)
165 0 : {
166 0 : struct net_reg *cursor;
167 0 : uint *h =
168 0 : tipc_slave_addr(addr) ? &this->highestDevice : &this->highestnode;
169 0 : uint tstop = tipc_slave_addr(addr) ? TIPC_SLAVE_MIN_ID : 1;
170 :
171 0 : if (tipc_node_id(addr) == *h) {
172 0 : while ((--(*h) >= tstop)
173 : && !tipc_node_available(this->nodes[*h])) ;
174 : }
175 0 : cursor = this->subscription.next;
176 0 : while (cursor != &this->subscription) {
177 0 : struct net_reg *nx = cursor->next;
178 :
179 0 : netwsub_handleUnavailable(cursor, addr); /* Might unlink */
180 0 : cursor = nx;
181 : }
182 0 : zone_handleunavailable(this->owner, addr);
183 : }
184 :
185 : void
186 : tipc_cluster_handleavailable(struct tipc_cluster *this, tipc_net_addr_t addr)
187 2 : {
188 2 : struct net_reg *s = this->subscription.next;
189 2 : uint p = tipc_node_id(addr);
190 :
191 : dbg(" Subn_handleAvailable(this = %p, addr =%x,node = %x)\n", this,
192 : addr, p);
193 2 : if (tipc_slave_addr(p)) {
194 0 : if (p > this->highestDevice)
195 0 : this->highestDevice = p;
196 2 : } else if (p > this->highestnode)
197 2 : this->highestnode = p;
198 : dbg(" Subn_handleAvailable 1 s = %p,%p\n", s, &this->subscription);
199 2 : while (s != &this->subscription) {
200 0 : struct net_reg *next = s->next;
201 :
202 : dbg(" Subn_handleAvailable 2 s->next: %p \n", s->next);
203 0 : netwsub_handleAvailable(s, addr);
204 : dbg(" Subn_handleAvailable 3 s->next: %p \n", s->next);
205 0 : s = next;
206 : }
207 : dbg(" Subn_handleAvailable: calling zone: HandleAv\n");
208 2 : zone_handleavailable(this->owner, addr);
209 : }
210 :
211 : /* Deterministic and fair selection of a router to the given remote cluster */
212 : tipc_net_addr_t
213 : tipc_cluster_selectrouter(struct tipc_cluster *this, uint ref)
214 0 : {
215 0 : uint ulim = this->highestnode;
216 0 : uint mask;
217 0 : uint tstart;
218 0 : uint p;
219 :
220 : assert(!tipc_local_addr(this->addr));
221 0 : if (!ulim)
222 0 : return 0;
223 :
224 : /* Start entry must be random */
225 0 : mask = TIPC_NODE_MAX_ID;
226 0 : while (mask > ulim)
227 0 : mask >>= 1;
228 0 : tstart = ref & mask;
229 0 : p = tstart;
230 :
231 : /* Lookup upwards with wrap-around */
232 0 : do {
233 0 : if (tipc_node_available(this->nodes[p]))
234 0 : break;
235 0 : } while (++p <= ulim);
236 0 : if (p > ulim) {
237 0 : p = 1;
238 0 : do {
239 0 : if (tipc_node_available(this->nodes[p]))
240 0 : break;
241 0 : } while (++p < tstart);
242 0 : if (p == tstart)
243 0 : return 0;
244 : }
245 : assert(p <= ulim);
246 0 : return tipc_node_selectrouter(this->nodes[p], ref);
247 : }
248 :
249 : /* Deterministic and fair selection of a node within the given */
250 : /* remote cluster */
251 : struct tipc_node *
252 : tipc_cluster_selectremotenode(struct tipc_cluster *this, uint selector)
253 0 : {
254 0 : uint mask = TIPC_NODE_MAX_ID;
255 0 : uint start_entry;
256 0 : uint p;
257 :
258 : assert(!tipc_local_addr(this->addr));
259 0 : if (!this->highestnode)
260 0 : return 0;
261 :
262 : /* Start entry must be random */
263 0 : while (mask > this->highestnode) {
264 0 : mask >>= 1;
265 : }
266 0 : start_entry = (selector & mask) ? selector & mask : 1u;
267 : assert(start_entry <= this->highestnode);
268 :
269 : /* Lookup upwards with wrap-around */
270 0 : for (p = start_entry; p <= this->highestnode; p++) {
271 0 : if (tipc_node_activelinks(this->nodes[p]))
272 0 : return this->nodes[p];
273 : }
274 0 : for (p = 1; p < start_entry; p++) {
275 0 : if (tipc_node_activelinks(this->nodes[p]))
276 0 : return this->nodes[p];
277 : }
278 0 : return 0;
279 : }
280 :
281 : /* Routing table management: See description in node.cc */
282 : static struct sk_buff *
283 : prepare_routing_msg(uint dataSize)
284 2 : {
285 2 : uint size = INTERNAL_HDR_SIZE + dataSize;
286 2 : struct sk_buff *buf;
287 2 : tipc_msg_hdr_t *msg;
288 :
289 2 : buf = buf_acquire(size);
290 2 : msg = buf_msg(buf);
291 2 : memset((char *) msg, 0, size);
292 4 : set_msg_version(msg, MSG_VERSION_1);
293 4 : set_msg_user(msg, ROUTING_MANAGER);
294 4 : set_hdr_size(msg, INTERNAL_HDR_SIZE);
295 2 : set_prev_node(msg, tipc_my_addr);
296 4 : set_msg_size(msg, size);
297 2 : return buf;
298 : }
299 :
300 : void
301 : tipc_cluster_multicastnewroute(struct tipc_cluster *this, tipc_net_addr_t dest,
302 : uint lower, uint upper)
303 2 : {
304 2 : struct sk_buff *buf = prepare_routing_msg(0);
305 2 : tipc_msg_hdr_t *msg = buf_msg(buf);
306 :
307 2 : set_remote_addr(msg, dest);
308 4 : set_msg_type(msg, ROUTE_ADDITION);
309 2 : send_multicast(this, buf, lower, upper);
310 : }
311 :
312 : void
313 : tipc_cluster_multicastlostroute(struct tipc_cluster *this, tipc_net_addr_t dest,
314 : uint lower, uint upper)
315 0 : {
316 0 : struct sk_buff *buf = prepare_routing_msg(0);
317 0 : tipc_msg_hdr_t *msg = buf_msg(buf);
318 :
319 0 : set_remote_addr(msg, dest);
320 0 : set_msg_type(msg, ROUTE_REMOVAL);
321 0 : send_multicast(this, buf, lower, upper);
322 : }
323 :
324 : void
325 : tipc_cluster_senddeviceroutes(struct tipc_cluster *this, tipc_net_addr_t dest)
326 2 : {
327 2 : uint highest = this->highestDevice;
328 2 : struct sk_buff *buf;
329 2 : tipc_msg_hdr_t *msg;
330 2 : uint i;
331 2 : uint send = 0;
332 2 : Link *l;
333 :
334 : assert(!tipc_slave_addr(dest));
335 : assert(tipc_local_addr(dest));
336 : assert(tipc_local_addr(this->addr));
337 2 : if (highest <= TIPC_SLAVE_MIN_ID)
338 0 : return;
339 0 : buf = prepare_routing_msg(highest - TIPC_SLAVE_MIN_ID + 1);
340 0 : msg = buf_msg(buf);
341 0 : set_remote_addr(msg, this->addr);
342 0 : set_msg_type(msg, DP_ROUTING_TABLE);
343 0 : for (i = TIPC_SLAVE_MIN_ID; i <= highest; i++) {
344 0 : if (this->nodes[i]
345 : && tipc_node_activelinks(this->nodes[i])) {
346 0 : send = 1;
347 0 : set_data_octet(msg, i);
348 : }
349 : }
350 0 : l = link_select(dest, 4);
351 0 : if (l && send)
352 0 : link_sendBuf(l, buf);
353 : else
354 0 : buf_discard(buf);
355 : }
356 :
357 : void
358 : tipc_cluster_sendexternalroutes(struct tipc_cluster *this, tipc_net_addr_t dest)
359 2 : {
360 2 : uint send = 0;
361 2 : uint highest = this->highestnode;
362 2 : struct sk_buff *buf;
363 2 : tipc_msg_hdr_t *msg;
364 2 : uint i;
365 2 : Link *l;
366 :
367 2 : if (tipc_local_addr(this->addr))
368 0 : return;
369 : assert(!tipc_slave_addr(dest));
370 : assert(tipc_local_addr(dest));
371 0 : highest = this->highestnode;
372 : dbg(" Ordering prep msg: highest = %i (%i)\n", highest, highest + 1);
373 0 : buf = prepare_routing_msg(highest + 1);
374 0 : msg = buf_msg(buf);
375 0 : set_remote_addr(msg, this->addr);
376 0 : set_msg_type(msg, EXT_ROUTING_TABLE);
377 :
378 0 : for (i = 1; i <= highest; i++) {
379 0 : if (this->nodes[i]
380 : && tipc_node_activelinks(this->nodes[i])) {
381 0 : send = 1;
382 : dbg(" Setting octet %i (%i)\n", i, i);
383 0 : set_data_octet(msg, i);
384 : }
385 : }
386 :
387 0 : l = link_select(dest, 4);
388 0 : if (l && send)
389 0 : link_sendBuf(l, buf);
390 : else
391 0 : buf_discard(buf);
392 :
393 : }
394 :
395 : void
396 : tipc_cluster_sendlocalroutes(struct tipc_cluster *this, tipc_net_addr_t dest)
397 0 : {
398 0 : uint send = 0;
399 0 : uint highest = this->highestnode;
400 0 : struct sk_buff *buf;
401 0 : tipc_msg_hdr_t *msg;
402 0 : uint i;
403 0 : Link *l;
404 :
405 : assert(tipc_slave_addr(dest));
406 : assert(tipc_local_addr(this->addr));
407 0 : buf = prepare_routing_msg(highest);
408 0 : msg = buf_msg(buf);
409 0 : set_remote_addr(msg, this->addr);
410 0 : set_msg_type(msg, LOCAL_ROUTING_TABLE);
411 0 : for (i = 1; i <= highest; i++) {
412 0 : if (this->nodes[i]
413 : && tipc_node_activelinks(this->nodes[i])) {
414 0 : send = 1;
415 0 : set_data_octet(msg, i);
416 : }
417 : }
418 :
419 0 : l = link_select(dest, 4);
420 0 : if (l && send)
421 0 : link_sendBuf(l, buf);
422 : else
423 0 : buf_discard(buf);
424 : }
425 :
426 : void
427 : tipc_cluster_handleroutingtablemsg(struct sk_buff *buf)
428 0 : {
429 : dbg(" Rec routing msg\n");
430 : {
431 0 : tipc_msg_hdr_t *msg = buf_msg(buf);
432 0 : tipc_net_addr_t addr = get_remote_addr(msg);
433 0 : uint z = tipc_zone_id(addr);
434 0 : uint s = tipc_cluster_id(addr);
435 0 : uint router = get_prev_node(msg);
436 0 : struct tipc_cluster *this = 0;
437 :
438 0 : if (!network.zones[z]->clusters[1])
439 0 : this = network.zones[z]->clusters[1];
440 : dbg(" Creating cluster for %x\n", get_remote_addr(msg));
441 0 : if (!this)
442 0 : this = tipc_cluster_new(get_remote_addr(msg));
443 : dbg(" Created cluster\n");
444 0 : switch (get_msg_type(msg)) {
445 : case LOCAL_ROUTING_TABLE:
446 : {
447 : assert(tipc_slave_addr(tipc_my_addr));
448 : }
449 : case EXT_ROUTING_TABLE:
450 : {
451 0 : __u8 *ptable =
452 0 : UD(buf)->data + get_hdr_size(msg);
453 0 : uint p;
454 0 : uint tableSize =
455 0 : get_msg_size(msg) - get_hdr_size(msg);
456 :
457 0 : for (p = 1; p < tableSize; p++) {
458 0 : if (ptable[p]) {
459 0 : struct tipc_node *node =
460 0 : this->nodes[p];
461 0 : if (!node)
462 0 : node =
463 : tipc_node_new
464 : (tipc_make_addr
465 : (z, s, p));
466 0 : tipc_node_addrouter(node,
467 : router);
468 : }
469 : }
470 0 : break;
471 : }
472 : case DP_ROUTING_TABLE:
473 : {
474 0 : __u8 *ptable =
475 0 : UD(buf)->data + get_hdr_size(msg);
476 0 : uint p;
477 0 : uint tableSize =
478 0 : get_msg_size(msg) - get_hdr_size(msg);
479 :
480 : assert(!tipc_slave_addr(tipc_my_addr));
481 : assert(tipc_local_addr(this->addr));
482 0 : for (p = 1; p < tableSize; p++) {
483 0 : if (ptable[p]) {
484 0 : struct tipc_node *node =
485 : this->nodes[p +
486 0 : TIPC_SLAVE_MIN_ID];
487 0 : if (!node)
488 0 : node =
489 : tipc_node_new
490 : (tipc_make_addr
491 : (z, s,
492 : p +
493 : TIPC_SLAVE_MIN_ID));
494 0 : tipc_node_addrouter(node,
495 : router);
496 : }
497 : }
498 0 : break;
499 : }
500 : case ROUTE_ADDITION:
501 : {
502 0 : struct tipc_node *node;
503 :
504 : dbg(" ROUTE ADD\n");
505 0 : if (!tipc_slave_addr(tipc_my_addr)) {
506 : assert(!tipc_local_addr(this->addr)
507 : ||
508 : tipc_slave_addr(get_remote_addr
509 : (msg)));
510 : } else {
511 : assert(tipc_local_addr(this->addr)
512 : &&
513 : !tipc_slave_addr(get_remote_addr
514 : (msg)));
515 : }
516 0 : node =
517 : this->
518 0 : nodes[tipc_node_id(get_remote_addr(msg))];
519 0 : if (!node)
520 0 : node =
521 0 : tipc_node_new(get_remote_addr(msg));
522 0 : tipc_node_addrouter(node, router);
523 0 : break;
524 : }
525 : case ROUTE_REMOVAL:
526 : {
527 0 : struct tipc_node *node;
528 :
529 0 : if (!tipc_slave_addr(tipc_my_addr)) {
530 : assert(!tipc_local_addr(this->addr)
531 : ||
532 : tipc_slave_addr(get_remote_addr
533 : (msg)));
534 : } else {
535 : assert(tipc_local_addr(this->addr)
536 : &&
537 : !tipc_slave_addr(get_remote_addr
538 : (msg)));
539 : }
540 0 : node =
541 : this->
542 0 : nodes[tipc_node_id(get_remote_addr(msg))];
543 0 : if (node)
544 0 : tipc_node_removerouter(node, router);
545 : break;
546 : }
547 : default:{
548 : assert
549 : (!"Illegal routing manager message received\n");
550 : }
551 : }
552 0 : buf_discard(buf);
553 : }
554 : }
555 :
556 : void
557 : tipc_cluster_removeasrouter(struct tipc_cluster *this, tipc_net_addr_t router)
558 0 : {
559 0 : uint start_entry = 1;
560 0 : uint tstop = this->highestnode;
561 0 : uint p;
562 :
563 0 : if (tipc_slave_addr(router))
564 0 : return; /* Device nodes can not be routers */
565 0 : if (tipc_local_addr(this->addr)) { /* No routes to local system nodes */
566 0 : start_entry = TIPC_SLAVE_MIN_ID;
567 0 : tstop = this->highestDevice;
568 : }
569 0 : for (p = start_entry; p <= tstop; p++) {
570 0 : struct tipc_node *node = this->nodes[p];
571 :
572 0 : if (node)
573 0 : tipc_node_removerouter(node, router);
574 : }
575 : }
576 :
577 : tipc_net_addr_t
578 : tipc_cluster_getrouter(tipc_net_addr_t dest)
579 0 : {
580 0 : struct tipc_cluster *this = 0;
581 0 : uint i = 1;
582 :
583 0 : this = network.zones[tipc_zone_id(dest)]->clusters[1];
584 0 : for (; i <= this->highestnode; i++) {
585 0 : if (this->nodes[i]) {
586 0 : return tipc_node_selectrouter(this->nodes[i], 0);
587 : }
588 : }
589 0 : return 0;
590 : }
591 :
592 : /* Multicast message to local nodes available via direct link */
593 : static void
594 : send_multicast(struct tipc_cluster *this, struct sk_buff *buf, uint lower,
595 : uint upper)
596 2 : {
597 2 : uint tstop;
598 2 : uint i;
599 :
600 : assert(lower <= upper);
601 : assert(((lower >= 1) && (lower <= TIPC_NODE_MAX_ID)) ||
602 : ((lower >= TIPC_SLAVE_MIN_ID)
603 : && (lower <= TIPC_SLAVE_MAX_ID)));
604 : assert(((upper >= 1) && (upper <= TIPC_NODE_MAX_ID))
605 : || ((upper >= TIPC_SLAVE_MIN_ID)
606 : && (upper <= TIPC_SLAVE_MAX_ID)));
607 : assert(tipc_local_addr(this->addr));
608 :
609 2 : tstop =
610 : tipc_slave_addr(upper) ? this->highestDevice : this->highestnode;
611 2 : if (tstop > upper)
612 2 : tstop = upper;
613 :
614 2 : for (i = lower; i <= tstop; i++) {
615 0 : Link *l;
616 0 : struct sk_buff *b;
617 0 : struct tipc_node *p = this->nodes[i];
618 :
619 0 : if (!p || (i == tipc_my_node.id))
620 0 : continue;
621 0 : l = p->activeLinks[i & 7];
622 0 : if (!l)
623 0 : continue;
624 0 : b = buf_copy(buf, UD(buf)->data);
625 0 : link_sendBuf(l, b);
626 : }
627 2 : buf_discard(buf);
628 : }
629 :
630 : /* Broadcast message to all nodes within cluster. */
631 : void
632 : tipc_cluster_broadcast(struct tipc_cluster *this, struct sk_buff *buf)
633 34 : {
634 34 : uint start_entry = 1;
635 34 : uint tstop = this->highestnode;
636 34 : uint x;
637 :
638 : assert(tipc_local_addr(this->addr)); /* For now */
639 102 : for (x = 1; x <= 2; x++) {
640 68 : uint i;
641 :
642 714 : for (i = start_entry; i <= tstop; i++) {
643 646 : Link *l;
644 646 : struct sk_buff *b;
645 646 : struct tipc_node *p = this->nodes[i];
646 :
647 646 : if (!p)
648 68 : continue;
649 68 : l = p->activeLinks[i & 7];
650 68 : if (!l) {
651 0 : l = link_select(p->addr, i);
652 0 : if (!l)
653 68 : continue;
654 : }
655 68 : b = buf_copy(buf, UD(buf)->data);
656 : set_dest_node(buf_msg(b),
657 : tipc_make_addr(tipc_my_zone.id,
658 68 : tipc_my_cluster.id, i));
659 68 : link_sendBuf(l, b);
660 : }
661 68 : start_entry = TIPC_SLAVE_MIN_ID;
662 68 : tstop = this->highestDevice;
663 : }
664 34 : buf_discard(buf);
665 : }
666 :
667 : void
668 : tipc_cluster_addtonodelist(struct tipc_cluster *this, tipc_node_list * list)
669 4 : {
670 4 : uint start = 1;
671 4 : uint stop = this->highestnode;
672 4 : uint i;
673 :
674 4 : if ((list->count * sizeof (list->nodes)) >= 65404)
675 4 : return;
676 12 : for (i = 1; i <= 2; i++) {
677 8 : uint p;
678 :
679 84 : for (p = start; p <= stop; p++) {
680 76 : struct tipc_node *node = this->nodes[p];
681 :
682 76 : if (node) {
683 8 : list->nodes[list->count].addr = node->addr;
684 8 : list->nodes[list->count++].available =
685 : tipc_node_available(node);
686 : }
687 : }
688 8 : start = TIPC_SLAVE_MIN_ID;
689 8 : stop = this->highestDevice;
690 : }
691 : }
692 :
693 : /* This array must be initiated before first message arrives: */
694 : void
695 : tipc_cluster_init(void)
696 1 : {
697 1 : localnodes =
698 : (struct tipc_node **) mem_alloc((TIPC_SLAVE_MAX_ID + 1) *
699 : sizeof (struct tipc_node *));
700 : assert(localnodes);
701 : memset(localnodes, 0,
702 1 : (TIPC_SLAVE_MAX_ID + 1) * sizeof (struct tipc_node *));
703 : }
|