From: Vivien Didelot <hidden> Date: 2017-06-07 22:14:32
The current code in DSA does not support cross-chip VLAN. This means
that in a multi-chip environment such as this one (similar to ZII Rev B)
[CPU].................... (mdio)
(eth0) | : : :
_|_____ _______ _______
[__sw0__]--[__sw1__]--[__sw2__]
| | | | | | | | |
v v v v v v v v v
p1 p2 p3 p4 p5 p6 p7 p8 p9
adding a VLAN to p9 won't be enough to reach the CPU, until at least one
port of sw0 and sw1 join the VLAN as well and become aware of the VID.
This patchset makes the DSA core program the VLAN on the CPU and DSA
links itself, which brings seamlessly cross-chip VLAN support to DSA.
With this series applied*, the hardware VLAN tables of a 3-switch setup
look like this after adding a VLAN to only one port of the end switch:
# cat /sys/class/net/br0/bridge/default_pvid
42
# cat /sys/kernel/debug/mv88e6xxx/sw{0,1,2}/vtu
# ip link set up master br0 dev lan6
# cat /sys/kernel/debug/mv88e6xxx/sw{0,1,2}/vtu
VID FID SID 0 1 2 3 4 5 6
42 1 0 x x x x x = =
VID FID SID 0 1 2 3 4 5 6
42 1 0 x x x x x = =
VID FID SID 0 1 2 3 4 5 6 7 8 9
42 1 0 u x x x x x x x x =
('x' is excluded, 'u' is untagged, '=' is unmodified DSA and CPU ports.)
Completely removing a VLAN entry (which is currently the responsibility
of drivers anyway) is not supported yet since it requires some caching.
(*) the output is shown from this out-of-tree debugfs patch:
https://github.com/vivien/linux/commit/7b61a684b9d6b6a499135a587c7f62a1fddceb8b.patch
Changes in v2:
- canonical incrementation (port++ instead of ++port)
- check CPU and DSA ports before purging a VLAN
- add Reviewed-by tags
Vivien Didelot (5):
net: dsa: mv88e6xxx: define membership on VLAN add
net: dsa: check VLAN capability of every switch
net: dsa: add CPU and DSA ports as VLAN members
net: dsa: mv88e6xxx: exclude all ports in new VLAN
net: dsa: mv88e6xxx: do not skip ports on VLAN del
drivers/net/dsa/mv88e6xxx/chip.c | 27 ++++++++++++++-------------
net/dsa/switch.c | 30 ++++++++++++++++++++----------
2 files changed, 34 insertions(+), 23 deletions(-)
--
2.13.1
From: Vivien Didelot <hidden> Date: 2017-06-07 22:14:34
Define the target port membership of the VLAN entry in
mv88e6xxx_port_vlan_add where ds is scoped.
Allow the DSA core to call later the port_vlan_add operation for CPU or
DSA ports, by using the Unmodified membership for these ports, as in the
current behavior.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <redacted>
---
drivers/net/dsa/mv88e6xxx/chip.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
From: Vivien Didelot <hidden> Date: 2017-06-07 22:14:35
In a multi-chip switch fabric, it is currently the responsibility of the
driver to add the CPU or DSA (interconnecting chips together) ports as
members of a new VLAN entry. This makes the drivers more complicated.
We want the DSA drivers to be stupid and the DSA core being the one
responsible for caring about the abstracted switch logic and topology.
Make the DSA core program the CPU and DSA ports as part of the VLAN.
This makes all chips of the data path to be aware of VIDs spanning the
the whole fabric and thus, seamlessly add support for cross-chip VLAN.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <redacted>
---
net/dsa/switch.c | 3 +++
1 file changed, 3 insertions(+)
From: Vivien Didelot <hidden> Date: 2017-06-07 22:14:37
Now that the VLAN object is propagated to every switch chip of the
switch fabric, we can easily ensure that they all support the required
VLAN operations before modifying an entry on a single switch.
To achieve that, remove the condition skipping other target switches,
and add a bitmap of VLAN members, eventually containing the target port,
if we are programming the switch target.
This will allow us to easily add other VLAN members, such as the DSA or
CPU ports (to introduce cross-chip VLAN support) or the other port
members if we want to reduce hardware accesses later.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <redacted>
---
net/dsa/switch.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
@@ -159,19 +159,27 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,{conststructswitchdev_obj_port_vlan*vlan=info->vlan;structswitchdev_trans*trans=info->trans;+DECLARE_BITMAP(members,ds->num_ports);+intport,err;-/* Do not care yet about other switch chips of the fabric */-if(ds->index!=info->sw_index)-return0;+/* Build a mask of VLAN members */+bitmap_zero(members,ds->num_ports);+if(ds->index==info->sw_index)+set_bit(info->port,members);if(switchdev_trans_ph_prepare(trans)){if(!ds->ops->port_vlan_prepare||!ds->ops->port_vlan_add)return-EOPNOTSUPP;-returnds->ops->port_vlan_prepare(ds,info->port,vlan,trans);+for_each_set_bit(port,members,ds->num_ports){+err=ds->ops->port_vlan_prepare(ds,port,vlan,trans);+if(err)+returnerr;+}}-ds->ops->port_vlan_add(ds,info->port,vlan,trans);+for_each_set_bit(port,members,ds->num_ports)+ds->ops->port_vlan_add(ds,port,vlan,trans);return0;}
@@ -181,14 +189,13 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds,{conststructswitchdev_obj_port_vlan*vlan=info->vlan;-/* Do not care yet about other switch chips of the fabric */-if(ds->index!=info->sw_index)-return0;-if(!ds->ops->port_vlan_del)return-EOPNOTSUPP;-returnds->ops->port_vlan_del(ds,info->port,vlan);+if(ds->index==info->sw_index)+returnds->ops->port_vlan_del(ds,info->port,vlan);++return0;}staticintdsa_switch_event(structnotifier_block*nb,
From: Vivien Didelot <hidden> Date: 2017-06-07 22:14:39
The mv88e6xxx driver currently tries to be smart and remove by itself a
VLAN entry from the VTU when the driven switch sees no user ports as
members of the VLAN.
This is bad in a multi-chip switch fabric, since a chip in between
others may have no bridge port members, but still needs to be aware of
the VID in order to correctly pass frames in the data path.
Now that the DSA core explicitly manages DSA and CPU ports, do not skip
them when checking remaining VLAN members.
Signed-off-by: Vivien Didelot <redacted>
---
drivers/net/dsa/mv88e6xxx/chip.c | 4 ----
1 file changed, 4 deletions(-)
@@ -1342,9 +1341,6 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,/* keep the VLAN unless all ports are excluded */vlan.valid=false;for(i=0;i<mv88e6xxx_num_ports(chip);++i){-if(dsa_is_cpu_port(ds,i)||dsa_is_dsa_port(ds,i))-continue;-if(vlan.member[i]!=GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER){vlan.valid=true;break;
From: Vivien Didelot <hidden> Date: 2017-06-07 22:15:49
Now that the DSA core adds the CPU and DSA ports itself to the new VLAN
entry, there is no need to include them as members of this VLAN when
initializing a new VTU entry.
As of now, initialize a new VTU entry with all ports excluded.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <redacted>
---
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
@@ -1159,11 +1159,10 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,entry->valid=true;entry->vid=vid;-/* Include only CPU and DSA ports */+/* Exclude all ports */for(i=0;i<mv88e6xxx_num_ports(chip);++i)-entry->member[i]=dsa_is_normal_port(chip->ds,i)?-GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER:-GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;+entry->member[i]=+GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;returnmv88e6xxx_atu_new(chip,&entry->fid);}
From: David Miller <davem@davemloft.net> Date: 2017-06-08 15:44:12
From: Vivien Didelot <redacted>
Date: Wed, 7 Jun 2017 18:12:12 -0400
The current code in DSA does not support cross-chip VLAN. This means
that in a multi-chip environment such as this one (similar to ZII Rev B)
...
adding a VLAN to p9 won't be enough to reach the CPU, until at least one
port of sw0 and sw1 join the VLAN as well and become aware of the VID.
This patchset makes the DSA core program the VLAN on the CPU and DSA
links itself, which brings seamlessly cross-chip VLAN support to DSA.
With this series applied*, the hardware VLAN tables of a 3-switch setup
look like this after adding a VLAN to only one port of the end switch:
...
Completely removing a VLAN entry (which is currently the responsibility
of drivers anyway) is not supported yet since it requires some caching.
(*) the output is shown from this out-of-tree debugfs patch:
https://github.com/vivien/linux/commit/7b61a684b9d6b6a499135a587c7f62a1fddceb8b.patch
Changes in v2:
- canonical incrementation (port++ instead of ++port)
- check CPU and DSA ports before purging a VLAN
- add Reviewed-by tags