diff options
Diffstat (limited to 'net/bridge/br_sysfs_if.c')
| -rw-r--r-- | net/bridge/br_sysfs_if.c | 111 | 
1 files changed, 65 insertions, 46 deletions
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index fd5799c9bc8..e561cd59b8a 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -23,42 +23,64 @@  struct brport_attribute {  	struct attribute	attr;  	ssize_t (*show)(struct net_bridge_port *, char *); -	ssize_t (*store)(struct net_bridge_port *, unsigned long); +	int (*store)(struct net_bridge_port *, unsigned long);  }; -#define BRPORT_ATTR(_name,_mode,_show,_store)		        \ -struct brport_attribute brport_attr_##_name = { 	        \ +#define BRPORT_ATTR(_name, _mode, _show, _store)		\ +const struct brport_attribute brport_attr_##_name = { 	        \  	.attr = {.name = __stringify(_name), 			\  		 .mode = _mode },				\  	.show	= _show,					\  	.store	= _store,					\  }; -static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) +#define BRPORT_ATTR_FLAG(_name, _mask)				\ +static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \ +{								\ +	return sprintf(buf, "%d\n", !!(p->flags & _mask));	\ +}								\ +static int store_##_name(struct net_bridge_port *p, unsigned long v) \ +{								\ +	return store_flag(p, v, _mask);				\ +}								\ +static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR,			\ +		   show_##_name, store_##_name) + +static int store_flag(struct net_bridge_port *p, unsigned long v, +		      unsigned long mask)  { -	return sprintf(buf, "%d\n", p->path_cost); +	unsigned long flags; + +	flags = p->flags; + +	if (v) +		flags |= mask; +	else +		flags &= ~mask; + +	if (flags != p->flags) { +		p->flags = flags; +		br_port_flags_change(p, mask); +		br_ifinfo_notify(RTM_NEWLINK, p); +	} +	return 0;  } -static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v) + +static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)  { -	br_stp_set_path_cost(p, v); -	return 0; +	return sprintf(buf, "%d\n", p->path_cost);  } +  static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, -		   show_path_cost, store_path_cost); +		   show_path_cost, br_stp_set_path_cost);  static ssize_t show_priority(struct net_bridge_port *p, char *buf)  {  	return sprintf(buf, "%d\n", p->priority);  } -static ssize_t store_priority(struct net_bridge_port *p, unsigned long v) -{ -	if (v >= (1<<(16-BR_PORT_BITS))) -		return -ERANGE; -	br_stp_set_port_priority(p, v); -	return 0; -} +  static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, -			 show_priority, store_priority); +			 show_priority, br_stp_set_port_priority);  static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)  { @@ -136,28 +158,18 @@ static ssize_t show_hold_timer(struct net_bridge_port *p,  }  static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); -static ssize_t store_flush(struct net_bridge_port *p, unsigned long v) +static int store_flush(struct net_bridge_port *p, unsigned long v)  {  	br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry  	return 0;  }  static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); -static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf) -{ -	int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0; -	return sprintf(buf, "%d\n", hairpin_mode); -} -static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v) -{ -	if (v) -		p->flags |= BR_HAIRPIN_MODE; -	else -		p->flags &= ~BR_HAIRPIN_MODE; -	return 0; -} -static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR, -		   show_hairpin_mode, store_hairpin_mode); +BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); +BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); +BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); +BRPORT_ATTR_FLAG(learning, BR_LEARNING); +BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD);  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING  static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -165,16 +177,18 @@ static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)  	return sprintf(buf, "%d\n", p->multicast_router);  } -static ssize_t store_multicast_router(struct net_bridge_port *p, +static int store_multicast_router(struct net_bridge_port *p,  				      unsigned long v)  {  	return br_multicast_set_port_router(p, v);  }  static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,  		   store_multicast_router); + +BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);  #endif -static struct brport_attribute *brport_attrs[] = { +static const struct brport_attribute *brport_attrs[] = {  	&brport_attr_path_cost,  	&brport_attr_priority,  	&brport_attr_port_id, @@ -191,8 +205,13 @@ static struct brport_attribute *brport_attrs[] = {  	&brport_attr_hold_timer,  	&brport_attr_flush,  	&brport_attr_hairpin_mode, +	&brport_attr_bpdu_guard, +	&brport_attr_root_block, +	&brport_attr_learning, +	&brport_attr_unicast_flood,  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING  	&brport_attr_multicast_router, +	&brport_attr_multicast_fast_leave,  #endif  	NULL  }; @@ -200,26 +219,26 @@ static struct brport_attribute *brport_attrs[] = {  #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)  #define to_brport(obj)	container_of(obj, struct net_bridge_port, kobj) -static ssize_t brport_show(struct kobject * kobj, -			   struct attribute * attr, char * buf) +static ssize_t brport_show(struct kobject *kobj, +			   struct attribute *attr, char *buf)  { -	struct brport_attribute * brport_attr = to_brport_attr(attr); -	struct net_bridge_port * p = to_brport(kobj); +	struct brport_attribute *brport_attr = to_brport_attr(attr); +	struct net_bridge_port *p = to_brport(kobj);  	return brport_attr->show(p, buf);  } -static ssize_t brport_store(struct kobject * kobj, -			    struct attribute * attr, -			    const char * buf, size_t count) +static ssize_t brport_store(struct kobject *kobj, +			    struct attribute *attr, +			    const char *buf, size_t count)  { -	struct brport_attribute * brport_attr = to_brport_attr(attr); -	struct net_bridge_port * p = to_brport(kobj); +	struct brport_attribute *brport_attr = to_brport_attr(attr); +	struct net_bridge_port *p = to_brport(kobj);  	ssize_t ret = -EINVAL;  	char *endp;  	unsigned long val; -	if (!capable(CAP_NET_ADMIN)) +	if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))  		return -EPERM;  	val = simple_strtoul(buf, &endp, 0); @@ -251,7 +270,7 @@ const struct sysfs_ops brport_sysfs_ops = {  int br_sysfs_addif(struct net_bridge_port *p)  {  	struct net_bridge *br = p->br; -	struct brport_attribute **a; +	const struct brport_attribute **a;  	int err;  	err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj,  | 
