net: dsa: install VLANs into the master's RX filter too
Most DSA switch tags shift the EtherType to the right, causing the master to not parse the VLAN as VLAN. However, not all switches do that (example: tail tags, tag_8021q etc), and if the DSA master has "rx-vlan-filter: on" in ethtool -k, then we have a problem. Therefore, we could populate the VLAN table of the master, just in case (for some switches it will not make a difference), so that network I/O can work even with a VLAN filtering master. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
adb256eb17
Коммит
2209158c90
|
@ -329,9 +329,10 @@ static int dsa_slave_vlan_add(struct net_device *dev,
|
||||||
const struct switchdev_obj *obj,
|
const struct switchdev_obj *obj,
|
||||||
struct switchdev_trans *trans)
|
struct switchdev_trans *trans)
|
||||||
{
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct switchdev_obj_port_vlan vlan;
|
struct switchdev_obj_port_vlan vlan;
|
||||||
int err;
|
int vid, err;
|
||||||
|
|
||||||
if (obj->orig_dev != dev)
|
if (obj->orig_dev != dev)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -366,6 +367,12 @@ static int dsa_slave_vlan_add(struct net_device *dev,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
for (vid = vlan.vid_begin; vid <= vlan.vid_end; vid++) {
|
||||||
|
err = vlan_vid_add(master, htons(ETH_P_8021Q), vid);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +416,10 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
|
||||||
static int dsa_slave_vlan_del(struct net_device *dev,
|
static int dsa_slave_vlan_del(struct net_device *dev,
|
||||||
const struct switchdev_obj *obj)
|
const struct switchdev_obj *obj)
|
||||||
{
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
|
struct switchdev_obj_port_vlan *vlan;
|
||||||
|
int vid, err;
|
||||||
|
|
||||||
if (obj->orig_dev != dev)
|
if (obj->orig_dev != dev)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -417,10 +427,19 @@ static int dsa_slave_vlan_del(struct net_device *dev,
|
||||||
if (dsa_port_skip_vlan_configuration(dp))
|
if (dsa_port_skip_vlan_configuration(dp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
|
||||||
|
|
||||||
/* Do not deprogram the CPU port as it may be shared with other user
|
/* Do not deprogram the CPU port as it may be shared with other user
|
||||||
* ports which can be members of this VLAN as well.
|
* ports which can be members of this VLAN as well.
|
||||||
*/
|
*/
|
||||||
return dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj));
|
err = dsa_port_vlan_del(dp, vlan);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++)
|
||||||
|
vlan_vid_del(master, htons(ETH_P_8021Q), vid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_port_obj_del(struct net_device *dev,
|
static int dsa_slave_port_obj_del(struct net_device *dev,
|
||||||
|
@ -1265,6 +1284,7 @@ static int dsa_slave_get_ts_info(struct net_device *dev,
|
||||||
static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
|
static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
|
||||||
u16 vid)
|
u16 vid)
|
||||||
{
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct switchdev_obj_port_vlan vlan = {
|
struct switchdev_obj_port_vlan vlan = {
|
||||||
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
|
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
|
||||||
|
@ -1298,12 +1318,13 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return vlan_vid_add(master, proto, vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
|
static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
|
||||||
u16 vid)
|
u16 vid)
|
||||||
{
|
{
|
||||||
|
struct net_device *master = dsa_slave_to_master(dev);
|
||||||
struct dsa_port *dp = dsa_slave_to_port(dev);
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
struct switchdev_obj_port_vlan vlan = {
|
struct switchdev_obj_port_vlan vlan = {
|
||||||
.vid_begin = vid,
|
.vid_begin = vid,
|
||||||
|
@ -1311,11 +1332,18 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
|
||||||
/* This API only allows programming tagged, non-PVID VIDs */
|
/* This API only allows programming tagged, non-PVID VIDs */
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
/* Do not deprogram the CPU port as it may be shared with other user
|
/* Do not deprogram the CPU port as it may be shared with other user
|
||||||
* ports which can be members of this VLAN as well.
|
* ports which can be members of this VLAN as well.
|
||||||
*/
|
*/
|
||||||
return dsa_port_vlan_del(dp, &vlan);
|
err = dsa_port_vlan_del(dp, &vlan);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
vlan_vid_del(master, proto, vid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dsa_hw_port {
|
struct dsa_hw_port {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче