• Vladimir Oltean's avatar
    net: dsa: felix: fix VLAN tag loss on CPU reception with ocelot-8021q · f1288fd7
    Vladimir Oltean authored
    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.
    
    From there, we need to perform software untagging, in the receive path,
    of stuff that was untagged on the wire.
    
    Fixes: 7c83a7c5 ("net: dsa: add a second tagger for Ocelot switches based on tag_8021q")
    Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    f1288fd7
felix.c 64 KB