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
2011-02-23 21:51:15 +03:00
* Copyright ( c ) 2005 , 2010 - 2011 , Wind River Systems
2006-01-02 21:04:38 +03:00
* 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 "link.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 ) ;
2010-12-31 21:59:34 +03:00
static u32 publ_cnt ;
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 ) ;
}
/**
* named_prepare_buf - allocate & initialize a publication message
*/
static struct sk_buff * named_prepare_buf ( u32 type , u32 size , u32 dest )
{
2011-05-31 23:03:18 +04:00
struct sk_buff * buf = tipc_buf_acquire ( INT_H_SIZE + size ) ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg ;
if ( buf ! = NULL ) {
msg = buf_msg ( buf ) ;
2011-05-31 23:03:18 +04:00
tipc_msg_init ( msg , NAME_DISTRIBUTOR , type , INT_H_SIZE , dest ) ;
msg_set_size ( msg , INT_H_SIZE + size ) ;
2006-01-02 21:04:38 +03:00
}
return buf ;
}
2010-12-31 21:59:19 +03:00
static void named_cluster_distribute ( struct sk_buff * buf )
{
struct sk_buff * buf_copy ;
struct tipc_node * n_ptr ;
2011-02-26 02:42:52 +03:00
list_for_each_entry ( n_ptr , & tipc_node_list , list ) {
2011-02-28 18:36:21 +03:00
if ( tipc_node_active_links ( n_ptr ) ) {
2010-12-31 21:59:19 +03:00
buf_copy = skb_copy ( buf , GFP_ATOMIC ) ;
if ( ! buf_copy )
break ;
msg_set_destnode ( buf_msg ( buf_copy ) , n_ptr - > addr ) ;
tipc_link_send ( buf_copy , n_ptr - > addr , n_ptr - > addr ) ;
}
}
buf_discard ( buf ) ;
}
2006-01-02 21:04:38 +03:00
/**
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 ) ;
2010-12-31 21:59:19 +03:00
named_cluster_distribute ( 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 ) {
2011-03-31 05:57:33 +04:00
warn ( " Withdrawal 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 ) ;
2010-12-31 21:59:19 +03:00
named_cluster_distribute ( 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
*/
2011-09-02 21:45:34 +04:00
void tipc_named_node_up ( unsigned long nodearg )
2006-01-02 21:04:38 +03:00
{
2011-05-31 19:05:02 +04:00
struct tipc_node * n_ptr ;
2011-12-30 05:58:42 +04:00
struct tipc_link * l_ptr ;
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 ;
2011-05-31 21:38:02 +04:00
struct list_head message_list ;
2011-09-02 21:45:34 +04:00
u32 node = ( u32 ) nodearg ;
2006-01-02 21:04:38 +03:00
u32 left = 0 ;
u32 rest ;
2011-05-31 19:05:02 +04:00
u32 max_item_buf = 0 ;
/* compute maximum amount of publication data to send per message */
read_lock_bh ( & tipc_net_lock ) ;
2011-09-02 21:45:34 +04:00
n_ptr = tipc_node_find ( node ) ;
2011-05-31 19:05:02 +04:00
if ( n_ptr ) {
tipc_node_lock ( n_ptr ) ;
l_ptr = n_ptr - > active_links [ 0 ] ;
if ( l_ptr )
max_item_buf = ( ( l_ptr - > max_pkt - INT_H_SIZE ) /
ITEM_SIZE ) * ITEM_SIZE ;
tipc_node_unlock ( n_ptr ) ;
}
read_unlock_bh ( & tipc_net_lock ) ;
if ( ! max_item_buf )
return ;
2006-01-02 21:04:38 +03:00
2011-05-31 21:38:02 +04:00
/* create list of publication messages, then send them as a unit */
INIT_LIST_HEAD ( & message_list ) ;
2007-02-09 17:25:21 +03:00
read_lock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
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 ) {
2011-05-31 21:38:02 +04:00
list_add_tail ( ( struct list_head * ) buf , & message_list ) ;
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 ) ;
2011-05-31 21:38:02 +04:00
tipc_link_send_names ( & message_list , ( u32 ) node ) ;
2006-01-02 21:04:38 +03:00
}
/**
2011-02-23 22:13:41 +03:00
* named_purge_publ - 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 .
*/
2011-02-23 22:13:41 +03:00
static void named_purge_publ ( struct publication * publ )
2006-01-02 21:04:38 +03:00
{
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 ) ;
p = tipc_nametbl_remove_publ ( publ - > type , publ - > lower ,
2006-01-18 02:38:21 +03:00
publ - > node , publ - > ref , publ - > key ) ;
2011-02-23 21:51:15 +03:00
if ( p )
tipc_nodesub_unsubscribe ( & p - > subscr ) ;
2006-01-18 02:38:21 +03:00
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 ) ;
}
2010-12-31 21:59:30 +03:00
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
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 ,
2011-02-23 22:13:41 +03:00
( net_ev_handler )
named_purge_publ ) ;
2006-01-02 21:04:38 +03:00
}
} else if ( msg_type ( msg ) = = WITHDRAWAL ) {
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
*
2011-10-14 22:42:25 +04:00
* This routine is called whenever TIPC networking is enabled .
2006-01-02 21:04:38 +03:00
* All existing publications by this node that have " cluster " or " zone " scope
2011-10-14 22:42:25 +04:00
* are updated to reflect the node ' s new network address .
2006-01-02 21:04:38 +03:00
*/
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 ) ;
2011-10-14 22:42:25 +04:00
list_for_each_entry ( publ , & publ_root , local_list )
2006-01-02 21:04:38 +03:00
publ - > node = tipc_own_addr ;
2011-10-14 22:42:25 +04:00
2007-02-09 17:25:21 +03:00
write_unlock_bh ( & tipc_nametbl_lock ) ;
2006-01-02 21:04:38 +03:00
}