All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters
@ 2020-09-20  1:47 Vladimir Oltean
  2020-09-20  1:47 ` [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER Vladimir Oltean
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

This series attempts to make DSA VLANs work in the presence of a master
interface that is:
- filtering, so it drops VLANs that aren't explicitly added to its
  filter list
- offloading, so the old assumptions in the tagging code about there
  being a VLAN tag in the skb are not necessarily true anymore.

For more context:
https://lore.kernel.org/netdev/20200910150738.mwhh2i6j2qgacqev@skbuf/

This probably marks the beginning of a series of patches in which DSA
starts paying much more attention to its upper interfaces, not only for
VLAN purposes but also for address filtering and for management of the
CPU flooding domain. There was a comment from Florian on whether we
could factor some of the mlxsw logic into some common functionality, but
it doesn't look so. This seems bound to be open-coded, but frankly there
isn't a lot to it.

Vladimir Oltean (9):
  net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from
    PRECHANGEUPPER
  net: dsa: rename dsa_slave_upper_vlan_check to something more
    suggestive
  net: dsa: convert check for 802.1Q upper when bridged into
    PRECHANGEUPPER
  net: dsa: convert denying bridge VLAN with existing 8021q upper to
    PRECHANGEUPPER
  net: dsa: refuse configuration in prepare phase of
    dsa_port_vlan_filtering()
  net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0
  net: dsa: install VLANs into the master's RX filter too
  net: dsa: tag_8021q: add VLANs to the master interface too
  net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags

 drivers/net/dsa/sja1105/sja1105_main.c |   7 +-
 include/linux/dsa/8021q.h              |   2 +
 net/dsa/port.c                         |  58 +++++++--
 net/dsa/slave.c                        | 156 ++++++++++++++++++-------
 net/dsa/switch.c                       |  41 -------
 net/dsa/tag_8021q.c                    |  20 +++-
 net/dsa/tag_sja1105.c                  |  21 +++-
 7 files changed, 206 insertions(+), 99 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:33   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive Vladimir Oltean
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

There doesn't seem to be any strong technical reason for doing it this
way, but we'll be adding more checks for invalid upper device
configurations, and it will be easier to have them all grouped under
PRECHANGEUPPER.

Tested that it still works:
ip link set br0 type bridge vlan_filtering 1
ip link add link swp2 name swp2.100 type vlan id 100
ip link set swp2.100 master br0
[   20.321312] br0: port 5(swp2.100) entered blocking state
[   20.326711] br0: port 5(swp2.100) entered disabled state
Error: dsa_core: Cannot enslave VLAN device into VLAN aware bridge.
[   20.346549] br0: port 5(swp2.100) entered blocking state
[   20.351957] br0: port 5(swp2.100) entered disabled state

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/slave.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index d6616c6f643d..a00275cda05f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1946,9 +1946,14 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
-	if (event == NETDEV_CHANGEUPPER) {
+	switch (event) {
+	case NETDEV_PRECHANGEUPPER:
 		if (!dsa_slave_dev_check(dev))
 			return dsa_slave_upper_vlan_check(dev, ptr);
+		break;
+	case NETDEV_CHANGEUPPER:
+		if (!dsa_slave_dev_check(dev))
+			return NOTIFY_DONE;
 
 		return dsa_slave_changeupper(dev, ptr);
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
  2020-09-20  1:47 ` [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:33   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER Vladimir Oltean
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

We'll be adding a new check in the PRECHANGEUPPER notifier, where we'll
need to check some VLAN uppers. It is hard to do that when there is
already a function named dsa_slave_upper_vlan_check. So rename this one.

Not to mention that this function probably shouldn't have started with
"dsa_slave_" in the first place, since the struct net_device argument
isn't a DSA slave, but an 8021q upper of one.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/slave.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index a00275cda05f..1bcba1c1b7cc 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1909,9 +1909,9 @@ static int dsa_slave_changeupper(struct net_device *dev,
 	return err;
 }
 
-static int dsa_slave_upper_vlan_check(struct net_device *dev,
-				      struct netdev_notifier_changeupper_info *
-				      info)
+static int
+dsa_prevent_bridging_8021q_upper(struct net_device *dev,
+				 struct netdev_notifier_changeupper_info *info)
 {
 	struct netlink_ext_ack *ext_ack;
 	struct net_device *slave;
@@ -1949,7 +1949,7 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
 	switch (event) {
 	case NETDEV_PRECHANGEUPPER:
 		if (!dsa_slave_dev_check(dev))
-			return dsa_slave_upper_vlan_check(dev, ptr);
+			return dsa_prevent_bridging_8021q_upper(dev, ptr);
 		break;
 	case NETDEV_CHANGEUPPER:
 		if (!dsa_slave_dev_check(dev))
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
  2020-09-20  1:47 ` [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER Vladimir Oltean
  2020-09-20  1:47 ` [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:34   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER Vladimir Oltean
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

DSA tries to prevent having a VLAN added by a bridge and by an 802.1Q
upper at the same time. It does that by checking the VID in
.ndo_vlan_rx_add_vid(), since that's something that the 8021q module
calls, via vlan_vid_add(). When a VLAN matches in both subsystems, this
check returns -EBUSY.

However the vlan_vid_add() function isn't specific to the 8021q module
in any way at all. It is simply the kernel's way to tell an interface to
add a VLAN to its RX filter and not drop that VLAN. So there's no reason
to return -EBUSY when somebody tries to call vlan_vid_add() for a VLAN
that was installed by the bridge. The proper behavior is to accept that
configuration.

So what's wrong is how DSA checks that it has an 8021q upper. It should
look at the actual uppers for that, not just assume that the 8021q
module was somewhere in the call stack of .ndo_vlan_rx_add_vid().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/slave.c | 74 +++++++++++++++++++++++++------------------------
 1 file changed, 38 insertions(+), 36 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1bcba1c1b7cc..1940c2458f0f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1240,26 +1240,9 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
 		/* This API only allows programming tagged, non-PVID VIDs */
 		.flags = 0,
 	};
-	struct bridge_vlan_info info;
 	struct switchdev_trans trans;
 	int ret;
 
-	/* Check for a possible bridge VLAN entry now since there is no
-	 * need to emulate the switchdev prepare + commit phase.
-	 */
-	if (dp->bridge_dev) {
-		if (dsa_port_skip_vlan_configuration(dp))
-			return 0;
-
-		/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
-		 * device, respectively the VID is not found, returning
-		 * 0 means success, which is a failure for us here.
-		 */
-		ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
-		if (ret == 0)
-			return -EBUSY;
-	}
-
 	/* User port... */
 	trans.ph_prepare = true;
 	ret = dsa_port_vlan_add(dp, &vlan, &trans);
@@ -1295,24 +1278,6 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
 		/* This API only allows programming tagged, non-PVID VIDs */
 		.flags = 0,
 	};
-	struct bridge_vlan_info info;
-	int ret;
-
-	/* Check for a possible bridge VLAN entry now since there is no
-	 * need to emulate the switchdev prepare + commit phase.
-	 */
-	if (dp->bridge_dev) {
-		if (dsa_port_skip_vlan_configuration(dp))
-			return 0;
-
-		/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
-		 * device, respectively the VID is not found, returning
-		 * 0 means success, which is a failure for us here.
-		 */
-		ret = br_vlan_get_info(dp->bridge_dev, vid, &info);
-		if (ret == 0)
-			return -EBUSY;
-	}
 
 	/* Do not deprogram the CPU port as it may be shared with other user
 	 * ports which can be members of this VLAN as well.
@@ -1941,16 +1906,53 @@ dsa_prevent_bridging_8021q_upper(struct net_device *dev,
 	return NOTIFY_DONE;
 }
 
+static int
+dsa_slave_check_8021q_upper(struct net_device *dev,
+			    struct netdev_notifier_changeupper_info *info)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct net_device *br = dp->bridge_dev;
+	struct bridge_vlan_info br_info;
+	struct netlink_ext_ack *extack;
+	int err = NOTIFY_DONE;
+	u16 vid;
+
+	if (!br)
+		return NOTIFY_DONE;
+
+	extack = netdev_notifier_info_to_extack(&info->info);
+	vid = vlan_dev_vlan_id(info->upper_dev);
+
+	/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
+	 * device, respectively the VID is not found, returning
+	 * 0 means success, which is a failure for us here.
+	 */
+	err = br_vlan_get_info(br, vid, &br_info);
+	if (err == 0) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "This VLAN is already configured by the bridge");
+		return notifier_from_errno(-EBUSY);
+	}
+
+	return NOTIFY_DONE;
+}
+
 static int dsa_slave_netdevice_event(struct notifier_block *nb,
 				     unsigned long event, void *ptr)
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 
 	switch (event) {
-	case NETDEV_PRECHANGEUPPER:
+	case NETDEV_PRECHANGEUPPER: {
+		struct netdev_notifier_changeupper_info *info = ptr;
+
 		if (!dsa_slave_dev_check(dev))
 			return dsa_prevent_bridging_8021q_upper(dev, ptr);
+
+		if (is_vlan_dev(info->upper_dev))
+			return dsa_slave_check_8021q_upper(dev, ptr);
 		break;
+	}
 	case NETDEV_CHANGEUPPER:
 		if (!dsa_slave_dev_check(dev))
 			return NOTIFY_DONE;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (2 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:37   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering() Vladimir Oltean
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

This is checking for the following order of operations, and makes sure
to deny that configuration:

ip link add link swp2 name swp2.100 type vlan id 100
ip link add br0 type bridge vlan_filtering 1
ip link set swp2 master br0
bridge vlan add dev swp2 vid 100

Instead of using vlan_for_each(), which looks at the VLAN filters
installed with vlan_vid_add(), just track the 8021q uppers. This has the
advantage of freeing up the vlan_vid_add() call for actual VLAN
filtering.

There is another change in this patch. The check is moved in slave.c,
from switch.c. I don't think it makes sense to have this 8021q upper
check for each switch port that gets notified of that VLAN addition
(these include DSA links and CPU ports, we know those can't have 8021q
uppers because they don't have a net_device registered for them), so
just do it in slave.c, for that one slave interface.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/slave.c  | 33 +++++++++++++++++++++++++++++++++
 net/dsa/switch.c | 41 -----------------------------------------
 2 files changed, 33 insertions(+), 41 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1940c2458f0f..b88a31a79e2f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -303,6 +303,28 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
 	return ret;
 }
 
+/* Must be called under rcu_read_lock() */
+static int
+dsa_slave_vlan_check_for_8021q_uppers(struct net_device *slave,
+				      const struct switchdev_obj_port_vlan *vlan)
+{
+	struct net_device *upper_dev;
+	struct list_head *iter;
+
+	netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) {
+		u16 vid;
+
+		if (!is_vlan_dev(upper_dev))
+			continue;
+
+		vid = vlan_dev_vlan_id(upper_dev);
+		if (vlan->vid_begin <= vid && vlan->vid_end >= vid)
+			return -EBUSY;
+	}
+
+	return 0;
+}
+
 static int dsa_slave_vlan_add(struct net_device *dev,
 			      const struct switchdev_obj *obj,
 			      struct switchdev_trans *trans)
@@ -319,6 +341,17 @@ static int dsa_slave_vlan_add(struct net_device *dev,
 
 	vlan = *SWITCHDEV_OBJ_PORT_VLAN(obj);
 
+	/* Deny adding a bridge VLAN when there is already an 802.1Q upper with
+	 * the same VID.
+	 */
+	if (trans->ph_prepare) {
+		rcu_read_lock();
+		err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
+		rcu_read_unlock();
+		if (err)
+			return err;
+	}
+
 	err = dsa_port_vlan_add(dp, &vlan, trans);
 	if (err)
 		return err;
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 86c8dc5c32a0..9afef6f0f9df 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -232,43 +232,6 @@ static int dsa_switch_mdb_del(struct dsa_switch *ds,
 	return 0;
 }
 
-static int dsa_port_vlan_device_check(struct net_device *vlan_dev,
-				      int vlan_dev_vid,
-				      void *arg)
-{
-	struct switchdev_obj_port_vlan *vlan = arg;
-	u16 vid;
-
-	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
-		if (vid == vlan_dev_vid)
-			return -EBUSY;
-	}
-
-	return 0;
-}
-
-static int dsa_port_vlan_check(struct dsa_switch *ds, int port,
-			       const struct switchdev_obj_port_vlan *vlan)
-{
-	const struct dsa_port *dp = dsa_to_port(ds, port);
-	int err = 0;
-
-	/* Device is not bridged, let it proceed with the VLAN device
-	 * creation.
-	 */
-	if (!dp->bridge_dev)
-		return err;
-
-	/* dsa_slave_vlan_rx_{add,kill}_vid() cannot use the prepare phase and
-	 * already checks whether there is an overlapping bridge VLAN entry
-	 * with the same VID, so here we only need to check that if we are
-	 * adding a bridge VLAN entry there is not an overlapping VLAN device
-	 * claiming that VID.
-	 */
-	return vlan_for_each(dp->slave, dsa_port_vlan_device_check,
-			     (void *)vlan);
-}
-
 static bool dsa_switch_vlan_match(struct dsa_switch *ds, int port,
 				  struct dsa_notifier_vlan_info *info)
 {
@@ -291,10 +254,6 @@ static int dsa_switch_vlan_prepare(struct dsa_switch *ds,
 
 	for (port = 0; port < ds->num_ports; port++) {
 		if (dsa_switch_vlan_match(ds, port, info)) {
-			err = dsa_port_vlan_check(ds, port, info->vlan);
-			if (err)
-				return err;
-
 			err = ds->ops->port_vlan_prepare(ds, port, info->vlan);
 			if (err)
 				return err;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering()
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (3 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:38   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0 Vladimir Oltean
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

The current logic beats me a little bit. The comment that "bridge skips
-EOPNOTSUPP, so skip the prepare phase" was introduced in commit
fb2dabad69f0 ("net: dsa: support VLAN filtering switchdev attr").

I'm not sure:
(a) ok, the bridge skips -EOPNOTSUPP, but, so what, where are we
    returning -EOPNOTSUPP?
(b) even if we are, and I'm just not seeing it, what is the causality
    relationship between the bridge skipping -EOPNOTSUPP and DSA
    skipping the prepare phase, and just returning zero?

One thing is certain beyond doubt though, and that is that DSA currently
refuses VLAN filtering from the "commit" phase instead of "prepare", and
that this is not a good thing:

ip link add br0 type bridge
ip link add br1 type bridge vlan_filtering 1
ip link set swp2 master br0
ip link set swp3 master br1
[ 3790.379389] 001: sja1105 spi0.1: VLAN filtering is a global setting
[ 3790.379399] 001: ------------[ cut here ]------------
[ 3790.379403] 001: WARNING: CPU: 1 PID: 515 at net/switchdev/switchdev.c:157 switchdev_port_attr_set_now+0x9c/0xa4
[ 3790.379420] 001: swp3: Commit of attribute (id=6) failed.
[ 3790.379533] 001: [<c11ff588>] (switchdev_port_attr_set_now) from [<c11b62e4>] (nbp_vlan_init+0x84/0x148)
[ 3790.379544] 001: [<c11b62e4>] (nbp_vlan_init) from [<c11a2ff0>] (br_add_if+0x514/0x670)
[ 3790.379554] 001: [<c11a2ff0>] (br_add_if) from [<c1031b5c>] (do_setlink+0x38c/0xab0)
[ 3790.379565] 001: [<c1031b5c>] (do_setlink) from [<c1036fe8>] (__rtnl_newlink+0x44c/0x748)
[ 3790.379573] 001: [<c1036fe8>] (__rtnl_newlink) from [<c1037328>] (rtnl_newlink+0x44/0x60)
[ 3790.379580] 001: [<c1037328>] (rtnl_newlink) from [<c10315fc>] (rtnetlink_rcv_msg+0x124/0x2f8)
[ 3790.379590] 001: [<c10315fc>] (rtnetlink_rcv_msg) from [<c10926b8>] (netlink_rcv_skb+0xb8/0x110)
[ 3790.379806] 001: ---[ end trace 0000000000000002 ]---
[ 3790.379819] 001: sja1105 spi0.1 swp3: failed to initialize vlan filtering on this port

So move the current logic that may fail (except ds->ops->port_vlan_filtering,
that is way harder) into the prepare stage of the switchdev transaction.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/port.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 46c9bf709683..794a03718838 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -232,15 +232,15 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 	struct dsa_switch *ds = dp->ds;
 	int err;
 
-	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
+	if (switchdev_trans_ph_prepare(trans)) {
+		if (!ds->ops->port_vlan_filtering)
+			return -EOPNOTSUPP;
 
-	if (!ds->ops->port_vlan_filtering)
-		return 0;
+		if (!dsa_port_can_apply_vlan_filtering(dp, vlan_filtering))
+			return -EINVAL;
 
-	if (!dsa_port_can_apply_vlan_filtering(dp, vlan_filtering))
-		return -EINVAL;
+		return 0;
+	}
 
 	if (dsa_port_is_vlan_filtering(dp) == vlan_filtering)
 		return 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (4 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering() Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:40   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too Vladimir Oltean
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

When the bridge has VLAN awareness disabled there isn't any duplication
of functionality, since the bridge does not process VLAN. Don't deny
adding 8021q uppers to DSA switch ports in that case. The switch is
supposed to simply pass traffic leaving the VLAN tag as-is, and the
stack will happily strip the VLAN tag for all 8021q uppers that exist.

We need to ensure that there are no 8021q uppers when the user attempts
to enable bridge vlan_filtering.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/port.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 net/dsa/slave.c |  4 ++--
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 794a03718838..9a4fb80d2731 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -193,11 +193,44 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
 	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
 }
 
+/* Must be called under rcu_read_lock() */
 static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
 					      bool vlan_filtering)
 {
 	struct dsa_switch *ds = dp->ds;
-	int i;
+	int err, i;
+
+	/* VLAN awareness was off, so the question is "can we turn it on".
+	 * We may have had 8021q uppers, those need to go. Make sure we don't
+	 * enter an inconsistent state: deny changing the VLAN awareness state
+	 * as long as we have 8021q uppers.
+	 */
+	if (vlan_filtering && dsa_is_user_port(ds, dp->index)) {
+		struct net_device *upper_dev, *slave = dp->slave;
+		struct net_device *br = dp->bridge_dev;
+		struct list_head *iter;
+
+		netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) {
+			struct bridge_vlan_info br_info;
+			u16 vid;
+
+			if (!is_vlan_dev(upper_dev))
+				continue;
+
+			vid = vlan_dev_vlan_id(upper_dev);
+
+			/* br_vlan_get_info() returns -EINVAL or -ENOENT if the
+			 * device, respectively the VID is not found, returning
+			 * 0 means success, which is a failure for us here.
+			 */
+			err = br_vlan_get_info(br, vid, &br_info);
+			if (err == 0) {
+				dev_err(ds->dev, "Must remove upper %s first\n",
+					upper_dev->name);
+				return false;
+			}
+		}
+	}
 
 	if (!ds->vlan_filtering_is_global)
 		return true;
@@ -233,10 +266,19 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
 	int err;
 
 	if (switchdev_trans_ph_prepare(trans)) {
+		bool apply;
+
 		if (!ds->ops->port_vlan_filtering)
 			return -EOPNOTSUPP;
 
-		if (!dsa_port_can_apply_vlan_filtering(dp, vlan_filtering))
+		/* We are called from dsa_slave_switchdev_blocking_event(),
+		 * which is not under rcu_read_lock(), unlike
+		 * dsa_slave_switchdev_event().
+		 */
+		rcu_read_lock();
+		apply = dsa_port_can_apply_vlan_filtering(dp, vlan_filtering);
+		rcu_read_unlock();
+		if (!apply)
 			return -EINVAL;
 
 		return 0;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index b88a31a79e2f..2de0ff18f2f5 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -344,7 +344,7 @@ static int dsa_slave_vlan_add(struct net_device *dev,
 	/* Deny adding a bridge VLAN when there is already an 802.1Q upper with
 	 * the same VID.
 	 */
-	if (trans->ph_prepare) {
+	if (trans->ph_prepare && br_vlan_enabled(dp->bridge_dev)) {
 		rcu_read_lock();
 		err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan);
 		rcu_read_unlock();
@@ -1950,7 +1950,7 @@ dsa_slave_check_8021q_upper(struct net_device *dev,
 	int err = NOTIFY_DONE;
 	u16 vid;
 
-	if (!br)
+	if (!br || !br_vlan_enabled(br))
 		return NOTIFY_DONE;
 
 	extack = netdev_notifier_info_to_extack(&info->info);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (5 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0 Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:43   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too Vladimir Oltean
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

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>
---
 net/dsa/slave.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 2de0ff18f2f5..0db161178cc0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -329,9 +329,10 @@ static int dsa_slave_vlan_add(struct net_device *dev,
 			      const struct switchdev_obj *obj,
 			      struct switchdev_trans *trans)
 {
+	struct net_device *master = dsa_slave_to_master(dev);
 	struct dsa_port *dp = dsa_slave_to_port(dev);
 	struct switchdev_obj_port_vlan vlan;
-	int err;
+	int vid, err;
 
 	if (obj->orig_dev != dev)
 		return -EOPNOTSUPP;
@@ -366,6 +367,12 @@ static int dsa_slave_vlan_add(struct net_device *dev,
 	if (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;
 }
 
@@ -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,
 			      const struct switchdev_obj *obj)
 {
+	struct net_device *master = dsa_slave_to_master(dev);
 	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct switchdev_obj_port_vlan *vlan;
+	int vid, err;
 
 	if (obj->orig_dev != dev)
 		return -EOPNOTSUPP;
@@ -417,10 +427,19 @@ static int dsa_slave_vlan_del(struct net_device *dev,
 	if (dsa_port_skip_vlan_configuration(dp))
 		return 0;
 
+	vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+
 	/* Do not deprogram the CPU port as it may be shared with other user
 	 * 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,
@@ -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,
 				     u16 vid)
 {
+	struct net_device *master = dsa_slave_to_master(dev);
 	struct dsa_port *dp = dsa_slave_to_port(dev);
 	struct switchdev_obj_port_vlan 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)
 		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,
 				      u16 vid)
 {
+	struct net_device *master = dsa_slave_to_master(dev);
 	struct dsa_port *dp = dsa_slave_to_port(dev);
 	struct switchdev_obj_port_vlan vlan = {
 		.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 */
 		.flags = 0,
 	};
+	int err;
 
 	/* Do not deprogram the CPU port as it may be shared with other user
 	 * 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 {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (6 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:44   ` Florian Fainelli
  2020-09-20  1:47 ` [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags Vladimir Oltean
  2020-09-20  2:44 ` [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Florian Fainelli
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

The whole purpose of tag_8021q is to send VLAN-tagged traffic to the
CPU, from which the driver can decode the source port and switch id.

Currently this only works if the VLAN filtering on the master is
disabled. Change that by explicitly adding code to tag_8021q.c to add
the VLANs corresponding to the tags to the filter of the master
interface.

Because we now need to call vlan_vid_add, then we also need to hold the
RTNL mutex. Propagate that requirement to the callers of dsa_8021q_setup
and modify the existing call sites as appropriate. Note that one call
path, sja1105_best_effort_vlan_filtering_set -> sja1105_vlan_filtering
-> sja1105_setup_8021q_tagging, was already holding this lock.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/sja1105/sja1105_main.c |  7 ++++++-
 include/linux/dsa/8021q.h              |  2 ++
 net/dsa/tag_8021q.c                    | 20 +++++++++++++++++++-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index cb1b0b6a63f3..4892ad4b0e86 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -3038,7 +3038,11 @@ static int sja1105_setup(struct dsa_switch *ds)
 	 * default, and that means vlan_filtering is 0 since they're not under
 	 * a bridge, so it's safe to set up switch tagging at this time.
 	 */
-	return sja1105_setup_8021q_tagging(ds, true);
+	rtnl_lock();
+	rc = sja1105_setup_8021q_tagging(ds, true);
+	rtnl_unlock();
+
+	return rc;
 }
 
 static void sja1105_teardown(struct dsa_switch *ds)
@@ -3539,6 +3543,7 @@ static int sja1105_probe(struct spi_device *spi)
 		return -ENOMEM;
 
 	priv->dsa_8021q_ctx->ops = &sja1105_dsa_8021q_ops;
+	priv->dsa_8021q_ctx->proto = htons(ETH_P_8021Q);
 	priv->dsa_8021q_ctx->ds = ds;
 
 	INIT_LIST_HEAD(&priv->dsa_8021q_ctx->crosschip_links);
diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h
index 2b003ae9fb38..88cd72dfa4e0 100644
--- a/include/linux/dsa/8021q.h
+++ b/include/linux/dsa/8021q.h
@@ -31,6 +31,8 @@ struct dsa_8021q_context {
 	const struct dsa_8021q_ops *ops;
 	struct dsa_switch *ds;
 	struct list_head crosschip_links;
+	/* EtherType of RX VID, used for filtering on master interface */
+	__be16 proto;
 };
 
 #define DSA_8021Q_N_SUBVLAN			8
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 5baeb0893950..8e3e8a5b8559 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -215,7 +215,8 @@ static int dsa_8021q_setup_port(struct dsa_8021q_context *ctx, int port,
 	int upstream = dsa_upstream_port(ctx->ds, port);
 	u16 rx_vid = dsa_8021q_rx_vid(ctx->ds, port);
 	u16 tx_vid = dsa_8021q_tx_vid(ctx->ds, port);
-	int i, err;
+	struct net_device *master;
+	int i, err, subvlan;
 
 	/* The CPU port is implicitly configured by
 	 * configuring the front-panel ports
@@ -223,6 +224,8 @@ static int dsa_8021q_setup_port(struct dsa_8021q_context *ctx, int port,
 	if (!dsa_is_user_port(ctx->ds, port))
 		return 0;
 
+	master = dsa_to_port(ctx->ds, port)->cpu_dp->master;
+
 	/* Add this user port's RX VID to the membership list of all others
 	 * (including itself). This is so that bridging will not be hindered.
 	 * L2 forwarding rules still take precedence when there are no VLAN
@@ -261,6 +264,19 @@ static int dsa_8021q_setup_port(struct dsa_8021q_context *ctx, int port,
 		return err;
 	}
 
+	/* Add to the master's RX filter not only @rx_vid, but in fact
+	 * the entire subvlan range, just in case this DSA switch might
+	 * want to use sub-VLANs.
+	 */
+	for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) {
+		u16 vid = dsa_8021q_rx_vid_subvlan(ctx->ds, port, subvlan);
+
+		if (enabled)
+			vlan_vid_add(master, ctx->proto, vid);
+		else
+			vlan_vid_del(master, ctx->proto, vid);
+	}
+
 	/* Finally apply the TX VID on this port and on the CPU port */
 	err = dsa_8021q_vid_apply(ctx, port, tx_vid, BRIDGE_VLAN_INFO_UNTAGGED,
 				  enabled);
@@ -285,6 +301,8 @@ int dsa_8021q_setup(struct dsa_8021q_context *ctx, bool enabled)
 {
 	int rc, port;
 
+	ASSERT_RTNL();
+
 	for (port = 0; port < ctx->ds->num_ports; port++) {
 		rc = dsa_8021q_setup_port(ctx, port, enabled);
 		if (rc < 0) {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (7 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too Vladimir Oltean
@ 2020-09-20  1:47 ` Vladimir Oltean
  2020-09-20  2:41   ` Florian Fainelli
  2020-09-20  2:44 ` [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Florian Fainelli
  9 siblings, 1 reply; 20+ messages in thread
From: Vladimir Oltean @ 2020-09-20  1:47 UTC (permalink / raw)
  To: netdev, davem
  Cc: andrew, f.fainelli, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba

Check whether there is any hwaccel VLAN tag on RX, and if there is,
treat it as the tag_8021q header.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 net/dsa/tag_sja1105.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 9b4a4d719291..3710f9daa46d 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -72,14 +72,21 @@ static inline bool sja1105_is_meta_frame(const struct sk_buff *skb)
 static bool sja1105_can_use_vlan_as_tags(const struct sk_buff *skb)
 {
 	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	u16 vlan_tci;
 
 	if (hdr->h_vlan_proto == htons(ETH_P_SJA1105))
 		return true;
 
-	if (hdr->h_vlan_proto != htons(ETH_P_8021Q))
+	if (hdr->h_vlan_proto != htons(ETH_P_8021Q) &&
+	    !skb_vlan_tag_present(skb))
 		return false;
 
-	return vid_is_dsa_8021q(ntohs(hdr->h_vlan_TCI) & VLAN_VID_MASK);
+	if (skb_vlan_tag_present(skb))
+		vlan_tci = skb_vlan_tag_get(skb);
+	else
+		vlan_tci = ntohs(hdr->h_vlan_TCI);
+
+	return vid_is_dsa_8021q(vlan_tci & VLAN_VID_MASK);
 }
 
 /* This is the first time the tagger sees the frame on RX.
@@ -283,7 +290,8 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
 
 	hdr = eth_hdr(skb);
 	tpid = ntohs(hdr->h_proto);
-	is_tagged = (tpid == ETH_P_SJA1105 || tpid == ETH_P_8021Q);
+	is_tagged = (tpid == ETH_P_SJA1105 || tpid == ETH_P_8021Q ||
+		     skb_vlan_tag_present(skb));
 	is_link_local = sja1105_is_link_local(skb);
 	is_meta = sja1105_is_meta_frame(skb);
 
@@ -292,7 +300,12 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
 	if (is_tagged) {
 		/* Normal traffic path. */
 		skb_push_rcsum(skb, ETH_HLEN);
-		__skb_vlan_pop(skb, &tci);
+		if (skb_vlan_tag_present(skb)) {
+			tci = skb_vlan_tag_get(skb);
+			__vlan_hwaccel_clear_tag(skb);
+		} else {
+			__skb_vlan_pop(skb, &tci);
+		}
 		skb_pull_rcsum(skb, ETH_HLEN);
 		skb_reset_network_header(skb);
 		skb_reset_transport_header(skb);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER
  2020-09-20  1:47 ` [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  2:33   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:33 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> There doesn't seem to be any strong technical reason for doing it this
> way, but we'll be adding more checks for invalid upper device
> configurations, and it will be easier to have them all grouped under
> PRECHANGEUPPER.
> 
> Tested that it still works:
> ip link set br0 type bridge vlan_filtering 1
> ip link add link swp2 name swp2.100 type vlan id 100
> ip link set swp2.100 master br0
> [   20.321312] br0: port 5(swp2.100) entered blocking state
> [   20.326711] br0: port 5(swp2.100) entered disabled state
> Error: dsa_core: Cannot enslave VLAN device into VLAN aware bridge.
> [   20.346549] br0: port 5(swp2.100) entered blocking state
> [   20.351957] br0: port 5(swp2.100) entered disabled state
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive
  2020-09-20  1:47 ` [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive Vladimir Oltean
@ 2020-09-20  2:33   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:33 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> We'll be adding a new check in the PRECHANGEUPPER notifier, where we'll
> need to check some VLAN uppers. It is hard to do that when there is
> already a function named dsa_slave_upper_vlan_check. So rename this one.
> 
> Not to mention that this function probably shouldn't have started with
> "dsa_slave_" in the first place, since the struct net_device argument
> isn't a DSA slave, but an 8021q upper of one.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER
  2020-09-20  1:47 ` [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  2:34   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:34 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> DSA tries to prevent having a VLAN added by a bridge and by an 802.1Q
> upper at the same time. It does that by checking the VID in
> .ndo_vlan_rx_add_vid(), since that's something that the 8021q module
> calls, via vlan_vid_add(). When a VLAN matches in both subsystems, this
> check returns -EBUSY.
> 
> However the vlan_vid_add() function isn't specific to the 8021q module
> in any way at all. It is simply the kernel's way to tell an interface to
> add a VLAN to its RX filter and not drop that VLAN. So there's no reason
> to return -EBUSY when somebody tries to call vlan_vid_add() for a VLAN
> that was installed by the bridge. The proper behavior is to accept that
> configuration.
> 
> So what's wrong is how DSA checks that it has an 8021q upper. It should
> look at the actual uppers for that, not just assume that the 8021q
> module was somewhere in the call stack of .ndo_vlan_rx_add_vid().
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER
  2020-09-20  1:47 ` [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER Vladimir Oltean
@ 2020-09-20  2:37   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:37 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> This is checking for the following order of operations, and makes sure
> to deny that configuration:
> 
> ip link add link swp2 name swp2.100 type vlan id 100
> ip link add br0 type bridge vlan_filtering 1
> ip link set swp2 master br0
> bridge vlan add dev swp2 vid 100
> 
> Instead of using vlan_for_each(), which looks at the VLAN filters
> installed with vlan_vid_add(), just track the 8021q uppers. This has the
> advantage of freeing up the vlan_vid_add() call for actual VLAN
> filtering.
> 
> There is another change in this patch. The check is moved in slave.c,
> from switch.c. I don't think it makes sense to have this 8021q upper
> check for each switch port that gets notified of that VLAN addition
> (these include DSA links and CPU ports, we know those can't have 8021q
> uppers because they don't have a net_device registered for them), so
> just do it in slave.c, for that one slave interface.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>   net/dsa/slave.c  | 33 +++++++++++++++++++++++++++++++++
>   net/dsa/switch.c | 41 -----------------------------------------
>   2 files changed, 33 insertions(+), 41 deletions(-)
> 
> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> index 1940c2458f0f..b88a31a79e2f 100644
> --- a/net/dsa/slave.c
> +++ b/net/dsa/slave.c
> @@ -303,6 +303,28 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
>   	return ret;
>   }
>   
> +/* Must be called under rcu_read_lock() */
> +static int
> +dsa_slave_vlan_check_for_8021q_uppers(struct net_device *slave,
> +				      const struct switchdev_obj_port_vlan *vlan)
> +{
> +	struct net_device *upper_dev;
> +	struct list_head *iter;
> +
> +	netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) {
> +		u16 vid;
> +
> +		if (!is_vlan_dev(upper_dev))
> +			continue;
> +
> +		vid = vlan_dev_vlan_id(upper_dev);
> +		if (vlan->vid_begin <= vid && vlan->vid_end >= vid)
> +			return -EBUSY;

I would find:
		if (vid >= vlan->vid_begin && vid <= vlan->vid_end)

more natural but this works too.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering()
  2020-09-20  1:47 ` [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering() Vladimir Oltean
@ 2020-09-20  2:38   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:38 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> The current logic beats me a little bit. The comment that "bridge skips
> -EOPNOTSUPP, so skip the prepare phase" was introduced in commit
> fb2dabad69f0 ("net: dsa: support VLAN filtering switchdev attr").
> 
> I'm not sure:
> (a) ok, the bridge skips -EOPNOTSUPP, but, so what, where are we
>      returning -EOPNOTSUPP?
> (b) even if we are, and I'm just not seeing it, what is the causality
>      relationship between the bridge skipping -EOPNOTSUPP and DSA
>      skipping the prepare phase, and just returning zero?
> 
> One thing is certain beyond doubt though, and that is that DSA currently
> refuses VLAN filtering from the "commit" phase instead of "prepare", and
> that this is not a good thing:
> 
> ip link add br0 type bridge
> ip link add br1 type bridge vlan_filtering 1
> ip link set swp2 master br0
> ip link set swp3 master br1
> [ 3790.379389] 001: sja1105 spi0.1: VLAN filtering is a global setting
> [ 3790.379399] 001: ------------[ cut here ]------------
> [ 3790.379403] 001: WARNING: CPU: 1 PID: 515 at net/switchdev/switchdev.c:157 switchdev_port_attr_set_now+0x9c/0xa4
> [ 3790.379420] 001: swp3: Commit of attribute (id=6) failed.
> [ 3790.379533] 001: [<c11ff588>] (switchdev_port_attr_set_now) from [<c11b62e4>] (nbp_vlan_init+0x84/0x148)
> [ 3790.379544] 001: [<c11b62e4>] (nbp_vlan_init) from [<c11a2ff0>] (br_add_if+0x514/0x670)
> [ 3790.379554] 001: [<c11a2ff0>] (br_add_if) from [<c1031b5c>] (do_setlink+0x38c/0xab0)
> [ 3790.379565] 001: [<c1031b5c>] (do_setlink) from [<c1036fe8>] (__rtnl_newlink+0x44c/0x748)
> [ 3790.379573] 001: [<c1036fe8>] (__rtnl_newlink) from [<c1037328>] (rtnl_newlink+0x44/0x60)
> [ 3790.379580] 001: [<c1037328>] (rtnl_newlink) from [<c10315fc>] (rtnetlink_rcv_msg+0x124/0x2f8)
> [ 3790.379590] 001: [<c10315fc>] (rtnetlink_rcv_msg) from [<c10926b8>] (netlink_rcv_skb+0xb8/0x110)
> [ 3790.379806] 001: ---[ end trace 0000000000000002 ]---
> [ 3790.379819] 001: sja1105 spi0.1 swp3: failed to initialize vlan filtering on this port
> 
> So move the current logic that may fail (except ds->ops->port_vlan_filtering,
> that is way harder) into the prepare stage of the switchdev transaction.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0
  2020-09-20  1:47 ` [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0 Vladimir Oltean
@ 2020-09-20  2:40   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:40 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> When the bridge has VLAN awareness disabled there isn't any duplication
> of functionality, since the bridge does not process VLAN. Don't deny
> adding 8021q uppers to DSA switch ports in that case. The switch is
> supposed to simply pass traffic leaving the VLAN tag as-is, and the
> stack will happily strip the VLAN tag for all 8021q uppers that exist.
> 
> We need to ensure that there are no 8021q uppers when the user attempts
> to enable bridge vlan_filtering.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags
  2020-09-20  1:47 ` [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags Vladimir Oltean
@ 2020-09-20  2:41   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:41 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> Check whether there is any hwaccel VLAN tag on RX, and if there is,
> treat it as the tag_8021q header.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too
  2020-09-20  1:47 ` [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too Vladimir Oltean
@ 2020-09-20  2:43   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:43 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> 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>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too
  2020-09-20  1:47 ` [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too Vladimir Oltean
@ 2020-09-20  2:44   ` Florian Fainelli
  0 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:44 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> The whole purpose of tag_8021q is to send VLAN-tagged traffic to the
> CPU, from which the driver can decode the source port and switch id.
> 
> Currently this only works if the VLAN filtering on the master is
> disabled. Change that by explicitly adding code to tag_8021q.c to add
> the VLANs corresponding to the tags to the filter of the master
> interface.
> 
> Because we now need to call vlan_vid_add, then we also need to hold the
> RTNL mutex. Propagate that requirement to the callers of dsa_8021q_setup
> and modify the existing call sites as appropriate. Note that one call
> path, sja1105_best_effort_vlan_filtering_set -> sja1105_vlan_filtering
> -> sja1105_setup_8021q_tagging, was already holding this lock.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters
  2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
                   ` (8 preceding siblings ...)
  2020-09-20  1:47 ` [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags Vladimir Oltean
@ 2020-09-20  2:44 ` Florian Fainelli
  9 siblings, 0 replies; 20+ messages in thread
From: Florian Fainelli @ 2020-09-20  2:44 UTC (permalink / raw)
  To: Vladimir Oltean, netdev, davem
  Cc: andrew, vivien.didelot, idosch, jiri, kurt.kanzenbach, kuba



On 9/19/2020 6:47 PM, Vladimir Oltean wrote:
> This series attempts to make DSA VLANs work in the presence of a master
> interface that is:
> - filtering, so it drops VLANs that aren't explicitly added to its
>    filter list
> - offloading, so the old assumptions in the tagging code about there
>    being a VLAN tag in the skb are not necessarily true anymore.
> 
> For more context:
> https://lore.kernel.org/netdev/20200910150738.mwhh2i6j2qgacqev@skbuf/
> 
> This probably marks the beginning of a series of patches in which DSA
> starts paying much more attention to its upper interfaces, not only for
> VLAN purposes but also for address filtering and for management of the
> CPU flooding domain. There was a comment from Florian on whether we
> could factor some of the mlxsw logic into some common functionality, but
> it doesn't look so. This seems bound to be open-coded, but frankly there
> isn't a lot to it.

This looks really good to me, thanks!

> 
> Vladimir Oltean (9):
>    net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from
>      PRECHANGEUPPER
>    net: dsa: rename dsa_slave_upper_vlan_check to something more
>      suggestive
>    net: dsa: convert check for 802.1Q upper when bridged into
>      PRECHANGEUPPER
>    net: dsa: convert denying bridge VLAN with existing 8021q upper to
>      PRECHANGEUPPER
>    net: dsa: refuse configuration in prepare phase of
>      dsa_port_vlan_filtering()
>    net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0
>    net: dsa: install VLANs into the master's RX filter too
>    net: dsa: tag_8021q: add VLANs to the master interface too
>    net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags
> 
>   drivers/net/dsa/sja1105/sja1105_main.c |   7 +-
>   include/linux/dsa/8021q.h              |   2 +
>   net/dsa/port.c                         |  58 +++++++--
>   net/dsa/slave.c                        | 156 ++++++++++++++++++-------
>   net/dsa/switch.c                       |  41 -------
>   net/dsa/tag_8021q.c                    |  20 +++-
>   net/dsa/tag_sja1105.c                  |  21 +++-
>   7 files changed, 206 insertions(+), 99 deletions(-)
> 

-- 
Florian

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2020-09-20  2:44 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-20  1:47 [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Vladimir Oltean
2020-09-20  1:47 ` [RFC PATCH 1/9] net: dsa: deny enslaving 802.1Q upper to VLAN-aware bridge from PRECHANGEUPPER Vladimir Oltean
2020-09-20  2:33   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 2/9] net: dsa: rename dsa_slave_upper_vlan_check to something more suggestive Vladimir Oltean
2020-09-20  2:33   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 3/9] net: dsa: convert check for 802.1Q upper when bridged into PRECHANGEUPPER Vladimir Oltean
2020-09-20  2:34   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 4/9] net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER Vladimir Oltean
2020-09-20  2:37   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 5/9] net: dsa: refuse configuration in prepare phase of dsa_port_vlan_filtering() Vladimir Oltean
2020-09-20  2:38   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 6/9] net: dsa: allow 8021q uppers while the bridge has vlan_filtering=0 Vladimir Oltean
2020-09-20  2:40   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 7/9] net: dsa: install VLANs into the master's RX filter too Vladimir Oltean
2020-09-20  2:43   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 8/9] net: dsa: tag_8021q: add VLANs to the master interface too Vladimir Oltean
2020-09-20  2:44   ` Florian Fainelli
2020-09-20  1:47 ` [RFC PATCH 9/9] net: dsa: tag_sja1105: add compatibility with hwaccel VLAN tags Vladimir Oltean
2020-09-20  2:41   ` Florian Fainelli
2020-09-20  2:44 ` [RFC PATCH 0/9] DSA with VLAN filtering and offloading masters Florian Fainelli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.