1. 09 8月, 2021 1 次提交
    • V
      net: dsa: centralize fast ageing when address learning is turned off · 045c45d1
      Vladimir Oltean 提交于
      Currently DSA leaves it down to device drivers to fast age the FDB on a
      port when address learning is disabled on it. There are 2 reasons for
      doing that in the first place:
      
      - when address learning is disabled by user space, through
        IFLA_BRPORT_LEARNING or the brport_attr_learning sysfs, what user
        space typically wants to achieve is to operate in a mode with no
        dynamic FDB entry on that port. But if the port is already up, some
        addresses might have been already learned on it, and it seems silly to
        wait for 5 minutes for them to expire until something useful can be
        done.
      
      - when a port leaves a bridge and becomes standalone, DSA turns off
        address learning on it. This also has the nice side effect of flushing
        the dynamically learned bridge FDB entries on it, which is a good idea
        because standalone ports should not have bridge FDB entries on them.
      
      We let drivers manage fast ageing under this condition because if DSA
      were to do it, it would need to track each port's learning state, and
      act upon the transition, which it currently doesn't.
      
      But there are 2 reasons why doing it is better after all:
      
      - drivers might get it wrong and not do it (see b53_port_set_learning)
      
      - we would like to flush the dynamic entries from the software bridge
        too, and letting drivers do that would be another pain point
      
      So track the port learning state and trigger a fast age process
      automatically within DSA.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      045c45d1
  2. 06 8月, 2021 3 次提交
    • D
      net: dsa: mt7530: drop untagged frames on VLAN-aware ports without PVID · 8fbebef8
      DENG Qingfang 提交于
      The driver currently still accepts untagged frames on VLAN-aware ports
      without PVID. Use PVC.ACC_FRM to drop untagged frames in that case.
      Signed-off-by: NDENG Qingfang <dqfext@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      8fbebef8
    • V
      net: dsa: don't disable multicast flooding to the CPU even without an IGMP querier · c73c5708
      Vladimir Oltean 提交于
      Commit 08cc83cc ("net: dsa: add support for BRIDGE_MROUTER
      attribute") added an option for users to turn off multicast flooding
      towards the CPU if they turn off the IGMP querier on a bridge which
      already has enslaved ports (echo 0 > /sys/class/net/br0/bridge/multicast_router).
      
      And commit a8b659e7 ("net: dsa: act as passthrough for bridge port flags")
      simply papered over that issue, because it moved the decision to flood
      the CPU with multicast (or not) from the DSA core down to individual drivers,
      instead of taking a more radical position then.
      
      The truth is that disabling multicast flooding to the CPU is simply
      something we are not prepared to do now, if at all. Some reasons:
      
      - ICMP6 neighbor solicitation messages are unregistered multicast
        packets as far as the bridge is concerned. So if we stop flooding
        multicast, the outside world cannot ping the bridge device's IPv6
        link-local address.
      
      - There might be foreign interfaces bridged with our DSA switch ports
        (sending a packet towards the host does not necessarily equal
        termination, but maybe software forwarding). So if there is no one
        interested in that multicast traffic in the local network stack, that
        doesn't mean nobody is.
      
      - PTP over L4 (IPv4, IPv6) is multicast, but is unregistered as far as
        the bridge is concerned. This should reach the CPU port.
      
      - The switch driver might not do FDB partitioning. And since we don't
        even bother to do more fine-grained flood disabling (such as "disable
        flooding _from_port_N_ towards the CPU port" as opposed to "disable
        flooding _from_any_port_ towards the CPU port"), this breaks standalone
        ports, or even multiple bridges where one has an IGMP querier and one
        doesn't.
      
      Reverting the logic makes all of the above work.
      
      Fixes: a8b659e7 ("net: dsa: act as passthrough for bridge port flags")
      Fixes: 08cc83cc ("net: dsa: add support for BRIDGE_MROUTER attribute")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      c73c5708
    • V
      net: dsa: mt7530: remove the .port_set_mrouter implementation · cbbf09b5
      Vladimir Oltean 提交于
      DSA's idea of optimizing out multicast flooding to the CPU port leaves
      quite a few holes open, so it should be reverted.
      
      The mt7530 driver is the only new driver which added a .port_set_mrouter
      implementation after the reorg from commit a8b659e7 ("net: dsa: act
      as passthrough for bridge port flags"), so it needs to be reverted
      separately so that the other revert commit can go a bit further down the
      git history.
      
      Fixes: 5a30833b ("net: dsa: mt7530: support MDB and bridge flag operations")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      cbbf09b5
  3. 05 8月, 2021 6 次提交
    • V
      net: dsa: sja1105: enable address learning on cascade ports · 81d45898
      Vladimir Oltean 提交于
      Right now, address learning is disabled on DSA ports, which means that a
      packet received over a DSA port from a cross-chip switch will be flooded
      to unrelated ports.
      
      It is desirable to eliminate that, but for that we need a breakdown of
      the possibilities for the sja1105 driver. A DSA port can be:
      
      - a downstream-facing cascade port. This is simple because it will
        always receive packets from a downstream switch, and there should be
        no other route to reach that downstream switch in the first place,
        which means it should be safe to learn that MAC address towards that
        switch.
      
      - an upstream-facing cascade port. This receives packets either:
        * autonomously forwarded by an upstream switch (and therefore these
          packets belong to the data plane of a bridge, so address learning
          should be ok), or
        * injected from the CPU. This deserves further discussion, as normally,
          an upstream-facing cascade port is no different than the CPU port
          itself. But with "H" topologies (a DSA link towards a switch that
          has its own CPU port), these are more "laterally-facing" cascade
          ports than they are "upstream-facing". Here, there is a risk that
          the port might learn the host addresses on the wrong port (on the
          DSA port instead of on its own CPU port), but this is solved by
          DSA's RX filtering infrastructure, which installs the host addresses
          as static FDB entries on the CPU port of all switches in a "H" tree.
          So even if there will be an attempt from the switch to migrate the
          FDB entry from the CPU port to the laterally-facing cascade port, it
          will fail to do that, because the FDB entry that already exists is
          static and cannot migrate. So address learning should be safe for
          this configuration too.
      
      Ok, so what about other MAC addresses coming from the host, not
      necessarily the bridge local FDB entries? What about MAC addresses
      dynamically learned on foreign interfaces, isn't there a risk that
      cascade ports will learn these entries dynamically when they are
      supposed to be delivered towards the CPU port? Well, that is correct,
      and this is why we also need to enable the assisted learning feature, to
      snoop for these addresses and write them to hardware as static FDB
      entries towards the CPU, to make the switch's learning process on the
      cascade ports ineffective for them. With assisted learning enabled, the
      hardware learning on the CPU port must be disabled.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      81d45898
    • V
      net: dsa: sja1105: suppress TX packets from looping back in "H" topologies · 0f9b762c
      Vladimir Oltean 提交于
      H topologies like this one have a problem:
      
               eth0                                                     eth1
                |                                                        |
             CPU port                                                CPU port
                |                        DSA link                        |
       sw0p0  sw0p1  sw0p2  sw0p3  sw0p4 -------- sw1p4  sw1p3  sw1p2  sw1p1  sw1p0
         |             |      |                            |      |             |
       user          user   user                         user   user          user
       port          port   port                         port   port          port
      
      Basically any packet sent by the eth0 DSA master can be flooded on the
      interconnecting DSA link sw0p4 <-> sw1p4 and it will be received by the
      eth1 DSA master too. Basically we are talking to ourselves.
      
      In VLAN-unaware mode, these packets are encoded using a tag_8021q TX
      VLAN, which dsa_8021q_rcv() rightfully cannot decode and complains.
      Whereas in VLAN-aware mode, the packets are encoded with a bridge VLAN
      which _can_ be decoded by the tagger running on eth1, so it will attempt
      to reinject that packet into the network stack (the bridge, if there is
      any port under eth1 that is under a bridge). In the case where the ports
      under eth1 are under the same cross-chip bridge as the ports under eth0,
      the TX packets will even be learned as RX packets. The only thing that
      will prevent loops with the software bridging path, and therefore
      disaster, is that the source port and the destination port are in the
      same hardware domain, and the bridge will receive packets from the
      driver with skb->offload_fwd_mark = true and will not forward between
      the two.
      
      The proper solution to this problem is to detect H topologies and
      enforce that all packets are received through the local switch and we do
      not attempt to receive packets on our CPU port from switches that have
      their own. This is a viable solution which works thanks to the fact that
      MAC addresses which should be filtered towards the host are installed by
      DSA as static MAC addresses towards the CPU port of each switch.
      
      TX from a CPU port towards the DSA port continues to be allowed, this is
      because sja1105 supports bridge TX forwarding offload, and the skb->dev
      used initially for xmit does not have any direct correlation with where
      the station that will respond to that packet is connected. It may very
      well happen that when we send a ping through a br0 interface that spans
      all switch ports, the xmit packet will exit the system through a DSA
      switch interface under eth1 (say sw1p2), but the destination station is
      connected to a switch port under eth0, like sw0p0. So the switch under
      eth1 needs to communicate on TX with the switch under eth0. The
      response, however, will not follow the same path, but instead, this
      patch enforces that the response is sent by the first switch directly to
      its DSA master which is eth0.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      0f9b762c
    • V
      net: dsa: sja1105: increase MTU to account for VLAN header on DSA ports · 777e55e3
      Vladimir Oltean 提交于
      Since all packets are transmitted as VLAN-tagged over a DSA link (this
      VLAN tag represents the tag_8021q header), we need to increase the MTU
      of these interfaces to account for the possibility that we are already
      transporting a user-visible VLAN header.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      777e55e3
    • V
      net: dsa: sja1105: manage VLANs on cascade ports · c5130029
      Vladimir Oltean 提交于
      Since commit ed040abc ("net: dsa: sja1105: use 4095 as the private
      VLAN for untagged traffic"), this driver uses a reserved value as pvid
      for the host port (DSA CPU port). Control packets which are sent as
      untagged get classified to this VLAN, and all ports are members of it
      (this is to be expected for control packets).
      
      Manage all cascade ports in the same way and allow control packets to
      egress everywhere.
      
      Also, all VLANs need to be sent as egress-tagged on all cascade ports.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      c5130029
    • V
      net: dsa: sja1105: manage the forwarding domain towards DSA ports · 3fa21270
      Vladimir Oltean 提交于
      Manage DSA links towards other switches, be they host ports or cascade
      ports, the same as the CPU port, i.e. allow forwarding and flooding
      unconditionally from all user ports.
      
      We send packets as always VLAN-tagged on a DSA port, and we rely on the
      cross-chip notifiers from tag_8021q to install the RX VLAN of a switch
      port only on the proper remote ports of another switch (the ports that
      are in the same bridging domain). So if there is no cross-chip bridging
      in the system, the flooded packets will be sent on the DSA ports too,
      but they will be dropped by the remote switches due to either
      (a) a lack of the RX VLAN in the VLAN table of the ingress DSA port, or
      (b) a lack of valid destinations for those packets, due to a lack of the
          RX VLAN on the user ports of the switch
      
      Note that switches which only transport packets in a cross-chip bridge,
      but have no user ports of their own as part of that bridge, such as
      switch 1 in this case:
      
                          DSA link                   DSA link
        sw0p0 sw0p1 sw0p2 -------- sw1p0 sw1p2 sw1p3 -------- sw2p0 sw2p2 sw2p3
      
      ip link set sw0p0 master br0
      ip link set sw2p3 master br0
      
      will still work, because the tag_8021q cross-chip notifiers keep the RX
      VLANs installed on all DSA ports.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      3fa21270
    • V
      net: dsa: sja1105: configure the cascade ports based on topology · 30a100e6
      Vladimir Oltean 提交于
      The sja1105 switch family has a feature called "cascade ports" which can
      be used in topologies where multiple SJA1105/SJA1110 switches are daisy
      chained. Upstream switches set this bit for the DSA link towards the
      downstream switches. This is used when the upstream switch receives a
      control packet (PTP, STP) from a downstream switch, because if the
      source port for a control packet is marked as a cascade port, then the
      source port, switch ID and RX timestamp will not be taken again on the
      upstream switch, it is assumed that this has already been done by the
      downstream switch (the leaf port in the tree) and that the CPU has
      everything it needs to decode the information from this packet.
      
      We need to distinguish between an upstream-facing DSA link and a
      downstream-facing DSA link, because the upstream-facing DSA links are
      "host ports" for the SJA1105/SJA1110 switches, and the downstream-facing
      DSA links are "cascade ports".
      
      Note that SJA1105 supports a single cascade port, so only daisy chain
      topologies work. With SJA1110, there can be more complex topologies such
      as:
      
                          eth0
                           |
                       host port
                           |
       sw0p0    sw0p1    sw0p2    sw0p3    sw0p4
         |        |                 |        |
       cascade  cascade            user     user
        port     port              port     port
         |        |
         |        |
         |        |
         |       host
         |       port
         |        |
         |      sw1p0    sw1p1    sw1p2    sw1p3    sw1p4
         |                 |        |        |        |
         |                user     user     user     user
        host              port     port     port     port
        port
         |
       sw2p0    sw2p1    sw2p2    sw2p3    sw2p4
                  |        |        |        |
                 user     user     user     user
                 port     port     port     port
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      30a100e6
  4. 04 8月, 2021 5 次提交
    • D
      net: dsa: mt7530: always install FDB entries with IVL and FID 1 · 73c447ca
      DENG Qingfang 提交于
      This reverts commit 7e777021 ("mt7530 mt7530_fdb_write only set ivl
      bit vid larger than 1").
      
      Before this series, the default value of all ports' PVID is 1, which is
      copied into the FDB entry, even if the ports are VLAN unaware. So
      `bridge fdb show` will show entries like `dev swp0 vlan 1 self` even on
      a VLAN-unaware bridge.
      
      The blamed commit does not solve that issue completely, instead it may
      cause a new issue that FDB is inaccessible in a VLAN-aware bridge with
      PVID 1.
      
      This series sets PVID to 0 on VLAN-unaware ports, so `bridge fdb show`
      will no longer print `vlan 1` on VLAN-unaware bridges, and that special
      case in fdb_write is not required anymore.
      
      Set FDB entries' filter ID to 1 to match the VLAN table.
      Signed-off-by: NDENG Qingfang <dqfext@gmail.com>
      Reviewed-by: NVladimir Oltean <olteanv@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      73c447ca
    • D
      net: dsa: mt7530: set STP state on filter ID 1 · a9e3f62d
      DENG Qingfang 提交于
      As filter ID 1 is the only one used for bridges, set STP state on it.
      Signed-off-by: NDENG Qingfang <dqfext@gmail.com>
      Reviewed-by: NVladimir Oltean <olteanv@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      a9e3f62d
    • D
      net: dsa: mt7530: use independent VLAN learning on VLAN-unaware bridges · 6087175b
      DENG Qingfang 提交于
      Consider the following bridge configuration, where bond0 is not
      offloaded:
      
               +-- br0 --+
              / /   |     \
             / /    |      \
            /  |    |     bond0
           /   |    |     /   \
         swp0 swp1 swp2 swp3 swp4
           .        .       .
           .        .       .
           A        B       C
      
      Ideally, when the switch receives a packet from swp3 or swp4, it should
      forward the packet to the CPU, according to the port matrix and unknown
      unicast flood settings.
      
      But packet loss will happen if the destination address is at one of the
      offloaded ports (swp0~2). For example, when client C sends a packet to
      A, the FDB lookup will indicate that it should be forwarded to swp0, but
      the port matrix of swp3 and swp4 is configured to only allow the CPU to
      be its destination, so it is dropped.
      
      However, this issue does not happen if the bridge is VLAN-aware. That is
      because VLAN-aware bridges use independent VLAN learning, i.e. use VID
      for FDB lookup, on offloaded ports. As swp3 and swp4 are not offloaded,
      shared VLAN learning with default filter ID of 0 is used instead. So the
      lookup for A with filter ID 0 never hits and the packet can be forwarded
      to the CPU.
      
      In the current code, only two combinations were used to toggle user
      ports' VLAN awareness: one is PCR.PORT_VLAN set to port matrix mode with
      PVC.VLAN_ATTR set to transparent port, the other is PCR.PORT_VLAN set to
      security mode with PVC.VLAN_ATTR set to user port.
      
      It turns out that only PVC.VLAN_ATTR contributes to VLAN awareness, and
      port matrix mode just skips the VLAN table lookup. The reference manual
      is somehow misleading when describing PORT_VLAN modes. It states that
      PORT_MEM (VLAN port member) is used for destination if the VLAN table
      lookup hits, but actually **PORT_MEM & PORT_MATRIX** (bitwise AND of
      VLAN port member and port matrix) is used instead, which means we can
      have two or more separate VLAN-aware bridges with the same PVID and
      traffic won't leak between them.
      
      Therefore, to solve this, enable independent VLAN learning with PVID 0
      on VLAN-unaware bridges, by setting their PCR.PORT_VLAN to fallback
      mode, while leaving standalone ports in port matrix mode. The CPU port
      is always set to fallback mode to serve those bridges.
      
      During testing, it is found that FDB lookup with filter ID of 0 will
      also hit entries with VID 0 even with independent VLAN learning. To
      avoid that, install all VLANs with filter ID of 1.
      Signed-off-by: NDENG Qingfang <dqfext@gmail.com>
      Reviewed-by: NVladimir Oltean <olteanv@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      6087175b
    • D
      net: dsa: mt7530: enable assisted learning on CPU port · 0b69c54c
      DENG Qingfang 提交于
      Consider the following bridge configuration, where bond0 is not
      offloaded:
      
               +-- br0 --+
              / /   |     \
             / /    |      \
            /  |    |     bond0
           /   |    |     /   \
         swp0 swp1 swp2 swp3 swp4
           .        .       .
           .        .       .
           A        B       C
      
      Address learning is enabled on offloaded ports (swp0~2) and the CPU
      port, so when client A sends a packet to C, the following will happen:
      
      1. The switch learns that client A can be reached at swp0.
      2. The switch probably already knows that client C can be reached at the
         CPU port, so it forwards the packet to the CPU.
      3. The bridge core knows client C can be reached at bond0, so it
         forwards the packet back to the switch.
      4. The switch learns that client A can be reached at the CPU port.
      5. The switch forwards the packet to either swp3 or swp4, according to
         the packet's tag.
      
      That makes client A's MAC address flap between swp0 and the CPU port. If
      client B sends a packet to A, it is possible that the packet is
      forwarded to the CPU. With offload_fwd_mark = 1, the bridge core won't
      forward it back to the switch, resulting in packet loss.
      
      As we have the assisted_learning_on_cpu_port in DSA core now, enable
      that and disable hardware learning on the CPU port.
      Signed-off-by: NDENG Qingfang <dqfext@gmail.com>
      Reviewed-by: NVladimir Oltean <oltean@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      0b69c54c
    • O
      net: dsa: qca: ar9331: reorder MDIO write sequence · d1a58c01
      Oleksij Rempel 提交于
      In case of this switch we work with 32bit registers on top of 16bit
      bus. Some registers (for example access to forwarding database) have
      trigger bit on the first 16bit half of request and the result +
      configuration of request in the second half. Without this patch, we would
      trigger database operation and overwrite result in one run.
      
      To make it work properly, we should do the second part of transfer
      before the first one is done.
      
      So far, this rule seems to work for all registers on this switch.
      
      Fixes: ec6698c2 ("net: dsa: add support for Atheros AR9331 built-in switch")
      Signed-off-by: NOleksij Rempel <o.rempel@pengutronix.de>
      Reviewed-by: NAndrew Lunn <andrew@lunn.ch>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Reviewed-by: NVladimir Oltean <olteanv@gmail.com>
      Link: https://lore.kernel.org/r/20210803063746.3600-1-o.rempel@pengutronix.deSigned-off-by: NJakub Kicinski <kuba@kernel.org>
      d1a58c01
  5. 02 8月, 2021 7 次提交
    • V
      net: dsa: mt7530: drop paranoid checks in .get_tag_protocol() · 244f8a80
      Vladimir Oltean 提交于
      It is desirable to reduce the surface of DSA_TAG_PROTO_NONE as much as
      we can, because we now have options for switches without hardware
      support for DSA tagging, and the occurrence in the mt7530 driver is in
      fact quite gratuitout and easy to remove. Since ds->ops->get_tag_protocol()
      is only called for CPU ports, the checks for a CPU port in
      mtk_get_tag_protocol() are redundant and can be removed.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Acked-by: NDENG Qingfang <dqfext@gmail.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      244f8a80
    • V
      net: dsa: sja1105: match FDB entries regardless of inner/outer VLAN tag · 47c2c0c2
      Vladimir Oltean 提交于
      On SJA1105P/Q/R/S and SJA1110, the L2 Lookup Table entries contain a
      maskable "inner/outer tag" bit which means:
      - when set to 1: match single-outer and double tagged frames
      - when set to 0: match untagged and single-inner tagged frames
      - when masked off: match all frames regardless of the type of tag
      
      This driver does not make any meaningful distinction between inner tags
      (matches on TPID) and outer tags (matches on TPID2). In fact, all VLAN
      table entries are installed as SJA1110_VLAN_D_TAG, which means that they
      match on both inner and outer tags.
      
      So it does not make sense that we install FDB entries with the IOTAG bit
      set to 1.
      
      In VLAN-unaware mode, we set both TPID and TPID2 to 0xdadb, so the
      switch will see frames as outer-tagged or double-tagged (never inner).
      So the FDB entries will match if IOTAG is set to 1.
      
      In VLAN-aware mode, we set TPID to 0x8100 and TPID2 to 0x88a8. So the
      switch will see untagged and 802.1Q-tagged packets as inner-tagged, and
      802.1ad-tagged packets as outer-tagged. So untagged and 802.1Q-tagged
      packets will not match FDB entries if IOTAG is set to 1, but 802.1ad
      tagged packets will. Strange.
      
      To fix this, simply mask off the IOTAG bit from FDB entries, and make
      them match regardless of whether the VLAN tag is inner or outer.
      
      Fixes: 1da73821 ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      47c2c0c2
    • V
      net: dsa: sja1105: be stateless with FDB entries on SJA1105P/Q/R/S/SJA1110 too · 589918df
      Vladimir Oltean 提交于
      Similar but not quite the same with what was done in commit b11f0a4c
      ("net: dsa: sja1105: be stateless when installing FDB entries") for
      SJA1105E/T, it is desirable to drop the priv->vlan_aware check and
      simply go ahead and install FDB entries in the VLAN that was given by
      the bridge.
      
      As opposed to SJA1105E/T, in SJA1105P/Q/R/S and SJA1110, the FDB is a
      maskable TCAM, and we are installing VLAN-unaware FDB entries with the
      VLAN ID masked off. However, such FDB entries might completely obscure
      VLAN-aware entries where the VLAN ID is included in the search mask,
      because the switch looks up the FDB from left to right and picks the
      first entry which results in a masked match. So it depends on whether
      the bridge installs first the VLAN-unaware or the VLAN-aware FDB entries.
      
      Anyway, if we had a VLAN-unaware FDB entry towards one set of DESTPORTS
      and a VLAN-aware one towards other set of DESTPORTS, the result is that
      the packets in VLAN-aware mode will be forwarded towards the DESTPORTS
      specified by the VLAN-unaware entry.
      
      To solve this, simply do not use the masked matching ability of the FDB
      for VLAN ID, and always match precisely on it. In VLAN-unaware mode, we
      configure the switch for shared VLAN learning, so the VLAN ID will be
      ignored anyway during lookup, so it is redundant to mask it off in the
      TCAM.
      
      This patch conflicts with net-next commit 0fac6aa0 ("net: dsa: sja1105:
      delete the best_effort_vlan_filtering mode") which changed this line:
      	if (priv->vlan_state != SJA1105_VLAN_UNAWARE) {
      into:
      	if (priv->vlan_aware) {
      
      When merging with net-next, the lines added by this patch should take
      precedence in the conflict resolution (i.e. the "if" condition should be
      deleted in both cases).
      
      Fixes: 1da73821 ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      589918df
    • V
      net: dsa: sja1105: ignore the FDB entry for unknown multicast when adding a new address · 728db843
      Vladimir Oltean 提交于
      Currently, when sja1105pqrs_fdb_add() is called for a host-joined IPv6
      MDB entry such as 33:33:00:00:00:6a, the search for that address will
      return the FDB entry for SJA1105_UNKNOWN_MULTICAST, which has a
      destination MAC of 01:00:00:00:00:00 and a mask of 01:00:00:00:00:00.
      It returns that entry because, well, it matches, in the sense that
      unknown multicast is supposed by design to match it...
      
      But the issue is that we then proceed to overwrite this entry with the
      one for our precise host-joined multicast address, and the unknown
      multicast entry is no longer there - unknown multicast is now flooded to
      the same group of ports as broadcast, which does not look up the FDB.
      
      To solve this problem, we should ignore searches that return the unknown
      multicast address as the match, and treat them as "no match" which will
      result in the entry being installed to hardware.
      
      For this to work properly, we need to put the result of the FDB search
      in a temporary variable in order to avoid overwriting the l2_lookup
      entry we want to program. The l2_lookup entry returned by the search
      might not have the same set of DESTPORTS and not even the same MACADDR
      as the entry we're trying to add.
      
      Fixes: 4d942354 ("net: dsa: sja1105: offload bridge port flags to device")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      728db843
    • V
      net: dsa: sja1105: invalidate dynamic FDB entries learned concurrently with statically added ones · 6c5fc159
      Vladimir Oltean 提交于
      The procedure to add a static FDB entry in sja1105 is concurrent with
      dynamic learning performed on all bridge ports and the CPU port.
      
      The switch looks up the FDB from left to right, and also learns
      dynamically from left to right, so it is possible that between the
      moment when we pick up a free slot to install an FDB entry, another slot
      to the left of that one becomes free due to an address ageing out, and
      that other slot is then immediately used by the switch to learn
      dynamically the same address as we're trying to add statically.
      
      The result is that we succeeded to add our static FDB entry, but it is
      being shadowed by a dynamic FDB entry to its left, and the switch will
      behave as if our static FDB entry did not exist.
      
      We cannot really prevent this from happening unless we make the entire
      process to add a static FDB entry a huge critical section where address
      learning is temporarily disabled on _all_ ports, and then re-enabled
      according to the configuration done by sja1105_port_set_learning.
      However, that is kind of disruptive for the operation of the network.
      
      What we can do alternatively is to simply read back the FDB for dynamic
      entries located before our newly added static one, and delete them.
      This will guarantee that our static FDB entry is now operational. It
      will still not guarantee that there aren't dynamic FDB entries to the
      _right_ of that static FDB entry, but at least those entries will age
      out by themselves since they aren't hit, and won't bother anyone.
      
      Fixes: 291d1e72 ("net: dsa: sja1105: Add support for FDB and MDB management")
      Fixes: 1da73821 ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      6c5fc159
    • V
      net: dsa: sja1105: overwrite dynamic FDB entries with static ones in .port_fdb_add · e11e865b
      Vladimir Oltean 提交于
      The SJA1105 switch family leaves it up to software to decide where
      within the FDB to install a static entry, and to concatenate destination
      ports for already existing entries (the FDB is also used for multicast
      entries), it is not as simple as just saying "please add this entry".
      
      This means we first need to search for an existing FDB entry before
      adding a new one. The driver currently manages to fool itself into
      thinking that if an FDB entry already exists, there is nothing to be
      done. But that FDB entry might be dynamically learned, case in which it
      should be replaced with a static entry, but instead it is left alone.
      
      This patch checks the LOCKEDS ("locked/static") bit from found FDB
      entries, and lets the code "goto skip_finding_an_index;" if the FDB
      entry was not static. So we also need to move the place where we set
      LOCKEDS = true, to cover the new case where a dynamic FDB entry existed
      but was dynamic.
      
      Fixes: 291d1e72 ("net: dsa: sja1105: Add support for FDB and MDB management")
      Fixes: 1da73821 ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e11e865b
    • V
      net: dsa: sja1105: fix static FDB writes for SJA1110 · cb81698f
      Vladimir Oltean 提交于
      The blamed commit made FDB access on SJA1110 functional only as far as
      dumping the existing entries goes, but anything having to do with an
      entry's index (adding, deleting) is still broken.
      
      There are in fact 2 problems, all caused by improperly inheriting the
      code from SJA1105P/Q/R/S:
      - An entry size is SJA1110_SIZE_L2_LOOKUP_ENTRY (24) bytes and not
        SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY (20) bytes
      - The "index" field within an FDB entry is at bits 10:1 for SJA1110 and
        not 15:6 as in SJA1105P/Q/R/S
      
      This patch moves the packing function for the cmd->index outside of
      sja1105pqrs_common_l2_lookup_cmd_packing() and into the device specific
      functions sja1105pqrs_l2_lookup_cmd_packing and
      sja1110_l2_lookup_cmd_packing.
      
      Fixes: 74e7feff ("net: dsa: sja1105: fix dynamic access to L2 Address Lookup table for SJA1110")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      cb81698f
  6. 29 7月, 2021 3 次提交
    • V
      net: dsa: sja1105: make sure untagged packets are dropped on ingress ports with no pvid · bef0746c
      Vladimir Oltean 提交于
      Surprisingly, this configuration:
      
      ip link add br0 type bridge vlan_filtering 1
      ip link set swp2 master br0
      bridge vlan del dev swp2 vid 1
      
      still has the sja1105 switch sending untagged packets to the CPU (and
      failing to decode them, since dsa_find_designated_bridge_port_by_vid
      searches by VID 1 and rightfully finds no bridge VLAN 1 on a port).
      
      Dumping the switch configuration, the VLANs are managed properly:
      - the pvid of swp2 is 1 in the MAC Configuration Table, but
      - only the CPU port is in the port membership of VLANID 1 in the VLAN
        Lookup Table
      
      When the ingress packets are tagged with VID 1, they are properly
      dropped. But when they are untagged, they are able to reach the CPU
      port. Also, when the pvid in the MAC Configuration Table is changed to
      e.g. 55 (an unused VLAN), the untagged packets are also dropped.
      
      So it looks like:
      - the switch bypasses ingress VLAN membership checks for untagged traffic
      - the reason why the untagged traffic is dropped when I make the pvid 55
        is due to the lack of valid destination ports in VLAN 55, rather than
        an ingress membership violation
      - the ingress VLAN membership cheks are only done for VLAN-tagged traffic
      
      Interesting. It looks like there is an explicit bit to drop untagged
      traffic, so we should probably be using that to preserve user expectations.
      
      Note that only VLAN-aware ports should drop untagged packets due to no
      pvid - when VLAN-unaware, the software bridge doesn't do this even if
      there is no pvid on any bridge port and on the bridge itself. So the new
      sja1105_drop_untagged() function cannot simply be called with "false"
      from sja1105_bridge_vlan_add() and with "true" from sja1105_bridge_vlan_del.
      Instead, we need to also consider the VLAN awareness state. That means
      we need to hook the "drop untagged" setting in all the same places where
      the "commit pvid" logic is, and it needs to factor in all the state when
      flipping the "drop untagged" bit: is our current pvid in the VLAN Lookup
      Table, and is the current port in that VLAN's port membership list?
      VLAN-unaware ports will never drop untagged frames because these checks
      always succeed by construction, and the tag_8021q VLANs cannot be changed
      by the user.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      bef0746c
    • V
      net: dsa: sja1105: reset the port pvid when leaving a VLAN-aware bridge · cde8078e
      Vladimir Oltean 提交于
      Now that we no longer have the ultra-central sja1105_build_vlan_table(),
      we need to be more careful about checking all corner cases manually.
      
      For example, when a port leaves a VLAN-aware bridge, it becomes
      standalone so its pvid should become a tag_8021q RX VLAN again. However,
      sja1105_commit_pvid() only gets called from sja1105_bridge_vlan_add()
      and from sja1105_vlan_filtering(), and no VLAN awareness change takes
      place (VLAN filtering is a global setting for sja1105, so the switch
      remains VLAN-aware overall).
      
      This means that we need to put another sja1105_commit_pvid() call in
      sja1105_bridge_member().
      
      Fixes: 6dfd23d3 ("net: dsa: sja1105: delete vlan delta save/restore logic")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      cde8078e
    • V
      net: dsa: sja1105: be stateless when installing FDB entries · b11f0a4c
      Vladimir Oltean 提交于
      Currently there are issues when adding a bridge FDB entry as VLAN-aware
      and deleting it as VLAN-unaware, or vice versa.
      
      However this is an unneeded complication, since the bridge always
      installs its default FDB entries in VLAN 0 to match on VLAN-unaware
      ports, and in the default_pvid (VLAN 1) to match on VLAN-aware ports.
      So instead of trying to outsmart the bridge, just install all entries it
      gives us, and they will start matching packets when the vlan_filtering
      mode changes.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b11f0a4c
  7. 27 7月, 2021 6 次提交
    • V
      net: dsa: sja1105: add bridge TX data plane offload based on tag_8021q · b6ad86e6
      Vladimir Oltean 提交于
      The main desire for having this feature in sja1105 is to support network
      stack termination for traffic coming from a VLAN-aware bridge.
      
      For sja1105, offloading the bridge data plane means sending packets
      as-is, with the proper VLAN tag, to the chip. The chip will look up its
      FDB and forward them to the correct destination port.
      
      But we support bridge data plane offload even for VLAN-unaware bridges,
      and the implementation there is different. In fact, VLAN-unaware
      bridging is governed by tag_8021q, so it makes sense to have the
      .bridge_fwd_offload_add() implementation fully within tag_8021q.
      The key difference is that we only support 1 VLAN-aware bridge, but we
      support multiple VLAN-unaware bridges. So we need to make sure that the
      forwarding domain is not crossed by packets injected from the stack.
      
      For this, we introduce the concept of a tag_8021q TX VLAN for bridge
      forwarding offload. As opposed to the regular TX VLANs which contain
      only 2 ports (the user port and the CPU port), a bridge data plane TX
      VLAN is "multicast" (or "imprecise"): it contains all the ports that are
      part of a certain bridge, and the hardware will select where the packet
      goes within this "imprecise" forwarding domain.
      
      Each VLAN-unaware bridge has its own "imprecise" TX VLAN, so we make use
      of the unique "bridge_num" provided by DSA for the data plane offload.
      We use the same 3 bits from the tag_8021q VLAN ID format to encode this
      bridge number.
      
      Note that these 3 bit positions have been used before for sub-VLANs in
      best-effort VLAN filtering mode. The difference is that for best-effort,
      the sub-VLANs were only valid on RX (and it was documented that the
      sub-VLAN field needed to be transmitted as zero). Whereas for the bridge
      data plane offload, these 3 bits are only valid on TX.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b6ad86e6
    • V
      net: dsa: sja1105: add support for imprecise RX · 884be12f
      Vladimir Oltean 提交于
      This is already common knowledge by now, but the sja1105 does not have
      hardware support for DSA tagging for data plane packets, and tag_8021q
      sets up a unique pvid per port, transmitted as VLAN-tagged towards the
      CPU, for the source port to be decoded nonetheless.
      
      When the port is part of a VLAN-aware bridge, the pvid committed to
      hardware is taken from the bridge and not from tag_8021q, so we need to
      work with that the best we can.
      
      Configure the switches to send all packets to the CPU as VLAN-tagged
      (even ones that were originally untagged on the wire) and make use of
      dsa_untag_bridge_pvid() to get rid of it before we send those packets up
      the network stack.
      
      With the classified VLAN used by hardware known to the tagger, we first
      peek at the VID in an attempt to figure out if the packet was received
      from a VLAN-unaware port (standalone or under a VLAN-unaware bridge),
      case in which we can continue to call dsa_8021q_rcv(). If that is not
      the case, the packet probably came from a VLAN-aware bridge. So we call
      the DSA helper that finds for us a "designated bridge port" - one that
      is a member of the VLAN ID from the packet, and is in the proper STP
      state - basically these are all checks performed by br_handle_frame() in
      the software RX data path.
      
      The bridge will accept the packet as valid even if the source port was
      maybe wrong. So it will maybe learn the MAC SA of the packet on the
      wrong port, and its software FDB will be out of sync with the hardware
      FDB. So replies towards this same MAC DA will not work, because the
      bridge will send towards a different netdev.
      
      This is where the bridge data plane offload ("imprecise TX") added by
      the next patch comes in handy. The software FDB is wrong, true, but the
      hardware FDB isn't, and by offloading the bridge forwarding plane we
      have a chance to right a wrong, and have the hardware look up the FDB
      for us for the reply packet. So it all cancels out.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      884be12f
    • V
      net: dsa: sja1105: deny more than one VLAN-aware bridge · 19fa937a
      Vladimir Oltean 提交于
      With tag_sja1105.c's only ability being to perform an imprecise RX
      procedure and identify whether a packet comes from a VLAN-aware bridge
      or not, we have no way to determine whether a packet with VLAN ID 5
      comes from, say, br0 or br1. Actually we could, but it would mean that
      we need to restrict all VLANs from br0 to be different from all VLANs
      from br1, and this includes the default_pvid, which makes a setup with 2
      VLAN-aware bridges highly imprectical.
      
      The fact of the matter is that this isn't even that big of a practical
      limitation, since even with a single VLAN-aware bridge we can pretty
      much enforce forwarding isolation based on the VLAN port membership.
      
      So in the end, tell the user that they need to model their setup using a
      single VLAN-aware bridge.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      19fa937a
    • V
      net: dsa: sja1105: deny 8021q uppers on ports · 4fbc08bd
      Vladimir Oltean 提交于
      Now that best-effort VLAN filtering is gone and we are left with the
      imprecise RX and imprecise TX based in VLAN-aware mode, where the tagger
      just guesses the source port based on plausibility of the VLAN ID, 8021q
      uppers installed on top of a standalone port, while other ports of that
      switch are under a VLAN-aware bridge don't quite "just work".
      
      In fact it could be possible to restrict the VLAN IDs used by the 8021q
      uppers to not be shared with VLAN IDs used by that VLAN-aware bridge,
      but then the tagger needs to be patched to search for 8021q uppers too,
      not just for the "designated bridge port" which will be introduced in a
      later patch.
      
      I haven't given a possible implementation full thought, it seems maybe
      possible but not worth the effort right now. The only certain thing is
      that currently the tagger won't be able to figure out the source port
      for these packets because they will come with the VLAN ID of the 8021q
      upper and are no longer retagged to a tag_8021q sub-VLAN like the best
      effort VLAN filtering code used to do. So just deny these for the
      moment.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      4fbc08bd
    • V
      net: dsa: sja1105: delete vlan delta save/restore logic · 6dfd23d3
      Vladimir Oltean 提交于
      With the best_effort_vlan_filtering mode now gone, the driver does not
      have 3 operating modes anymore (VLAN-unaware, VLAN-aware and best effort),
      but only 2.
      
      The idea is that we will gain support for network stack I/O through a
      VLAN-aware bridge, using the data plane offload framework (imprecise RX,
      imprecise TX). So the VLAN-aware use case will be more functional.
      
      But standalone ports that are part of the same switch when some other
      ports are under a VLAN-aware bridge should work too. Termination on
      those should work through the tag_8021q RX VLAN and TX VLAN.
      
      This was not possible using the old logic, because:
      - in VLAN-unaware mode, only the tag_8021q VLANs were committed to hw
      - in VLAN-aware mode, only the bridge VLANs were committed to hw
      - in best-effort VLAN mode, both the tag_8021q and bridge VLANs were
        committed to hw
      
      The strategy for the new VLAN-aware mode is to allow the bridge and the
      tag_8021q VLANs to coexist in the VLAN table at the same time.
      
      [ yes, we need to make sure that the bridge cannot install a tag_8021q
        VLAN, but ]
      
      This means that the save/restore logic introduced by commit ec5ae610
      ("net: dsa: sja1105: save/restore VLANs using a delta commit method")
      does not serve a purpose any longer. We can delete it and restore the
      old code that simply adds a VLAN to the VLAN table and calls it a day.
      
      Note that we keep the sja1105_commit_pvid() function from those days,
      but adapt it slightly. Ports that are under a VLAN-aware bridge use the
      bridge's pvid, ports that are standalone or under a VLAN-unaware bridge
      use the tag_8021q pvid, for local termination or VLAN-unaware forwarding.
      
      Now, when the vlan_filtering property is toggled for the bridge, the
      pvid of the ports beneath it is the only thing that's changing, we no
      longer delete some VLANs and restore others.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      6dfd23d3
    • C
      net: dsa: sja1105: remove redundant re-assignment of pointer table · d63f8877
      Colin Ian King 提交于
      The pointer table is being re-assigned with a value that is never
      read. The assignment is redundant and can be removed.
      
      Addresses-Coverity: ("Unused value")
      Signed-off-by: NColin Ian King <colin.king@canonical.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d63f8877
  8. 24 7月, 2021 1 次提交
  9. 23 7月, 2021 1 次提交
    • V
      net: dsa: mv88e6xxx: map virtual bridges with forwarding offload in the PVT · ce5df689
      Vladimir Oltean 提交于
      The mv88e6xxx switches have the ability to receive FORWARD (data plane)
      frames from the CPU port and route them according to the FDB. We can use
      this to offload the forwarding process of packets sent by the software
      bridge.
      
      Because DSA supports bridge domain isolation between user ports, just
      sending FORWARD frames is not enough, as they might leak the intended
      broadcast domain of the bridge on behalf of which the packets are sent.
      
      It should be noted that FORWARD frames are also (and typically) used to
      forward data plane packets on DSA links in cross-chip topologies. The
      FORWARD frame header contains the source port and switch ID, and
      switches receiving this frame header forward the packet according to
      their cross-chip port-based VLAN table (PVT).
      
      To address the bridging domain isolation in the context of offloading
      the forwarding on TX, the idea is that we can reuse the parts of the PVT
      that don't have any physical switch mapped to them, one entry for each
      software bridge. The switches will therefore think that behind their
      upstream port lie many switches, all in fact backed up by software
      bridges through tag_dsa.c, which constructs FORWARD packets with the
      right switch ID corresponding to each bridge.
      
      The mapping we use is absolutely trivial: DSA gives us a unique bridge
      number, and we add the number of the physical switches in the DSA switch
      tree to that, to obtain a unique virtual bridge device number to use in
      the PVT.
      Co-developed-by: NTobias Waldekranz <tobias@waldekranz.com>
      Signed-off-by: NTobias Waldekranz <tobias@waldekranz.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      ce5df689
  10. 22 7月, 2021 1 次提交
    • V
      net: dsa: sja1105: make VID 4095 a bridge VLAN too · e40cba94
      Vladimir Oltean 提交于
      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
      8841f6e6 ("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 ad1afb00 ("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 ed040abc ("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: ec5ae610 ("net: dsa: sja1105: save/restore VLANs using a delta commit method")
      Reported-by: NRadu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e40cba94
  11. 20 7月, 2021 6 次提交
    • E
      mt7530 mt7530_fdb_write only set ivl bit vid larger than 1 · 7e777021
      Eric Woudstra 提交于
      Fixes my earlier patch which broke vlan unaware bridges.
      
      The IVL bit now only gets set for vid's larger than 1.
      
      Fixes: 11d8d98c ("mt7530 fix mt7530_fdb_write vid missing ivl bit")
      Signed-off-by: NEric Woudstra <ericwouds@gmail.com>
      Reviewed-by: NFlorian Fainelli <f.fainelli@gmail.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      7e777021
    • V
      net: dsa: tag_8021q: add proper cross-chip notifier support · c64b9c05
      Vladimir Oltean 提交于
      The big problem which mandates cross-chip notifiers for tag_8021q is
      this:
      
                                                   |
          sw0p0     sw0p1     sw0p2     sw0p3     sw0p4
       [  user ] [  user ] [  user ] [  dsa  ] [  cpu  ]
                                         |
                                         +---------+
                                                   |
          sw1p0     sw1p1     sw1p2     sw1p3     sw1p4
       [  user ] [  user ] [  user ] [  dsa  ] [  dsa  ]
                                         |
                                         +---------+
                                                   |
          sw2p0     sw2p1     sw2p2     sw2p3     sw2p4
       [  user ] [  user ] [  user ] [  dsa  ] [  dsa  ]
      
      When the user runs:
      
      ip link add br0 type bridge
      ip link set sw0p0 master br0
      ip link set sw2p0 master br0
      
      It doesn't work.
      
      This is because dsa_8021q_crosschip_bridge_join() assumes that "ds" and
      "other_ds" are at most 1 hop away from each other, so it is sufficient
      to add the RX VLAN of {ds, port} into {other_ds, other_port} and vice
      versa and presto, the cross-chip link works. When there is another
      switch in the middle, such as in this case switch 1 with its DSA links
      sw1p3 and sw1p4, somebody needs to tell it about these VLANs too.
      
      Which is exactly why the problem is quadratic: when a port joins a
      bridge, for each port in the tree that's already in that same bridge we
      notify a tag_8021q VLAN addition of that port's RX VLAN to the entire
      tree. It is a very complicated web of VLANs.
      
      It must be mentioned that currently we install tag_8021q VLANs on too
      many ports (DSA links - to be precise, on all of them). For example,
      when sw2p0 joins br0, and assuming sw1p0 was part of br0 too, we add the
      RX VLAN of sw2p0 on the DSA links of switch 0 too, even though there
      isn't any port of switch 0 that is a member of br0 (at least yet).
      In theory we could notify only the switches which sit in between the
      port joining the bridge and the port reacting to that bridge_join event.
      But in practice that is impossible, because of the way 'link' properties
      are described in the device tree. The DSA bindings require DT writers to
      list out not only the real/physical DSA links, but in fact the entire
      routing table, like for example switch 0 above will have:
      
      	sw0p3: port@3 {
      		link = <&sw1p4 &sw2p4>;
      	};
      
      This was done because:
      
      /* TODO: ideally DSA ports would have a single dp->link_dp member,
       * and no dst->rtable nor this struct dsa_link would be needed,
       * but this would require some more complex tree walking,
       * so keep it stupid at the moment and list them all.
       */
      
      but it is a perfect example of a situation where too much information is
      actively detrimential, because we are now in the position where we
      cannot distinguish a real DSA link from one that is put there to avoid
      the 'complex tree walking'. And because DT is ABI, there is not much we
      can change.
      
      And because we do not know which DSA links are real and which ones
      aren't, we can't really know if DSA switch A is in the data path between
      switches B and C, in the general case.
      
      So this is why tag_8021q RX VLANs are added on all DSA links, and
      probably why it will never change.
      
      On the other hand, at least the number of additions/deletions is well
      balanced, and this means that once we implement reference counting at
      the cross-chip notifier level a la fdb/mdb, there is absolutely zero
      need for a struct dsa_8021q_crosschip_link, it's all self-managing.
      
      In fact, with the tag_8021q notifiers emitted from the bridge join
      notifiers, it becomes so generic that sja1105 does not need to do
      anything anymore, we can just delete its implementation of the
      .crosschip_bridge_{join,leave} methods.
      
      Among other things we can simply delete is the home-grown implementation
      of sja1105_notify_crosschip_switches(). The reason why that is wrong is
      because it is not quadratic - it only covers remote switches to which we
      have a cross-chip bridging link and that does not cover in-between
      switches. This deletion is part of the same patch because sja1105 used
      to poke deep inside the guts of the tag_8021q context in order to do
      that. Because the cross-chip links went away, so needs the sja1105 code.
      
      Last but not least, dsa_8021q_setup_port() is simplified (and also
      renamed). Because our TAG_8021Q_VLAN_ADD notifier is designed to react
      on the CPU port too, the four dsa_8021q_vid_apply() calls:
      - 1 for RX VLAN on user port
      - 1 for the user port's RX VLAN on the CPU port
      - 1 for TX VLAN on user port
      - 1 for the user port's TX VLAN on the CPU port
      
      now get squashed into only 2 notifier calls via
      dsa_port_tag_8021q_vlan_add.
      
      And because the notifiers to add and to delete a tag_8021q VLAN are
      distinct, now we finally break up the port setup and teardown into
      separate functions instead of relying on a "bool enabled" flag which
      tells us what to do. Arguably it should have been this way from the
      get go.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      c64b9c05
    • V
      net: dsa: tag_8021q: absorb dsa_8021q_setup into dsa_tag_8021q_{,un}register · 328621f6
      Vladimir Oltean 提交于
      Right now, setting up tag_8021q is a 2-step operation for a driver,
      first the context structure needs to be created, then the VLANs need to
      be installed on the ports. A similar thing is true for teardown.
      
      Merge the 2 steps into the register/unregister methods, to be as
      transparent as possible for the driver as to what tag_8021q does behind
      the scenes. This also gets rid of the funny "bool setup == true means
      setup, == false means teardown" API that tag_8021q used to expose.
      
      Note that dsa_tag_8021q_register() must be called at least in the
      .setup() driver method and never earlier (like in the driver probe
      function). This is because the DSA switch tree is not initialized at
      probe time, and the cross-chip notifiers will not work.
      
      For symmetry with .setup(), the unregister method should be put in
      .teardown().
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      328621f6
    • V
      net: dsa: make tag_8021q operations part of the core · 5da11eb4
      Vladimir Oltean 提交于
      Make tag_8021q a more central element of DSA and move the 2 driver
      specific operations outside of struct dsa_8021q_context (which is
      supposed to hold dynamic data and not really constant function
      pointers).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      5da11eb4
    • V
      net: dsa: let the core manage the tag_8021q context · d7b1fd52
      Vladimir Oltean 提交于
      The basic problem description is as follows:
      
      Be there 3 switches in a daisy chain topology:
      
                                                   |
          sw0p0     sw0p1     sw0p2     sw0p3     sw0p4
       [  user ] [  user ] [  user ] [  dsa  ] [  cpu  ]
                                         |
                                         +---------+
                                                   |
          sw1p0     sw1p1     sw1p2     sw1p3     sw1p4
       [  user ] [  user ] [  user ] [  dsa  ] [  dsa  ]
                                         |
                                         +---------+
                                                   |
          sw2p0     sw2p1     sw2p2     sw2p3     sw2p4
       [  user ] [  user ] [  user ] [  user ] [  dsa  ]
      
      The CPU will not be able to ping through the user ports of the
      bottom-most switch (like for example sw2p0), simply because tag_8021q
      was not coded up for this scenario - it has always assumed DSA switch
      trees with a single switch.
      
      To add support for the topology above, we must admit that the RX VLAN of
      sw2p0 must be added on some ports of switches 0 and 1 as well. This is
      in fact a textbook example of thing that can use the cross-chip notifier
      framework that DSA has set up in switch.c.
      
      There is only one problem: core DSA (switch.c) is not able right now to
      make the connection between a struct dsa_switch *ds and a struct
      dsa_8021q_context *ctx. Right now, it is drivers who call into
      tag_8021q.c and always provide a struct dsa_8021q_context *ctx pointer,
      and tag_8021q.c calls them back with the .tag_8021q_vlan_{add,del}
      methods.
      
      But with cross-chip notifiers, it is possible for tag_8021q to call
      drivers without drivers having ever asked for anything. A good example
      is right above: when sw2p0 wants to set itself up for tag_8021q,
      the .tag_8021q_vlan_add method needs to be called for switches 1 and 0,
      so that they transport sw2p0's VLANs towards the CPU without dropping
      them.
      
      So instead of letting drivers manage the tag_8021q context, add a
      tag_8021q_ctx pointer inside of struct dsa_switch, which will be
      populated when dsa_tag_8021q_register() returns success.
      
      The patch is fairly long-winded because we are partly reverting commit
      5899ee36 ("net: dsa: tag_8021q: add a context structure") which made
      the driver-facing tag_8021q API use "ctx" instead of "ds". Now that we
      can access "ctx" directly from "ds", this is no longer needed.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      d7b1fd52
    • V
      net: dsa: tag_8021q: create dsa_tag_8021q_{register,unregister} helpers · cedf4670
      Vladimir Oltean 提交于
      In preparation of moving tag_8021q to core DSA, move all initialization
      and teardown related to tag_8021q which is currently done by drivers in
      2 functions called "register" and "unregister". These will gather more
      functionality in future patches, which will better justify the chosen
      naming scheme.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      cedf4670