Skip to content

Commit d540491

Browse files
committed
Merge branch 'switchdev_ageing_time'
Scott Feldman says: ==================== switchdev: push bridge ageing_time attribute down Push bridge-level attributes down to switchdev drivers. This patchset adds the infrastructure and then pushes, as an example, ageing_time attribute down from bridge to switchdev (rocker) driver. Add some range-checking for ageing_time. RTNETLINK answers: Numerical result out of range Up until now, switchdev attrs where port-level attrs, so the netdev used in switchdev_attr_set() would be a switch port or bond of switch ports. With bridge-level attrs, the netdev passed to switchdev_attr_set() is the bridge netdev. The same recusive algo is used to visit the leaves of the stacked drivers to set the attr, it's just in this case we start one layer higher in the stack. One note is not all ports in the bridge may support setting a bridge-level attribute, so rather than failing the entire set, we'll skip over those ports returning -EOPNOTSUPP. v2->v3: Per Jiri review: push only ageing_time attr down at this time, and don't pass raw bridge IFLA_BR_* values; rather use new switchdev attr ID for ageing_time. v1->v2: rebase w/ net-next ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 7533ce3 + d0cf57f commit d540491

File tree

8 files changed

+56
-8
lines changed

8 files changed

+56
-8
lines changed

drivers/net/ethernet/rocker/rocker.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4361,6 +4361,18 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
43614361
return err;
43624362
}
43634363

4364+
static int rocker_port_bridge_ageing_time(struct rocker_port *rocker_port,
4365+
struct switchdev_trans *trans,
4366+
u32 ageing_time)
4367+
{
4368+
if (!switchdev_trans_ph_prepare(trans)) {
4369+
rocker_port->ageing_time = clock_t_to_jiffies(ageing_time);
4370+
mod_timer(&rocker_port->rocker->fdb_cleanup_timer, jiffies);
4371+
}
4372+
4373+
return 0;
4374+
}
4375+
43644376
static int rocker_port_attr_set(struct net_device *dev,
43654377
struct switchdev_attr *attr,
43664378
struct switchdev_trans *trans)
@@ -4378,6 +4390,10 @@ static int rocker_port_attr_set(struct net_device *dev,
43784390
err = rocker_port_brport_flags_set(rocker_port, trans,
43794391
attr->u.brport_flags);
43804392
break;
4393+
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
4394+
err = rocker_port_bridge_ageing_time(rocker_port, trans,
4395+
attr->u.ageing_time);
4396+
break;
43814397
default:
43824398
err = -EOPNOTSUPP;
43834399
break;

include/net/switchdev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/list.h>
1717

1818
#define SWITCHDEV_F_NO_RECURSE BIT(0)
19+
#define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1)
1920

2021
struct switchdev_trans_item {
2122
struct list_head list;
@@ -43,6 +44,7 @@ enum switchdev_attr_id {
4344
SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
4445
SWITCHDEV_ATTR_ID_PORT_STP_STATE,
4546
SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
47+
SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
4648
};
4749

4850
struct switchdev_attr {
@@ -52,6 +54,7 @@ struct switchdev_attr {
5254
struct netdev_phys_item_id ppid; /* PORT_PARENT_ID */
5355
u8 stp_state; /* PORT_STP_STATE */
5456
unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */
57+
u32 ageing_time; /* BRIDGE_AGEING_TIME */
5558
} u;
5659
};
5760

net/bridge/br_ioctl.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
200200
if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
201201
return -EPERM;
202202

203-
br->ageing_time = clock_t_to_jiffies(args[1]);
204-
return 0;
203+
return br_set_ageing_time(br, args[1]);
205204

206205
case BRCTL_GET_PORT_INFO:
207206
{

net/bridge/br_netlink.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,9 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
870870
}
871871

872872
if (data[IFLA_BR_AGEING_TIME]) {
873-
u32 ageing_time = nla_get_u32(data[IFLA_BR_AGEING_TIME]);
874-
875-
br->ageing_time = clock_t_to_jiffies(ageing_time);
873+
err = br_set_ageing_time(br, nla_get_u32(data[IFLA_BR_AGEING_TIME]));
874+
if (err)
875+
return err;
876876
}
877877

878878
if (data[IFLA_BR_STP_STATE]) {

net/bridge/br_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
882882
int br_set_forward_delay(struct net_bridge *br, unsigned long x);
883883
int br_set_hello_time(struct net_bridge *br, unsigned long x);
884884
int br_set_max_age(struct net_bridge *br, unsigned long x);
885+
int br_set_ageing_time(struct net_bridge *br, u32 ageing_time);
885886

886887

887888
/* br_stp_if.c */

net/bridge/br_stp.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,29 @@ int br_set_max_age(struct net_bridge *br, unsigned long val)
566566

567567
}
568568

569+
int br_set_ageing_time(struct net_bridge *br, u32 ageing_time)
570+
{
571+
struct switchdev_attr attr = {
572+
.id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
573+
.flags = SWITCHDEV_F_SKIP_EOPNOTSUPP,
574+
.u.ageing_time = ageing_time,
575+
};
576+
unsigned long t = clock_t_to_jiffies(ageing_time);
577+
int err;
578+
579+
if (t < BR_MIN_AGEING_TIME || t > BR_MAX_AGEING_TIME)
580+
return -ERANGE;
581+
582+
err = switchdev_port_attr_set(br->dev, &attr);
583+
if (err)
584+
return err;
585+
586+
br->ageing_time = t;
587+
mod_timer(&br->gc_timer, jiffies);
588+
589+
return 0;
590+
}
591+
569592
void __br_set_forward_delay(struct net_bridge *br, unsigned long t)
570593
{
571594
br->bridge_forward_delay = t;

net/bridge/br_sysfs_br.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ static ssize_t ageing_time_show(struct device *d,
102102

103103
static int set_ageing_time(struct net_bridge *br, unsigned long val)
104104
{
105-
br->ageing_time = clock_t_to_jiffies(val);
106-
return 0;
105+
return br_set_ageing_time(br, val);
107106
}
108107

109108
static ssize_t ageing_time_store(struct device *d,

net/switchdev/switchdev.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ static int __switchdev_port_attr_set(struct net_device *dev,
147147
return ops->switchdev_port_attr_set(dev, attr, trans);
148148

149149
if (attr->flags & SWITCHDEV_F_NO_RECURSE)
150-
return err;
150+
goto done;
151151

152152
/* Switch device port(s) may be stacked under
153153
* bond/team/vlan dev, so recurse down to set attr on
@@ -156,10 +156,17 @@ static int __switchdev_port_attr_set(struct net_device *dev,
156156

157157
netdev_for_each_lower_dev(dev, lower_dev, iter) {
158158
err = __switchdev_port_attr_set(lower_dev, attr, trans);
159+
if (err == -EOPNOTSUPP &&
160+
attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
161+
continue;
159162
if (err)
160163
break;
161164
}
162165

166+
done:
167+
if (err == -EOPNOTSUPP && attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP)
168+
err = 0;
169+
163170
return err;
164171
}
165172

0 commit comments

Comments
 (0)