lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 3 Mar 2022 22:59:21 +0200
From:   Vladimir Oltean <olteanv@...il.com>
To:     Tobias Waldekranz <tobias@...dekranz.com>
Cc:     davem@...emloft.net, kuba@...nel.org, Andrew Lunn <andrew@...n.ch>,
        Vivien Didelot <vivien.didelot@...il.com>,
        Florian Fainelli <f.fainelli@...il.com>,
        Jiri Pirko <jiri@...nulli.us>,
        Ivan Vecera <ivecera@...hat.com>,
        Roopa Prabhu <roopa@...dia.com>,
        Nikolay Aleksandrov <razor@...ckwall.org>,
        Russell King <linux@...linux.org.uk>,
        Petr Machata <petrm@...dia.com>,
        Cooper Lees <me@...perlees.com>,
        Ido Schimmel <idosch@...dia.com>,
        Matt Johnston <matt@...econstruct.com.au>,
        linux-kernel@...r.kernel.org, netdev@...r.kernel.org,
        bridge@...ts.linux-foundation.org
Subject: Re: [PATCH v2 net-next 04/10] net: bridge: mst: Notify switchdev
 drivers of VLAN MSTI migrations

On Tue, Mar 01, 2022 at 11:03:15AM +0100, Tobias Waldekranz wrote:
> Whenever a VLAN moves to a new MSTI, send a switchdev notification so
> that switchdevs can...
> 
> ...either refuse the migration if the hardware does not support
> offloading of MST...
> 
> ..or track a bridge's VID to MSTI mapping when offloading is
> supported.
> 
> Signed-off-by: Tobias Waldekranz <tobias@...dekranz.com>
> ---
>  include/net/switchdev.h   | 10 +++++++
>  net/bridge/br_mst.c       | 15 +++++++++++
>  net/bridge/br_switchdev.c | 57 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 82 insertions(+)
> 
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 3e424d40fae3..39e57aa5005a 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -28,6 +28,7 @@ enum switchdev_attr_id {
>  	SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
>  	SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
>  	SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
> +	SWITCHDEV_ATTR_ID_VLAN_MSTI,
>  };
>  
>  struct switchdev_brport_flags {
> @@ -35,6 +36,14 @@ struct switchdev_brport_flags {
>  	unsigned long mask;
>  };
>  
> +struct switchdev_vlan_attr {
> +	u16 vid;
> +
> +	union {
> +		u16 msti;
> +	};

Do you see other VLAN attributes that would be added in the future, such
as to justify making this a single-element union from the get-go?
Anyway if that is the case, we're lacking an id for the attribute type,
so we'd end up needing to change drivers when a second union element
appears. Otherwise they'd all expect an u16 msti.

> +};
> +
>  struct switchdev_attr {
>  	struct net_device *orig_dev;
>  	enum switchdev_attr_id id;
> @@ -50,6 +59,7 @@ struct switchdev_attr {
>  		u16 vlan_protocol;			/* BRIDGE_VLAN_PROTOCOL */
>  		bool mc_disabled;			/* MC_DISABLED */
>  		u8 mrp_port_role;			/* MRP_PORT_ROLE */
> +		struct switchdev_vlan_attr vlan_attr;	/* VLAN_* */
>  	} u;
>  };
>  
> diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
> index 8dea8e7257fd..aba603675165 100644
> --- a/net/bridge/br_mst.c
> +++ b/net/bridge/br_mst.c
> @@ -7,6 +7,7 @@
>   */
>  
>  #include <linux/kernel.h>
> +#include <net/switchdev.h>
>  
>  #include "br_private.h"
>  
> @@ -65,9 +66,23 @@ static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)
>  
>  int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti)
>  {
> +	struct switchdev_attr attr = {
> +		.id = SWITCHDEV_ATTR_ID_VLAN_MSTI,
> +		.flags = SWITCHDEV_F_DEFER,

Is the bridge spinlock held (atomic context), or otherwise why is
SWITCHDEV_F_DEFER needed here?

> +		.orig_dev = mv->br->dev,
> +		.u.vlan_attr = {
> +			.vid = mv->vid,
> +			.msti = msti,
> +		},
> +	};
>  	struct net_bridge_vlan_group *vg;
>  	struct net_bridge_vlan *pv;
>  	struct net_bridge_port *p;
> +	int err;
> +
> +	err = switchdev_port_attr_set(mv->br->dev, &attr, NULL);

Treating a "VLAN attribute" as a "port attribute of the bridge" is
pushing the taxonomy just a little, but I don't have a better suggestion.

> +	if (err && err != -EOPNOTSUPP)
> +		return err;
>  
>  	mv->msti = msti;
>  
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index 6f6a70121a5e..160d7659f88a 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -428,6 +428,57 @@ static int br_switchdev_vlan_replay(struct net_device *br_dev,
>  	return 0;
>  }
>  
> +static int br_switchdev_mst_replay(struct net_device *br_dev,
> +				   const void *ctx, bool adding,
> +				   struct notifier_block *nb,
> +				   struct netlink_ext_ack *extack)

"bool adding" is unused, and replaying the VLAN to MSTI associations
before deleting them makes little sense anyway.

I understand the appeal of symmetry, so maybe put an

	if (adding) {
		err = br_switchdev_vlan_attr_replay(...);
		if (err && err != -EOPNOTSUPP)
			return err;
	}

at the end of br_switchdev_vlan_replay()?

> +{
> +	struct switchdev_notifier_port_attr_info attr_info = {
> +		.info = {
> +			.dev = br_dev,
> +			.extack = extack,
> +			.ctx = ctx,
> +		},
> +	};
> +	struct net_bridge *br = netdev_priv(br_dev);
> +	struct net_bridge_vlan_group *vg;
> +	struct net_bridge_vlan *v;
> +	int err;
> +
> +	ASSERT_RTNL();
> +
> +	if (!nb)
> +		return 0;
> +
> +	if (!netif_is_bridge_master(br_dev))
> +		return -EINVAL;
> +
> +	vg = br_vlan_group(br);
> +
> +	list_for_each_entry(v, &vg->vlan_list, vlist) {
> +		struct switchdev_attr attr = {
> +			.id = SWITCHDEV_ATTR_ID_VLAN_MSTI,
> +			.flags = SWITCHDEV_F_DEFER,

I don't think SWITCHDEV_F_DEFER has any effect on a replay.

> +			.orig_dev = br_dev,
> +			.u.vlan_attr = {
> +				.vid = v->vid,
> +				.msti = v->msti,
> +			}
> +		};
> +
> +		if (!v->msti)
> +			continue;
> +
> +		attr_info.attr = &attr;
> +		err = nb->notifier_call(nb, SWITCHDEV_PORT_ATTR_SET, &attr_info);
> +		err = notifier_to_errno(err);
> +		if (err)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +
>  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
>  struct br_switchdev_mdb_complete_info {
>  	struct net_bridge_port *port;
> @@ -695,6 +746,10 @@ static int nbp_switchdev_sync_objs(struct net_bridge_port *p, const void *ctx,
>  	if (err && err != -EOPNOTSUPP)
>  		return err;
>  
> +	err = br_switchdev_mst_replay(br_dev, ctx, true, blocking_nb, extack);
> +	if (err && err != -EOPNOTSUPP)
> +		return err;
> +
>  	err = br_switchdev_mdb_replay(br_dev, dev, ctx, true, blocking_nb,
>  				      extack);
>  	if (err && err != -EOPNOTSUPP)
> @@ -719,6 +774,8 @@ static void nbp_switchdev_unsync_objs(struct net_bridge_port *p,
>  
>  	br_switchdev_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL);
>  
> +	br_switchdev_mst_replay(br_dev, ctx, false, blocking_nb, NULL);
> +
>  	br_switchdev_vlan_replay(br_dev, ctx, false, blocking_nb, NULL);
>  }
>  
> -- 
> 2.25.1
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ