Skip to content

Commit

Permalink
bridge: try switchdev op first in __vlan_vid_add/del
Browse files Browse the repository at this point in the history
Some drivers need to implement both switchdev vlan ops and
vid_add/kill ndos. For that to work in bridge code, we need to try
switchdev op first when adding/deleting vlan id.

Signed-off-by: Jiri Pirko <[email protected]>
Signed-off-by: Ido Schimmel <[email protected]>
Acked-by: Scott Feldman <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jpirko authored and davem330 committed Oct 13, 2015
1 parent 3703ebe commit 0944d6b
Showing 1 changed file with 22 additions and 36 deletions.
58 changes: 22 additions & 36 deletions net/bridge/br_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,20 @@ static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
u16 vid, u16 flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
struct switchdev_obj_port_vlan v = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
.flags = flags,
.vid_begin = vid,
.vid_end = vid,
};
int err;

/* If driver uses VLAN ndo ops, use 8021q to install vid
* on device, otherwise try switchdev ops to install vid.
/* Try switchdev op first. In case it is not supported, fallback to
* 8021q add.
*/

if (ops->ndo_vlan_rx_add_vid) {
err = vlan_vid_add(dev, br->vlan_proto, vid);
} else {
struct switchdev_obj_port_vlan v = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
.flags = flags,
.vid_begin = vid,
.vid_end = vid,
};

err = switchdev_port_obj_add(dev, &v.obj);
if (err == -EOPNOTSUPP)
err = 0;
}

err = switchdev_port_obj_add(dev, &v.obj);
if (err == -EOPNOTSUPP)
return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
}

Expand Down Expand Up @@ -122,27 +114,21 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
u16 vid)
{
const struct net_device_ops *ops = dev->netdev_ops;
int err = 0;
struct switchdev_obj_port_vlan v = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
.vid_begin = vid,
.vid_end = vid,
};
int err;

/* If driver uses VLAN ndo ops, use 8021q to delete vid
* on device, otherwise try switchdev ops to delete vid.
/* Try switchdev op first. In case it is not supported, fallback to
* 8021q del.
*/

if (ops->ndo_vlan_rx_kill_vid) {
err = switchdev_port_obj_del(dev, &v.obj);
if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
} else {
struct switchdev_obj_port_vlan v = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
.vid_begin = vid,
.vid_end = vid,
};

err = switchdev_port_obj_del(dev, &v.obj);
if (err == -EOPNOTSUPP)
err = 0;
return 0;
}

return err;
}

Expand Down

0 comments on commit 0944d6b

Please sign in to comment.