forked from mirrors/linux
		
	net: bridge: Notify about bridge VLANs
A driver might need to react to changes in settings of brentry VLANs. Therefore send switchdev port notifications for these as well. Reuse SWITCHDEV_OBJ_ID_PORT_VLAN for this purpose. Listeners should use netif_is_bridge_master() on orig_dev to determine whether the notification is about a bridge port or a bridge. Signed-off-by: Petr Machata <petrm@mellanox.com> Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									a73bceb86d
								
							
						
					
					
						commit
						9c86ce2c1a
					
				
					 1 changed files with 25 additions and 3 deletions
				
			
		| 
						 | 
					@ -246,6 +246,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
 | 
				
			||||||
			goto out_filt;
 | 
								goto out_filt;
 | 
				
			||||||
		v->brvlan = masterv;
 | 
							v->brvlan = masterv;
 | 
				
			||||||
		v->stats = masterv->stats;
 | 
							v->stats = masterv->stats;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = br_switchdev_port_vlan_add(dev, v->vid, flags);
 | 
				
			||||||
 | 
							if (err && err != -EOPNOTSUPP)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Add the dev mac and count the vlan only if it's usable */
 | 
						/* Add the dev mac and count the vlan only if it's usable */
 | 
				
			||||||
| 
						 | 
					@ -281,6 +285,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
 | 
				
			||||||
			br_vlan_put_master(masterv);
 | 
								br_vlan_put_master(masterv);
 | 
				
			||||||
			v->brvlan = NULL;
 | 
								v->brvlan = NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							br_switchdev_port_vlan_del(dev, v->vid);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	goto out;
 | 
						goto out;
 | 
				
			||||||
| 
						 | 
					@ -306,6 +312,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
 | 
				
			||||||
		err = __vlan_vid_del(p->dev, p->br, v->vid);
 | 
							err = __vlan_vid_del(p->dev, p->br, v->vid);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = br_switchdev_port_vlan_del(v->br->dev, v->vid);
 | 
				
			||||||
 | 
							if (err && err != -EOPNOTSUPP)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							err = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (br_vlan_should_use(v)) {
 | 
						if (br_vlan_should_use(v)) {
 | 
				
			||||||
| 
						 | 
					@ -558,16 +569,22 @@ static int br_vlan_add_existing(struct net_bridge *br,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags);
 | 
				
			||||||
 | 
						if (err && err != -EOPNOTSUPP)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!br_vlan_is_brentry(vlan)) {
 | 
						if (!br_vlan_is_brentry(vlan)) {
 | 
				
			||||||
		/* Trying to change flags of non-existent bridge vlan */
 | 
							/* Trying to change flags of non-existent bridge vlan */
 | 
				
			||||||
		if (!(flags & BRIDGE_VLAN_INFO_BRENTRY))
 | 
							if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) {
 | 
				
			||||||
			return -EINVAL;
 | 
								err = -EINVAL;
 | 
				
			||||||
 | 
								goto err_flags;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		/* It was only kept for port vlans, now make it real */
 | 
							/* It was only kept for port vlans, now make it real */
 | 
				
			||||||
		err = br_fdb_insert(br, NULL, br->dev->dev_addr,
 | 
							err = br_fdb_insert(br, NULL, br->dev->dev_addr,
 | 
				
			||||||
				    vlan->vid);
 | 
									    vlan->vid);
 | 
				
			||||||
		if (err) {
 | 
							if (err) {
 | 
				
			||||||
			br_err(br, "failed to insert local address into bridge forwarding table\n");
 | 
								br_err(br, "failed to insert local address into bridge forwarding table\n");
 | 
				
			||||||
			return err;
 | 
								goto err_fdb_insert;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		refcount_inc(&vlan->refcnt);
 | 
							refcount_inc(&vlan->refcnt);
 | 
				
			||||||
| 
						 | 
					@ -580,6 +597,11 @@ static int br_vlan_add_existing(struct net_bridge *br,
 | 
				
			||||||
		*changed = true;
 | 
							*changed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_fdb_insert:
 | 
				
			||||||
 | 
					err_flags:
 | 
				
			||||||
 | 
						br_switchdev_port_vlan_del(br->dev, vlan->vid);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Must be protected by RTNL.
 | 
					/* Must be protected by RTNL.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue