@ -20,6 +20,7 @@
*/
# include "main.h"
# include "bat_sysfs.h"
# include "gateway_client.h"
# include "gateway_common.h"
# include "hard-interface.h"
@ -97,40 +98,19 @@ static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
void gw_deselect ( struct bat_priv * bat_priv )
{
gw_select ( bat_priv , NULL ) ;
atomic_set ( & bat_priv - > gw_reselect , 1 ) ;
}
void gw_election ( struct bat_priv * bat_priv )
static struct gw_node * gw_get_best_gw_node ( struct bat_priv * bat_priv )
{
struct hlist_node * node ;
struct gw_node * gw_node , * curr_gw = NULL , * curr_gw_tmp = NULL ;
struct neigh_node * router ;
uint8_t max_tq = 0 ;
struct hlist_node * node ;
struct gw_node * gw_node , * curr_gw = NULL ;
uint32_t max_gw_factor = 0 , tmp_gw_factor = 0 ;
uint8_t max_tq = 0 ;
int down , up ;
/**
* The batman daemon checks here if we already passed a full originator
* cycle in order to make sure we don ' t choose the first gateway we
* hear about . This check is based on the daemon ' s uptime which we
* don ' t have .
* */
if ( atomic_read ( & bat_priv - > gw_mode ) ! = GW_MODE_CLIENT )
return ;
curr_gw = gw_get_selected_gw_node ( bat_priv ) ;
if ( curr_gw )
goto out ;
rcu_read_lock ( ) ;
if ( hlist_empty ( & bat_priv - > gw_list ) ) {
bat_dbg ( DBG_BATMAN , bat_priv ,
" Removing selected gateway - "
" no gateway in range \n " ) ;
gw_deselect ( bat_priv ) ;
goto unlock ;
}
hlist_for_each_entry_rcu ( gw_node , node , & bat_priv - > gw_list , list ) {
if ( gw_node - > deleted )
continue ;
@ -139,6 +119,9 @@ void gw_election(struct bat_priv *bat_priv)
if ( ! router )
continue ;
if ( ! atomic_inc_not_zero ( & gw_node - > refcount ) )
goto next ;
switch ( atomic_read ( & bat_priv - > gw_sel_class ) ) {
case 1 : /* fast connection */
gw_bandwidth_to_kbit ( gw_node - > orig_node - > gw_flags ,
@ -151,8 +134,12 @@ void gw_election(struct bat_priv *bat_priv)
if ( ( tmp_gw_factor > max_gw_factor ) | |
( ( tmp_gw_factor = = max_gw_factor ) & &
( router - > tq_avg > max_tq ) ) )
curr_gw_tmp = gw_node ;
( router - > tq_avg > max_tq ) ) ) {
if ( curr_gw )
gw_node_free_ref ( curr_gw ) ;
curr_gw = gw_node ;
atomic_inc ( & curr_gw - > refcount ) ;
}
break ;
default : /**
@ -163,8 +150,12 @@ void gw_election(struct bat_priv *bat_priv)
* soon as a better gateway appears which has
* $ routing_class more tq points )
* */
if ( router - > tq_avg > max_tq )
curr_gw_tmp = gw_node ;
if ( router - > tq_avg > max_tq ) {
if ( curr_gw )
gw_node_free_ref ( curr_gw ) ;
curr_gw = gw_node ;
atomic_inc ( & curr_gw - > refcount ) ;
}
break ;
}
@ -174,42 +165,75 @@ void gw_election(struct bat_priv *bat_priv)
if ( tmp_gw_factor > max_gw_factor )
max_gw_factor = tmp_gw_factor ;
gw_node_free_ref ( gw_node ) ;
next :
neigh_node_free_ref ( router ) ;
}
rcu_read_unlock ( ) ;
if ( curr_gw ! = curr_gw_tmp ) {
router = orig_node_get_router ( curr_gw_tmp - > orig_node ) ;
if ( ! router )
goto unlock ;
return curr_gw ;
}
if ( ( curr_gw ) & & ( ! curr_gw_tmp ) )
bat_dbg ( DBG_BATMAN , bat_priv ,
" Removing selected gateway - "
" no gateway in range \n " ) ;
else if ( ( ! curr_gw ) & & ( curr_gw_tmp ) )
bat_dbg ( DBG_BATMAN , bat_priv ,
" Adding route to gateway %pM "
" (gw_flags: %i, tq: %i) \n " ,
curr_gw_tmp - > orig_node - > orig ,
curr_gw_tmp - > orig_node - > gw_flags ,
router - > tq_avg ) ;
else
bat_dbg ( DBG_BATMAN , bat_priv ,
" Changing route to gateway %pM "
" (gw_flags: %i, tq: %i) \n " ,
curr_gw_tmp - > orig_node - > orig ,
curr_gw_tmp - > orig_node - > gw_flags ,
router - > tq_avg ) ;
void gw_election ( struct bat_priv * bat_priv )
{
struct gw_node * curr_gw = NULL , * next_gw = NULL ;
struct neigh_node * router = NULL ;
neigh_node_free_ref ( router ) ;
gw_select ( bat_priv , curr_gw_tmp ) ;
/**
* The batman daemon checks here if we already passed a full originator
* cycle in order to make sure we don ' t choose the first gateway we
* hear about . This check is based on the daemon ' s uptime which we
* don ' t have .
* */
if ( atomic_read ( & bat_priv - > gw_mode ) ! = GW_MODE_CLIENT )
goto out ;
if ( ! atomic_dec_not_zero ( & bat_priv - > gw_reselect ) )
goto out ;
curr_gw = gw_get_selected_gw_node ( bat_priv ) ;
next_gw = gw_get_best_gw_node ( bat_priv ) ;
if ( curr_gw = = next_gw )
goto out ;
if ( next_gw ) {
router = orig_node_get_router ( next_gw - > orig_node ) ;
if ( ! router ) {
gw_deselect ( bat_priv ) ;
goto out ;
}
}
unlock :
rcu_read_unlock ( ) ;
if ( ( curr_gw ) & & ( ! next_gw ) ) {
bat_dbg ( DBG_BATMAN , bat_priv ,
" Removing selected gateway - no gateway in range \n " ) ;
} else if ( ( ! curr_gw ) & & ( next_gw ) ) {
bat_dbg ( DBG_BATMAN , bat_priv ,
" Adding route to gateway %pM (gw_flags: %i, tq: %i) \n " ,
next_gw - > orig_node - > orig ,
next_gw - > orig_node - > gw_flags ,
router - > tq_avg ) ;
} else {
bat_dbg ( DBG_BATMAN , bat_priv ,
" Changing route to gateway %pM "
" (gw_flags: %i, tq: %i) \n " ,
next_gw - > orig_node - > orig ,
next_gw - > orig_node - > gw_flags ,
router - > tq_avg ) ;
}
gw_select ( bat_priv , next_gw ) ;
out :
if ( curr_gw )
gw_node_free_ref ( curr_gw ) ;
if ( next_gw )
gw_node_free_ref ( next_gw ) ;
if ( router )
neigh_node_free_ref ( router ) ;
}
void gw_check_election ( struct bat_priv * bat_priv , struct orig_node * orig_node )