@ -24,6 +24,7 @@
# include "network-coding.h"
# include "originator.h"
# include "hard-interface.h"
# include "soft-interface.h"
# include "gateway_common.h"
# include "gateway_client.h"
@ -39,6 +40,53 @@ static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
return netdev_priv ( net_dev ) ;
}
/**
* batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
* @ obj : kobject to covert
*
* Returns the associated batadv_priv struct .
*/
static struct batadv_priv * batadv_vlan_kobj_to_batpriv ( struct kobject * obj )
{
/* VLAN specific attributes are located in the root sysfs folder if they
* refer to the untagged VLAN . .
*/
if ( ! strcmp ( BATADV_SYSFS_IF_MESH_SUBDIR , obj - > name ) )
return batadv_kobj_to_batpriv ( obj ) ;
/* ..while the attributes for the tagged vlans are located in
* the in the corresponding " vlan%VID " subfolder
*/
return batadv_kobj_to_batpriv ( obj - > parent ) ;
}
/**
* batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct
* @ obj : kobject to covert
*
* Returns the associated softif_vlan struct if found , NULL otherwise .
*/
static struct batadv_softif_vlan *
batadv_kobj_to_vlan ( struct batadv_priv * bat_priv , struct kobject * obj )
{
struct batadv_softif_vlan * vlan_tmp , * vlan = NULL ;
rcu_read_lock ( ) ;
hlist_for_each_entry_rcu ( vlan_tmp , & bat_priv - > softif_vlan_list , list ) {
if ( vlan_tmp - > kobj ! = obj )
continue ;
if ( ! atomic_inc_not_zero ( & vlan_tmp - > refcount ) )
continue ;
vlan = vlan_tmp ;
break ;
}
rcu_read_unlock ( ) ;
return vlan ;
}
# define BATADV_UEV_TYPE_VAR "BATTYPE="
# define BATADV_UEV_ACTION_VAR "BATACTION="
# define BATADV_UEV_DATA_VAR "BATDATA="
@ -53,6 +101,15 @@ static char *batadv_uev_type_str[] = {
" gw "
} ;
/* Use this, if you have customized show and store functions for vlan attrs */
# define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \
struct batadv_attribute batadv_attr_vlan_ # # _name = { \
. attr = { . name = __stringify ( _name ) , \
. mode = _mode } , \
. show = _show , \
. store = _store , \
} ;
/* Use this, if you have customized show and store functions */
# define BATADV_ATTR(_name, _mode, _show, _store) \
struct batadv_attribute batadv_attr_ # # _name = { \
@ -122,6 +179,41 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \
static BATADV_ATTR ( _name , _mode , batadv_show_ # # _name , \
batadv_store_ # # _name )
# define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
ssize_t batadv_store_vlan_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff , \
size_t count ) \
{ \
struct batadv_priv * bat_priv = batadv_vlan_kobj_to_batpriv ( kobj ) ; \
struct batadv_softif_vlan * vlan = batadv_kobj_to_vlan ( bat_priv , \
kobj ) ; \
size_t res = __batadv_store_bool_attr ( buff , count , _post_func , \
attr , & vlan - > _name , \
bat_priv - > soft_iface ) ; \
batadv_softif_vlan_free_ref ( vlan ) ; \
return res ; \
}
# define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
ssize_t batadv_show_vlan_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
{ \
struct batadv_priv * bat_priv = batadv_vlan_kobj_to_batpriv ( kobj ) ; \
struct batadv_softif_vlan * vlan = batadv_kobj_to_vlan ( bat_priv , \
kobj ) ; \
size_t res = sprintf ( buff , " %s \n " , \
atomic_read ( & vlan - > _name ) = = 0 ? \
" disabled " : " enabled " ) ; \
batadv_softif_vlan_free_ref ( vlan ) ; \
return res ; \
}
/* Use this, if you are going to turn a [name] in the vlan struct on or off */
# define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \
static BATADV_ATTR_VLAN_STORE_BOOL ( _name , _post_func ) \
static BATADV_ATTR_VLAN_SHOW_BOOL ( _name ) \
static BATADV_ATTR_VLAN ( _name , _mode , batadv_show_vlan_ # # _name , \
batadv_store_vlan_ # # _name )
static int batadv_store_bool_attr ( char * buff , size_t count ,
struct net_device * net_dev ,
@ -407,6 +499,13 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
NULL ,
} ;
/**
* batadv_vlan_attrs - array of vlan specific sysfs attributes
*/
static struct batadv_attribute * batadv_vlan_attrs [ ] = {
NULL ,
} ;
int batadv_sysfs_add_meshif ( struct net_device * dev )
{
struct kobject * batif_kobject = & dev - > dev . kobj ;
@ -457,6 +556,80 @@ void batadv_sysfs_del_meshif(struct net_device *dev)
bat_priv - > mesh_obj = NULL ;
}
/**
* batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
* @ dev : netdev of the mesh interface
* @ vlan : private data of the newly added VLAN interface
*
* Returns 0 on success and - ENOMEM if any of the structure allocations fails .
*/
int batadv_sysfs_add_vlan ( struct net_device * dev ,
struct batadv_softif_vlan * vlan )
{
char vlan_subdir [ sizeof ( BATADV_SYSFS_VLAN_SUBDIR_PREFIX ) + 5 ] ;
struct batadv_priv * bat_priv = netdev_priv ( dev ) ;
struct batadv_attribute * * bat_attr ;
int err ;
if ( vlan - > vid & BATADV_VLAN_HAS_TAG ) {
sprintf ( vlan_subdir , BATADV_SYSFS_VLAN_SUBDIR_PREFIX " %hu " ,
vlan - > vid & VLAN_VID_MASK ) ;
vlan - > kobj = kobject_create_and_add ( vlan_subdir ,
bat_priv - > mesh_obj ) ;
if ( ! vlan - > kobj ) {
batadv_err ( dev , " Can't add sysfs directory: %s/%s \n " ,
dev - > name , vlan_subdir ) ;
goto out ;
}
} else {
/* the untagged LAN uses the root folder to store its "VLAN
* specific attributes "
*/
vlan - > kobj = bat_priv - > mesh_obj ;
kobject_get ( bat_priv - > mesh_obj ) ;
}
for ( bat_attr = batadv_vlan_attrs ; * bat_attr ; + + bat_attr ) {
err = sysfs_create_file ( vlan - > kobj ,
& ( ( * bat_attr ) - > attr ) ) ;
if ( err ) {
batadv_err ( dev , " Can't add sysfs file: %s/%s/%s \n " ,
dev - > name , vlan_subdir ,
( ( * bat_attr ) - > attr ) . name ) ;
goto rem_attr ;
}
}
return 0 ;
rem_attr :
for ( bat_attr = batadv_vlan_attrs ; * bat_attr ; + + bat_attr )
sysfs_remove_file ( vlan - > kobj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( vlan - > kobj ) ;
vlan - > kobj = NULL ;
out :
return - ENOMEM ;
}
/**
* batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
* @ bat_priv : the bat priv with all the soft interface information
* @ vlan : the private data of the VLAN to destroy
*/
void batadv_sysfs_del_vlan ( struct batadv_priv * bat_priv ,
struct batadv_softif_vlan * vlan )
{
struct batadv_attribute * * bat_attr ;
for ( bat_attr = batadv_vlan_attrs ; * bat_attr ; + + bat_attr )
sysfs_remove_file ( vlan - > kobj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( vlan - > kobj ) ;
vlan - > kobj = NULL ;
}
static ssize_t batadv_show_mesh_iface ( struct kobject * kobj ,
struct attribute * attr , char * buff )
{