• Vladimir Oltean's avatar
    net: mscc: ocelot: fix tagged VLAN refusal while under a VLAN-unaware bridge · 276d37eb
    Vladimir Oltean authored
    Currently the following set of commands fails:
    
    $ ip link add br0 type bridge # vlan_filtering 0
    $ ip link set swp0 master br0
    $ bridge vlan
    port              vlan-id
    swp0              1 PVID Egress Untagged
    $ bridge vlan add dev swp0 vid 10
    Error: mscc_ocelot_switch_lib: Port with more than one egress-untagged VLAN cannot have egress-tagged VLANs.
    
    Dumping ocelot->vlans, one can see that the 2 egress-untagged VLANs on swp0 are
    vid 1 (the bridge PVID) and vid 4094, a PVID used privately by the driver for
    VLAN-unaware bridging. So this is why bridge vid 10 is refused, despite
    'bridge vlan' showing a single egress untagged VLAN.
    
    As mentioned in the comment added, having this private VLAN does not impose
    restrictions to the hardware configuration, yet it is a bookkeeping problem.
    
    There are 2 possible solutions.
    
    One is to make the functions that operate on VLAN-unaware pvids:
    - ocelot_add_vlan_unaware_pvid()
    - ocelot_del_vlan_unaware_pvid()
    - ocelot_port_setup_dsa_8021q_cpu()
    - ocelot_port_teardown_dsa_8021q_cpu()
    call something different than ocelot_vlan_member_(add|del)(), the latter being
    the real problem, because it allocates a struct ocelot_bridge_vlan *vlan which
    it adds to ocelot->vlans. We don't really *need* the private VLANs in
    ocelot->vlans, it's just that we have the extra convenience of having the
    vlan->portmask cached in software (whereas without these structures, we'd have
    to create a raw ocelot_vlant_rmw_mask() procedure which reads back the current
    port mask from hardware).
    
    The other solution is to filter out the private VLANs from
    ocelot_port_num_untagged_vlans(), since they aren't what callers care about.
    We only need to do this to the mentioned function and not to
    ocelot_port_num_tagged_vlans(), because private VLANs are never egress-tagged.
    
    Nothing else seems to be broken in either solution, but the first one requires
    more rework which will conflict with the net-next change  36a0bf44 ("net:
    mscc: ocelot: set up tag_8021q CPU ports independent of user port affinity"),
    and I'd like to avoid that. So go with the other one.
    
    Fixes: 54c31984 ("net: mscc: ocelot: enforce FDB isolation when VLAN-unaware")
    Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
    Link: https://lore.kernel.org/r/20220927122042.1100231-1-vladimir.oltean@nxp.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    276d37eb
ocelot.c 92.3 KB