mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	net: bridge: mst: Notify switchdev drivers of VLAN MSTI migrations
Whenever a VLAN moves to a new MSTI, send a switchdev notification so that switchdevs can track a bridge's VID to MSTI mappings. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									87c167bb94
								
							
						
					
					
						commit
						6284c723d9
					
				
					 3 changed files with 66 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -29,6 +29,7 @@ enum switchdev_attr_id {
 | 
			
		|||
	SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
 | 
			
		||||
	SWITCHDEV_ATTR_ID_BRIDGE_MST,
 | 
			
		||||
	SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
 | 
			
		||||
	SWITCHDEV_ATTR_ID_VLAN_MSTI,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct switchdev_brport_flags {
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +37,11 @@ struct switchdev_brport_flags {
 | 
			
		|||
	unsigned long mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct switchdev_vlan_msti {
 | 
			
		||||
	u16 vid;
 | 
			
		||||
	u16 msti;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct switchdev_attr {
 | 
			
		||||
	struct net_device *orig_dev;
 | 
			
		||||
	enum switchdev_attr_id id;
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +58,7 @@ struct switchdev_attr {
 | 
			
		|||
		bool mst;				/* BRIDGE_MST */
 | 
			
		||||
		bool mc_disabled;			/* MC_DISABLED */
 | 
			
		||||
		u8 mrp_port_role;			/* MRP_PORT_ROLE */
 | 
			
		||||
		struct switchdev_vlan_msti vlan_msti;	/* VLAN_MSTI */
 | 
			
		||||
	} u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,13 +69,26 @@ 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,
 | 
			
		||||
		.orig_dev = mv->br->dev,
 | 
			
		||||
		.u.vlan_msti = {
 | 
			
		||||
			.vid = mv->vid,
 | 
			
		||||
			.msti = msti,
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
	struct net_bridge_vlan_group *vg;
 | 
			
		||||
	struct net_bridge_vlan *pv;
 | 
			
		||||
	struct net_bridge_port *p;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (mv->msti == msti)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	err = switchdev_port_attr_set(mv->br->dev, &attr, NULL);
 | 
			
		||||
	if (err && err != -EOPNOTSUPP)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	mv->msti = msti;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(p, &mv->br->port_list, list) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -331,6 +331,46 @@ br_switchdev_fdb_replay(const struct net_device *br_dev, const void *ctx,
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int br_switchdev_vlan_attr_replay(struct net_device *br_dev,
 | 
			
		||||
					 const void *ctx,
 | 
			
		||||
					 struct notifier_block *nb,
 | 
			
		||||
					 struct netlink_ext_ack *extack)
 | 
			
		||||
{
 | 
			
		||||
	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 switchdev_attr attr;
 | 
			
		||||
	struct net_bridge_vlan *v;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	attr_info.attr = &attr;
 | 
			
		||||
	attr.orig_dev = br_dev;
 | 
			
		||||
 | 
			
		||||
	vg = br_vlan_group(br);
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(v, &vg->vlan_list, vlist) {
 | 
			
		||||
		if (v->msti) {
 | 
			
		||||
			attr.id = SWITCHDEV_ATTR_ID_VLAN_MSTI;
 | 
			
		||||
			attr.u.vlan_msti.vid = v->vid;
 | 
			
		||||
			attr.u.vlan_msti.msti = v->msti;
 | 
			
		||||
 | 
			
		||||
			err = nb->notifier_call(nb, SWITCHDEV_PORT_ATTR_SET,
 | 
			
		||||
						&attr_info);
 | 
			
		||||
			err = notifier_to_errno(err);
 | 
			
		||||
			if (err)
 | 
			
		||||
				return err;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
br_switchdev_vlan_replay_one(struct notifier_block *nb,
 | 
			
		||||
			     struct net_device *dev,
 | 
			
		||||
| 
						 | 
				
			
			@ -425,6 +465,12 @@ static int br_switchdev_vlan_replay(struct net_device *br_dev,
 | 
			
		|||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (adding) {
 | 
			
		||||
		err = br_switchdev_vlan_attr_replay(br_dev, ctx, nb, extack);
 | 
			
		||||
		if (err)
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue