lkml.org 
[lkml]   [2021]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 135/223] net: dsa: sja1105: make VID 4095 a bridge VLAN too
    Date
    From: Vladimir Oltean <vladimir.oltean@nxp.com>

    [ Upstream commit e40cba9490bab1414d45c2d62defc0ad4f6e4136 ]

    This simple series of commands:

    ip link add br0 type bridge vlan_filtering 1
    ip link set swp0 master br0

    fails on sja1105 with the following error:
    [ 33.439103] sja1105 spi0.1: vlan-lookup-table needs to have at least the default untagged VLAN
    [ 33.447710] sja1105 spi0.1: Invalid config, cannot upload
    Warning: sja1105: Failed to change VLAN Ethertype.

    For context, sja1105 has 3 operating modes:
    - SJA1105_VLAN_UNAWARE: the dsa_8021q_vlans are committed to hardware
    - SJA1105_VLAN_FILTERING_FULL: the bridge_vlans are committed to hardware
    - SJA1105_VLAN_FILTERING_BEST_EFFORT: both the dsa_8021q_vlans and the
    bridge_vlans are committed to hardware

    Swapping out a VLAN list and another in happens in
    sja1105_build_vlan_table(), which performs a delta update procedure.
    That function is called from a few places, notably from
    sja1105_vlan_filtering() which is called from the
    SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING handler.

    The above set of 2 commands fails when run on a kernel pre-commit
    8841f6e63f2c ("net: dsa: sja1105: make devlink property
    best_effort_vlan_filtering true by default"). So the priv->vlan_state
    transition that takes place is between VLAN-unaware and full VLAN
    filtering. So the dsa_8021q_vlans are swapped out and the bridge_vlans
    are swapped in.

    So why does it fail?

    Well, the bridge driver, through nbp_vlan_init(), first sets up the
    SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING attribute, and only then
    proceeds to call nbp_vlan_add for the default_pvid.

    So when we swap out the dsa_8021q_vlans and swap in the bridge_vlans in
    the SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING handler, there are no bridge
    VLANs (yet). So we have wiped the VLAN table clean, and the low-level
    static config checker complains of an invalid configuration. We _will_
    add the bridge VLANs using the dynamic config interface, albeit later,
    when nbp_vlan_add() calls us. So it is natural that it fails.

    So why did it ever work?

    Surprisingly, it looks like I only tested this configuration with 2
    things set up in a particular way:
    - a network manager that brings all ports up
    - a kernel with CONFIG_VLAN_8021Q=y

    It is widely known that commit ad1afb003939 ("vlan_dev: VLAN 0 should be
    treated as "no vlan tag" (802.1p packet)") installs VID 0 to every net
    device that comes up. DSA treats these VLANs as bridge VLANs, and
    therefore, in my testing, the list of bridge_vlans was never empty.

    However, if CONFIG_VLAN_8021Q is not enabled, or the port is not up when
    it joins a VLAN-aware bridge, the bridge_vlans list will be temporarily
    empty, and the sja1105_static_config_reload() call from
    sja1105_vlan_filtering() will fail.

    To fix this, the simplest thing is to keep VID 4095, the one used for
    CPU-injected control packets since commit ed040abca4c1 ("net: dsa:
    sja1105: use 4095 as the private VLAN for untagged traffic"), in the
    list of bridge VLANs too, not just the list of tag_8021q VLANs. This
    ensures that the list of bridge VLANs will never be empty.

    Fixes: ec5ae61076d0 ("net: dsa: sja1105: save/restore VLANs using a delta commit method")
    Reported-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
    Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/dsa/sja1105/sja1105_main.c | 6 ++++++
    1 file changed, 6 insertions(+)

    diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
    index ebe4d33cda27..6e5dbe9f3892 100644
    --- a/drivers/net/dsa/sja1105/sja1105_main.c
    +++ b/drivers/net/dsa/sja1105/sja1105_main.c
    @@ -378,6 +378,12 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
    if (dsa_is_cpu_port(ds, port))
    v->pvid = true;
    list_add(&v->list, &priv->dsa_8021q_vlans);
    +
    + v = kmemdup(v, sizeof(*v), GFP_KERNEL);
    + if (!v)
    + return -ENOMEM;
    +
    + list_add(&v->list, &priv->bridge_vlans);
    }

    ((struct sja1105_vlan_lookup_entry *)table->entries)[0] = pvid;
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-26 18:33    [W:5.238 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site