]> bbs.cooldavid.org Git - net-next-2.6.git/blob - net/tipc/cluster.c
tipc: cleanup function namespace
[net-next-2.6.git] / net / tipc / cluster.c
1 /*
2  * net/tipc/cluster.c: TIPC cluster management routines
3  *
4  * Copyright (c) 2000-2006, Ericsson AB
5  * Copyright (c) 2005, 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 "cluster.h"
39 #include "addr.h"
40 #include "node_subscr.h"
41 #include "link.h"
42 #include "node.h"
43 #include "net.h"
44 #include "msg.h"
45 #include "bearer.h"
46
47 static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
48                                 u32 lower, u32 upper);
49 static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest);
50
51 struct tipc_node **tipc_local_nodes = NULL;
52 struct tipc_node_map tipc_cltr_bcast_nodes = {0,{0,}};
53 u32 tipc_highest_allowed_slave = 0;
54
55 struct cluster *tipc_cltr_create(u32 addr)
56 {
57         struct _zone *z_ptr;
58         struct cluster *c_ptr;
59         int max_nodes;
60
61         c_ptr = kzalloc(sizeof(*c_ptr), GFP_ATOMIC);
62         if (c_ptr == NULL) {
63                 warn("Cluster creation failure, no memory\n");
64                 return NULL;
65         }
66
67         c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
68         if (in_own_cluster(addr))
69                 max_nodes = LOWEST_SLAVE + tipc_max_slaves;
70         else
71                 max_nodes = tipc_max_nodes + 1;
72
73         c_ptr->nodes = kcalloc(max_nodes + 1, sizeof(void*), GFP_ATOMIC);
74         if (c_ptr->nodes == NULL) {
75                 warn("Cluster creation failure, no memory for node area\n");
76                 kfree(c_ptr);
77                 return NULL;
78         }
79
80         if (in_own_cluster(addr))
81                 tipc_local_nodes = c_ptr->nodes;
82         c_ptr->highest_slave = LOWEST_SLAVE - 1;
83         c_ptr->highest_node = 0;
84
85         z_ptr = tipc_zone_find(tipc_zone(addr));
86         if (!z_ptr) {
87                 z_ptr = tipc_zone_create(addr);
88         }
89         if (!z_ptr) {
90                 kfree(c_ptr->nodes);
91                 kfree(c_ptr);
92                 return NULL;
93         }
94
95         tipc_zone_attach_cluster(z_ptr, c_ptr);
96         c_ptr->owner = z_ptr;
97         return c_ptr;
98 }
99
100 void tipc_cltr_delete(struct cluster *c_ptr)
101 {
102         u32 n_num;
103
104         if (!c_ptr)
105                 return;
106         for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
107                 tipc_node_delete(c_ptr->nodes[n_num]);
108         }
109         for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
110                 tipc_node_delete(c_ptr->nodes[n_num]);
111         }
112         kfree(c_ptr->nodes);
113         kfree(c_ptr);
114 }
115
116
117 void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr)
118 {
119         u32 n_num = tipc_node(n_ptr->addr);
120         u32 max_n_num = tipc_max_nodes;
121
122         if (in_own_cluster(n_ptr->addr))
123                 max_n_num = tipc_highest_allowed_slave;
124         assert(n_num > 0);
125         assert(n_num <= max_n_num);
126         assert(c_ptr->nodes[n_num] == NULL);
127         c_ptr->nodes[n_num] = n_ptr;
128         if (n_num > c_ptr->highest_node)
129                 c_ptr->highest_node = n_num;
130 }
131
132 /**
133  * tipc_cltr_select_router - select router to a cluster
134  *
135  * Uses deterministic and fair algorithm.
136  */
137
138 u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref)
139 {
140         u32 n_num;
141         u32 ulim = c_ptr->highest_node;
142         u32 mask;
143         u32 tstart;
144
145         assert(!in_own_cluster(c_ptr->addr));
146         if (!ulim)
147                 return 0;
148
149         /* Start entry must be random */
150         mask = tipc_max_nodes;
151         while (mask > ulim)
152                 mask >>= 1;
153         tstart = ref & mask;
154         n_num = tstart;
155
156         /* Lookup upwards with wrap-around */
157         do {
158                 if (tipc_node_is_up(c_ptr->nodes[n_num]))
159                         break;
160         } while (++n_num <= ulim);
161         if (n_num > ulim) {
162                 n_num = 1;
163                 do {
164                         if (tipc_node_is_up(c_ptr->nodes[n_num]))
165                                 break;
166                 } while (++n_num < tstart);
167                 if (n_num == tstart)
168                         return 0;
169         }
170         assert(n_num <= ulim);
171         return tipc_node_select_router(c_ptr->nodes[n_num], ref);
172 }
173
174 /**
175  * tipc_cltr_select_node - select destination node within a remote cluster
176  *
177  * Uses deterministic and fair algorithm.
178  */
179
180 struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
181 {
182         u32 n_num;
183         u32 mask = tipc_max_nodes;
184         u32 start_entry;
185
186         assert(!in_own_cluster(c_ptr->addr));
187         if (!c_ptr->highest_node)
188                 return NULL;
189
190         /* Start entry must be random */
191         while (mask > c_ptr->highest_node) {
192                 mask >>= 1;
193         }
194         start_entry = (selector & mask) ? selector & mask : 1u;
195         assert(start_entry <= c_ptr->highest_node);
196
197         /* Lookup upwards with wrap-around */
198         for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
199                 if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
200                         return c_ptr->nodes[n_num];
201         }
202         for (n_num = 1; n_num < start_entry; n_num++) {
203                 if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
204                         return c_ptr->nodes[n_num];
205         }
206         return NULL;
207 }
208
209 /*
210  *    Routing table management: See description in node.c
211  */
212
213 static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
214 {
215         u32 size = INT_H_SIZE + data_size;
216         struct sk_buff *buf = tipc_buf_acquire(size);
217         struct tipc_msg *msg;
218
219         if (buf) {
220                 msg = buf_msg(buf);
221                 memset((char *)msg, 0, size);
222                 tipc_msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest);
223         }
224         return buf;
225 }
226
227 void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest,
228                              u32 lower, u32 upper)
229 {
230         struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
231         struct tipc_msg *msg;
232
233         if (buf) {
234                 msg = buf_msg(buf);
235                 msg_set_remote_node(msg, dest);
236                 msg_set_type(msg, ROUTE_ADDITION);
237                 tipc_cltr_multicast(c_ptr, buf, lower, upper);
238         } else {
239                 warn("Memory squeeze: broadcast of new route failed\n");
240         }
241 }
242
243 void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest,
244                                 u32 lower, u32 upper)
245 {
246         struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
247         struct tipc_msg *msg;
248
249         if (buf) {
250                 msg = buf_msg(buf);
251                 msg_set_remote_node(msg, dest);
252                 msg_set_type(msg, ROUTE_REMOVAL);
253                 tipc_cltr_multicast(c_ptr, buf, lower, upper);
254         } else {
255                 warn("Memory squeeze: broadcast of lost route failed\n");
256         }
257 }
258
259 void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest)
260 {
261         struct sk_buff *buf;
262         struct tipc_msg *msg;
263         u32 highest = c_ptr->highest_slave;
264         u32 n_num;
265         int send = 0;
266
267         assert(!is_slave(dest));
268         assert(in_own_cluster(dest));
269         assert(in_own_cluster(c_ptr->addr));
270         if (highest <= LOWEST_SLAVE)
271                 return;
272         buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
273                                             c_ptr->addr);
274         if (buf) {
275                 msg = buf_msg(buf);
276                 msg_set_remote_node(msg, c_ptr->addr);
277                 msg_set_type(msg, SLAVE_ROUTING_TABLE);
278                 for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
279                         if (c_ptr->nodes[n_num] &&
280                             tipc_node_has_active_links(c_ptr->nodes[n_num])) {
281                                 send = 1;
282                                 msg_set_dataoctet(msg, n_num);
283                         }
284                 }
285                 if (send)
286                         tipc_link_send(buf, dest, dest);
287                 else
288                         buf_discard(buf);
289         } else {
290                 warn("Memory squeeze: broadcast of lost route failed\n");
291         }
292 }
293
294 void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest)
295 {
296         struct sk_buff *buf;
297         struct tipc_msg *msg;
298         u32 highest = c_ptr->highest_node;
299         u32 n_num;
300         int send = 0;
301
302         if (in_own_cluster(c_ptr->addr))
303                 return;
304         assert(!is_slave(dest));
305         assert(in_own_cluster(dest));
306         highest = c_ptr->highest_node;
307         buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr);
308         if (buf) {
309                 msg = buf_msg(buf);
310                 msg_set_remote_node(msg, c_ptr->addr);
311                 msg_set_type(msg, EXT_ROUTING_TABLE);
312                 for (n_num = 1; n_num <= highest; n_num++) {
313                         if (c_ptr->nodes[n_num] &&
314                             tipc_node_has_active_links(c_ptr->nodes[n_num])) {
315                                 send = 1;
316                                 msg_set_dataoctet(msg, n_num);
317                         }
318                 }
319                 if (send)
320                         tipc_link_send(buf, dest, dest);
321                 else
322                         buf_discard(buf);
323         } else {
324                 warn("Memory squeeze: broadcast of external route failed\n");
325         }
326 }
327
328 void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest)
329 {
330         struct sk_buff *buf;
331         struct tipc_msg *msg;
332         u32 highest = c_ptr->highest_node;
333         u32 n_num;
334         int send = 0;
335
336         assert(is_slave(dest));
337         assert(in_own_cluster(c_ptr->addr));
338         buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr);
339         if (buf) {
340                 msg = buf_msg(buf);
341                 msg_set_remote_node(msg, c_ptr->addr);
342                 msg_set_type(msg, LOCAL_ROUTING_TABLE);
343                 for (n_num = 1; n_num <= highest; n_num++) {
344                         if (c_ptr->nodes[n_num] &&
345                             tipc_node_has_active_links(c_ptr->nodes[n_num])) {
346                                 send = 1;
347                                 msg_set_dataoctet(msg, n_num);
348                         }
349                 }
350                 if (send)
351                         tipc_link_send(buf, dest, dest);
352                 else
353                         buf_discard(buf);
354         } else {
355                 warn("Memory squeeze: broadcast of local route failed\n");
356         }
357 }
358
359 void tipc_cltr_recv_routing_table(struct sk_buff *buf)
360 {
361         struct tipc_msg *msg = buf_msg(buf);
362         struct cluster *c_ptr;
363         struct tipc_node *n_ptr;
364         unchar *node_table;
365         u32 table_size;
366         u32 router;
367         u32 rem_node = msg_remote_node(msg);
368         u32 z_num;
369         u32 c_num;
370         u32 n_num;
371
372         c_ptr = tipc_cltr_find(rem_node);
373         if (!c_ptr) {
374                 c_ptr = tipc_cltr_create(rem_node);
375                 if (!c_ptr) {
376                         buf_discard(buf);
377                         return;
378                 }
379         }
380
381         node_table = buf->data + msg_hdr_sz(msg);
382         table_size = msg_size(msg) - msg_hdr_sz(msg);
383         router = msg_prevnode(msg);
384         z_num = tipc_zone(rem_node);
385         c_num = tipc_cluster(rem_node);
386
387         switch (msg_type(msg)) {
388         case LOCAL_ROUTING_TABLE:
389                 assert(is_slave(tipc_own_addr));
390         case EXT_ROUTING_TABLE:
391                 for (n_num = 1; n_num < table_size; n_num++) {
392                         if (node_table[n_num]) {
393                                 u32 addr = tipc_addr(z_num, c_num, n_num);
394                                 n_ptr = c_ptr->nodes[n_num];
395                                 if (!n_ptr) {
396                                         n_ptr = tipc_node_create(addr);
397                                 }
398                                 if (n_ptr)
399                                         tipc_node_add_router(n_ptr, router);
400                         }
401                 }
402                 break;
403         case SLAVE_ROUTING_TABLE:
404                 assert(!is_slave(tipc_own_addr));
405                 assert(in_own_cluster(c_ptr->addr));
406                 for (n_num = 1; n_num < table_size; n_num++) {
407                         if (node_table[n_num]) {
408                                 u32 slave_num = n_num + LOWEST_SLAVE;
409                                 u32 addr = tipc_addr(z_num, c_num, slave_num);
410                                 n_ptr = c_ptr->nodes[slave_num];
411                                 if (!n_ptr) {
412                                         n_ptr = tipc_node_create(addr);
413                                 }
414                                 if (n_ptr)
415                                         tipc_node_add_router(n_ptr, router);
416                         }
417                 }
418                 break;
419         case ROUTE_ADDITION:
420                 if (!is_slave(tipc_own_addr)) {
421                         assert(!in_own_cluster(c_ptr->addr) ||
422                                is_slave(rem_node));
423                 } else {
424                         assert(in_own_cluster(c_ptr->addr) &&
425                                !is_slave(rem_node));
426                 }
427                 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
428                 if (!n_ptr)
429                         n_ptr = tipc_node_create(rem_node);
430                 if (n_ptr)
431                         tipc_node_add_router(n_ptr, router);
432                 break;
433         case ROUTE_REMOVAL:
434                 if (!is_slave(tipc_own_addr)) {
435                         assert(!in_own_cluster(c_ptr->addr) ||
436                                is_slave(rem_node));
437                 } else {
438                         assert(in_own_cluster(c_ptr->addr) &&
439                                !is_slave(rem_node));
440                 }
441                 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
442                 if (n_ptr)
443                         tipc_node_remove_router(n_ptr, router);
444                 break;
445         default:
446                 assert(!"Illegal routing manager message received\n");
447         }
448         buf_discard(buf);
449 }
450
451 void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router)
452 {
453         u32 start_entry;
454         u32 tstop;
455         u32 n_num;
456
457         if (is_slave(router))
458                 return; /* Slave nodes can not be routers */
459
460         if (in_own_cluster(c_ptr->addr)) {
461                 start_entry = LOWEST_SLAVE;
462                 tstop = c_ptr->highest_slave;
463         } else {
464                 start_entry = 1;
465                 tstop = c_ptr->highest_node;
466         }
467
468         for (n_num = start_entry; n_num <= tstop; n_num++) {
469                 if (c_ptr->nodes[n_num]) {
470                         tipc_node_remove_router(c_ptr->nodes[n_num], router);
471                 }
472         }
473 }
474
475 /**
476  * tipc_cltr_multicast - multicast message to local nodes
477  */
478
479 static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
480                          u32 lower, u32 upper)
481 {
482         struct sk_buff *buf_copy;
483         struct tipc_node *n_ptr;
484         u32 n_num;
485         u32 tstop;
486
487         assert(lower <= upper);
488         assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
489                ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave)));
490         assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
491                ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave)));
492         assert(in_own_cluster(c_ptr->addr));
493
494         tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
495         if (tstop > upper)
496                 tstop = upper;
497         for (n_num = lower; n_num <= tstop; n_num++) {
498                 n_ptr = c_ptr->nodes[n_num];
499                 if (n_ptr && tipc_node_has_active_links(n_ptr)) {
500                         buf_copy = skb_copy(buf, GFP_ATOMIC);
501                         if (buf_copy == NULL)
502                                 break;
503                         msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
504                         tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
505                 }
506         }
507         buf_discard(buf);
508 }
509
510 /**
511  * tipc_cltr_broadcast - broadcast message to all nodes within cluster
512  */
513
514 void tipc_cltr_broadcast(struct sk_buff *buf)
515 {
516         struct sk_buff *buf_copy;
517         struct cluster *c_ptr;
518         struct tipc_node *n_ptr;
519         u32 n_num;
520         u32 tstart;
521         u32 tstop;
522         u32 node_type;
523
524         if (tipc_mode == TIPC_NET_MODE) {
525                 c_ptr = tipc_cltr_find(tipc_own_addr);
526                 assert(in_own_cluster(c_ptr->addr));    /* For now */
527
528                 /* Send to standard nodes, then repeat loop sending to slaves */
529                 tstart = 1;
530                 tstop = c_ptr->highest_node;
531                 for (node_type = 1; node_type <= 2; node_type++) {
532                         for (n_num = tstart; n_num <= tstop; n_num++) {
533                                 n_ptr = c_ptr->nodes[n_num];
534                                 if (n_ptr && tipc_node_has_active_links(n_ptr)) {
535                                         buf_copy = skb_copy(buf, GFP_ATOMIC);
536                                         if (buf_copy == NULL)
537                                                 goto exit;
538                                         msg_set_destnode(buf_msg(buf_copy),
539                                                          n_ptr->addr);
540                                         tipc_link_send(buf_copy, n_ptr->addr,
541                                                        n_ptr->addr);
542                                 }
543                         }
544                         tstart = LOWEST_SLAVE;
545                         tstop = c_ptr->highest_slave;
546                 }
547         }
548 exit:
549         buf_discard(buf);
550 }
551
552 int tipc_cltr_init(void)
553 {
554         tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
555         return tipc_cltr_create(tipc_own_addr) ? 0 : -ENOMEM;
556 }
557