2006-01-02 21:04:38 +03:00
/*
* net / tipc / cluster . c : TIPC cluster management routines
2007-02-09 17:25:21 +03:00
*
2006-01-11 21:14:19 +03:00
* Copyright ( c ) 2000 - 2006 , Ericsson AB
2006-01-02 21:04:38 +03:00
* Copyright ( c ) 2005 , Wind River Systems
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
2006-01-11 15:30:43 +03:00
* 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 .
*
* 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 .
2006-01-02 21:04:38 +03:00
*
* 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
* POSSIBILITY OF SUCH DAMAGE .
*/
# include "core.h"
# include "cluster.h"
# include "addr.h"
# include "node_subscr.h"
# include "link.h"
# include "node.h"
# include "net.h"
# include "msg.h"
# include "bearer.h"
2006-03-21 09:37:52 +03:00
static void tipc_cltr_multicast ( struct cluster * c_ptr , struct sk_buff * buf ,
u32 lower , u32 upper ) ;
2006-03-21 09:38:33 +03:00
static struct sk_buff * tipc_cltr_prepare_routing_msg ( u32 data_size , u32 dest ) ;
2006-01-02 21:04:38 +03:00
2008-09-03 10:38:32 +04:00
struct tipc_node * * tipc_local_nodes = NULL ;
struct tipc_node_map tipc_cltr_bcast_nodes = { 0 , { 0 , } } ;
2006-01-18 02:38:21 +03:00
u32 tipc_highest_allowed_slave = 0 ;
2006-01-02 21:04:38 +03:00
2006-01-18 02:38:21 +03:00
struct cluster * tipc_cltr_create ( u32 addr )
2006-01-02 21:04:38 +03:00
{
struct _zone * z_ptr ;
struct cluster * c_ptr ;
2007-02-09 17:25:21 +03:00
int max_nodes ;
2006-01-02 21:04:38 +03:00
2006-07-22 01:51:30 +04:00
c_ptr = kzalloc ( sizeof ( * c_ptr ) , GFP_ATOMIC ) ;
2006-06-26 10:52:17 +04:00
if ( c_ptr = = NULL ) {
warn ( " Cluster creation failure, no memory \n " ) ;
2006-03-21 09:36:47 +03:00
return NULL ;
2006-06-26 10:52:17 +04:00
}
2006-01-02 21:04:38 +03:00
c_ptr - > addr = tipc_addr ( tipc_zone ( addr ) , tipc_cluster ( addr ) , 0 ) ;
if ( in_own_cluster ( addr ) )
max_nodes = LOWEST_SLAVE + tipc_max_slaves ;
else
max_nodes = tipc_max_nodes + 1 ;
2006-06-26 10:52:17 +04:00
2006-07-22 01:51:30 +04:00
c_ptr - > nodes = kcalloc ( max_nodes + 1 , sizeof ( void * ) , GFP_ATOMIC ) ;
2006-01-02 21:04:38 +03:00
if ( c_ptr - > nodes = = NULL ) {
2006-06-26 10:52:17 +04:00
warn ( " Cluster creation failure, no memory for node area \n " ) ;
2006-01-02 21:04:38 +03:00
kfree ( c_ptr ) ;
2006-03-21 09:36:47 +03:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
2006-06-26 10:52:17 +04:00
2006-01-02 21:04:38 +03:00
if ( in_own_cluster ( addr ) )
2006-01-18 02:38:21 +03:00
tipc_local_nodes = c_ptr - > nodes ;
2006-01-02 21:04:38 +03:00
c_ptr - > highest_slave = LOWEST_SLAVE - 1 ;
c_ptr - > highest_node = 0 ;
2007-02-09 17:25:21 +03:00
2006-01-18 02:38:21 +03:00
z_ptr = tipc_zone_find ( tipc_zone ( addr ) ) ;
2006-06-26 10:52:17 +04:00
if ( ! z_ptr ) {
2006-01-18 02:38:21 +03:00
z_ptr = tipc_zone_create ( addr ) ;
2006-01-02 21:04:38 +03:00
}
2006-06-26 10:52:17 +04:00
if ( ! z_ptr ) {
kfree ( c_ptr - > nodes ) ;
2006-01-02 21:04:38 +03:00
kfree ( c_ptr ) ;
2006-06-26 10:52:17 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
2006-06-26 10:52:17 +04:00
tipc_zone_attach_cluster ( z_ptr , c_ptr ) ;
c_ptr - > owner = z_ptr ;
2006-01-02 21:04:38 +03:00
return c_ptr ;
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_delete ( struct cluster * c_ptr )
2006-01-02 21:04:38 +03:00
{
u32 n_num ;
if ( ! c_ptr )
return ;
for ( n_num = 1 ; n_num < = c_ptr - > highest_node ; n_num + + ) {
2006-01-18 02:38:21 +03:00
tipc_node_delete ( c_ptr - > nodes [ n_num ] ) ;
2006-01-02 21:04:38 +03:00
}
for ( n_num = LOWEST_SLAVE ; n_num < = c_ptr - > highest_slave ; n_num + + ) {
2006-01-18 02:38:21 +03:00
tipc_node_delete ( c_ptr - > nodes [ n_num ] ) ;
2006-01-02 21:04:38 +03:00
}
kfree ( c_ptr - > nodes ) ;
kfree ( c_ptr ) ;
}
2006-01-18 02:38:21 +03:00
u32 tipc_cltr_next_node ( struct cluster * c_ptr , u32 addr )
2006-01-02 21:04:38 +03:00
{
2008-09-03 10:38:32 +04:00
struct tipc_node * n_ptr ;
2006-01-02 21:04:38 +03:00
u32 n_num = tipc_node ( addr ) + 1 ;
if ( ! c_ptr )
return addr ;
for ( ; n_num < = c_ptr - > highest_node ; n_num + + ) {
n_ptr = c_ptr - > nodes [ n_num ] ;
2006-01-18 02:38:21 +03:00
if ( n_ptr & & tipc_node_has_active_links ( n_ptr ) )
2006-01-02 21:04:38 +03:00
return n_ptr - > addr ;
}
for ( n_num = 1 ; n_num < tipc_node ( addr ) ; n_num + + ) {
n_ptr = c_ptr - > nodes [ n_num ] ;
2006-01-18 02:38:21 +03:00
if ( n_ptr & & tipc_node_has_active_links ( n_ptr ) )
2006-01-02 21:04:38 +03:00
return n_ptr - > addr ;
}
return 0 ;
}
2008-09-03 10:38:32 +04:00
void tipc_cltr_attach_node ( struct cluster * c_ptr , struct tipc_node * n_ptr )
2006-01-02 21:04:38 +03:00
{
u32 n_num = tipc_node ( n_ptr - > addr ) ;
u32 max_n_num = tipc_max_nodes ;
if ( in_own_cluster ( n_ptr - > addr ) )
2006-01-18 02:38:21 +03:00
max_n_num = tipc_highest_allowed_slave ;
2006-01-02 21:04:38 +03:00
assert ( n_num > 0 ) ;
assert ( n_num < = max_n_num ) ;
2008-02-25 05:38:31 +03:00
assert ( c_ptr - > nodes [ n_num ] = = NULL ) ;
2006-01-02 21:04:38 +03:00
c_ptr - > nodes [ n_num ] = n_ptr ;
if ( n_num > c_ptr - > highest_node )
c_ptr - > highest_node = n_num ;
}
/**
2006-01-18 02:38:21 +03:00
* tipc_cltr_select_router - select router to a cluster
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Uses deterministic and fair algorithm .
*/
2006-01-18 02:38:21 +03:00
u32 tipc_cltr_select_router ( struct cluster * c_ptr , u32 ref )
2006-01-02 21:04:38 +03:00
{
u32 n_num ;
u32 ulim = c_ptr - > highest_node ;
u32 mask ;
u32 tstart ;
assert ( ! in_own_cluster ( c_ptr - > addr ) ) ;
if ( ! ulim )
return 0 ;
/* Start entry must be random */
mask = tipc_max_nodes ;
while ( mask > ulim )
mask > > = 1 ;
tstart = ref & mask ;
n_num = tstart ;
/* Lookup upwards with wrap-around */
do {
2006-01-18 02:38:21 +03:00
if ( tipc_node_is_up ( c_ptr - > nodes [ n_num ] ) )
2006-01-02 21:04:38 +03:00
break ;
} while ( + + n_num < = ulim ) ;
if ( n_num > ulim ) {
n_num = 1 ;
do {
2006-01-18 02:38:21 +03:00
if ( tipc_node_is_up ( c_ptr - > nodes [ n_num ] ) )
2006-01-02 21:04:38 +03:00
break ;
} while ( + + n_num < tstart ) ;
if ( n_num = = tstart )
return 0 ;
}
assert ( n_num < = ulim ) ;
2006-01-18 02:38:21 +03:00
return tipc_node_select_router ( c_ptr - > nodes [ n_num ] , ref ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_cltr_select_node - select destination node within a remote cluster
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Uses deterministic and fair algorithm .
*/
2008-09-03 10:38:32 +04:00
struct tipc_node * tipc_cltr_select_node ( struct cluster * c_ptr , u32 selector )
2006-01-02 21:04:38 +03:00
{
u32 n_num ;
u32 mask = tipc_max_nodes ;
u32 start_entry ;
assert ( ! in_own_cluster ( c_ptr - > addr ) ) ;
if ( ! c_ptr - > highest_node )
2006-03-21 09:36:47 +03:00
return NULL ;
2006-01-02 21:04:38 +03:00
/* Start entry must be random */
while ( mask > c_ptr - > highest_node ) {
mask > > = 1 ;
}
start_entry = ( selector & mask ) ? selector & mask : 1u ;
assert ( start_entry < = c_ptr - > highest_node ) ;
/* Lookup upwards with wrap-around */
for ( n_num = start_entry ; n_num < = c_ptr - > highest_node ; n_num + + ) {
2006-01-18 02:38:21 +03:00
if ( tipc_node_has_active_links ( c_ptr - > nodes [ n_num ] ) )
2006-01-02 21:04:38 +03:00
return c_ptr - > nodes [ n_num ] ;
}
for ( n_num = 1 ; n_num < start_entry ; n_num + + ) {
2006-01-18 02:38:21 +03:00
if ( tipc_node_has_active_links ( c_ptr - > nodes [ n_num ] ) )
2006-01-02 21:04:38 +03:00
return c_ptr - > nodes [ n_num ] ;
}
2006-03-21 09:36:47 +03:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
/*
* Routing table management : See description in node . c
*/
2006-03-21 09:37:52 +03:00
static struct sk_buff * tipc_cltr_prepare_routing_msg ( u32 data_size , u32 dest )
2006-01-02 21:04:38 +03:00
{
u32 size = INT_H_SIZE + data_size ;
struct sk_buff * buf = buf_acquire ( size ) ;
struct tipc_msg * msg ;
if ( buf ) {
msg = buf_msg ( buf ) ;
memset ( ( char * ) msg , 0 , size ) ;
2008-06-05 04:37:34 +04:00
msg_init ( msg , ROUTE_DISTRIBUTOR , 0 , INT_H_SIZE , dest ) ;
2006-01-02 21:04:38 +03:00
}
return buf ;
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_bcast_new_route ( struct cluster * c_ptr , u32 dest ,
2006-01-02 21:04:38 +03:00
u32 lower , u32 upper )
{
2006-01-18 02:38:21 +03:00
struct sk_buff * buf = tipc_cltr_prepare_routing_msg ( 0 , c_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg ;
if ( buf ) {
msg = buf_msg ( buf ) ;
msg_set_remote_node ( msg , dest ) ;
msg_set_type ( msg , ROUTE_ADDITION ) ;
2006-01-18 02:38:21 +03:00
tipc_cltr_multicast ( c_ptr , buf , lower , upper ) ;
2006-01-02 21:04:38 +03:00
} else {
warn ( " Memory squeeze: broadcast of new route failed \n " ) ;
}
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_bcast_lost_route ( struct cluster * c_ptr , u32 dest ,
u32 lower , u32 upper )
2006-01-02 21:04:38 +03:00
{
2006-01-18 02:38:21 +03:00
struct sk_buff * buf = tipc_cltr_prepare_routing_msg ( 0 , c_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg ;
if ( buf ) {
msg = buf_msg ( buf ) ;
msg_set_remote_node ( msg , dest ) ;
msg_set_type ( msg , ROUTE_REMOVAL ) ;
2006-01-18 02:38:21 +03:00
tipc_cltr_multicast ( c_ptr , buf , lower , upper ) ;
2006-01-02 21:04:38 +03:00
} else {
warn ( " Memory squeeze: broadcast of lost route failed \n " ) ;
}
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_send_slave_routes ( struct cluster * c_ptr , u32 dest )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct tipc_msg * msg ;
u32 highest = c_ptr - > highest_slave ;
u32 n_num ;
int send = 0 ;
assert ( ! is_slave ( dest ) ) ;
assert ( in_own_cluster ( dest ) ) ;
assert ( in_own_cluster ( c_ptr - > addr ) ) ;
if ( highest < = LOWEST_SLAVE )
return ;
2006-01-18 02:38:21 +03:00
buf = tipc_cltr_prepare_routing_msg ( highest - LOWEST_SLAVE + 1 ,
c_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
if ( buf ) {
msg = buf_msg ( buf ) ;
msg_set_remote_node ( msg , c_ptr - > addr ) ;
msg_set_type ( msg , SLAVE_ROUTING_TABLE ) ;
for ( n_num = LOWEST_SLAVE ; n_num < = highest ; n_num + + ) {
2007-02-09 17:25:21 +03:00
if ( c_ptr - > nodes [ n_num ] & &
2006-01-18 02:38:21 +03:00
tipc_node_has_active_links ( c_ptr - > nodes [ n_num ] ) ) {
2006-01-02 21:04:38 +03:00
send = 1 ;
msg_set_dataoctet ( msg , n_num ) ;
}
}
if ( send )
2006-01-18 02:38:21 +03:00
tipc_link_send ( buf , dest , dest ) ;
2006-01-02 21:04:38 +03:00
else
buf_discard ( buf ) ;
} else {
warn ( " Memory squeeze: broadcast of lost route failed \n " ) ;
}
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_send_ext_routes ( struct cluster * c_ptr , u32 dest )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct tipc_msg * msg ;
u32 highest = c_ptr - > highest_node ;
u32 n_num ;
int send = 0 ;
if ( in_own_cluster ( c_ptr - > addr ) )
return ;
assert ( ! is_slave ( dest ) ) ;
assert ( in_own_cluster ( dest ) ) ;
highest = c_ptr - > highest_node ;
2006-01-18 02:38:21 +03:00
buf = tipc_cltr_prepare_routing_msg ( highest + 1 , c_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
if ( buf ) {
msg = buf_msg ( buf ) ;
msg_set_remote_node ( msg , c_ptr - > addr ) ;
msg_set_type ( msg , EXT_ROUTING_TABLE ) ;
for ( n_num = 1 ; n_num < = highest ; n_num + + ) {
2007-02-09 17:25:21 +03:00
if ( c_ptr - > nodes [ n_num ] & &
2006-01-18 02:38:21 +03:00
tipc_node_has_active_links ( c_ptr - > nodes [ n_num ] ) ) {
2006-01-02 21:04:38 +03:00
send = 1 ;
msg_set_dataoctet ( msg , n_num ) ;
}
}
if ( send )
2006-01-18 02:38:21 +03:00
tipc_link_send ( buf , dest , dest ) ;
2006-01-02 21:04:38 +03:00
else
buf_discard ( buf ) ;
} else {
warn ( " Memory squeeze: broadcast of external route failed \n " ) ;
}
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_send_local_routes ( struct cluster * c_ptr , u32 dest )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct tipc_msg * msg ;
u32 highest = c_ptr - > highest_node ;
u32 n_num ;
int send = 0 ;
assert ( is_slave ( dest ) ) ;
assert ( in_own_cluster ( c_ptr - > addr ) ) ;
2006-01-18 02:38:21 +03:00
buf = tipc_cltr_prepare_routing_msg ( highest , c_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
if ( buf ) {
msg = buf_msg ( buf ) ;
msg_set_remote_node ( msg , c_ptr - > addr ) ;
msg_set_type ( msg , LOCAL_ROUTING_TABLE ) ;
for ( n_num = 1 ; n_num < = highest ; n_num + + ) {
2007-02-09 17:25:21 +03:00
if ( c_ptr - > nodes [ n_num ] & &
2006-01-18 02:38:21 +03:00
tipc_node_has_active_links ( c_ptr - > nodes [ n_num ] ) ) {
2006-01-02 21:04:38 +03:00
send = 1 ;
msg_set_dataoctet ( msg , n_num ) ;
}
}
if ( send )
2006-01-18 02:38:21 +03:00
tipc_link_send ( buf , dest , dest ) ;
2006-01-02 21:04:38 +03:00
else
buf_discard ( buf ) ;
} else {
warn ( " Memory squeeze: broadcast of local route failed \n " ) ;
}
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_recv_routing_table ( struct sk_buff * buf )
2006-01-02 21:04:38 +03:00
{
struct tipc_msg * msg = buf_msg ( buf ) ;
struct cluster * c_ptr ;
2008-09-03 10:38:32 +04:00
struct tipc_node * n_ptr ;
2006-01-02 21:04:38 +03:00
unchar * node_table ;
u32 table_size ;
u32 router ;
u32 rem_node = msg_remote_node ( msg ) ;
u32 z_num ;
u32 c_num ;
u32 n_num ;
2006-01-18 02:38:21 +03:00
c_ptr = tipc_cltr_find ( rem_node ) ;
2006-01-02 21:04:38 +03:00
if ( ! c_ptr ) {
2006-01-18 02:38:21 +03:00
c_ptr = tipc_cltr_create ( rem_node ) ;
2006-01-02 21:04:38 +03:00
if ( ! c_ptr ) {
buf_discard ( buf ) ;
return ;
}
}
node_table = buf - > data + msg_hdr_sz ( msg ) ;
table_size = msg_size ( msg ) - msg_hdr_sz ( msg ) ;
router = msg_prevnode ( msg ) ;
z_num = tipc_zone ( rem_node ) ;
c_num = tipc_cluster ( rem_node ) ;
switch ( msg_type ( msg ) ) {
case LOCAL_ROUTING_TABLE :
assert ( is_slave ( tipc_own_addr ) ) ;
case EXT_ROUTING_TABLE :
for ( n_num = 1 ; n_num < table_size ; n_num + + ) {
if ( node_table [ n_num ] ) {
u32 addr = tipc_addr ( z_num , c_num , n_num ) ;
n_ptr = c_ptr - > nodes [ n_num ] ;
if ( ! n_ptr ) {
2006-01-18 02:38:21 +03:00
n_ptr = tipc_node_create ( addr ) ;
2006-01-02 21:04:38 +03:00
}
if ( n_ptr )
2006-01-18 02:38:21 +03:00
tipc_node_add_router ( n_ptr , router ) ;
2006-01-02 21:04:38 +03:00
}
}
break ;
case SLAVE_ROUTING_TABLE :
assert ( ! is_slave ( tipc_own_addr ) ) ;
assert ( in_own_cluster ( c_ptr - > addr ) ) ;
for ( n_num = 1 ; n_num < table_size ; n_num + + ) {
if ( node_table [ n_num ] ) {
u32 slave_num = n_num + LOWEST_SLAVE ;
u32 addr = tipc_addr ( z_num , c_num , slave_num ) ;
n_ptr = c_ptr - > nodes [ slave_num ] ;
if ( ! n_ptr ) {
2006-01-18 02:38:21 +03:00
n_ptr = tipc_node_create ( addr ) ;
2006-01-02 21:04:38 +03:00
}
if ( n_ptr )
2006-01-18 02:38:21 +03:00
tipc_node_add_router ( n_ptr , router ) ;
2006-01-02 21:04:38 +03:00
}
}
break ;
case ROUTE_ADDITION :
if ( ! is_slave ( tipc_own_addr ) ) {
assert ( ! in_own_cluster ( c_ptr - > addr )
| | is_slave ( rem_node ) ) ;
} else {
assert ( in_own_cluster ( c_ptr - > addr )
& & ! is_slave ( rem_node ) ) ;
}
n_ptr = c_ptr - > nodes [ tipc_node ( rem_node ) ] ;
if ( ! n_ptr )
2006-01-18 02:38:21 +03:00
n_ptr = tipc_node_create ( rem_node ) ;
2006-01-02 21:04:38 +03:00
if ( n_ptr )
2006-01-18 02:38:21 +03:00
tipc_node_add_router ( n_ptr , router ) ;
2006-01-02 21:04:38 +03:00
break ;
case ROUTE_REMOVAL :
if ( ! is_slave ( tipc_own_addr ) ) {
assert ( ! in_own_cluster ( c_ptr - > addr )
| | is_slave ( rem_node ) ) ;
} else {
assert ( in_own_cluster ( c_ptr - > addr )
& & ! is_slave ( rem_node ) ) ;
}
n_ptr = c_ptr - > nodes [ tipc_node ( rem_node ) ] ;
if ( n_ptr )
2006-01-18 02:38:21 +03:00
tipc_node_remove_router ( n_ptr , router ) ;
2006-01-02 21:04:38 +03:00
break ;
default :
assert ( ! " Illegal routing manager message received \n " ) ;
}
buf_discard ( buf ) ;
}
2006-01-18 02:38:21 +03:00
void tipc_cltr_remove_as_router ( struct cluster * c_ptr , u32 router )
2006-01-02 21:04:38 +03:00
{
u32 start_entry ;
u32 tstop ;
u32 n_num ;
if ( is_slave ( router ) )
return ; /* Slave nodes can not be routers */
if ( in_own_cluster ( c_ptr - > addr ) ) {
start_entry = LOWEST_SLAVE ;
tstop = c_ptr - > highest_slave ;
} else {
start_entry = 1 ;
tstop = c_ptr - > highest_node ;
}
for ( n_num = start_entry ; n_num < = tstop ; n_num + + ) {
if ( c_ptr - > nodes [ n_num ] ) {
2006-01-18 02:38:21 +03:00
tipc_node_remove_router ( c_ptr - > nodes [ n_num ] , router ) ;
2006-01-02 21:04:38 +03:00
}
}
}
/**
2007-02-09 17:25:21 +03:00
* tipc_cltr_multicast - multicast message to local nodes
2006-01-02 21:04:38 +03:00
*/
2006-03-21 09:37:52 +03:00
static void tipc_cltr_multicast ( struct cluster * c_ptr , struct sk_buff * buf ,
2006-01-18 02:38:21 +03:00
u32 lower , u32 upper )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf_copy ;
2008-09-03 10:38:32 +04:00
struct tipc_node * n_ptr ;
2006-01-02 21:04:38 +03:00
u32 n_num ;
u32 tstop ;
assert ( lower < = upper ) ;
assert ( ( ( lower > = 1 ) & & ( lower < = tipc_max_nodes ) ) | |
2006-01-18 02:38:21 +03:00
( ( lower > = LOWEST_SLAVE ) & & ( lower < = tipc_highest_allowed_slave ) ) ) ;
2006-01-02 21:04:38 +03:00
assert ( ( ( upper > = 1 ) & & ( upper < = tipc_max_nodes ) ) | |
2006-01-18 02:38:21 +03:00
( ( upper > = LOWEST_SLAVE ) & & ( upper < = tipc_highest_allowed_slave ) ) ) ;
2006-01-02 21:04:38 +03:00
assert ( in_own_cluster ( c_ptr - > addr ) ) ;
tstop = is_slave ( upper ) ? c_ptr - > highest_slave : c_ptr - > highest_node ;
if ( tstop > upper )
tstop = upper ;
for ( n_num = lower ; n_num < = tstop ; n_num + + ) {
n_ptr = c_ptr - > nodes [ n_num ] ;
2006-01-18 02:38:21 +03:00
if ( n_ptr & & tipc_node_has_active_links ( n_ptr ) ) {
2006-01-02 21:04:38 +03:00
buf_copy = skb_copy ( buf , GFP_ATOMIC ) ;
if ( buf_copy = = NULL )
break ;
msg_set_destnode ( buf_msg ( buf_copy ) , n_ptr - > addr ) ;
2006-01-18 02:38:21 +03:00
tipc_link_send ( buf_copy , n_ptr - > addr , n_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
}
}
buf_discard ( buf ) ;
}
/**
2006-01-18 02:38:21 +03:00
* tipc_cltr_broadcast - broadcast message to all nodes within cluster
2006-01-02 21:04:38 +03:00
*/
2006-01-18 02:38:21 +03:00
void tipc_cltr_broadcast ( struct sk_buff * buf )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf_copy ;
struct cluster * c_ptr ;
2008-09-03 10:38:32 +04:00
struct tipc_node * n_ptr ;
2006-01-02 21:04:38 +03:00
u32 n_num ;
u32 tstart ;
u32 tstop ;
u32 node_type ;
if ( tipc_mode = = TIPC_NET_MODE ) {
2006-01-18 02:38:21 +03:00
c_ptr = tipc_cltr_find ( tipc_own_addr ) ;
2006-01-02 21:04:38 +03:00
assert ( in_own_cluster ( c_ptr - > addr ) ) ; /* For now */
/* Send to standard nodes, then repeat loop sending to slaves */
tstart = 1 ;
tstop = c_ptr - > highest_node ;
for ( node_type = 1 ; node_type < = 2 ; node_type + + ) {
for ( n_num = tstart ; n_num < = tstop ; n_num + + ) {
n_ptr = c_ptr - > nodes [ n_num ] ;
2006-01-18 02:38:21 +03:00
if ( n_ptr & & tipc_node_has_active_links ( n_ptr ) ) {
2006-01-02 21:04:38 +03:00
buf_copy = skb_copy ( buf , GFP_ATOMIC ) ;
if ( buf_copy = = NULL )
goto exit ;
2007-02-09 17:25:21 +03:00
msg_set_destnode ( buf_msg ( buf_copy ) ,
2006-01-02 21:04:38 +03:00
n_ptr - > addr ) ;
2007-02-09 17:25:21 +03:00
tipc_link_send ( buf_copy , n_ptr - > addr ,
2006-01-18 02:38:21 +03:00
n_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
}
}
tstart = LOWEST_SLAVE ;
tstop = c_ptr - > highest_slave ;
}
}
exit :
buf_discard ( buf ) ;
}
2006-01-18 02:38:21 +03:00
int tipc_cltr_init ( void )
2006-01-02 21:04:38 +03:00
{
2006-01-18 02:38:21 +03:00
tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves ;
2008-07-15 09:44:01 +04:00
return tipc_cltr_create ( tipc_own_addr ) ? 0 : - ENOMEM ;
2006-01-02 21:04:38 +03:00
}