Message ID | 20210209151936.97382-4-olteanv@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Cleanup in brport flags switchdev offload for DSA | expand |
On Tue, Feb 09, 2021 at 05:19:28PM +0200, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > Currently br_switchdev_set_port_flag has two options for error handling > and neither is good: > - The driver returns -EOPNOTSUPP in PRE_BRIDGE_FLAGS if it doesn't > support offloading that flag, and this gets silently ignored and > converted to an errno of 0. Nobody does this. > - The driver returns some other error code, like -EINVAL, in > PRE_BRIDGE_FLAGS, and br_switchdev_set_port_flag shouts loudly. > > The problem is that we'd like to offload some port flags during bridge > join and leave, but also not have the bridge shout at us if those fail. > But on the other hand we'd like the user to know that we can't offload > something when they set that through netlink. And since we can't have > the driver return -EOPNOTSUPP or -EINVAL depending on whether it's > called by the user or internally by the bridge, let's just add an extack > argument to br_switchdev_set_port_flag and propagate it to its callers. > Then, when we need offloading to really fail silently, this can simply > be passed a NULL argument. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> > --- The build fails because since I started working on v2 and until I sent it, Jakub merged net into net-next which contained this fix: https://patchwork.kernel.org/project/netdevbpf/patch/20210207194733.1811529-1-olteanv@gmail.com/ for which I couldn't change prototype due to it missing in net-next. I think I would like to rather wait to gather some feedback first before respinning v3, if possible.
On Tue, Feb 09, 2021 at 07:36:31PM +0200, Vladimir Oltean wrote: > On Tue, Feb 09, 2021 at 05:19:28PM +0200, Vladimir Oltean wrote: > > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > > > Currently br_switchdev_set_port_flag has two options for error handling > > and neither is good: > > - The driver returns -EOPNOTSUPP in PRE_BRIDGE_FLAGS if it doesn't > > support offloading that flag, and this gets silently ignored and > > converted to an errno of 0. Nobody does this. > > - The driver returns some other error code, like -EINVAL, in > > PRE_BRIDGE_FLAGS, and br_switchdev_set_port_flag shouts loudly. > > > > The problem is that we'd like to offload some port flags during bridge > > join and leave, but also not have the bridge shout at us if those fail. > > But on the other hand we'd like the user to know that we can't offload > > something when they set that through netlink. And since we can't have > > the driver return -EOPNOTSUPP or -EINVAL depending on whether it's > > called by the user or internally by the bridge, let's just add an extack > > argument to br_switchdev_set_port_flag and propagate it to its callers. > > Then, when we need offloading to really fail silently, this can simply > > be passed a NULL argument. > > > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> > > --- > > The build fails because since I started working on v2 and until I sent > it, Jakub merged net into net-next which contained this fix: > https://patchwork.kernel.org/project/netdevbpf/patch/20210207194733.1811529-1-olteanv@gmail.com/ > for which I couldn't change prototype due to it missing in net-next. > I think I would like to rather wait to gather some feedback first before > respinning v3, if possible. It seems that in the sysfs call path br_switchdev_set_port_flag() will be called with the bridge lock held, which is going to be a problem given that patch #8 allows this function to block.
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 2c110bcbc6d0..3ba23fb95370 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -866,7 +866,8 @@ static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], } /* Process bridge protocol info on port */ -static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) +static int br_setport(struct net_bridge_port *p, struct nlattr *tb[], + struct netlink_ext_ack *extack) { unsigned long old_flags, changed_mask; bool br_vlan_tunnel_old; @@ -898,7 +899,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) spin_unlock_bh(&p->br->lock); - err = br_switchdev_set_port_flag(p, p->flags, changed_mask); + err = br_switchdev_set_port_flag(p, p->flags, changed_mask, extack); if (err) { spin_lock_bh(&p->br->lock); p->flags = old_flags; @@ -1021,7 +1022,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags, if (err) return err; - err = br_setport(p, tb); + err = br_setport(p, tb, extack); } else { /* Binary compatibility with old RSTP */ if (nla_len(protinfo) < sizeof(u8)) @@ -1111,7 +1112,7 @@ static int br_port_slave_changelink(struct net_device *brdev, if (!data) return 0; - return br_setport(br_port_get_rtnl(dev), data); + return br_setport(br_port_get_rtnl(dev), data, extack); } static int br_port_fill_slave_info(struct sk_buff *skb, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d242ba668e47..a1639d41188b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1575,7 +1575,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, const struct sk_buff *skb); int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask); + unsigned long mask, + struct netlink_ext_ack *extack); void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type); int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, @@ -1605,7 +1606,8 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, static inline int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask) + unsigned long mask, + struct netlink_ext_ack *extack) { return 0; } diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index c004ade25ac0..ac8dead86bf2 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -60,7 +60,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask) + unsigned long mask, + struct netlink_ext_ack *extack) { struct switchdev_attr attr = { .orig_dev = p->dev, @@ -80,14 +81,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, /* We run from atomic context here */ err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, - &info.info, NULL); + &info.info, extack); err = notifier_to_errno(err); if (err == -EOPNOTSUPP) return 0; if (err) { - br_warn(p->br, "bridge flag offload is not supported %u(%s)\n", - (unsigned int)p->port_no, p->dev->name); + if (extack && !extack->_msg) + NL_SET_ERR_MSG_MOD(extack, + "bridge flag offload is not supported"); return -EOPNOTSUPP; } @@ -97,8 +99,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, err = switchdev_port_attr_set(p->dev, &attr); if (err) { - br_warn(p->br, "error setting offload flag on port %u(%s)\n", - (unsigned int)p->port_no, p->dev->name); + NL_SET_ERR_MSG_MOD(extack, "error setting offload flag on port"); return err; }