2010-12-13 14:19:28 +03:00
/*
2012-01-01 03:41:38 +04:00
* Copyright ( C ) 2010 - 2012 B . A . T . M . A . N . contributors :
2010-12-13 14:19:28 +03:00
*
* Marek Lindner
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA
*
*/
# include "main.h"
# include "bat_sysfs.h"
# include "translation-table.h"
# include "originator.h"
# include "hard-interface.h"
# include "gateway_common.h"
# include "gateway_client.h"
# include "vis.h"
2011-06-05 12:20:19 +04:00
static struct net_device * kobj_to_netdev ( struct kobject * obj )
{
struct device * dev = container_of ( obj - > parent , struct device , kobj ) ;
return to_net_dev ( dev ) ;
}
static struct bat_priv * kobj_to_batpriv ( struct kobject * obj )
{
struct net_device * net_dev = kobj_to_netdev ( obj ) ;
return netdev_priv ( net_dev ) ;
}
2010-12-13 14:19:28 +03:00
2011-04-26 20:26:01 +04:00
# define UEV_TYPE_VAR "BATTYPE="
# define UEV_ACTION_VAR "BATACTION="
# define UEV_DATA_VAR "BATDATA="
static char * uev_action_str [ ] = {
" add " ,
" del " ,
" change "
} ;
static char * uev_type_str [ ] = {
" gw "
} ;
2010-12-13 14:19:28 +03:00
/* Use this, if you have customized show and store functions */
# define BAT_ATTR(_name, _mode, _show, _store) \
struct bat_attribute bat_attr_ # # _name = { \
. attr = { . name = __stringify ( _name ) , \
. mode = _mode } , \
. show = _show , \
. store = _store , \
} ;
2012-03-11 02:17:51 +04:00
# define BAT_ATTR_SIF_STORE_BOOL(_name, _post_func) \
2010-12-13 14:19:28 +03:00
ssize_t store_ # # _name ( struct kobject * kobj , struct attribute * attr , \
char * buff , size_t count ) \
{ \
struct net_device * net_dev = kobj_to_netdev ( kobj ) ; \
struct bat_priv * bat_priv = netdev_priv ( net_dev ) ; \
return __store_bool_attr ( buff , count , _post_func , attr , \
& bat_priv - > _name , net_dev ) ; \
}
2012-03-11 02:17:51 +04:00
# define BAT_ATTR_SIF_SHOW_BOOL(_name) \
ssize_t show_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
2010-12-13 14:19:28 +03:00
{ \
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ; \
return sprintf ( buff , " %s \n " , \
atomic_read ( & bat_priv - > _name ) = = 0 ? \
" disabled " : " enabled " ) ; \
} \
2012-03-11 02:17:51 +04:00
/* Use this, if you are going to turn a [name] in the soft-interface
* ( bat_priv ) on or off */
# define BAT_ATTR_SIF_BOOL(_name, _mode, _post_func) \
static BAT_ATTR_SIF_STORE_BOOL ( _name , _post_func ) \
static BAT_ATTR_SIF_SHOW_BOOL ( _name ) \
2010-12-13 14:19:28 +03:00
static BAT_ATTR ( _name , _mode , show_ # # _name , store_ # # _name )
2012-03-11 02:17:51 +04:00
# define BAT_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func) \
2010-12-13 14:19:28 +03:00
ssize_t store_ # # _name ( struct kobject * kobj , struct attribute * attr , \
2012-03-11 02:17:51 +04:00
char * buff , size_t count ) \
2010-12-13 14:19:28 +03:00
{ \
struct net_device * net_dev = kobj_to_netdev ( kobj ) ; \
struct bat_priv * bat_priv = netdev_priv ( net_dev ) ; \
return __store_uint_attr ( buff , count , _min , _max , _post_func , \
attr , & bat_priv - > _name , net_dev ) ; \
}
2012-03-11 02:17:51 +04:00
# define BAT_ATTR_SIF_SHOW_UINT(_name) \
ssize_t show_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
2010-12-13 14:19:28 +03:00
{ \
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ; \
return sprintf ( buff , " %i \n " , atomic_read ( & bat_priv - > _name ) ) ; \
} \
2012-03-11 02:17:51 +04:00
/* Use this, if you are going to set [name] in the soft-interface
* ( bat_priv ) to an unsigned integer value */
# define BAT_ATTR_SIF_UINT(_name, _mode, _min, _max, _post_func) \
static BAT_ATTR_SIF_STORE_UINT ( _name , _min , _max , _post_func ) \
static BAT_ATTR_SIF_SHOW_UINT ( _name ) \
2010-12-13 14:19:28 +03:00
static BAT_ATTR ( _name , _mode , show_ # # _name , store_ # # _name )
2012-03-11 02:17:52 +04:00
# define BAT_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
ssize_t store_ # # _name ( struct kobject * kobj , struct attribute * attr , \
char * buff , size_t count ) \
{ \
struct net_device * net_dev = kobj_to_netdev ( kobj ) ; \
struct hard_iface * hard_iface = hardif_get_by_netdev ( net_dev ) ; \
ssize_t length ; \
\
if ( ! hard_iface ) \
return 0 ; \
\
length = __store_uint_attr ( buff , count , _min , _max , _post_func , \
attr , & hard_iface - > _name , net_dev ) ; \
\
hardif_free_ref ( hard_iface ) ; \
return length ; \
}
# define BAT_ATTR_HIF_SHOW_UINT(_name) \
ssize_t show_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
{ \
struct net_device * net_dev = kobj_to_netdev ( kobj ) ; \
struct hard_iface * hard_iface = hardif_get_by_netdev ( net_dev ) ; \
ssize_t length ; \
\
if ( ! hard_iface ) \
return 0 ; \
\
length = sprintf ( buff , " %i \n " , atomic_read ( & hard_iface - > _name ) ) ; \
\
hardif_free_ref ( hard_iface ) ; \
return length ; \
}
/* Use this, if you are going to set [name] in hard_iface to an
* unsigned integer value */
# define BAT_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \
static BAT_ATTR_HIF_STORE_UINT ( _name , _min , _max , _post_func ) \
static BAT_ATTR_HIF_SHOW_UINT ( _name ) \
static BAT_ATTR ( _name , _mode , show_ # # _name , store_ # # _name )
2010-12-13 14:19:28 +03:00
static int store_bool_attr ( char * buff , size_t count ,
struct net_device * net_dev ,
2011-05-15 01:14:50 +04:00
const char * attr_name , atomic_t * attr )
2010-12-13 14:19:28 +03:00
{
int enabled = - 1 ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
if ( ( strncmp ( buff , " 1 " , 2 ) = = 0 ) | |
( strncmp ( buff , " enable " , 7 ) = = 0 ) | |
( strncmp ( buff , " enabled " , 8 ) = = 0 ) )
enabled = 1 ;
if ( ( strncmp ( buff , " 0 " , 2 ) = = 0 ) | |
( strncmp ( buff , " disable " , 8 ) = = 0 ) | |
( strncmp ( buff , " disabled " , 9 ) = = 0 ) )
enabled = 0 ;
if ( enabled < 0 ) {
bat_info ( net_dev ,
" %s: Invalid parameter received: %s \n " ,
attr_name , buff ) ;
return - EINVAL ;
}
if ( atomic_read ( attr ) = = enabled )
return count ;
bat_info ( net_dev , " %s: Changing from: %s to: %s \n " , attr_name ,
atomic_read ( attr ) = = 1 ? " enabled " : " disabled " ,
enabled = = 1 ? " enabled " : " disabled " ) ;
2012-04-15 09:58:06 +04:00
atomic_set ( attr , ( unsigned int ) enabled ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
static inline ssize_t __store_bool_attr ( char * buff , size_t count ,
void ( * post_func ) ( struct net_device * ) ,
struct attribute * attr ,
atomic_t * attr_store , struct net_device * net_dev )
{
int ret ;
2011-05-15 01:14:50 +04:00
ret = store_bool_attr ( buff , count , net_dev , attr - > name , attr_store ) ;
2010-12-13 14:19:28 +03:00
if ( post_func & & ret )
post_func ( net_dev ) ;
return ret ;
}
2011-05-15 01:14:50 +04:00
static int store_uint_attr ( const char * buff , size_t count ,
struct net_device * net_dev , const char * attr_name ,
2010-12-13 14:19:28 +03:00
unsigned int min , unsigned int max , atomic_t * attr )
{
unsigned long uint_val ;
int ret ;
2011-09-30 15:32:01 +04:00
ret = kstrtoul ( buff , 10 , & uint_val ) ;
2010-12-13 14:19:28 +03:00
if ( ret ) {
bat_info ( net_dev ,
" %s: Invalid parameter received: %s \n " ,
attr_name , buff ) ;
return - EINVAL ;
}
if ( uint_val < min ) {
bat_info ( net_dev , " %s: Value is too small: %lu min: %u \n " ,
attr_name , uint_val , min ) ;
return - EINVAL ;
}
if ( uint_val > max ) {
bat_info ( net_dev , " %s: Value is too big: %lu max: %u \n " ,
attr_name , uint_val , max ) ;
return - EINVAL ;
}
if ( atomic_read ( attr ) = = uint_val )
return count ;
bat_info ( net_dev , " %s: Changing from: %i to: %lu \n " ,
attr_name , atomic_read ( attr ) , uint_val ) ;
atomic_set ( attr , uint_val ) ;
return count ;
}
2011-05-15 01:14:50 +04:00
static inline ssize_t __store_uint_attr ( const char * buff , size_t count ,
2010-12-13 14:19:28 +03:00
int min , int max ,
void ( * post_func ) ( struct net_device * ) ,
2011-05-15 01:14:50 +04:00
const struct attribute * attr ,
2010-12-13 14:19:28 +03:00
atomic_t * attr_store , struct net_device * net_dev )
{
int ret ;
2011-05-15 01:14:50 +04:00
ret = store_uint_attr ( buff , count , net_dev , attr - > name ,
2010-12-13 14:19:28 +03:00
min , max , attr_store ) ;
if ( post_func & & ret )
post_func ( net_dev ) ;
return ret ;
}
static ssize_t show_vis_mode ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ;
int vis_mode = atomic_read ( & bat_priv - > vis_mode ) ;
return sprintf ( buff , " %s \n " ,
vis_mode = = VIS_TYPE_CLIENT_UPDATE ?
" client " : " server " ) ;
}
static ssize_t store_vis_mode ( struct kobject * kobj , struct attribute * attr ,
char * buff , size_t count )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
struct bat_priv * bat_priv = netdev_priv ( net_dev ) ;
unsigned long val ;
int ret , vis_mode_tmp = - 1 ;
2011-09-30 15:32:01 +04:00
ret = kstrtoul ( buff , 10 , & val ) ;
2010-12-13 14:19:28 +03:00
if ( ( ( count = = 2 ) & & ( ! ret ) & & ( val = = VIS_TYPE_CLIENT_UPDATE ) ) | |
( strncmp ( buff , " client " , 6 ) = = 0 ) | |
( strncmp ( buff , " off " , 3 ) = = 0 ) )
vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE ;
if ( ( ( count = = 2 ) & & ( ! ret ) & & ( val = = VIS_TYPE_SERVER_SYNC ) ) | |
( strncmp ( buff , " server " , 6 ) = = 0 ) )
vis_mode_tmp = VIS_TYPE_SERVER_SYNC ;
if ( vis_mode_tmp < 0 ) {
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
bat_info ( net_dev ,
2012-03-07 12:07:45 +04:00
" Invalid parameter for 'vis mode' setting received: %s \n " ,
buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( & bat_priv - > vis_mode ) = = vis_mode_tmp )
return count ;
bat_info ( net_dev , " Changing vis mode from: %s to: %s \n " ,
atomic_read ( & bat_priv - > vis_mode ) = = VIS_TYPE_CLIENT_UPDATE ?
" client " : " server " , vis_mode_tmp = = VIS_TYPE_CLIENT_UPDATE ?
" client " : " server " ) ;
2012-04-15 09:58:06 +04:00
atomic_set ( & bat_priv - > vis_mode , ( unsigned int ) vis_mode_tmp ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
2011-11-28 20:15:37 +04:00
static ssize_t show_bat_algo ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ;
return sprintf ( buff , " %s \n " , bat_priv - > bat_algo_ops - > name ) ;
}
2010-12-13 14:19:28 +03:00
static void post_gw_deselect ( struct net_device * net_dev )
{
struct bat_priv * bat_priv = netdev_priv ( net_dev ) ;
gw_deselect ( bat_priv ) ;
}
static ssize_t show_gw_mode ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ;
int bytes_written ;
switch ( atomic_read ( & bat_priv - > gw_mode ) ) {
case GW_MODE_CLIENT :
bytes_written = sprintf ( buff , " %s \n " , GW_MODE_CLIENT_NAME ) ;
break ;
case GW_MODE_SERVER :
bytes_written = sprintf ( buff , " %s \n " , GW_MODE_SERVER_NAME ) ;
break ;
default :
bytes_written = sprintf ( buff , " %s \n " , GW_MODE_OFF_NAME ) ;
break ;
}
return bytes_written ;
}
static ssize_t store_gw_mode ( struct kobject * kobj , struct attribute * attr ,
char * buff , size_t count )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
struct bat_priv * bat_priv = netdev_priv ( net_dev ) ;
char * curr_gw_mode_str ;
int gw_mode_tmp = - 1 ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
if ( strncmp ( buff , GW_MODE_OFF_NAME , strlen ( GW_MODE_OFF_NAME ) ) = = 0 )
gw_mode_tmp = GW_MODE_OFF ;
if ( strncmp ( buff , GW_MODE_CLIENT_NAME ,
2012-02-28 13:55:36 +04:00
strlen ( GW_MODE_CLIENT_NAME ) ) = = 0 )
2010-12-13 14:19:28 +03:00
gw_mode_tmp = GW_MODE_CLIENT ;
if ( strncmp ( buff , GW_MODE_SERVER_NAME ,
2012-02-28 13:55:36 +04:00
strlen ( GW_MODE_SERVER_NAME ) ) = = 0 )
2010-12-13 14:19:28 +03:00
gw_mode_tmp = GW_MODE_SERVER ;
if ( gw_mode_tmp < 0 ) {
bat_info ( net_dev ,
2012-03-07 12:07:45 +04:00
" Invalid parameter for 'gw mode' setting received: %s \n " ,
buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( & bat_priv - > gw_mode ) = = gw_mode_tmp )
return count ;
switch ( atomic_read ( & bat_priv - > gw_mode ) ) {
case GW_MODE_CLIENT :
curr_gw_mode_str = GW_MODE_CLIENT_NAME ;
break ;
case GW_MODE_SERVER :
curr_gw_mode_str = GW_MODE_SERVER_NAME ;
break ;
default :
curr_gw_mode_str = GW_MODE_OFF_NAME ;
break ;
}
bat_info ( net_dev , " Changing gw mode from: %s to: %s \n " ,
curr_gw_mode_str , buff ) ;
gw_deselect ( bat_priv ) ;
2012-04-15 09:58:06 +04:00
atomic_set ( & bat_priv - > gw_mode , ( unsigned int ) gw_mode_tmp ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
static ssize_t show_gw_bwidth ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct bat_priv * bat_priv = kobj_to_batpriv ( kobj ) ;
int down , up ;
int gw_bandwidth = atomic_read ( & bat_priv - > gw_bandwidth ) ;
gw_bandwidth_to_kbit ( gw_bandwidth , & down , & up ) ;
return sprintf ( buff , " %i%s/%i%s \n " ,
( down > 2048 ? down / 1024 : down ) ,
( down > 2048 ? " MBit " : " KBit " ) ,
( up > 2048 ? up / 1024 : up ) ,
( up > 2048 ? " MBit " : " KBit " ) ) ;
}
static ssize_t store_gw_bwidth ( struct kobject * kobj , struct attribute * attr ,
char * buff , size_t count )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
return gw_bandwidth_set ( net_dev , buff , count ) ;
}
2012-03-11 02:17:51 +04:00
BAT_ATTR_SIF_BOOL ( aggregated_ogms , S_IRUGO | S_IWUSR , NULL ) ;
BAT_ATTR_SIF_BOOL ( bonding , S_IRUGO | S_IWUSR , NULL ) ;
2012-01-22 23:00:27 +04:00
# ifdef CONFIG_BATMAN_ADV_BLA
2012-03-11 02:17:51 +04:00
BAT_ATTR_SIF_BOOL ( bridge_loop_avoidance , S_IRUGO | S_IWUSR , NULL ) ;
2012-01-22 23:00:27 +04:00
# endif
2012-03-11 02:17:51 +04:00
BAT_ATTR_SIF_BOOL ( fragmentation , S_IRUGO | S_IWUSR , update_min_mtu ) ;
BAT_ATTR_SIF_BOOL ( ap_isolation , S_IRUGO | S_IWUSR , NULL ) ;
2010-12-13 14:19:28 +03:00
static BAT_ATTR ( vis_mode , S_IRUGO | S_IWUSR , show_vis_mode , store_vis_mode ) ;
2011-11-28 20:15:37 +04:00
static BAT_ATTR ( routing_algo , S_IRUGO , show_bat_algo , NULL ) ;
2010-12-13 14:19:28 +03:00
static BAT_ATTR ( gw_mode , S_IRUGO | S_IWUSR , show_gw_mode , store_gw_mode ) ;
2012-03-11 02:17:51 +04:00
BAT_ATTR_SIF_UINT ( orig_interval , S_IRUGO | S_IWUSR , 2 * JITTER , INT_MAX , NULL ) ;
BAT_ATTR_SIF_UINT ( hop_penalty , S_IRUGO | S_IWUSR , 0 , TQ_MAX_VALUE , NULL ) ;
BAT_ATTR_SIF_UINT ( gw_sel_class , S_IRUGO | S_IWUSR , 1 , TQ_MAX_VALUE ,
post_gw_deselect ) ;
2010-12-13 14:19:28 +03:00
static BAT_ATTR ( gw_bandwidth , S_IRUGO | S_IWUSR , show_gw_bwidth ,
store_gw_bwidth ) ;
# ifdef CONFIG_BATMAN_ADV_DEBUG
2012-05-09 11:50:45 +04:00
BAT_ATTR_SIF_UINT ( log_level , S_IRUGO | S_IWUSR , 0 , DBG_ALL , NULL ) ;
2010-12-13 14:19:28 +03:00
# endif
static struct bat_attribute * mesh_attrs [ ] = {
& bat_attr_aggregated_ogms ,
& bat_attr_bonding ,
2012-01-22 23:00:27 +04:00
# ifdef CONFIG_BATMAN_ADV_BLA
2012-01-22 23:00:20 +04:00
& bat_attr_bridge_loop_avoidance ,
2012-01-22 23:00:27 +04:00
# endif
2010-12-13 14:19:28 +03:00
& bat_attr_fragmentation ,
2011-07-07 17:35:36 +04:00
& bat_attr_ap_isolation ,
2010-12-13 14:19:28 +03:00
& bat_attr_vis_mode ,
2011-11-28 20:15:37 +04:00
& bat_attr_routing_algo ,
2010-12-13 14:19:28 +03:00
& bat_attr_gw_mode ,
& bat_attr_orig_interval ,
& bat_attr_hop_penalty ,
& bat_attr_gw_sel_class ,
& bat_attr_gw_bandwidth ,
# ifdef CONFIG_BATMAN_ADV_DEBUG
& bat_attr_log_level ,
# endif
NULL ,
} ;
2012-05-12 04:09:24 +04:00
int batadv_sysfs_add_meshif ( struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
struct kobject * batif_kobject = & dev - > dev . kobj ;
struct bat_priv * bat_priv = netdev_priv ( dev ) ;
struct bat_attribute * * bat_attr ;
int err ;
bat_priv - > mesh_obj = kobject_create_and_add ( SYSFS_IF_MESH_SUBDIR ,
batif_kobject ) ;
if ( ! bat_priv - > mesh_obj ) {
bat_err ( dev , " Can't add sysfs directory: %s/%s \n " , dev - > name ,
SYSFS_IF_MESH_SUBDIR ) ;
goto out ;
}
for ( bat_attr = mesh_attrs ; * bat_attr ; + + bat_attr ) {
err = sysfs_create_file ( bat_priv - > mesh_obj ,
& ( ( * bat_attr ) - > attr ) ) ;
if ( err ) {
bat_err ( dev , " Can't add sysfs file: %s/%s/%s \n " ,
dev - > name , SYSFS_IF_MESH_SUBDIR ,
( ( * bat_attr ) - > attr ) . name ) ;
goto rem_attr ;
}
}
return 0 ;
rem_attr :
for ( bat_attr = mesh_attrs ; * bat_attr ; + + bat_attr )
sysfs_remove_file ( bat_priv - > mesh_obj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( bat_priv - > mesh_obj ) ;
bat_priv - > mesh_obj = NULL ;
out :
return - ENOMEM ;
}
2012-05-12 04:09:24 +04:00
void batadv_sysfs_del_meshif ( struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
struct bat_priv * bat_priv = netdev_priv ( dev ) ;
struct bat_attribute * * bat_attr ;
for ( bat_attr = mesh_attrs ; * bat_attr ; + + bat_attr )
sysfs_remove_file ( bat_priv - > mesh_obj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( bat_priv - > mesh_obj ) ;
bat_priv - > mesh_obj = NULL ;
}
static ssize_t show_mesh_iface ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
2011-02-18 15:33:20 +03:00
struct hard_iface * hard_iface = hardif_get_by_netdev ( net_dev ) ;
2010-12-13 14:19:28 +03:00
ssize_t length ;
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return 0 ;
2011-02-18 15:33:20 +03:00
length = sprintf ( buff , " %s \n " , hard_iface - > if_status = = IF_NOT_IN_USE ?
" none " : hard_iface - > soft_iface - > name ) ;
2010-12-13 14:19:28 +03:00
2011-02-18 15:33:20 +03:00
hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return length ;
}
static ssize_t store_mesh_iface ( struct kobject * kobj , struct attribute * attr ,
char * buff , size_t count )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
2011-02-18 15:33:20 +03:00
struct hard_iface * hard_iface = hardif_get_by_netdev ( net_dev ) ;
2010-12-13 14:19:28 +03:00
int status_tmp = - 1 ;
2011-02-10 17:33:51 +03:00
int ret = count ;
2010-12-13 14:19:28 +03:00
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return count ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
if ( strlen ( buff ) > = IFNAMSIZ ) {
2012-03-07 12:07:45 +04:00
pr_err ( " Invalid parameter for 'mesh_iface' setting received: interface name too long '%s' \n " ,
buff ) ;
2011-02-18 15:33:20 +03:00
hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( strncmp ( buff , " none " , 4 ) = = 0 )
status_tmp = IF_NOT_IN_USE ;
else
status_tmp = IF_I_WANT_YOU ;
2011-02-18 15:33:20 +03:00
if ( hard_iface - > if_status = = status_tmp )
goto out ;
if ( ( hard_iface - > soft_iface ) & &
( strncmp ( hard_iface - > soft_iface - > name , buff , IFNAMSIZ ) = = 0 ) )
2011-02-10 17:33:51 +03:00
goto out ;
2010-12-13 14:19:28 +03:00
2011-05-03 15:10:06 +04:00
if ( ! rtnl_trylock ( ) ) {
ret = - ERESTARTSYS ;
goto out ;
}
2010-12-13 14:19:28 +03:00
if ( status_tmp = = IF_NOT_IN_USE ) {
2011-02-18 15:33:20 +03:00
hardif_disable_interface ( hard_iface ) ;
2011-05-03 15:10:06 +04:00
goto unlock ;
2010-12-13 14:19:28 +03:00
}
/* if the interface already is in use */
2011-05-03 15:10:06 +04:00
if ( hard_iface - > if_status ! = IF_NOT_IN_USE )
2011-02-18 15:33:20 +03:00
hardif_disable_interface ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
2011-02-18 15:33:20 +03:00
ret = hardif_enable_interface ( hard_iface , buff ) ;
2010-12-13 14:19:28 +03:00
2011-05-03 15:10:06 +04:00
unlock :
rtnl_unlock ( ) ;
2011-02-10 17:33:51 +03:00
out :
2011-02-18 15:33:20 +03:00
hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return ret ;
}
static ssize_t show_iface_status ( struct kobject * kobj , struct attribute * attr ,
char * buff )
{
struct net_device * net_dev = kobj_to_netdev ( kobj ) ;
2011-02-18 15:33:20 +03:00
struct hard_iface * hard_iface = hardif_get_by_netdev ( net_dev ) ;
2010-12-13 14:19:28 +03:00
ssize_t length ;
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return 0 ;
2011-02-18 15:33:20 +03:00
switch ( hard_iface - > if_status ) {
2010-12-13 14:19:28 +03:00
case IF_TO_BE_REMOVED :
length = sprintf ( buff , " disabling \n " ) ;
break ;
case IF_INACTIVE :
length = sprintf ( buff , " inactive \n " ) ;
break ;
case IF_ACTIVE :
length = sprintf ( buff , " active \n " ) ;
break ;
case IF_TO_BE_ACTIVATED :
length = sprintf ( buff , " enabling \n " ) ;
break ;
case IF_NOT_IN_USE :
default :
length = sprintf ( buff , " not in use \n " ) ;
break ;
}
2011-02-18 15:33:20 +03:00
hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return length ;
}
static BAT_ATTR ( mesh_iface , S_IRUGO | S_IWUSR ,
show_mesh_iface , store_mesh_iface ) ;
static BAT_ATTR ( iface_status , S_IRUGO , show_iface_status , NULL ) ;
static struct bat_attribute * batman_attrs [ ] = {
& bat_attr_mesh_iface ,
& bat_attr_iface_status ,
NULL ,
} ;
2012-05-12 04:09:24 +04:00
int batadv_sysfs_add_hardif ( struct kobject * * hardif_obj , struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
struct kobject * hardif_kobject = & dev - > dev . kobj ;
struct bat_attribute * * bat_attr ;
int err ;
* hardif_obj = kobject_create_and_add ( SYSFS_IF_BAT_SUBDIR ,
hardif_kobject ) ;
if ( ! * hardif_obj ) {
bat_err ( dev , " Can't add sysfs directory: %s/%s \n " , dev - > name ,
SYSFS_IF_BAT_SUBDIR ) ;
goto out ;
}
for ( bat_attr = batman_attrs ; * bat_attr ; + + bat_attr ) {
err = sysfs_create_file ( * hardif_obj , & ( ( * bat_attr ) - > attr ) ) ;
if ( err ) {
bat_err ( dev , " Can't add sysfs file: %s/%s/%s \n " ,
dev - > name , SYSFS_IF_BAT_SUBDIR ,
( ( * bat_attr ) - > attr ) . name ) ;
goto rem_attr ;
}
}
return 0 ;
rem_attr :
for ( bat_attr = batman_attrs ; * bat_attr ; + + bat_attr )
sysfs_remove_file ( * hardif_obj , & ( ( * bat_attr ) - > attr ) ) ;
out :
return - ENOMEM ;
}
2012-05-12 04:09:24 +04:00
void batadv_sysfs_del_hardif ( struct kobject * * hardif_obj )
2010-12-13 14:19:28 +03:00
{
kobject_put ( * hardif_obj ) ;
* hardif_obj = NULL ;
}
2011-04-26 20:26:01 +04:00
2012-05-12 04:09:24 +04:00
int batadv_throw_uevent ( struct bat_priv * bat_priv , enum uev_type type ,
enum uev_action action , const char * data )
2011-04-26 20:26:01 +04:00
{
2012-05-05 15:27:28 +04:00
int ret = - ENOMEM ;
2011-04-26 20:26:01 +04:00
struct hard_iface * primary_if = NULL ;
struct kobject * bat_kobj ;
char * uevent_env [ 4 ] = { NULL , NULL , NULL , NULL } ;
primary_if = primary_if_get_selected ( bat_priv ) ;
if ( ! primary_if )
goto out ;
bat_kobj = & primary_if - > soft_iface - > dev . kobj ;
uevent_env [ 0 ] = kmalloc ( strlen ( UEV_TYPE_VAR ) +
strlen ( uev_type_str [ type ] ) + 1 ,
GFP_ATOMIC ) ;
if ( ! uevent_env [ 0 ] )
goto out ;
sprintf ( uevent_env [ 0 ] , " %s%s " , UEV_TYPE_VAR , uev_type_str [ type ] ) ;
uevent_env [ 1 ] = kmalloc ( strlen ( UEV_ACTION_VAR ) +
strlen ( uev_action_str [ action ] ) + 1 ,
GFP_ATOMIC ) ;
if ( ! uevent_env [ 1 ] )
goto out ;
sprintf ( uevent_env [ 1 ] , " %s%s " , UEV_ACTION_VAR , uev_action_str [ action ] ) ;
/* If the event is DEL, ignore the data field */
if ( action ! = UEV_DEL ) {
uevent_env [ 2 ] = kmalloc ( strlen ( UEV_DATA_VAR ) +
strlen ( data ) + 1 , GFP_ATOMIC ) ;
if ( ! uevent_env [ 2 ] )
goto out ;
sprintf ( uevent_env [ 2 ] , " %s%s " , UEV_DATA_VAR , data ) ;
}
ret = kobject_uevent_env ( bat_kobj , KOBJ_CHANGE , uevent_env ) ;
out :
kfree ( uevent_env [ 0 ] ) ;
kfree ( uevent_env [ 1 ] ) ;
kfree ( uevent_env [ 2 ] ) ;
if ( primary_if )
hardif_free_ref ( primary_if ) ;
if ( ret )
2012-03-07 12:07:45 +04:00
bat_dbg ( DBG_BATMAN , bat_priv ,
" Impossible to send uevent for (%s,%s,%s) event (err: %d) \n " ,
2011-04-26 20:26:01 +04:00
uev_type_str [ type ] , uev_action_str [ action ] ,
( action = = UEV_DEL ? " NULL " : data ) , ret ) ;
return ret ;
}