2006-01-02 21:04:38 +03:00
/*
* net / tipc / discover . c
2007-02-09 17:25:21 +03:00
*
2006-01-11 20:40:41 +03:00
* Copyright ( c ) 2003 - 2006 , Ericsson AB
2011-01-07 21:00:11 +03:00
* Copyright ( c ) 2005 - 2006 , 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 "discover.h"
# define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */
# define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */
# define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */
2007-02-09 17:25:21 +03:00
/*
2006-01-02 21:04:38 +03:00
* TODO : Most of the inter - cluster setup stuff should be
* rewritten , and be made conformant with specification .
2007-02-09 17:25:21 +03:00
*/
2006-01-02 21:04:38 +03:00
/**
* struct link_req - information about an ongoing link setup request
* @ bearer : bearer issuing requests
* @ dest : destination address for request messages
2011-04-21 01:24:07 +04:00
* @ domain : network domain to which links can be established
2006-01-02 21:04:38 +03:00
* @ buf : request message to be ( repeatedly ) sent
* @ timer : timer governing period between requests
* @ timer_intv : current interval between requests ( in ms )
*/
struct link_req {
2011-01-07 21:00:11 +03:00
struct tipc_bearer * bearer ;
2006-01-02 21:04:38 +03:00
struct tipc_media_addr dest ;
2011-04-21 01:24:07 +04:00
u32 domain ;
2006-01-02 21:04:38 +03:00
struct sk_buff * buf ;
struct timer_list timer ;
unsigned int timer_intv ;
} ;
2007-02-09 17:25:21 +03:00
/**
2006-01-18 02:38:21 +03:00
* tipc_disc_init_msg - initialize a link setup message
2006-01-02 21:04:38 +03:00
* @ type : message type ( request or response )
* @ dest_domain : network domain of node ( s ) which should respond to message
* @ b_ptr : ptr to bearer issuing message
*/
2006-03-21 09:37:52 +03:00
static struct sk_buff * tipc_disc_init_msg ( u32 type ,
u32 dest_domain ,
2011-01-07 21:00:11 +03:00
struct tipc_bearer * b_ptr )
2006-01-02 21:04:38 +03:00
{
2011-03-01 00:02:30 +03:00
struct sk_buff * buf = tipc_buf_acquire ( INT_H_SIZE ) ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg ;
if ( buf ) {
msg = buf_msg ( buf ) ;
2011-03-01 00:02:30 +03:00
tipc_msg_init ( msg , LINK_CONFIG , type , INT_H_SIZE , dest_domain ) ;
2008-06-05 04:54:48 +04:00
msg_set_non_seq ( msg , 1 ) ;
2006-01-02 21:04:38 +03:00
msg_set_dest_domain ( msg , dest_domain ) ;
msg_set_bc_netid ( msg , tipc_net_id ) ;
2011-01-07 21:00:11 +03:00
msg_set_media_addr ( msg , & b_ptr - > addr ) ;
2006-01-02 21:04:38 +03:00
}
return buf ;
}
2006-10-17 08:44:59 +04:00
/**
* disc_dupl_alert - issue node address duplication alert
* @ b_ptr : pointer to bearer detecting duplication
* @ node_addr : duplicated node address
* @ media_addr : media address advertised by duplicated node
*/
2011-01-07 21:00:11 +03:00
static void disc_dupl_alert ( struct tipc_bearer * b_ptr , u32 node_addr ,
2006-10-17 08:44:59 +04:00
struct tipc_media_addr * media_addr )
{
char node_addr_str [ 16 ] ;
char media_addr_str [ 64 ] ;
struct print_buf pb ;
2010-05-11 18:30:12 +04:00
tipc_addr_string_fill ( node_addr_str , node_addr ) ;
2006-10-17 08:44:59 +04:00
tipc_printbuf_init ( & pb , media_addr_str , sizeof ( media_addr_str ) ) ;
tipc_media_addr_printf ( & pb , media_addr ) ;
tipc_printbuf_validate ( & pb ) ;
warn ( " Duplicate %s using %s seen on <%s> \n " ,
2011-01-07 21:00:11 +03:00
node_addr_str , media_addr_str , b_ptr - > name ) ;
2006-10-17 08:44:59 +04:00
}
2006-01-02 21:04:38 +03:00
/**
2006-01-18 02:38:21 +03:00
* tipc_disc_recv_msg - handle incoming link setup message ( request or response )
2006-01-02 21:04:38 +03:00
* @ buf : buffer containing message
2008-06-05 04:32:35 +04:00
* @ b_ptr : bearer that message arrived on
2006-01-02 21:04:38 +03:00
*/
2011-01-07 21:00:11 +03:00
void tipc_disc_recv_msg ( struct sk_buff * buf , struct tipc_bearer * b_ptr )
2006-01-02 21:04:38 +03:00
{
2011-02-28 18:03:05 +03:00
struct tipc_node * n_ptr ;
2006-01-02 21:04:38 +03:00
struct link * link ;
2011-02-28 18:03:05 +03:00
struct tipc_media_addr media_addr , * addr ;
struct sk_buff * rbuf ;
2006-01-02 21:04:38 +03:00
struct tipc_msg * msg = buf_msg ( buf ) ;
u32 dest = msg_dest_domain ( msg ) ;
u32 orig = msg_prevnode ( msg ) ;
u32 net_id = msg_bc_netid ( msg ) ;
u32 type = msg_type ( msg ) ;
2011-02-28 18:03:05 +03:00
int link_fully_up ;
2006-01-02 21:04:38 +03:00
2010-12-31 21:59:32 +03:00
msg_get_media_addr ( msg , & media_addr ) ;
2006-01-02 21:04:38 +03:00
buf_discard ( buf ) ;
2011-02-28 18:03:05 +03:00
/* Validate discovery message from requesting node */
2006-01-02 21:04:38 +03:00
if ( net_id ! = tipc_net_id )
return ;
2006-01-18 02:38:21 +03:00
if ( ! tipc_addr_domain_valid ( dest ) )
2006-01-02 21:04:38 +03:00
return ;
2006-01-18 02:38:21 +03:00
if ( ! tipc_addr_node_valid ( orig ) )
2006-01-02 21:04:38 +03:00
return ;
2006-10-17 08:44:59 +04:00
if ( orig = = tipc_own_addr ) {
2011-01-07 21:00:11 +03:00
if ( memcmp ( & media_addr , & b_ptr - > addr , sizeof ( media_addr ) ) )
2006-10-17 08:44:59 +04:00
disc_dupl_alert ( b_ptr , tipc_own_addr , & media_addr ) ;
2006-01-02 21:04:38 +03:00
return ;
2006-10-17 08:44:59 +04:00
}
2010-05-11 18:30:12 +04:00
if ( ! tipc_in_scope ( dest , tipc_own_addr ) )
2006-01-02 21:04:38 +03:00
return ;
2011-04-21 01:24:07 +04:00
if ( ! tipc_in_scope ( b_ptr - > link_req - > domain , orig ) )
2011-02-28 18:03:05 +03:00
return ;
2010-08-17 15:00:16 +04:00
2011-02-28 18:03:05 +03:00
/* Locate structure corresponding to requesting node */
n_ptr = tipc_node_find ( orig ) ;
if ( ! n_ptr ) {
n_ptr = tipc_node_create ( orig ) ;
if ( ! n_ptr )
2010-08-17 15:00:16 +04:00
return ;
2011-02-28 18:03:05 +03:00
}
tipc_node_lock ( n_ptr ) ;
/* Don't talk to neighbor during cleanup after last session */
if ( n_ptr - > cleanup_required ) {
tipc_node_unlock ( n_ptr ) ;
return ;
}
2010-08-17 15:00:16 +04:00
2011-02-28 18:03:05 +03:00
link = n_ptr - > links [ b_ptr - > identity ] ;
/* Create a link endpoint for this bearer, if necessary */
if ( ! link ) {
2011-02-28 19:32:27 +03:00
link = tipc_link_create ( n_ptr , b_ptr , & media_addr ) ;
2006-01-02 21:04:38 +03:00
if ( ! link ) {
2011-02-28 18:03:05 +03:00
tipc_node_unlock ( n_ptr ) ;
return ;
2006-01-02 21:04:38 +03:00
}
2011-02-28 18:03:05 +03:00
}
/*
* Ensure requesting node ' s media address is correct
*
* If media address doesn ' t match and the link is working , reject the
* request ( must be from a duplicate node ) .
*
* If media address doesn ' t match and the link is not working , accept
* the new media address and reset the link to ensure it starts up
* cleanly .
*/
addr = & link - > media_addr ;
if ( memcmp ( addr , & media_addr , sizeof ( * addr ) ) ) {
if ( tipc_link_is_up ( link ) | | ( ! link - > started ) ) {
disc_dupl_alert ( b_ptr , orig , & media_addr ) ;
tipc_node_unlock ( n_ptr ) ;
2006-01-02 21:04:38 +03:00
return ;
}
2011-02-28 18:03:05 +03:00
warn ( " Resetting link <%s>, peer interface address changed \n " ,
link - > name ) ;
memcpy ( addr , & media_addr , sizeof ( * addr ) ) ;
tipc_link_reset ( link ) ;
}
/* Accept discovery message & send response, if necessary */
link_fully_up = link_working_working ( link ) ;
2011-02-28 18:56:23 +03:00
2011-02-28 19:04:08 +03:00
if ( ( type = = DSC_REQ_MSG ) & & ! link_fully_up & & ! b_ptr - > blocked ) {
2011-02-28 18:56:23 +03:00
rbuf = tipc_disc_init_msg ( DSC_RESP_MSG , orig , b_ptr ) ;
if ( rbuf ) {
b_ptr - > media - > send_msg ( rbuf , b_ptr , & media_addr ) ;
buf_discard ( rbuf ) ;
}
2006-01-02 21:04:38 +03:00
}
2011-02-28 18:56:23 +03:00
tipc_node_unlock ( n_ptr ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_disc_stop_link_req - stop sending periodic link setup requests
2006-01-02 21:04:38 +03:00
* @ req : ptr to link request structure
*/
2007-02-09 17:25:21 +03:00
void tipc_disc_stop_link_req ( struct link_req * req )
2006-01-02 21:04:38 +03:00
{
if ( ! req )
return ;
2007-02-09 17:25:21 +03:00
2006-01-02 21:04:38 +03:00
k_cancel_timer ( & req - > timer ) ;
k_term_timer ( & req - > timer ) ;
buf_discard ( req - > buf ) ;
kfree ( req ) ;
2007-02-09 17:25:21 +03:00
}
2006-01-02 21:04:38 +03:00
/**
2006-01-18 02:38:21 +03:00
* tipc_disc_update_link_req - update frequency of periodic link setup requests
2006-01-02 21:04:38 +03:00
* @ req : ptr to link request structure
*/
2007-02-09 17:25:21 +03:00
void tipc_disc_update_link_req ( struct link_req * req )
2006-01-02 21:04:38 +03:00
{
if ( ! req )
return ;
if ( req - > timer_intv = = TIPC_LINK_REQ_SLOW ) {
if ( ! req - > bearer - > nodes . count ) {
req - > timer_intv = TIPC_LINK_REQ_FAST ;
k_start_timer ( & req - > timer , req - > timer_intv ) ;
}
} else if ( req - > timer_intv = = TIPC_LINK_REQ_FAST ) {
if ( req - > bearer - > nodes . count ) {
req - > timer_intv = TIPC_LINK_REQ_SLOW ;
k_start_timer ( & req - > timer , req - > timer_intv ) ;
}
} else {
/* leave timer "as is" if haven't yet reached a "normal" rate */
}
2007-02-09 17:25:21 +03:00
}
2006-01-02 21:04:38 +03:00
/**
* disc_timeout - send a periodic link setup request
* @ req : ptr to link request structure
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Called whenever a link setup request timer associated with a bearer expires .
*/
2007-02-09 17:25:21 +03:00
static void disc_timeout ( struct link_req * req )
2006-01-02 21:04:38 +03:00
{
2011-01-07 21:00:11 +03:00
spin_lock_bh ( & req - > bearer - > lock ) ;
2006-01-02 21:04:38 +03:00
2011-01-07 21:00:11 +03:00
req - > bearer - > media - > send_msg ( req - > buf , req - > bearer , & req - > dest ) ;
2006-01-02 21:04:38 +03:00
if ( ( req - > timer_intv = = TIPC_LINK_REQ_SLOW ) | |
( req - > timer_intv = = TIPC_LINK_REQ_FAST ) ) {
/* leave timer interval "as is" if already at a "normal" rate */
} else {
req - > timer_intv * = 2 ;
2006-06-26 10:53:47 +04:00
if ( req - > timer_intv > TIPC_LINK_REQ_FAST )
req - > timer_intv = TIPC_LINK_REQ_FAST ;
2007-02-09 17:25:21 +03:00
if ( ( req - > timer_intv = = TIPC_LINK_REQ_FAST ) & &
2006-01-02 21:04:38 +03:00
( req - > bearer - > nodes . count ) )
req - > timer_intv = TIPC_LINK_REQ_SLOW ;
}
k_start_timer ( & req - > timer , req - > timer_intv ) ;
2011-01-07 21:00:11 +03:00
spin_unlock_bh ( & req - > bearer - > lock ) ;
2006-01-02 21:04:38 +03:00
}
/**
2006-01-18 02:38:21 +03:00
* tipc_disc_init_link_req - start sending periodic link setup requests
2006-01-02 21:04:38 +03:00
* @ b_ptr : ptr to bearer issuing requests
* @ dest : destination address for request messages
2011-04-21 01:24:07 +04:00
* @ dest_domain : network domain to which links can be established
2007-02-09 17:25:21 +03:00
*
2006-01-02 21:04:38 +03:00
* Returns pointer to link request structure , or NULL if unable to create .
*/
2011-01-07 21:00:11 +03:00
struct link_req * tipc_disc_init_link_req ( struct tipc_bearer * b_ptr ,
2006-01-18 02:38:21 +03:00
const struct tipc_media_addr * dest ,
2011-01-25 22:39:59 +03:00
u32 dest_domain )
2006-01-02 21:04:38 +03:00
{
struct link_req * req ;
2006-07-22 02:52:20 +04:00
req = kmalloc ( sizeof ( * req ) , GFP_ATOMIC ) ;
2006-01-02 21:04:38 +03:00
if ( ! req )
return NULL ;
2011-01-25 22:39:59 +03:00
req - > buf = tipc_disc_init_msg ( DSC_REQ_MSG , dest_domain , b_ptr ) ;
2006-01-02 21:04:38 +03:00
if ( ! req - > buf ) {
kfree ( req ) ;
return NULL ;
}
memcpy ( & req - > dest , dest , sizeof ( * dest ) ) ;
req - > bearer = b_ptr ;
2011-04-21 01:24:07 +04:00
req - > domain = dest_domain ;
2006-01-02 21:04:38 +03:00
req - > timer_intv = TIPC_LINK_REQ_INIT ;
k_init_timer ( & req - > timer , ( Handler ) disc_timeout , ( unsigned long ) req ) ;
k_start_timer ( & req - > timer , req - > timer_intv ) ;
return req ;
2007-02-09 17:25:21 +03:00
}
2006-01-02 21:04:38 +03:00