Skip to content

Commit

Permalink
net: dsa: Give drivers the chance to veto certain upper devices
Browse files Browse the repository at this point in the history
Some switches rely on unique pvids to ensure port separation in
standalone mode, because they don't have a port forwarding matrix
configurable in hardware. So, setups like a group of 2 uppers with the
same VLAN, swp0.100 and swp1.100, will cause traffic tagged with VLAN
100 to be autonomously forwarded between these switch ports, in spite
of there being no bridge between swp0 and swp1.

These drivers need to prevent this from happening. They need to have
VLAN filtering enabled in standalone mode (so they'll drop frames tagged
with unknown VLANs) and they can only accept an 8021q upper on a port as
long as it isn't installed on any other port too. So give them the
chance to veto bad user requests.

Signed-off-by: Vladimir Oltean <[email protected]>
[Kurt: Pass info instead of ptr]
Signed-off-by: Kurt Kanzenbach <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
vladimiroltean authored and kuba-moo committed Nov 5, 2020
1 parent 01ef09c commit e358bef
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/net/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,12 @@ struct dsa_switch_ops {
void (*get_regs)(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *p);

/*
* Upper device tracking.
*/
int (*port_prechangeupper)(struct dsa_switch *ds, int port,
struct netdev_notifier_changeupper_info *info);

/*
* Bridge integration
*/
Expand Down
12 changes: 12 additions & 0 deletions net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -2032,10 +2032,22 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
switch (event) {
case NETDEV_PRECHANGEUPPER: {
struct netdev_notifier_changeupper_info *info = ptr;
struct dsa_switch *ds;
struct dsa_port *dp;
int err;

if (!dsa_slave_dev_check(dev))
return dsa_prevent_bridging_8021q_upper(dev, ptr);

dp = dsa_slave_to_port(dev);
ds = dp->ds;

if (ds->ops->port_prechangeupper) {
err = ds->ops->port_prechangeupper(ds, dp->index, info);
if (err)
return notifier_from_errno(err);
}

if (is_vlan_dev(info->upper_dev))
return dsa_slave_check_8021q_upper(dev, ptr);
break;
Expand Down

0 comments on commit e358bef

Please sign in to comment.