|
@@ -43,7 +43,14 @@ static ssize_t store_bridge_parm(struct device *d,
|
|
|
if (endp == buf)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ if (!rtnl_trylock())
|
|
|
+ return restart_syscall();
|
|
|
+
|
|
|
err = (*set)(br, val);
|
|
|
+ if (!err)
|
|
|
+ netdev_state_change(br->dev);
|
|
|
+ rtnl_unlock();
|
|
|
+
|
|
|
return err ? err : len;
|
|
|
}
|
|
|
|
|
@@ -101,15 +108,7 @@ static ssize_t ageing_time_show(struct device *d,
|
|
|
|
|
|
static int set_ageing_time(struct net_bridge *br, unsigned long val)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (!rtnl_trylock())
|
|
|
- return restart_syscall();
|
|
|
-
|
|
|
- ret = br_set_ageing_time(br, val);
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
- return ret;
|
|
|
+ return br_set_ageing_time(br, val);
|
|
|
}
|
|
|
|
|
|
static ssize_t ageing_time_store(struct device *d,
|
|
@@ -128,27 +127,18 @@ static ssize_t stp_state_show(struct device *d,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static int set_stp_state(struct net_bridge *br, unsigned long val)
|
|
|
+{
|
|
|
+ br_stp_set_enabled(br, val);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t stp_state_store(struct device *d,
|
|
|
struct device_attribute *attr, const char *buf,
|
|
|
size_t len)
|
|
|
{
|
|
|
- struct net_bridge *br = to_bridge(d);
|
|
|
- char *endp;
|
|
|
- unsigned long val;
|
|
|
-
|
|
|
- if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
- val = simple_strtoul(buf, &endp, 0);
|
|
|
- if (endp == buf)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (!rtnl_trylock())
|
|
|
- return restart_syscall();
|
|
|
- br_stp_set_enabled(br, val);
|
|
|
- rtnl_unlock();
|
|
|
-
|
|
|
- return len;
|
|
|
+ return store_bridge_parm(d, buf, len, set_stp_state);
|
|
|
}
|
|
|
static DEVICE_ATTR_RW(stp_state);
|
|
|
|
|
@@ -160,29 +150,22 @@ static ssize_t group_fwd_mask_show(struct device *d,
|
|
|
return sprintf(buf, "%#x\n", br->group_fwd_mask);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-static ssize_t group_fwd_mask_store(struct device *d,
|
|
|
- struct device_attribute *attr,
|
|
|
- const char *buf,
|
|
|
- size_t len)
|
|
|
+static int set_group_fwd_mask(struct net_bridge *br, unsigned long val)
|
|
|
{
|
|
|
- struct net_bridge *br = to_bridge(d);
|
|
|
- char *endp;
|
|
|
- unsigned long val;
|
|
|
-
|
|
|
- if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
- val = simple_strtoul(buf, &endp, 0);
|
|
|
- if (endp == buf)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
if (val & BR_GROUPFWD_RESTRICTED)
|
|
|
return -EINVAL;
|
|
|
|
|
|
br->group_fwd_mask = val;
|
|
|
|
|
|
- return len;
|
|
|
+ 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);
|
|
|
}
|
|
|
static DEVICE_ATTR_RW(group_fwd_mask);
|
|
|
|
|
@@ -328,6 +311,7 @@ static ssize_t group_addr_store(struct device *d,
|
|
|
|
|
|
br->group_addr_set = true;
|
|
|
br_recalculate_fwd_mask(br);
|
|
|
+ netdev_state_change(br->dev);
|
|
|
|
|
|
rtnl_unlock();
|
|
|
|
|
@@ -336,17 +320,17 @@ static ssize_t group_addr_store(struct device *d,
|
|
|
|
|
|
static DEVICE_ATTR_RW(group_addr);
|
|
|
|
|
|
+static int set_flush(struct net_bridge *br, unsigned long val)
|
|
|
+{
|
|
|
+ br_fdb_flush(br);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t flush_store(struct device *d,
|
|
|
struct device_attribute *attr,
|
|
|
const char *buf, size_t len)
|
|
|
{
|
|
|
- struct net_bridge *br = to_bridge(d);
|
|
|
-
|
|
|
- if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
- br_fdb_flush(br);
|
|
|
- return len;
|
|
|
+ return store_bridge_parm(d, buf, len, set_flush);
|
|
|
}
|
|
|
static DEVICE_ATTR_WO(flush);
|
|
|
|