blob: 405be87157ba011c433fb166875ff8711306356a [file] [log] [blame]
Per Lidenb97bf3f2006-01-02 19:04:38 +01001/*
2 * net/tipc/cluster.c: TIPC cluster management routines
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +09003 *
Per Liden593a5f22006-01-11 19:14:19 +01004 * Copyright (c) 2000-2006, Ericsson AB
Per Lidenb97bf3f2006-01-02 19:04:38 +01005 * Copyright (c) 2005, Wind River Systems
Per Lidenb97bf3f2006-01-02 19:04:38 +01006 * 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 *
Per Liden9ea1fd32006-01-11 13:30:43 +010011 * 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.
Per Lidenb97bf3f2006-01-02 19:04:38 +010023 *
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"
Per Lidenb97bf3f2006-01-02 19:04:38 +010039#include "link.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010040
Adrian Bunk988f0882006-03-20 22:37:52 -080041static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
42 u32 lower, u32 upper);
Per Lidenb97bf3f2006-01-02 19:04:38 +010043
David S. Miller6c000552008-09-02 23:38:32 -070044struct tipc_node **tipc_local_nodes = NULL;
45struct tipc_node_map tipc_cltr_bcast_nodes = {0,{0,}};
Per Liden4323add2006-01-18 00:38:21 +010046u32 tipc_highest_allowed_slave = 0;
Per Lidenb97bf3f2006-01-02 19:04:38 +010047
Per Liden4323add2006-01-18 00:38:21 +010048struct cluster *tipc_cltr_create(u32 addr)
Per Lidenb97bf3f2006-01-02 19:04:38 +010049{
50 struct _zone *z_ptr;
51 struct cluster *c_ptr;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +090052 int max_nodes;
Per Lidenb97bf3f2006-01-02 19:04:38 +010053
Panagiotis Issaris0da974f2006-07-21 14:51:30 -070054 c_ptr = kzalloc(sizeof(*c_ptr), GFP_ATOMIC);
Allan Stephensa10bd922006-06-25 23:52:17 -070055 if (c_ptr == NULL) {
56 warn("Cluster creation failure, no memory\n");
Sam Ravnborg1fc54d82006-03-20 22:36:47 -080057 return NULL;
Allan Stephensa10bd922006-06-25 23:52:17 -070058 }
Per Lidenb97bf3f2006-01-02 19:04:38 +010059
60 c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
61 if (in_own_cluster(addr))
62 max_nodes = LOWEST_SLAVE + tipc_max_slaves;
63 else
64 max_nodes = tipc_max_nodes + 1;
Allan Stephensa10bd922006-06-25 23:52:17 -070065
Panagiotis Issaris0da974f2006-07-21 14:51:30 -070066 c_ptr->nodes = kcalloc(max_nodes + 1, sizeof(void*), GFP_ATOMIC);
Per Lidenb97bf3f2006-01-02 19:04:38 +010067 if (c_ptr->nodes == NULL) {
Allan Stephensa10bd922006-06-25 23:52:17 -070068 warn("Cluster creation failure, no memory for node area\n");
Per Lidenb97bf3f2006-01-02 19:04:38 +010069 kfree(c_ptr);
Sam Ravnborg1fc54d82006-03-20 22:36:47 -080070 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +010071 }
Allan Stephensa10bd922006-06-25 23:52:17 -070072
Per Lidenb97bf3f2006-01-02 19:04:38 +010073 if (in_own_cluster(addr))
Per Liden4323add2006-01-18 00:38:21 +010074 tipc_local_nodes = c_ptr->nodes;
Per Lidenb97bf3f2006-01-02 19:04:38 +010075 c_ptr->highest_slave = LOWEST_SLAVE - 1;
76 c_ptr->highest_node = 0;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +090077
Per Liden4323add2006-01-18 00:38:21 +010078 z_ptr = tipc_zone_find(tipc_zone(addr));
Allan Stephensa10bd922006-06-25 23:52:17 -070079 if (!z_ptr) {
Per Liden4323add2006-01-18 00:38:21 +010080 z_ptr = tipc_zone_create(addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +010081 }
Allan Stephensa10bd922006-06-25 23:52:17 -070082 if (!z_ptr) {
83 kfree(c_ptr->nodes);
Per Lidenb97bf3f2006-01-02 19:04:38 +010084 kfree(c_ptr);
Allan Stephensa10bd922006-06-25 23:52:17 -070085 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +010086 }
87
Allan Stephensa10bd922006-06-25 23:52:17 -070088 tipc_zone_attach_cluster(z_ptr, c_ptr);
89 c_ptr->owner = z_ptr;
Per Lidenb97bf3f2006-01-02 19:04:38 +010090 return c_ptr;
91}
92
Per Liden4323add2006-01-18 00:38:21 +010093void tipc_cltr_delete(struct cluster *c_ptr)
Per Lidenb97bf3f2006-01-02 19:04:38 +010094{
95 u32 n_num;
96
97 if (!c_ptr)
98 return;
99 for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
Per Liden4323add2006-01-18 00:38:21 +0100100 tipc_node_delete(c_ptr->nodes[n_num]);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100101 }
102 for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
Per Liden4323add2006-01-18 00:38:21 +0100103 tipc_node_delete(c_ptr->nodes[n_num]);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100104 }
105 kfree(c_ptr->nodes);
106 kfree(c_ptr);
107}
108
Per Lidenb97bf3f2006-01-02 19:04:38 +0100109
David S. Miller6c000552008-09-02 23:38:32 -0700110void tipc_cltr_attach_node(struct cluster *c_ptr, struct tipc_node *n_ptr)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100111{
112 u32 n_num = tipc_node(n_ptr->addr);
113 u32 max_n_num = tipc_max_nodes;
114
115 if (in_own_cluster(n_ptr->addr))
Per Liden4323add2006-01-18 00:38:21 +0100116 max_n_num = tipc_highest_allowed_slave;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100117 assert(n_num > 0);
118 assert(n_num <= max_n_num);
Harvey Harrison5f2f40a2008-02-24 18:38:31 -0800119 assert(c_ptr->nodes[n_num] == NULL);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100120 c_ptr->nodes[n_num] = n_ptr;
121 if (n_num > c_ptr->highest_node)
122 c_ptr->highest_node = n_num;
123}
124
125/**
Per Liden4323add2006-01-18 00:38:21 +0100126 * tipc_cltr_select_router - select router to a cluster
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900127 *
Per Lidenb97bf3f2006-01-02 19:04:38 +0100128 * Uses deterministic and fair algorithm.
129 */
130
Per Liden4323add2006-01-18 00:38:21 +0100131u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100132{
133 u32 n_num;
134 u32 ulim = c_ptr->highest_node;
135 u32 mask;
136 u32 tstart;
137
138 assert(!in_own_cluster(c_ptr->addr));
139 if (!ulim)
140 return 0;
141
142 /* Start entry must be random */
143 mask = tipc_max_nodes;
144 while (mask > ulim)
145 mask >>= 1;
146 tstart = ref & mask;
147 n_num = tstart;
148
149 /* Lookup upwards with wrap-around */
150 do {
Per Liden4323add2006-01-18 00:38:21 +0100151 if (tipc_node_is_up(c_ptr->nodes[n_num]))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100152 break;
153 } while (++n_num <= ulim);
154 if (n_num > ulim) {
155 n_num = 1;
156 do {
Per Liden4323add2006-01-18 00:38:21 +0100157 if (tipc_node_is_up(c_ptr->nodes[n_num]))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100158 break;
159 } while (++n_num < tstart);
160 if (n_num == tstart)
161 return 0;
162 }
163 assert(n_num <= ulim);
Per Liden4323add2006-01-18 00:38:21 +0100164 return tipc_node_select_router(c_ptr->nodes[n_num], ref);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100165}
166
167/**
Per Liden4323add2006-01-18 00:38:21 +0100168 * tipc_cltr_select_node - select destination node within a remote cluster
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900169 *
Per Lidenb97bf3f2006-01-02 19:04:38 +0100170 * Uses deterministic and fair algorithm.
171 */
172
David S. Miller6c000552008-09-02 23:38:32 -0700173struct tipc_node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100174{
175 u32 n_num;
176 u32 mask = tipc_max_nodes;
177 u32 start_entry;
178
179 assert(!in_own_cluster(c_ptr->addr));
180 if (!c_ptr->highest_node)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800181 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100182
183 /* Start entry must be random */
184 while (mask > c_ptr->highest_node) {
185 mask >>= 1;
186 }
187 start_entry = (selector & mask) ? selector & mask : 1u;
188 assert(start_entry <= c_ptr->highest_node);
189
190 /* Lookup upwards with wrap-around */
191 for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
Per Liden4323add2006-01-18 00:38:21 +0100192 if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100193 return c_ptr->nodes[n_num];
194 }
195 for (n_num = 1; n_num < start_entry; n_num++) {
Per Liden4323add2006-01-18 00:38:21 +0100196 if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100197 return c_ptr->nodes[n_num];
198 }
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800199 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100200}
201
202/*
203 * Routing table management: See description in node.c
204 */
205
Adrian Bunk988f0882006-03-20 22:37:52 -0800206static struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100207{
208 u32 size = INT_H_SIZE + data_size;
stephen hemminger31e3c3f2010-10-13 13:20:35 +0000209 struct sk_buff *buf = tipc_buf_acquire(size);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100210 struct tipc_msg *msg;
211
212 if (buf) {
213 msg = buf_msg(buf);
214 memset((char *)msg, 0, size);
Allan Stephensc68ca7b2010-05-11 14:30:12 +0000215 tipc_msg_init(msg, ROUTE_DISTRIBUTOR, 0, INT_H_SIZE, dest);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100216 }
217 return buf;
218}
219
Per Liden4323add2006-01-18 00:38:21 +0100220void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest,
Per Lidenb97bf3f2006-01-02 19:04:38 +0100221 u32 lower, u32 upper)
222{
Per Liden4323add2006-01-18 00:38:21 +0100223 struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100224 struct tipc_msg *msg;
225
226 if (buf) {
227 msg = buf_msg(buf);
228 msg_set_remote_node(msg, dest);
229 msg_set_type(msg, ROUTE_ADDITION);
Per Liden4323add2006-01-18 00:38:21 +0100230 tipc_cltr_multicast(c_ptr, buf, lower, upper);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100231 } else {
232 warn("Memory squeeze: broadcast of new route failed\n");
233 }
234}
235
Per Liden4323add2006-01-18 00:38:21 +0100236void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest,
237 u32 lower, u32 upper)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100238{
Per Liden4323add2006-01-18 00:38:21 +0100239 struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100240 struct tipc_msg *msg;
241
242 if (buf) {
243 msg = buf_msg(buf);
244 msg_set_remote_node(msg, dest);
245 msg_set_type(msg, ROUTE_REMOVAL);
Per Liden4323add2006-01-18 00:38:21 +0100246 tipc_cltr_multicast(c_ptr, buf, lower, upper);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100247 } else {
248 warn("Memory squeeze: broadcast of lost route failed\n");
249 }
250}
251
Per Liden4323add2006-01-18 00:38:21 +0100252void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100253{
254 struct sk_buff *buf;
255 struct tipc_msg *msg;
256 u32 highest = c_ptr->highest_slave;
257 u32 n_num;
258 int send = 0;
259
260 assert(!is_slave(dest));
261 assert(in_own_cluster(dest));
262 assert(in_own_cluster(c_ptr->addr));
263 if (highest <= LOWEST_SLAVE)
264 return;
Per Liden4323add2006-01-18 00:38:21 +0100265 buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
266 c_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100267 if (buf) {
268 msg = buf_msg(buf);
269 msg_set_remote_node(msg, c_ptr->addr);
270 msg_set_type(msg, SLAVE_ROUTING_TABLE);
271 for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900272 if (c_ptr->nodes[n_num] &&
Per Liden4323add2006-01-18 00:38:21 +0100273 tipc_node_has_active_links(c_ptr->nodes[n_num])) {
Per Lidenb97bf3f2006-01-02 19:04:38 +0100274 send = 1;
275 msg_set_dataoctet(msg, n_num);
276 }
277 }
278 if (send)
Per Liden4323add2006-01-18 00:38:21 +0100279 tipc_link_send(buf, dest, dest);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100280 else
281 buf_discard(buf);
282 } else {
283 warn("Memory squeeze: broadcast of lost route failed\n");
284 }
285}
286
Per Liden4323add2006-01-18 00:38:21 +0100287void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100288{
289 struct sk_buff *buf;
290 struct tipc_msg *msg;
291 u32 highest = c_ptr->highest_node;
292 u32 n_num;
293 int send = 0;
294
295 if (in_own_cluster(c_ptr->addr))
296 return;
297 assert(!is_slave(dest));
298 assert(in_own_cluster(dest));
299 highest = c_ptr->highest_node;
Per Liden4323add2006-01-18 00:38:21 +0100300 buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100301 if (buf) {
302 msg = buf_msg(buf);
303 msg_set_remote_node(msg, c_ptr->addr);
304 msg_set_type(msg, EXT_ROUTING_TABLE);
305 for (n_num = 1; n_num <= highest; n_num++) {
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900306 if (c_ptr->nodes[n_num] &&
Per Liden4323add2006-01-18 00:38:21 +0100307 tipc_node_has_active_links(c_ptr->nodes[n_num])) {
Per Lidenb97bf3f2006-01-02 19:04:38 +0100308 send = 1;
309 msg_set_dataoctet(msg, n_num);
310 }
311 }
312 if (send)
Per Liden4323add2006-01-18 00:38:21 +0100313 tipc_link_send(buf, dest, dest);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100314 else
315 buf_discard(buf);
316 } else {
317 warn("Memory squeeze: broadcast of external route failed\n");
318 }
319}
320
Per Liden4323add2006-01-18 00:38:21 +0100321void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100322{
323 struct sk_buff *buf;
324 struct tipc_msg *msg;
325 u32 highest = c_ptr->highest_node;
326 u32 n_num;
327 int send = 0;
328
329 assert(is_slave(dest));
330 assert(in_own_cluster(c_ptr->addr));
Per Liden4323add2006-01-18 00:38:21 +0100331 buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100332 if (buf) {
333 msg = buf_msg(buf);
334 msg_set_remote_node(msg, c_ptr->addr);
335 msg_set_type(msg, LOCAL_ROUTING_TABLE);
336 for (n_num = 1; n_num <= highest; n_num++) {
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900337 if (c_ptr->nodes[n_num] &&
Per Liden4323add2006-01-18 00:38:21 +0100338 tipc_node_has_active_links(c_ptr->nodes[n_num])) {
Per Lidenb97bf3f2006-01-02 19:04:38 +0100339 send = 1;
340 msg_set_dataoctet(msg, n_num);
341 }
342 }
343 if (send)
Per Liden4323add2006-01-18 00:38:21 +0100344 tipc_link_send(buf, dest, dest);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100345 else
346 buf_discard(buf);
347 } else {
348 warn("Memory squeeze: broadcast of local route failed\n");
349 }
350}
351
Per Liden4323add2006-01-18 00:38:21 +0100352void tipc_cltr_recv_routing_table(struct sk_buff *buf)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100353{
354 struct tipc_msg *msg = buf_msg(buf);
355 struct cluster *c_ptr;
David S. Miller6c000552008-09-02 23:38:32 -0700356 struct tipc_node *n_ptr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100357 unchar *node_table;
358 u32 table_size;
359 u32 router;
360 u32 rem_node = msg_remote_node(msg);
361 u32 z_num;
362 u32 c_num;
363 u32 n_num;
364
Per Liden4323add2006-01-18 00:38:21 +0100365 c_ptr = tipc_cltr_find(rem_node);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100366 if (!c_ptr) {
Per Liden4323add2006-01-18 00:38:21 +0100367 c_ptr = tipc_cltr_create(rem_node);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100368 if (!c_ptr) {
369 buf_discard(buf);
370 return;
371 }
372 }
373
374 node_table = buf->data + msg_hdr_sz(msg);
375 table_size = msg_size(msg) - msg_hdr_sz(msg);
376 router = msg_prevnode(msg);
377 z_num = tipc_zone(rem_node);
378 c_num = tipc_cluster(rem_node);
379
380 switch (msg_type(msg)) {
381 case LOCAL_ROUTING_TABLE:
382 assert(is_slave(tipc_own_addr));
383 case EXT_ROUTING_TABLE:
384 for (n_num = 1; n_num < table_size; n_num++) {
385 if (node_table[n_num]) {
386 u32 addr = tipc_addr(z_num, c_num, n_num);
387 n_ptr = c_ptr->nodes[n_num];
388 if (!n_ptr) {
Per Liden4323add2006-01-18 00:38:21 +0100389 n_ptr = tipc_node_create(addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100390 }
391 if (n_ptr)
Per Liden4323add2006-01-18 00:38:21 +0100392 tipc_node_add_router(n_ptr, router);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100393 }
394 }
395 break;
396 case SLAVE_ROUTING_TABLE:
397 assert(!is_slave(tipc_own_addr));
398 assert(in_own_cluster(c_ptr->addr));
399 for (n_num = 1; n_num < table_size; n_num++) {
400 if (node_table[n_num]) {
401 u32 slave_num = n_num + LOWEST_SLAVE;
402 u32 addr = tipc_addr(z_num, c_num, slave_num);
403 n_ptr = c_ptr->nodes[slave_num];
404 if (!n_ptr) {
Per Liden4323add2006-01-18 00:38:21 +0100405 n_ptr = tipc_node_create(addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100406 }
407 if (n_ptr)
Per Liden4323add2006-01-18 00:38:21 +0100408 tipc_node_add_router(n_ptr, router);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100409 }
410 }
411 break;
412 case ROUTE_ADDITION:
413 if (!is_slave(tipc_own_addr)) {
Joe Perchesf64f9e72009-11-29 16:55:45 -0800414 assert(!in_own_cluster(c_ptr->addr) ||
415 is_slave(rem_node));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100416 } else {
Joe Perchesf64f9e72009-11-29 16:55:45 -0800417 assert(in_own_cluster(c_ptr->addr) &&
418 !is_slave(rem_node));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100419 }
420 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
421 if (!n_ptr)
Per Liden4323add2006-01-18 00:38:21 +0100422 n_ptr = tipc_node_create(rem_node);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100423 if (n_ptr)
Per Liden4323add2006-01-18 00:38:21 +0100424 tipc_node_add_router(n_ptr, router);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100425 break;
426 case ROUTE_REMOVAL:
427 if (!is_slave(tipc_own_addr)) {
Joe Perchesf64f9e72009-11-29 16:55:45 -0800428 assert(!in_own_cluster(c_ptr->addr) ||
429 is_slave(rem_node));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100430 } else {
Joe Perchesf64f9e72009-11-29 16:55:45 -0800431 assert(in_own_cluster(c_ptr->addr) &&
432 !is_slave(rem_node));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100433 }
434 n_ptr = c_ptr->nodes[tipc_node(rem_node)];
435 if (n_ptr)
Per Liden4323add2006-01-18 00:38:21 +0100436 tipc_node_remove_router(n_ptr, router);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100437 break;
438 default:
439 assert(!"Illegal routing manager message received\n");
440 }
441 buf_discard(buf);
442}
443
Per Liden4323add2006-01-18 00:38:21 +0100444void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100445{
446 u32 start_entry;
447 u32 tstop;
448 u32 n_num;
449
450 if (is_slave(router))
451 return; /* Slave nodes can not be routers */
452
453 if (in_own_cluster(c_ptr->addr)) {
454 start_entry = LOWEST_SLAVE;
455 tstop = c_ptr->highest_slave;
456 } else {
457 start_entry = 1;
458 tstop = c_ptr->highest_node;
459 }
460
461 for (n_num = start_entry; n_num <= tstop; n_num++) {
462 if (c_ptr->nodes[n_num]) {
Per Liden4323add2006-01-18 00:38:21 +0100463 tipc_node_remove_router(c_ptr->nodes[n_num], router);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100464 }
465 }
466}
467
468/**
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900469 * tipc_cltr_multicast - multicast message to local nodes
Per Lidenb97bf3f2006-01-02 19:04:38 +0100470 */
471
Adrian Bunk988f0882006-03-20 22:37:52 -0800472static void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
Per Liden4323add2006-01-18 00:38:21 +0100473 u32 lower, u32 upper)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100474{
475 struct sk_buff *buf_copy;
David S. Miller6c000552008-09-02 23:38:32 -0700476 struct tipc_node *n_ptr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100477 u32 n_num;
478 u32 tstop;
479
480 assert(lower <= upper);
481 assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
Per Liden4323add2006-01-18 00:38:21 +0100482 ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave)));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100483 assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
Per Liden4323add2006-01-18 00:38:21 +0100484 ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave)));
Per Lidenb97bf3f2006-01-02 19:04:38 +0100485 assert(in_own_cluster(c_ptr->addr));
486
487 tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
488 if (tstop > upper)
489 tstop = upper;
490 for (n_num = lower; n_num <= tstop; n_num++) {
491 n_ptr = c_ptr->nodes[n_num];
Per Liden4323add2006-01-18 00:38:21 +0100492 if (n_ptr && tipc_node_has_active_links(n_ptr)) {
Per Lidenb97bf3f2006-01-02 19:04:38 +0100493 buf_copy = skb_copy(buf, GFP_ATOMIC);
494 if (buf_copy == NULL)
495 break;
496 msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
Per Liden4323add2006-01-18 00:38:21 +0100497 tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100498 }
499 }
500 buf_discard(buf);
501}
502
503/**
Per Liden4323add2006-01-18 00:38:21 +0100504 * tipc_cltr_broadcast - broadcast message to all nodes within cluster
Per Lidenb97bf3f2006-01-02 19:04:38 +0100505 */
506
Per Liden4323add2006-01-18 00:38:21 +0100507void tipc_cltr_broadcast(struct sk_buff *buf)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100508{
509 struct sk_buff *buf_copy;
510 struct cluster *c_ptr;
David S. Miller6c000552008-09-02 23:38:32 -0700511 struct tipc_node *n_ptr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100512 u32 n_num;
513 u32 tstart;
514 u32 tstop;
515 u32 node_type;
516
517 if (tipc_mode == TIPC_NET_MODE) {
Per Liden4323add2006-01-18 00:38:21 +0100518 c_ptr = tipc_cltr_find(tipc_own_addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100519 assert(in_own_cluster(c_ptr->addr)); /* For now */
520
521 /* Send to standard nodes, then repeat loop sending to slaves */
522 tstart = 1;
523 tstop = c_ptr->highest_node;
524 for (node_type = 1; node_type <= 2; node_type++) {
525 for (n_num = tstart; n_num <= tstop; n_num++) {
526 n_ptr = c_ptr->nodes[n_num];
Per Liden4323add2006-01-18 00:38:21 +0100527 if (n_ptr && tipc_node_has_active_links(n_ptr)) {
Per Lidenb97bf3f2006-01-02 19:04:38 +0100528 buf_copy = skb_copy(buf, GFP_ATOMIC);
529 if (buf_copy == NULL)
530 goto exit;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900531 msg_set_destnode(buf_msg(buf_copy),
Per Lidenb97bf3f2006-01-02 19:04:38 +0100532 n_ptr->addr);
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900533 tipc_link_send(buf_copy, n_ptr->addr,
Per Liden4323add2006-01-18 00:38:21 +0100534 n_ptr->addr);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100535 }
536 }
537 tstart = LOWEST_SLAVE;
538 tstop = c_ptr->highest_slave;
539 }
540 }
541exit:
542 buf_discard(buf);
543}
544
Per Liden4323add2006-01-18 00:38:21 +0100545int tipc_cltr_init(void)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100546{
Per Liden4323add2006-01-18 00:38:21 +0100547 tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
Allan Stephens0e35fd52008-07-14 22:44:01 -0700548 return tipc_cltr_create(tipc_own_addr) ? 0 : -ENOMEM;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100549}
550