Commit 934d0f03 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-avoid-cross-chip-vlan-sync'

Tobias Waldekranz says:

====================
net: dsa: Avoid cross-chip syncing of VLAN filtering

This bug has been latent in the source for quite some time, I suspect
due to the homogeneity of both typical configurations and hardware.

On singlechip systems, this would never be triggered. The only reason
I saw it on my multichip system was because not all chips had the same
number of ports, which means that the misdemeanor alien call turned
into a felony array-out-of-bounds access.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 51d555cf 108dc874
...@@ -113,26 +113,15 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds, ...@@ -113,26 +113,15 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds,
return dsa_tag_8021q_bridge_join(ds, info); return dsa_tag_8021q_bridge_join(ds, info);
} }
static int dsa_switch_bridge_leave(struct dsa_switch *ds, static int dsa_switch_sync_vlan_filtering(struct dsa_switch *ds,
struct dsa_notifier_bridge_info *info) struct dsa_notifier_bridge_info *info)
{ {
struct dsa_switch_tree *dst = ds->dst;
struct netlink_ext_ack extack = {0}; struct netlink_ext_ack extack = {0};
bool change_vlan_filtering = false; bool change_vlan_filtering = false;
bool vlan_filtering; bool vlan_filtering;
struct dsa_port *dp; struct dsa_port *dp;
int err; int err;
if (dst->index == info->tree_index && ds->index == info->sw_index &&
ds->ops->port_bridge_leave)
ds->ops->port_bridge_leave(ds, info->port, info->bridge);
if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
ds->ops->crosschip_bridge_leave)
ds->ops->crosschip_bridge_leave(ds, info->tree_index,
info->sw_index, info->port,
info->bridge);
if (ds->needs_standalone_vlan_filtering && if (ds->needs_standalone_vlan_filtering &&
!br_vlan_enabled(info->bridge.dev)) { !br_vlan_enabled(info->bridge.dev)) {
change_vlan_filtering = true; change_vlan_filtering = true;
...@@ -172,6 +161,31 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, ...@@ -172,6 +161,31 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
return err; return err;
} }
return 0;
}
static int dsa_switch_bridge_leave(struct dsa_switch *ds,
struct dsa_notifier_bridge_info *info)
{
struct dsa_switch_tree *dst = ds->dst;
int err;
if (dst->index == info->tree_index && ds->index == info->sw_index &&
ds->ops->port_bridge_leave)
ds->ops->port_bridge_leave(ds, info->port, info->bridge);
if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
ds->ops->crosschip_bridge_leave)
ds->ops->crosschip_bridge_leave(ds, info->tree_index,
info->sw_index, info->port,
info->bridge);
if (ds->dst->index == info->tree_index && ds->index == info->sw_index) {
err = dsa_switch_sync_vlan_filtering(ds, info);
if (err)
return err;
}
return dsa_tag_8021q_bridge_leave(ds, info); return dsa_tag_8021q_bridge_leave(ds, info);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment