|
@@ -149,6 +149,39 @@ static ssize_t store_stp_state(struct device *d,
|
|
|
static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
|
|
|
store_stp_state);
|
|
|
|
|
|
+static ssize_t show_group_fwd_mask(struct device *d,
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
+{
|
|
|
+ struct net_bridge *br = to_bridge(d);
|
|
|
+ return sprintf(buf, "%#x\n", br->group_fwd_mask);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static ssize_t store_group_fwd_mask(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 (!capable(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;
|
|
|
+}
|
|
|
+static DEVICE_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask,
|
|
|
+ store_group_fwd_mask);
|
|
|
+
|
|
|
static ssize_t show_priority(struct device *d, struct device_attribute *attr,
|
|
|
char *buf)
|
|
|
{
|
|
@@ -652,6 +685,7 @@ static struct attribute *bridge_attrs[] = {
|
|
|
&dev_attr_max_age.attr,
|
|
|
&dev_attr_ageing_time.attr,
|
|
|
&dev_attr_stp_state.attr,
|
|
|
+ &dev_attr_group_fwd_mask.attr,
|
|
|
&dev_attr_priority.attr,
|
|
|
&dev_attr_bridge_id.attr,
|
|
|
&dev_attr_root_id.attr,
|