net: dsa: support VLAN filtering switchdev attr
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>
Fri, 26 Feb 2016 18:16:00 +0000 (13:16 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 1 Mar 2016 21:24:51 +0000 (16:24 -0500)
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>
include/net/dsa.h
net/dsa/slave.c

index 3dd54867174ae120bfe39f91930befda86d57d00..26c0a3fa009a8a292a8c69601fdb4dc089ec250c 100644 (file)
@@ -305,6 +305,8 @@ struct dsa_switch_driver {
        /*
         * VLAN support
         */
+       int     (*port_vlan_filtering)(struct dsa_switch *ds, int port,
+                                      bool vlan_filtering);
        int     (*port_vlan_prepare)(struct dsa_switch *ds, int port,
                                     const struct switchdev_obj_port_vlan *vlan,
                                     struct switchdev_trans *trans);
index cde29239b60d2fd7694327226a2149e1597641b1..27bf03d11670cd982b072bc02bf0331b0308e6b4 100644 (file)
@@ -317,6 +317,24 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state)
        return ret;
 }
 
+static int dsa_slave_vlan_filtering(struct net_device *dev,
+                                   const struct switchdev_attr *attr,
+                                   struct switchdev_trans *trans)
+{
+       struct dsa_slave_priv *p = netdev_priv(dev);
+       struct dsa_switch *ds = p->parent;
+
+       /* bridge skips -EOPNOTSUPP, so skip the prepare phase */
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
+       if (ds->drv->port_vlan_filtering)
+               return ds->drv->port_vlan_filtering(ds, p->port,
+                                                   attr->u.vlan_filtering);
+
+       return 0;
+}
+
 static int dsa_slave_port_attr_set(struct net_device *dev,
                                   const struct switchdev_attr *attr,
                                   struct switchdev_trans *trans)
@@ -333,6 +351,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
                        ret = ds->drv->port_stp_update(ds, p->port,
                                                       attr->u.stp_state);
                break;
+       case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
+               ret = dsa_slave_vlan_filtering(dev, attr, trans);
+               break;
        default:
                ret = -EOPNOTSUPP;
                break;