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"
/**
2012-04-18 01:57:52 +04:00
* struct publ_list - list of publications made by this node
* @ list : circular list of publications
* @ list_size : number of entries in list
2006-01-02 21:04:38 +03:00
*/
2012-04-18 01:57:52 +04:00
struct publ_list {
struct list_head list ;
u32 size ;
} ;
2006-01-02 21:04:38 +03:00
2012-04-18 01:57:52 +04:00
static struct publ_list publ_zone = {
. list = LIST_HEAD_INIT ( publ_zone . list ) ,
. size = 0 ,
} ;
2012-04-18 01:57:52 +04:00
static struct publ_list publ_cluster = {
. list = LIST_HEAD_INIT ( publ_cluster . list ) ,
. size = 0 ,
} ;
2006-01-02 21:04:38 +03:00
2012-04-18 01:57:52 +04:00
static struct publ_list publ_node = {
. list = LIST_HEAD_INIT ( publ_node . list ) ,
. size = 0 ,
} ;
static struct publ_list * publ_lists [ ] = {
NULL ,
& publ_zone , /* publ_lists[TIPC_ZONE_SCOPE] */
& publ_cluster , /* publ_lists[TIPC_CLUSTER_SCOPE] */
& publ_node /* publ_lists[TIPC_NODE_SCOPE] */
} ;
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 ;
}
2014-04-28 14:00:10 +04:00
void named_cluster_distribute ( struct sk_buff * buf )
2010-12-31 21:59:19 +03:00
{
2014-07-17 04:40:58 +04:00
struct sk_buff * obuf ;
struct tipc_node * node ;
u32 dnode ;
2010-12-31 21:59:19 +03:00
2014-03-27 08:54:37 +04:00
rcu_read_lock ( ) ;
2014-07-17 04:40:58 +04:00
list_for_each_entry_rcu ( node , & tipc_node_list , list ) {
dnode = node - > addr ;
if ( in_own_node ( dnode ) )
continue ;
if ( ! tipc_node_active_links ( node ) )
continue ;
obuf = skb_copy ( buf , GFP_ATOMIC ) ;
if ( ! obuf )
break ;
msg_set_destnode ( buf_msg ( obuf ) , dnode ) ;
2014-07-17 04:41:03 +04:00
tipc_link_xmit ( obuf , dnode , dnode ) ;
2010-12-31 21:59:19 +03:00
}
2014-03-27 08:54:37 +04:00
rcu_read_unlock ( ) ;
2010-12-31 21:59:19 +03:00
2011-11-04 21:24:29 +04:00
kfree_skb ( buf ) ;
2010-12-31 21:59:19 +03:00
}
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
*/
2014-04-28 14:00:10 +04:00
struct sk_buff * tipc_named_publish ( struct publication * publ )
2006-01-02 21:04:38 +03:00
{
struct sk_buff * buf ;
struct distr_item * item ;
2012-04-18 01:57:52 +04:00
list_add_tail ( & publ - > local_list , & publ_lists [ publ - > scope ] - > list ) ;
publ_lists [ publ - > scope ] - > size + + ;
2006-01-02 21:04:38 +03:00
2012-04-18 01:57:52 +04:00
if ( publ - > scope = = TIPC_NODE_SCOPE )
2014-04-28 14:00:10 +04:00
return NULL ;
2012-04-18 01:57:52 +04:00
2006-01-02 21:04:38 +03:00
buf = named_prepare_buf ( PUBLICATION , ITEM_SIZE , 0 ) ;
if ( ! buf ) {
2012-06-29 08:16:37 +04:00
pr_warn ( " Publication distribution failure \n " ) ;
2014-04-28 14:00:10 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
publ_to_item ( item , publ ) ;
2014-04-28 14:00:10 +04:00
return 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
*/
2014-04-28 14:00:10 +04:00
struct sk_buff * 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 ) ;
2012-04-18 01:57:52 +04:00
publ_lists [ publ - > scope ] - > size - - ;
2006-01-02 21:04:38 +03:00
2012-04-18 01:57:52 +04:00
if ( publ - > scope = = TIPC_NODE_SCOPE )
2014-04-28 14:00:10 +04:00
return NULL ;
2012-04-18 01:57:52 +04:00
2006-01-02 21:04:38 +03:00
buf = named_prepare_buf ( WITHDRAWAL , ITEM_SIZE , 0 ) ;
if ( ! buf ) {
2012-06-29 08:16:37 +04:00
pr_warn ( " Withdrawal distribution failure \n " ) ;
2014-04-28 14:00:10 +04:00
return NULL ;
2006-01-02 21:04:38 +03:00
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
publ_to_item ( item , publ ) ;
2014-04-28 14:00:10 +04:00
return buf ;
2006-01-02 21:04:38 +03:00
}
2014-07-17 04:40:58 +04:00
/**
2012-04-18 01:57:52 +04:00
* named_distribute - prepare name info for bulk distribution to another node
2014-07-17 04:40:58 +04:00
* @ msg_list : list of messages ( buffers ) to be returned from this function
* @ dnode : node to be updated
* @ pls : linked list of publication items to be packed into buffer chain
2012-04-18 01:57:52 +04:00
*/
2014-07-17 04:40:58 +04:00
static void named_distribute ( struct list_head * msg_list , u32 dnode ,
struct publ_list * pls )
2012-04-18 01:57:52 +04:00
{
struct publication * publ ;
struct sk_buff * buf = NULL ;
struct distr_item * item = NULL ;
2014-07-17 04:40:58 +04:00
uint dsz = pls - > size * ITEM_SIZE ;
uint msg_dsz = ( tipc_node_get_mtu ( dnode , 0 ) / ITEM_SIZE ) * ITEM_SIZE ;
uint rem = dsz ;
uint msg_rem = 0 ;
2012-04-18 01:57:52 +04:00
list_for_each_entry ( publ , & pls - > list , local_list ) {
2014-07-17 04:40:58 +04:00
/* Prepare next buffer: */
2012-04-18 01:57:52 +04:00
if ( ! buf ) {
2014-07-17 04:40:58 +04:00
msg_rem = min_t ( uint , rem , msg_dsz ) ;
rem - = msg_rem ;
buf = named_prepare_buf ( PUBLICATION , msg_rem , dnode ) ;
2012-04-18 01:57:52 +04:00
if ( ! buf ) {
2012-06-29 08:16:37 +04:00
pr_warn ( " Bulk publication failure \n " ) ;
2012-04-18 01:57:52 +04:00
return ;
}
item = ( struct distr_item * ) msg_data ( buf_msg ( buf ) ) ;
}
2014-07-17 04:40:58 +04:00
/* Pack publication into message: */
2012-04-18 01:57:52 +04:00
publ_to_item ( item , publ ) ;
item + + ;
2014-07-17 04:40:58 +04:00
msg_rem - = ITEM_SIZE ;
/* Append full buffer to list: */
if ( ! msg_rem ) {
list_add_tail ( ( struct list_head * ) buf , msg_list ) ;
2012-04-18 01:57:52 +04:00
buf = NULL ;
}
}
}
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
*/
2014-07-17 04:40:58 +04:00
void tipc_named_node_up ( u32 dnode )
2006-01-02 21:04:38 +03:00
{
2014-07-17 04:40:58 +04:00
LIST_HEAD ( msg_list ) ;
struct sk_buff * buf_chain ;
2011-05-31 21:38:02 +04:00
2007-02-09 17:25:21 +03:00
read_lock_bh ( & tipc_nametbl_lock ) ;
2014-07-17 04:40:58 +04:00
named_distribute ( & msg_list , dnode , & publ_cluster ) ;
named_distribute ( & msg_list , dnode , & publ_zone ) ;
2007-02-09 17:25:21 +03:00
read_unlock_bh ( & tipc_nametbl_lock ) ;
2011-05-31 21:38:02 +04:00
2014-07-17 04:40:58 +04:00
/* Convert circular list to linear list and send: */
buf_chain = ( struct sk_buff * ) msg_list . next ;
( ( struct sk_buff * ) msg_list . prev ) - > next = NULL ;
2014-07-17 04:41:03 +04:00
tipc_link_xmit ( buf_chain , dnode , dnode ) ;
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 ) {
2012-06-29 08:16:37 +04:00
pr_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 ) ;
2006-06-26 10:51:37 +04:00
}
2010-12-31 21:59:30 +03:00
kfree ( p ) ;
2006-01-02 21:04:38 +03:00
}
/**
2014-02-18 12:06:46 +04:00
* tipc_named_rcv - process name table update message sent by another node
2006-01-02 21:04:38 +03:00
*/
2014-02-18 12:06:46 +04:00
void tipc_named_rcv ( 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 {
2012-06-29 08:16:37 +04:00
pr_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 {
2012-06-29 08:16:37 +04:00
pr_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 ) ;
2011-11-04 21:24:29 +04:00
kfree_skb ( buf ) ;
2006-01-02 21:04:38 +03:00
}
/**
2012-04-18 01:57:52 +04:00
* tipc_named_reinit - re - initialize local publications
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 .
2012-04-18 01:57:52 +04:00
* All name table entries published by this node 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 ;
2012-04-18 01:57:52 +04:00
int scope ;
2006-01-02 21:04:38 +03:00
2007-02-09 17:25:21 +03:00
write_lock_bh ( & tipc_nametbl_lock ) ;
2011-10-14 22:42:25 +04:00
2012-04-18 01:57:52 +04:00
for ( scope = TIPC_ZONE_SCOPE ; scope < = TIPC_NODE_SCOPE ; scope + + )
2012-04-18 01:57:52 +04:00
list_for_each_entry ( publ , & publ_lists [ scope ] - > list , local_list )
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
}