2006-01-02 21:04:38 +03:00
/*
* net / tipc / name_distr . c : TIPC name distribution code
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 .
*
2006-01-11 15:30:43 +03:00
* Redistribution and use in source and binary forms , with or without
2006-01-02 21:04:38 +03:00
* 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 .
2006-01-02 21:04:38 +03:00
*
2006-01-11 15:30:43 +03:00
* 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
2006-01-02 21:04:38 +03:00
* POSSIBILITY OF SUCH DAMAGE .
*/
# include "core.h"
# include "cluster.h"
# include "dbg.h"
# include "link.h"
# include "msg.h"
# include "name_distr.h"
# define ITEM_SIZE sizeof(struct distr_item)
/**
* struct distr_item - publication info distributed to other nodes
* @ type : name sequence type
* @ lower : name sequence lower bound
* @ upper : name sequence upper bound
* @ ref : publishing port reference
* @ key : publication key
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* = = = > All fields are stored in network byte order . < = = =
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* First 3 fields identify ( name or ) name sequence being published .
* Reference field uniquely identifies port that published name sequence .
* Key field uniquely identifies publication , in the event a port has
* multiple publications of the same name sequence .
2007-02-09 17:25:21 +03:00
*
* Note : There is no field that identifies the publishing node because it is
2006-01-02 21:04:38 +03:00
* the same for all items contained within a publication message .
*/
struct distr_item {
2006-11-08 11:19:09 +03:00
__be32 type ;
__be32 lower ;
__be32 upper ;
__be32 ref ;
__be32 key ;
2006-01-02 21:04:38 +03:00
} ;
/**
2007-02-09 17:25:21 +03:00
* List of externally visible publications by this node - -
2006-01-02 21:04:38 +03:00
* that is , all publications having scope > TIPC_NODE_SCOPE .
*/
static LIST_HEAD ( publ_root ) ;
2007-02-09 17:25:21 +03:00
static u32 publ_cnt = 0 ;
2006-01-02 21:04:38 +03:00
/**
* publ_to_item - add publication info to a publication message
*/
static void publ_to_item ( struct distr_item * i , struct publication * p )
{
i - > type = htonl ( p - > type ) ;
i - > lower = htonl ( p - > lower ) ;
i - > upper = htonl ( p - > upper ) ;
i - > ref = htonl ( p - > ref ) ;
i - > key = htonl ( p - > key ) ;
dbg ( " publ_to_item: %u, %u, %u \n " , p - > type , p - > lower , p - > upper ) ;
}
/**
* named_prepare_buf - allocate & initialize a publication message
*/
static struct sk_buff * named_prepare_buf ( u32 type , u32 size , u32 dest )
{
2007-02-09 17:25:21 +03:00
struct sk_buff * buf = buf_acquire ( LONG_H_SIZE + size ) ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg ;
if ( buf ! = NULL ) {
msg = buf_msg ( buf ) ;
2008-06-05 04:37:34 +04:00
msg_init ( msg , NAME_DISTRIBUTOR , type , LONG_H_SIZE , dest ) ;
2006-01-02 21:04:38 +03:00
msg_set_size ( msg , LONG_H_SIZE + size ) ;
}
return buf ;
}
/**
2006-01-18 02:38:21 +03:00
* tipc_named_publish - tell other nodes about a new publication by this node
2006-01-02 21:04:38 +03:00
*/
2006-01-18 02:38:21 +03:00
void tipc_named_publish ( struct publication * publ )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct distr_item * item ;
2006-10-17 08:56:04 +04:00
list_add_tail ( & publ - > local_list , & publ_root ) ;
2006-01-02 21:04:38 +03:00
publ_cnt + + ;
buf = named_prepare_buf ( PUBLICATION , ITEM_SIZE , 0 ) ;
if ( ! buf ) {
2006-06-26 10:52:17 +04:00
warn ( " Publication distribution failure \n " ) ;
2006-01-02 21:04:38 +03:00
return ;
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
publ_to_item ( item , publ ) ;
2006-01-18 02:38:21 +03:00
dbg ( " tipc_named_withdraw: broadcasting publish msg \n " ) ;
tipc_cltr_broadcast ( buf ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_named_withdraw - tell other nodes about a withdrawn publication by this node
2006-01-02 21:04:38 +03:00
*/
2006-01-18 02:38:21 +03:00
void tipc_named_withdraw ( struct publication * publ )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct distr_item * item ;
list_del ( & publ - > local_list ) ;
publ_cnt - - ;
buf = named_prepare_buf ( WITHDRAWAL , ITEM_SIZE , 0 ) ;
if ( ! buf ) {
2006-06-26 10:52:17 +04:00
warn ( " Withdrawl distribution failure \n " ) ;
2006-01-02 21:04:38 +03:00
return ;
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
publ_to_item ( item , publ ) ;
2006-01-18 02:38:21 +03:00
dbg ( " tipc_named_withdraw: broadcasting withdraw msg \n " ) ;
tipc_cltr_broadcast ( buf ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_named_node_up - tell specified node about all publications by this node
2006-01-02 21:04:38 +03:00
*/
2006-01-18 02:38:21 +03:00
void tipc_named_node_up ( unsigned long node )
2006-01-02 21:04:38 +03:00
{
struct publication * publ ;
2006-03-21 09:36:47 +03:00
struct distr_item * item = NULL ;
struct sk_buff * buf = NULL ;
2006-01-02 21:04:38 +03:00
u32 left = 0 ;
u32 rest ;
u32 max_item_buf ;
2007-02-09 17:25:21 +03:00
read_lock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE ;
max_item_buf * = ITEM_SIZE ;
rest = publ_cnt * ITEM_SIZE ;
list_for_each_entry ( publ , & publ_root , local_list ) {
if ( ! buf ) {
left = ( rest < = max_item_buf ) ? rest : max_item_buf ;
rest - = left ;
2007-02-09 17:25:21 +03:00
buf = named_prepare_buf ( PUBLICATION , left , node ) ;
2006-06-26 10:52:17 +04:00
if ( ! buf ) {
warn ( " Bulk publication distribution failure \n " ) ;
2006-01-02 21:04:38 +03:00
goto exit ;
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
}
publ_to_item ( item , publ ) ;
item + + ;
left - = ITEM_SIZE ;
if ( ! left ) {
msg_set_link_selector ( buf_msg ( buf ) , node ) ;
2006-01-18 02:38:21 +03:00
dbg ( " tipc_named_node_up: sending publish msg to "
2007-02-09 17:25:21 +03:00
" <%u.%u.%u> \n " , tipc_zone ( node ) ,
2006-01-02 21:04:38 +03:00
tipc_cluster ( node ) , tipc_node ( node ) ) ;
2006-01-18 02:38:21 +03:00
tipc_link_send ( buf , node , node ) ;
2006-03-21 09:36:47 +03:00
buf = NULL ;
2006-01-02 21:04:38 +03:00
}
}
exit :
2007-02-09 17:25:21 +03:00
read_unlock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
}
/**
* node_is_down - remove publication associated with a failed node
2007-02-09 17:25:21 +03:00
*
* Invoked for each publication issued by a newly failed node .
2006-01-02 21:04:38 +03:00
* Removes publication structure from name table & deletes it .
* In rare cases the link may have come back up again when this
* function is called , and we have two items representing the same
* publication . Nudge this item ' s key to distinguish it from the other .
* ( Note : Publication ' s node subscription is already unsubscribed . )
*/
static void node_is_down ( struct publication * publ )
{
struct publication * p ;
2006-06-26 10:51:37 +04:00
2007-02-09 17:25:21 +03:00
write_lock_bh ( & tipc_nametbl_lock ) ;
dbg ( " node_is_down: withdrawing %u, %u, %u \n " ,
2006-01-02 21:04:38 +03:00
publ - > type , publ - > lower , publ - > upper ) ;
2007-02-09 17:25:21 +03:00
publ - > key + = 1222345 ;
p = tipc_nametbl_remove_publ ( publ - > type , publ - > lower ,
2006-01-18 02:38:21 +03:00
publ - > node , publ - > ref , publ - > key ) ;
write_unlock_bh ( & tipc_nametbl_lock ) ;
2006-06-26 10:51:37 +04:00
2007-02-09 17:25:21 +03:00
if ( p ! = publ ) {
2006-06-26 10:51:37 +04:00
err ( " Unable to remove publication from failed node \n "
" (type=%u, lower=%u, node=0x%x, ref=%u, key=%u) \n " ,
publ - > type , publ - > lower , publ - > node , publ - > ref , publ - > key ) ;
}
if ( p ) {
kfree ( p ) ;
}
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_named_recv - process name table update message sent by another node
2006-01-02 21:04:38 +03:00
*/
2006-01-18 02:38:21 +03:00
void tipc_named_recv ( struct sk_buff * buf )
2006-01-02 21:04:38 +03:00
{
struct publication * publ ;
struct tipc_msg * msg = buf_msg ( buf ) ;
struct distr_item * item = ( struct distr_item * ) msg_data ( msg ) ;
u32 count = msg_data_sz ( msg ) / ITEM_SIZE ;
2007-02-09 17:25:21 +03:00
write_lock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
while ( count - - ) {
if ( msg_type ( msg ) = = PUBLICATION ) {
2007-02-09 17:25:21 +03:00
dbg ( " tipc_named_recv: got publication for %u, %u, %u \n " ,
2006-01-02 21:04:38 +03:00
ntohl ( item - > type ) , ntohl ( item - > lower ) ,
ntohl ( item - > upper ) ) ;
2007-02-09 17:25:21 +03:00
publ = tipc_nametbl_insert_publ ( ntohl ( item - > type ) ,
2006-01-18 02:38:21 +03:00
ntohl ( item - > lower ) ,
ntohl ( item - > upper ) ,
TIPC_CLUSTER_SCOPE ,
2007-02-09 17:25:21 +03:00
msg_orignode ( msg ) ,
2006-01-18 02:38:21 +03:00
ntohl ( item - > ref ) ,
ntohl ( item - > key ) ) ;
2006-01-02 21:04:38 +03:00
if ( publ ) {
2007-02-09 17:25:21 +03:00
tipc_nodesub_subscribe ( & publ - > subscr ,
msg_orignode ( msg ) ,
2006-01-18 02:38:21 +03:00
publ ,
( net_ev_handler ) node_is_down ) ;
2006-01-02 21:04:38 +03:00
}
} else if ( msg_type ( msg ) = = WITHDRAWAL ) {
2007-02-09 17:25:21 +03:00
dbg ( " tipc_named_recv: got withdrawl for %u, %u, %u \n " ,
2006-01-02 21:04:38 +03:00
ntohl ( item - > type ) , ntohl ( item - > lower ) ,
ntohl ( item - > upper ) ) ;
2006-01-18 02:38:21 +03:00
publ = tipc_nametbl_remove_publ ( ntohl ( item - > type ) ,
ntohl ( item - > lower ) ,
msg_orignode ( msg ) ,
ntohl ( item - > ref ) ,
ntohl ( item - > key ) ) ;
2006-01-02 21:04:38 +03:00
if ( publ ) {
2006-01-18 02:38:21 +03:00
tipc_nodesub_unsubscribe ( & publ - > subscr ) ;
2007-02-09 17:25:21 +03:00
kfree ( publ ) ;
2006-06-26 10:51:37 +04:00
} else {
err ( " Unable to remove publication by node 0x%x \n "
" (type=%u, lower=%u, ref=%u, key=%u) \n " ,
msg_orignode ( msg ) ,
ntohl ( item - > type ) , ntohl ( item - > lower ) ,
ntohl ( item - > ref ) , ntohl ( item - > key ) ) ;
2006-01-02 21:04:38 +03:00
}
} else {
2006-06-26 10:52:17 +04:00
warn ( " Unrecognized name table message received \n " ) ;
2006-01-02 21:04:38 +03:00
}
item + + ;
}
2007-02-09 17:25:21 +03:00
write_unlock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
buf_discard ( buf ) ;
}
/**
2006-01-18 02:38:21 +03:00
* tipc_named_reinit - re - initialize local publication list
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* This routine is called whenever TIPC networking is ( re ) enabled .
* All existing publications by this node that have " cluster " or " zone " scope
* are updated to reflect the node ' s current network address .
* ( If the node ' s address is unchanged , the update loop terminates immediately . )
*/
2006-01-18 02:38:21 +03:00
void tipc_named_reinit ( void )
2006-01-02 21:04:38 +03:00
{
struct publication * publ ;
2007-02-09 17:25:21 +03:00
write_lock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
list_for_each_entry ( publ , & publ_root , local_list ) {
if ( publ - > node = = tipc_own_addr )
break ;
publ - > node = tipc_own_addr ;
}
2007-02-09 17:25:21 +03:00
write_unlock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
}