2005-04-17 02:20:36 +04:00
/*
2013-08-06 04:44:46 +04:00
* Sysfs attributes of bridge
2005-04-17 02:20:36 +04:00
* Linux ethernet bridge
*
* Authors :
* Stephen Hemminger < shemminger @ osdl . org >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
2006-01-11 23:17:47 +03:00
# include <linux/capability.h>
2005-04-17 02:20:36 +04:00
# include <linux/kernel.h>
# include <linux/netdevice.h>
2012-09-18 04:01:12 +04:00
# include <linux/etherdevice.h>
2005-04-17 02:20:36 +04:00
# include <linux/if_bridge.h>
# include <linux/rtnetlink.h>
# include <linux/spinlock.h>
# include <linux/times.h>
2017-02-02 21:15:33 +03:00
# include <linux/sched/signal.h>
2005-04-17 02:20:36 +04:00
# include "br_private.h"
2008-11-13 10:39:10 +03:00
# define to_bridge(cd) ((struct net_bridge *)netdev_priv(to_net_dev(cd)))
2005-04-17 02:20:36 +04:00
/*
* Common code for storing bridge parameters .
*/
2002-04-09 23:14:34 +04:00
static ssize_t store_bridge_parm ( struct device * d ,
2005-04-17 02:20:36 +04:00
const char * buf , size_t len ,
2008-09-09 00:44:40 +04:00
int ( * set ) ( struct net_bridge * , unsigned long ) )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
char * endp ;
unsigned long val ;
2008-09-09 00:44:40 +04:00
int err ;
2005-04-17 02:20:36 +04:00
2012-11-16 07:03:08 +04:00
if ( ! ns_capable ( dev_net ( br - > dev ) - > user_ns , CAP_NET_ADMIN ) )
2005-04-17 02:20:36 +04:00
return - EPERM ;
val = simple_strtoul ( buf , & endp , 0 ) ;
if ( endp = = buf )
return - EINVAL ;
2016-04-08 19:03:31 +03:00
if ( ! rtnl_trylock ( ) )
return restart_syscall ( ) ;
2008-09-09 00:44:40 +04:00
err = ( * set ) ( br , val ) ;
2016-04-08 19:03:31 +03:00
if ( ! err )
netdev_state_change ( br - > dev ) ;
rtnl_unlock ( ) ;
2008-09-09 00:44:40 +04:00
return err ? err : len ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static ssize_t forward_delay_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %lu \n " , jiffies_to_clock_t ( br - > forward_delay ) ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t forward_delay_store ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
2005-04-17 02:20:36 +04:00
{
2011-04-04 18:03:33 +04:00
return store_bridge_parm ( d , buf , len , br_set_forward_delay ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( forward_delay ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t hello_time_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
return sprintf ( buf , " %lu \n " ,
2002-04-09 23:14:34 +04:00
jiffies_to_clock_t ( to_bridge ( d ) - > hello_time ) ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static ssize_t hello_time_store ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , const char * buf ,
2005-04-17 02:20:36 +04:00
size_t len )
{
2011-04-04 18:03:33 +04:00
return store_bridge_parm ( d , buf , len , br_set_hello_time ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( hello_time ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t max_age_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
return sprintf ( buf , " %lu \n " ,
2002-04-09 23:14:34 +04:00
jiffies_to_clock_t ( to_bridge ( d ) - > max_age ) ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static ssize_t max_age_store ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
const char * buf , size_t len )
2005-04-17 02:20:36 +04:00
{
2011-04-04 18:03:33 +04:00
return store_bridge_parm ( d , buf , len , br_set_max_age ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( max_age ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t ageing_time_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %lu \n " , jiffies_to_clock_t ( br - > ageing_time ) ) ;
}
2008-09-09 00:44:40 +04:00
static int set_ageing_time ( struct net_bridge * br , unsigned long val )
2005-04-17 02:20:36 +04:00
{
2016-04-08 19:03:31 +03:00
return br_set_ageing_time ( br , val ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static ssize_t ageing_time_store ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return store_bridge_parm ( d , buf , len , set_ageing_time ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( ageing_time ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t stp_state_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %d \n " , br - > stp_enabled ) ;
}
2016-04-08 19:03:30 +03:00
static int set_stp_state ( struct net_bridge * br , unsigned long val )
2005-04-17 02:20:36 +04:00
{
2007-08-15 00:21:34 +04:00
br_stp_set_enabled ( br , val ) ;
2016-04-08 19:03:30 +03:00
return 0 ;
}
static ssize_t stp_state_store ( struct device * d ,
struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_stp_state ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( stp_state ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t group_fwd_mask_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
2011-10-03 22:14:46 +04:00
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %#x \n " , br - > group_fwd_mask ) ;
}
2016-04-08 19:03:29 +03:00
static int set_group_fwd_mask ( struct net_bridge * br , unsigned long val )
2011-10-03 22:14:46 +04:00
{
if ( val & BR_GROUPFWD_RESTRICTED )
return - EINVAL ;
br - > group_fwd_mask = val ;
2016-04-08 19:03:29 +03:00
return 0 ;
}
static ssize_t group_fwd_mask_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_group_fwd_mask ) ;
2011-10-03 22:14:46 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( group_fwd_mask ) ;
2011-10-03 22:14:46 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t priority_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %d \n " ,
( br - > bridge_id . prio [ 0 ] < < 8 ) | br - > bridge_id . prio [ 1 ] ) ;
}
2008-09-09 00:44:40 +04:00
static int set_priority ( struct net_bridge * br , unsigned long val )
2005-04-17 02:20:36 +04:00
{
br_stp_set_bridge_priority ( br , ( u16 ) val ) ;
2008-09-09 00:44:40 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static ssize_t priority_store ( struct device * d , struct device_attribute * attr ,
const char * buf , size_t len )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return store_bridge_parm ( d , buf , len , set_priority ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( priority ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t root_id_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return br_show_bridge_id ( buf , & to_bridge ( d ) - > designated_root ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( root_id ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t bridge_id_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return br_show_bridge_id ( buf , & to_bridge ( d ) - > bridge_id ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( bridge_id ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t root_port_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return sprintf ( buf , " %d \n " , to_bridge ( d ) - > root_port ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( root_port ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t root_path_cost_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return sprintf ( buf , " %d \n " , to_bridge ( d ) - > root_path_cost ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( root_path_cost ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t topology_change_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
return sprintf ( buf , " %d \n " , to_bridge ( d ) - > topology_change ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( topology_change ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t topology_change_detected_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %d \n " , br - > topology_change_detected ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( topology_change_detected ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t hello_timer_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %ld \n " , br_timer_value ( & br - > hello_timer ) ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( hello_timer ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t tcn_timer_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %ld \n " , br_timer_value ( & br - > tcn_timer ) ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( tcn_timer ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t topology_change_timer_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2005-04-17 02:20:36 +04:00
return sprintf ( buf , " %ld \n " , br_timer_value ( & br - > topology_change_timer ) ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( topology_change_timer ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t gc_timer_show ( struct device * d , struct device_attribute * attr ,
2002-04-09 23:14:34 +04:00
char * buf )
2005-04-17 02:20:36 +04:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2017-02-04 20:05:07 +03:00
return sprintf ( buf , " %ld \n " , br_timer_value ( & br - > gc_work . timer ) ) ;
2005-04-17 02:20:36 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RO ( gc_timer ) ;
2005-04-17 02:20:36 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t group_addr_show ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr , char * buf )
2006-03-21 09:59:21 +03:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2017-12-19 21:10:53 +03:00
return sprintf ( buf , " %pM \n " , br - > group_addr ) ;
2006-03-21 09:59:21 +03:00
}
2014-01-06 23:00:44 +04:00
static ssize_t group_addr_store ( struct device * d ,
2002-04-09 23:14:34 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
2006-03-21 09:59:21 +03:00
{
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( d ) ;
2012-11-01 13:10:04 +04:00
u8 new_addr [ 6 ] ;
2006-03-21 09:59:21 +03:00
2012-11-16 07:03:08 +04:00
if ( ! ns_capable ( dev_net ( br - > dev ) - > user_ns , CAP_NET_ADMIN ) )
2006-03-21 09:59:21 +03:00
return - EPERM ;
2017-12-19 21:10:53 +03:00
if ( ! mac_pton ( buf , new_addr ) )
2006-03-21 09:59:21 +03:00
return - EINVAL ;
2012-11-01 13:11:11 +04:00
if ( ! is_link_local_ether_addr ( new_addr ) )
2006-03-21 09:59:21 +03:00
return - EINVAL ;
2009-11-30 03:55:45 +03:00
if ( new_addr [ 5 ] = = 1 | | /* 802.3x Pause address */
new_addr [ 5 ] = = 2 | | /* 802.3ad Slow protocols */
new_addr [ 5 ] = = 3 ) /* 802.1X PAE address */
2006-03-21 09:59:21 +03:00
return - EINVAL ;
2014-06-10 15:59:25 +04:00
if ( ! rtnl_trylock ( ) )
return restart_syscall ( ) ;
2006-03-21 09:59:21 +03:00
spin_lock_bh ( & br - > lock ) ;
2017-12-19 21:10:53 +03:00
ether_addr_copy ( br - > group_addr , new_addr ) ;
2006-03-21 09:59:21 +03:00
spin_unlock_bh ( & br - > lock ) ;
2014-06-10 15:59:25 +04:00
br - > group_addr_set = true ;
br_recalculate_fwd_mask ( br ) ;
2016-04-08 19:03:31 +03:00
netdev_state_change ( br - > dev ) ;
2014-06-10 15:59:25 +04:00
rtnl_unlock ( ) ;
2006-03-21 09:59:21 +03:00
return len ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( group_addr ) ;
2006-03-21 09:59:21 +03:00
2016-04-08 19:03:28 +03:00
static int set_flush ( struct net_bridge * br , unsigned long val )
{
br_fdb_flush ( br ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t flush_store ( struct device * d ,
2007-04-09 23:57:54 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
2016-04-08 19:03:28 +03:00
return store_bridge_parm ( d , buf , len , set_flush ) ;
2007-04-09 23:57:54 +04:00
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_WO ( flush ) ;
2006-03-21 09:59:21 +03:00
2010-02-27 22:41:49 +03:00
# ifdef CONFIG_BRIDGE_IGMP_SNOOPING
2014-01-06 23:00:44 +04:00
static ssize_t multicast_router_show ( struct device * d ,
2010-02-27 22:41:49 +03:00
struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , br - > multicast_router ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_router_store ( struct device * d ,
2010-02-27 22:41:49 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_set_router ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_router ) ;
2010-02-27 22:41:50 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_snooping_show ( struct device * d ,
2010-02-27 22:41:50 +03:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , ! br - > multicast_disabled ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_snooping_store ( struct device * d ,
2010-02-27 22:41:50 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_toggle ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_snooping ) ;
2010-02-27 22:41:51 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_query_use_ifaddr_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
2013-05-22 01:52:54 +04:00
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , br - > multicast_query_use_ifaddr ) ;
}
static int set_query_use_ifaddr ( struct net_bridge * br , unsigned long val )
{
br - > multicast_query_use_ifaddr = ! ! val ;
return 0 ;
}
static ssize_t
2014-01-06 23:00:44 +04:00
multicast_query_use_ifaddr_store ( struct device * d ,
2013-05-22 01:52:54 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , set_query_use_ifaddr ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_query_use_ifaddr ) ;
2013-05-22 01:52:54 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_querier_show ( struct device * d ,
2012-04-13 06:37:42 +04:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , br - > multicast_querier ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_querier_store ( struct device * d ,
2012-04-13 06:37:42 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_set_querier ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_querier ) ;
2012-04-13 06:37:42 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t hash_elasticity_show ( struct device * d ,
2010-02-27 22:41:51 +03:00
struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > hash_elasticity ) ;
}
static int set_elasticity ( struct net_bridge * br , unsigned long val )
{
br - > hash_elasticity = val ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t hash_elasticity_store ( struct device * d ,
2010-02-27 22:41:51 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , set_elasticity ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( hash_elasticity ) ;
2010-02-27 22:41:51 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t hash_max_show ( struct device * d , struct device_attribute * attr ,
2010-02-27 22:41:51 +03:00
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > hash_max ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t hash_max_store ( struct device * d , struct device_attribute * attr ,
2010-02-27 22:41:51 +03:00
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_set_hash_max ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( hash_max ) ;
2010-02-27 22:41:52 +03:00
2016-11-21 15:03:24 +03:00
static ssize_t multicast_igmp_version_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > multicast_igmp_version ) ;
}
static ssize_t multicast_igmp_version_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_set_igmp_version ) ;
}
static DEVICE_ATTR_RW ( multicast_igmp_version ) ;
2014-01-06 23:00:44 +04:00
static ssize_t multicast_last_member_count_show ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > multicast_last_member_count ) ;
}
static int set_last_member_count ( struct net_bridge * br , unsigned long val )
{
br - > multicast_last_member_count = val ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_last_member_count_store ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , set_last_member_count ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_last_member_count ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_startup_query_count_show (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > multicast_startup_query_count ) ;
}
static int set_startup_query_count ( struct net_bridge * br , unsigned long val )
{
br - > multicast_startup_query_count = val ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_startup_query_count_store (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_startup_query_count ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_startup_query_count ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_last_member_interval_show (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_last_member_interval ) ) ;
}
static int set_last_member_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_last_member_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_last_member_interval_store (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_last_member_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_last_member_interval ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_membership_interval_show (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_membership_interval ) ) ;
}
static int set_membership_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_membership_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_membership_interval_store (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_membership_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_membership_interval ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_querier_interval_show ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_querier_interval ) ) ;
}
static int set_querier_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_querier_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_querier_interval_store ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , set_querier_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_querier_interval ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_query_interval_show ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_query_interval ) ) ;
}
static int set_query_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_query_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_query_interval_store ( struct device * d ,
2010-02-27 22:41:52 +03:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , set_query_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_query_interval ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_query_response_interval_show (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf (
buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_query_response_interval ) ) ;
}
static int set_query_response_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_query_response_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_query_response_interval_store (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_query_response_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_query_response_interval ) ;
2010-02-27 22:41:52 +03:00
2014-01-06 23:00:44 +04:00
static ssize_t multicast_startup_query_interval_show (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf (
buf , " %lu \n " ,
jiffies_to_clock_t ( br - > multicast_startup_query_interval ) ) ;
}
static int set_startup_query_interval ( struct net_bridge * br , unsigned long val )
{
br - > multicast_startup_query_interval = clock_t_to_jiffies ( val ) ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t multicast_startup_query_interval_store (
2010-02-27 22:41:52 +03:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_startup_query_interval ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( multicast_startup_query_interval ) ;
2016-06-28 17:57:06 +03:00
static ssize_t multicast_stats_enabled_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > multicast_stats_enabled ) ;
}
static int set_stats_enabled ( struct net_bridge * br , unsigned long val )
{
br - > multicast_stats_enabled = ! ! val ;
return 0 ;
}
static ssize_t multicast_stats_enabled_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_stats_enabled ) ;
}
static DEVICE_ATTR_RW ( multicast_stats_enabled ) ;
2016-11-21 15:03:25 +03:00
# if IS_ENABLED(CONFIG_IPV6)
static ssize_t multicast_mld_version_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > multicast_mld_version ) ;
}
static ssize_t multicast_mld_version_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_multicast_set_mld_version ) ;
}
static DEVICE_ATTR_RW ( multicast_mld_version ) ;
# endif
2010-02-27 22:41:49 +03:00
# endif
2014-09-18 13:29:03 +04:00
# if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_iptables_show (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > nf_call_iptables ) ;
}
static int set_nf_call_iptables ( struct net_bridge * br , unsigned long val )
{
br - > nf_call_iptables = val ? true : false ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_iptables_store (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_nf_call_iptables ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( nf_call_iptables ) ;
2010-07-02 11:32:57 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_ip6tables_show (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > nf_call_ip6tables ) ;
}
static int set_nf_call_ip6tables ( struct net_bridge * br , unsigned long val )
{
br - > nf_call_ip6tables = val ? true : false ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_ip6tables_store (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_nf_call_ip6tables ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( nf_call_ip6tables ) ;
2010-07-02 11:32:57 +04:00
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_arptables_show (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > nf_call_arptables ) ;
}
static int set_nf_call_arptables ( struct net_bridge * br , unsigned long val )
{
br - > nf_call_arptables = val ? true : false ;
return 0 ;
}
2014-01-06 23:00:44 +04:00
static ssize_t nf_call_arptables_store (
2010-07-02 11:32:57 +04:00
struct device * d , struct device_attribute * attr , const char * buf ,
size_t len )
{
return store_bridge_parm ( d , buf , len , set_nf_call_arptables ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( nf_call_arptables ) ;
2010-07-02 11:32:57 +04:00
# endif
2013-02-13 16:00:09 +04:00
# ifdef CONFIG_BRIDGE_VLAN_FILTERING
2014-01-06 23:00:44 +04:00
static ssize_t vlan_filtering_show ( struct device * d ,
2013-02-13 16:00:09 +04:00
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , br - > vlan_enabled ) ;
}
2014-01-06 23:00:44 +04:00
static ssize_t vlan_filtering_store ( struct device * d ,
2013-02-13 16:00:09 +04:00
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_vlan_filter_toggle ) ;
}
2014-01-06 23:00:44 +04:00
static DEVICE_ATTR_RW ( vlan_filtering ) ;
2014-06-10 15:59:25 +04:00
static ssize_t vlan_protocol_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %#06x \n " , ntohs ( br - > vlan_proto ) ) ;
}
static ssize_t vlan_protocol_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_vlan_set_proto ) ;
}
static DEVICE_ATTR_RW ( vlan_protocol ) ;
2014-10-03 19:29:16 +04:00
static ssize_t default_pvid_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %d \n " , br - > default_pvid ) ;
}
static ssize_t default_pvid_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_vlan_set_default_pvid ) ;
}
static DEVICE_ATTR_RW ( default_pvid ) ;
2016-04-30 11:25:28 +03:00
static ssize_t vlan_stats_enabled_show ( struct device * d ,
struct device_attribute * attr ,
char * buf )
{
struct net_bridge * br = to_bridge ( d ) ;
return sprintf ( buf , " %u \n " , br - > vlan_stats_enabled ) ;
}
static ssize_t vlan_stats_enabled_store ( struct device * d ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
return store_bridge_parm ( d , buf , len , br_vlan_set_stats ) ;
}
static DEVICE_ATTR_RW ( vlan_stats_enabled ) ;
2013-02-13 16:00:09 +04:00
# endif
2010-02-27 22:41:49 +03:00
2005-04-17 02:20:36 +04:00
static struct attribute * bridge_attrs [ ] = {
2002-04-09 23:14:34 +04:00
& dev_attr_forward_delay . attr ,
& dev_attr_hello_time . attr ,
& dev_attr_max_age . attr ,
& dev_attr_ageing_time . attr ,
& dev_attr_stp_state . attr ,
2011-10-03 22:14:46 +04:00
& dev_attr_group_fwd_mask . attr ,
2002-04-09 23:14:34 +04:00
& dev_attr_priority . attr ,
& dev_attr_bridge_id . attr ,
& dev_attr_root_id . attr ,
& dev_attr_root_path_cost . attr ,
& dev_attr_root_port . attr ,
& dev_attr_topology_change . attr ,
& dev_attr_topology_change_detected . attr ,
& dev_attr_hello_timer . attr ,
& dev_attr_tcn_timer . attr ,
& dev_attr_topology_change_timer . attr ,
& dev_attr_gc_timer . attr ,
& dev_attr_group_addr . attr ,
2007-04-09 23:57:54 +04:00
& dev_attr_flush . attr ,
2010-02-27 22:41:49 +03:00
# ifdef CONFIG_BRIDGE_IGMP_SNOOPING
& dev_attr_multicast_router . attr ,
2010-02-27 22:41:50 +03:00
& dev_attr_multicast_snooping . attr ,
2012-04-13 06:37:42 +04:00
& dev_attr_multicast_querier . attr ,
2013-05-22 01:52:54 +04:00
& dev_attr_multicast_query_use_ifaddr . attr ,
2010-02-27 22:41:51 +03:00
& dev_attr_hash_elasticity . attr ,
& dev_attr_hash_max . attr ,
2010-02-27 22:41:52 +03:00
& dev_attr_multicast_last_member_count . attr ,
& dev_attr_multicast_startup_query_count . attr ,
& dev_attr_multicast_last_member_interval . attr ,
& dev_attr_multicast_membership_interval . attr ,
& dev_attr_multicast_querier_interval . attr ,
& dev_attr_multicast_query_interval . attr ,
& dev_attr_multicast_query_response_interval . attr ,
& dev_attr_multicast_startup_query_interval . attr ,
2016-06-28 17:57:06 +03:00
& dev_attr_multicast_stats_enabled . attr ,
2016-11-21 15:03:24 +03:00
& dev_attr_multicast_igmp_version . attr ,
2016-11-21 15:03:25 +03:00
# if IS_ENABLED(CONFIG_IPV6)
& dev_attr_multicast_mld_version . attr ,
# endif
2010-07-02 11:32:57 +04:00
# endif
2014-09-18 13:29:03 +04:00
# if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
2010-07-02 11:32:57 +04:00
& dev_attr_nf_call_iptables . attr ,
& dev_attr_nf_call_ip6tables . attr ,
& dev_attr_nf_call_arptables . attr ,
2013-02-13 16:00:09 +04:00
# endif
# ifdef CONFIG_BRIDGE_VLAN_FILTERING
& dev_attr_vlan_filtering . attr ,
2014-06-10 15:59:25 +04:00
& dev_attr_vlan_protocol . attr ,
2014-10-03 19:29:16 +04:00
& dev_attr_default_pvid . attr ,
2016-04-30 11:25:28 +03:00
& dev_attr_vlan_stats_enabled . attr ,
2010-02-27 22:41:49 +03:00
# endif
2005-04-17 02:20:36 +04:00
NULL
} ;
2017-06-29 14:09:38 +03:00
static const struct attribute_group bridge_group = {
2005-04-17 02:20:36 +04:00
. name = SYSFS_BRIDGE_ATTR ,
. attrs = bridge_attrs ,
} ;
/*
* Export the forwarding information table as a binary file
* The records are struct __fdb_entry .
*
* Returns the number of bytes read .
*/
2010-05-13 05:28:57 +04:00
static ssize_t brforward_read ( struct file * filp , struct kobject * kobj ,
2007-06-09 09:57:22 +04:00
struct bin_attribute * bin_attr ,
char * buf , loff_t off , size_t count )
2005-04-17 02:20:36 +04:00
{
2015-12-23 15:42:21 +03:00
struct device * dev = kobj_to_dev ( kobj ) ;
2002-04-09 23:14:34 +04:00
struct net_bridge * br = to_bridge ( dev ) ;
2005-04-17 02:20:36 +04:00
int n ;
/* must read whole records */
if ( off % sizeof ( struct __fdb_entry ) ! = 0 )
return - EINVAL ;
2007-02-09 17:24:35 +03:00
n = br_fdb_fillbuf ( br , buf ,
2005-04-17 02:20:36 +04:00
count / sizeof ( struct __fdb_entry ) ,
off / sizeof ( struct __fdb_entry ) ) ;
if ( n > 0 )
n * = sizeof ( struct __fdb_entry ) ;
2007-02-09 17:24:35 +03:00
2005-04-17 02:20:36 +04:00
return n ;
}
static struct bin_attribute bridge_forward = {
. attr = { . name = SYSFS_BRIDGE_FDB ,
2018-03-24 01:54:38 +03:00
. mode = 0444 , } ,
2005-04-17 02:20:36 +04:00
. read = brforward_read ,
} ;
/*
* Add entries in sysfs onto the existing network class device
* for the bridge .
* Adds a attribute group " bridge " containing tuning parameters .
* Binary attribute containing the forward table
* Sub directory to hold links to interfaces .
*
* Note : the ifobj exists only to be a subdirectory
* to hold links . The ifobj exists in same data structure
* as it ' s parent the bridge so reference counting works .
*/
int br_sysfs_addbr ( struct net_device * dev )
{
2002-04-09 23:14:34 +04:00
struct kobject * brobj = & dev - > dev . kobj ;
2005-04-17 02:20:36 +04:00
struct net_bridge * br = netdev_priv ( dev ) ;
int err ;
err = sysfs_create_group ( brobj , & bridge_group ) ;
if ( err ) {
pr_info ( " %s: can't create group %s/%s \n " ,
2008-03-06 07:47:47 +03:00
__func__ , dev - > name , bridge_group . name ) ;
2005-04-17 02:20:36 +04:00
goto out1 ;
}
err = sysfs_create_bin_file ( brobj , & bridge_forward ) ;
if ( err ) {
2006-10-26 10:07:37 +04:00
pr_info ( " %s: can't create attribute file %s/%s \n " ,
2008-03-06 07:47:47 +03:00
__func__ , dev - > name , bridge_forward . attr . name ) ;
2005-04-17 02:20:36 +04:00
goto out2 ;
}
2007-12-17 22:54:39 +03:00
br - > ifobj = kobject_create_and_add ( SYSFS_BRIDGE_PORT_SUBDIR , brobj ) ;
if ( ! br - > ifobj ) {
2005-04-17 02:20:36 +04:00
pr_info ( " %s: can't add kobject (directory) %s/%s \n " ,
2008-03-06 07:47:47 +03:00
__func__ , dev - > name , SYSFS_BRIDGE_PORT_SUBDIR ) ;
2016-12-03 14:33:23 +03:00
err = - ENOMEM ;
2005-04-17 02:20:36 +04:00
goto out3 ;
}
return 0 ;
out3 :
2002-04-09 23:14:34 +04:00
sysfs_remove_bin_file ( & dev - > dev . kobj , & bridge_forward ) ;
2005-04-17 02:20:36 +04:00
out2 :
2002-04-09 23:14:34 +04:00
sysfs_remove_group ( & dev - > dev . kobj , & bridge_group ) ;
2005-04-17 02:20:36 +04:00
out1 :
return err ;
}
void br_sysfs_delbr ( struct net_device * dev )
{
2002-04-09 23:14:34 +04:00
struct kobject * kobj = & dev - > dev . kobj ;
2005-04-17 02:20:36 +04:00
struct net_bridge * br = netdev_priv ( dev ) ;
2007-12-20 19:13:05 +03:00
kobject_put ( br - > ifobj ) ;
2005-04-17 02:20:36 +04:00
sysfs_remove_bin_file ( kobj , & bridge_forward ) ;
sysfs_remove_group ( kobj , & bridge_group ) ;
}