diff options
author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2016-02-26 13:16:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-01 16:24:51 -0500 |
commit | fb2dabad69f099fb9c03a44276778911da50ba29 (patch) | |
tree | 07dd9149cfb77ba1cc114da5f104b618574ae64d | |
parent | 7f66ee41566d00f80ed15c0cec0b237f7af8ac0f (diff) |
net: dsa: support VLAN filtering switchdev attr
When a user explicitly requests VLAN filtering with something like:
# echo 1 > /sys/class/net/<bridge>/bridge/vlan_filtering
Switchdev propagates a SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING port
attribute.
Add support for it in the DSA layer with a new port_vlan_filtering
function to let drivers toggle 802.1Q filtering on user demand.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/dsa.h | 2 | ||||
-rw-r--r-- | net/dsa/slave.c | 21 |
2 files changed, 23 insertions, 0 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h index 3dd54867174a..26c0a3fa009a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h | |||
@@ -305,6 +305,8 @@ struct dsa_switch_driver { | |||
305 | /* | 305 | /* |
306 | * VLAN support | 306 | * VLAN support |
307 | */ | 307 | */ |
308 | int (*port_vlan_filtering)(struct dsa_switch *ds, int port, | ||
309 | bool vlan_filtering); | ||
308 | int (*port_vlan_prepare)(struct dsa_switch *ds, int port, | 310 | int (*port_vlan_prepare)(struct dsa_switch *ds, int port, |
309 | const struct switchdev_obj_port_vlan *vlan, | 311 | const struct switchdev_obj_port_vlan *vlan, |
310 | struct switchdev_trans *trans); | 312 | struct switchdev_trans *trans); |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index cde29239b60d..27bf03d11670 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -317,6 +317,24 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state) | |||
317 | return ret; | 317 | return ret; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int dsa_slave_vlan_filtering(struct net_device *dev, | ||
321 | const struct switchdev_attr *attr, | ||
322 | struct switchdev_trans *trans) | ||
323 | { | ||
324 | struct dsa_slave_priv *p = netdev_priv(dev); | ||
325 | struct dsa_switch *ds = p->parent; | ||
326 | |||
327 | /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ | ||
328 | if (switchdev_trans_ph_prepare(trans)) | ||
329 | return 0; | ||
330 | |||
331 | if (ds->drv->port_vlan_filtering) | ||
332 | return ds->drv->port_vlan_filtering(ds, p->port, | ||
333 | attr->u.vlan_filtering); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
320 | static int dsa_slave_port_attr_set(struct net_device *dev, | 338 | static int dsa_slave_port_attr_set(struct net_device *dev, |
321 | const struct switchdev_attr *attr, | 339 | const struct switchdev_attr *attr, |
322 | struct switchdev_trans *trans) | 340 | struct switchdev_trans *trans) |
@@ -333,6 +351,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev, | |||
333 | ret = ds->drv->port_stp_update(ds, p->port, | 351 | ret = ds->drv->port_stp_update(ds, p->port, |
334 | attr->u.stp_state); | 352 | attr->u.stp_state); |
335 | break; | 353 | break; |
354 | case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: | ||
355 | ret = dsa_slave_vlan_filtering(dev, attr, trans); | ||
356 | break; | ||
336 | default: | 357 | default: |
337 | ret = -EOPNOTSUPP; | 358 | ret = -EOPNOTSUPP; |
338 | break; | 359 | break; |