mbox series

[net,00/14] VLAN fixes for Ocelot driver

Message ID 20240815000707.2006121-1-vladimir.oltean@nxp.com
Headers show
Series VLAN fixes for Ocelot driver | expand

Message

Vladimir Oltean Aug. 15, 2024, 12:06 a.m. UTC
This is a collection of patches I've gathered over the past several
months.

Patches 1-6/14 are supporting patches for selftests.

Patch 9/14 fixes PTP TX from a VLAN upper of a VLAN-aware bridge port
when using the "ocelot-8021q" tagging protocol. Patch 7/14 is its
supporting selftest.

Patch 10/14 fixes the QoS class used by PTP in the same case as above.
It is hard to quantify - there is no selftest.

Patch 11/14 fixes potential data corruption during PTP TX in the same
case as above. Again, there is no selftest.

Patch 13/14 fixes RX in the same case as above - 8021q upper of a
VLAN-aware bridge port, with the "ocelot-8021q" tagging protocol. Patch
12/14 is a supporting patch for this in the DSA core, and 7/14 is also
its selftest.

Patch 14/14 ensures that VLAN-aware bridges offloaded to Ocelot only
react to the ETH_P_8021Q TPID, and treat absolutely everything else as
VLAN-untagged, including ETH_P_8021AD. Patch 8/14 is the supporting
selftest.

Vladimir Oltean (14):
  selftests: net: local_termination: refactor macvlan creation/deletion
  selftests: net: local_termination: parameterize sending interface
  selftests: net: local_termination: parameterize test name
  selftests: net: local_termination: add one more test for VLAN-aware
    bridges
  selftests: net: local_termination: introduce new tests which capture
    VLAN behavior
  selftests: net: local_termination: don't use xfail_on_veth()
  selftests: net: local_termination: add PTP frames to the mix
  selftests: net: bridge_vlan_aware: test that other TPIDs are seen as
    untagged
  net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and
    register injection
  net: mscc: ocelot: fix QoS class for injected packets with
    "ocelot-8021q"
  net: mscc: ocelot: serialize access to the injection/extraction groups
  net: dsa: provide a software untagging function on RX for VLAN-aware
    bridges
  net: dsa: felix: fix VLAN tag loss on CPU reception with ocelot-8021q
  net: mscc: ocelot: treat 802.1ad tagged traffic as 802.1Q-untagged

 drivers/net/dsa/ocelot/felix.c                | 126 ++++-
 drivers/net/ethernet/mscc/ocelot.c            | 279 +++++++++++-
 drivers/net/ethernet/mscc/ocelot_fdma.c       |   3 +-
 drivers/net/ethernet/mscc/ocelot_vcap.c       |   1 +
 drivers/net/ethernet/mscc/ocelot_vsc7514.c    |   4 +
 include/linux/dsa/ocelot.h                    |  47 ++
 include/net/dsa.h                             |  16 +-
 include/soc/mscc/ocelot.h                     |  12 +-
 include/soc/mscc/ocelot_vcap.h                |   2 +
 net/dsa/tag.c                                 |   5 +-
 net/dsa/tag.h                                 | 135 ++++--
 net/dsa/tag_ocelot.c                          |  37 +-
 .../net/forwarding/bridge_vlan_aware.sh       |  54 ++-
 tools/testing/selftests/net/forwarding/lib.sh |  57 +++
 .../net/forwarding/local_termination.sh       | 431 +++++++++++++++---
 15 files changed, 1036 insertions(+), 173 deletions(-)

Comments

Vladimir Oltean Aug. 15, 2024, 12:07 a.m. UTC | #1
There is a major design bug with ocelot-8021q, which is that it expects
more of the hardware than the hardware can actually do. The short
summary of the issue is that when a port is under a VLAN-aware bridge
and we use this tagging protocol, VLAN upper interfaces of this port do
not see RX traffic.

We use VCAP ES0 (egress rewriter) rules towards the tag_8021q CPU port
to encapsulate packets with an outer tag, later stripped by software,
that depends on the source user port. We do this so that packets can be
identified in ocelot_rcv(). To be precise, we create rules with
push_outer_tag = OCELOT_ES0_TAG and push_inner_tag = 0.

With this configuration, we expect the switch to keep the inner tag
configuration as found in the packet (if it was untagged on user port
ingress, keep it untagged, otherwise preserve the VLAN tag unmodified
as the inner tag towards the tag_8021q CPU port). But this is not what
happens.

Instead, table "Tagging Combinations" from the user manual suggests
that when the ES0 action is "PUSH_OUTER_TAG=1 and PUSH_INNER_TAG=0",
there will be "no inner tag". Experimentation further clarifies what
this means.

It appears that this "inner tag" which is not pushed into the packet on
its egress towards the CPU is none other than the classified VLAN.

When the ingress user port is standalone or under a VLAN-unaware bridge,
the classified VLAN is a discardable quantity: it is a fixed value - the
result of ocelot_vlan_unaware_pvid()'s configuration, and actually
independent of the VID from any 802.1Q header that may be in the frame.
It is actually preferable to discard the "inner tag" in this case.

The problem is when the ingress port is under a VLAN-aware bridge.
Then, the classified VLAN is taken from the frame's 802.1Q header, with
a fallback on the bridge port's PVID. It would be very good to not
discard the "inner tag" here, because if we do, we break communication
with any 8021q VLAN uppers that the port might have. These have a
processing path outside the bridge.

There seems to be nothing else we can do except to change the
configuration for VCAP ES0 rules, to actually push the inner VLAN into
the frame. There are 2 options for that, first is to push a fixed value
specified in the rule, and second is to push a fixed value, plus
(aka arithmetic +) the classified VLAN. We choose the second option,
and we select that fixed value as 0. Thus, what is pushed in the inner
tag is just the classified VLAN.