• V
    net: mscc: ocelot: don't add VID 0 to ocelot->vlans when leaving VLAN-aware bridge · 1fcb8fb3
    Vladimir Oltean 提交于
    DSA, through dsa_port_bridge_leave(), first notifies the port of the
    fact that it left a bridge, then, if that bridge was VLAN-aware, it
    notifies the port of the change in VLAN awareness state, towards
    VLAN-unaware mode.
    
    So ocelot_port_vlan_filtering() can be called when ocelot_port->bridge
    is NULL, and this makes ocelot_add_vlan_unaware_pvid() create a struct
    ocelot_bridge_vlan with a vid of 0 and an "untagged" setting of true on
    that port.
    
    In a way this structure correctly reflects the reality, but by design,
    VID 0 (OCELOT_STANDALONE_PVID) was not meant to be kept in the bridge
    VLAN list of the driver, but managed separately.
    
    Having OCELOT_STANDALONE_PVID in ocelot->vlans makes us trip up on
    several sanity checks that did not expect to have this VID there.
    For example, after we leave a VLAN-aware bridge and we re-join it, we
    can no longer program egress-tagged VLANs to hardware:
    
     # ip link add br0 type bridge vlan_filtering 1 && ip link set br0 up
     # ip link set swp0 master br0
     # ip link set swp0 nomaster
     # ip link set swp0 master br0
     # bridge vlan add dev swp0 vid 100
    Error: mscc_ocelot_switch_lib: Port with more than one egress-untagged VLAN cannot have egress-tagged VLANs.
    
    But this configuration is in fact supported by the hardware, since we
    could use OCELOT_PORT_TAG_NATIVE. According to its comment:
    
    /* all VLANs except the native VLAN and VID 0 are egress-tagged */
    
    yet when assessing the eligibility for this mode, we do not check for
    VID 0 in ocelot_port_uses_native_vlan(), instead we just ensure that
    ocelot_port_num_untagged_vlans() == 1. This is simply because VID 0
    doesn't have a bridge VLAN structure.
    
    The way I identify the problem is that ocelot_port_vlan_filtering(false)
    only means to call ocelot_add_vlan_unaware_pvid() when we dynamically
    turn off VLAN awareness for a bridge we are under, and the PVID changes
    from the bridge PVID to a reserved PVID based on the bridge number.
    
    Since OCELOT_STANDALONE_PVID is statically added to the VLAN table
    during ocelot_vlan_init() and never removed afterwards, calling
    ocelot_add_vlan_unaware_pvid() for it is not intended and does not serve
    any purpose.
    
    Fix the issue by avoiding the call to ocelot_add_vlan_unaware_pvid(vid=0)
    when we're resetting VLAN awareness after leaving the bridge, to become
    a standalone port.
    
    Fixes: 54c31984 ("net: mscc: ocelot: enforce FDB isolation when VLAN-unaware")
    Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    1fcb8fb3
ocelot.c 89.1 KB