Skip to content
  1. Dec 09, 2021
    • Vladimir Oltean's avatar
      net: dsa: keep the bridge_dev and bridge_num as part of the same structure · d3eed0e5
      Vladimir Oltean authored
      
      
      The main desire behind this is to provide coherent bridge information to
      the fast path without locking.
      
      For example, right now we set dp->bridge_dev and dp->bridge_num from
      separate code paths, it is theoretically possible for a packet
      transmission to read these two port properties consecutively and find a
      bridge number which does not correspond with the bridge device.
      
      Another desire is to start passing more complex bridge information to
      dsa_switch_ops functions. For example, with FDB isolation, it is
      expected that drivers will need to be passed the bridge which requested
      an FDB/MDB entry to be offloaded, and along with that bridge_dev, the
      associated bridge_num should be passed too, in case the driver might
      want to implement an isolation scheme based on that number.
      
      We already pass the {bridge_dev, bridge_num} pair to the TX forwarding
      offload switch API, however we'd like to remove that and squash it into
      the basic bridge join/leave API. So that means we need to pass this
      pair to the bridge join/leave API.
      
      During dsa_port_bridge_leave, first we unset dp->bridge_dev, then we
      call the driver's .port_bridge_leave with what used to be our
      dp->bridge_dev, but provided as an argument.
      
      When bridge_dev and bridge_num get folded into a single structure, we
      need to preserve this behavior in dsa_port_bridge_leave: we need a copy
      of what used to be in dp->bridge.
      
      Switch drivers check bridge membership by comparing dp->bridge_dev with
      the provided bridge_dev, but now, if we provide the struct dsa_bridge as
      a pointer, they cannot keep comparing dp->bridge to the provided
      pointer, since this only points to an on-stack copy. To make this
      obvious and prevent driver writers from forgetting and doing stupid
      things, in this new API, the struct dsa_bridge is provided as a full
      structure (not very large, contains an int and a pointer) instead of a
      pointer. An explicit comparison function needs to be used to determine
      bridge membership: dsa_port_offloads_bridge().
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      d3eed0e5
    • Vladimir Oltean's avatar
      net: dsa: export bridging offload helpers to drivers · 6a43cba3
      Vladimir Oltean authored
      
      
      Move the static inline helpers from net/dsa/dsa_priv.h to
      include/net/dsa.h, so that drivers can call functions such as
      dsa_port_offloads_bridge_dev(), which will be necessary after the
      transition to a more complex bridge structure.
      
      More functions than are needed right now are being moved, but this is
      done for uniformity.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      6a43cba3
    • Vladimir Oltean's avatar
      net: dsa: rename dsa_port_offloads_bridge to dsa_port_offloads_bridge_dev · 936db8a2
      Vladimir Oltean authored
      
      
      Currently the majority of dsa_port_bridge_dev_get() calls in drivers is
      just to check whether a port is under the bridge device provided as
      argument by the DSA API.
      
      We'd like to change that DSA API so that a more complex structure is
      provided as argument. To keep things more generic, and considering that
      the new complex structure will be provided by value and not by
      reference, direct comparisons between dp->bridge and the provided bridge
      will be broken. The generic way to do the checking would simply be to
      do something like dsa_port_offloads_bridge(dp, &bridge).
      
      But there's a problem, we already have a function named that way, which
      actually takes a bridge_dev net_device as argument. Rename it so that we
      can use dsa_port_offloads_bridge for something else.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      936db8a2
    • Vladimir Oltean's avatar
      net: dsa: hide dp->bridge_dev and dp->bridge_num in drivers behind helpers · 41fb0cf1
      Vladimir Oltean authored
      
      
      The location of the bridge device pointer and number is going to change.
      It is not going to be kept individually per port, but in a common
      structure allocated dynamically and which will have lockdep validation.
      
      Use the helpers to access these elements so that we have a migration
      path to the new organization.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      41fb0cf1
    • Vladimir Oltean's avatar
      net: dsa: hide dp->bridge_dev and dp->bridge_num in the core behind helpers · 36cbf39b
      Vladimir Oltean authored
      
      
      The location of the bridge device pointer and number is going to change.
      It is not going to be kept individually per port, but in a common
      structure allocated dynamically and which will have lockdep validation.
      
      Create helpers to access these elements so that we have a migration path
      to the new organization.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      36cbf39b
    • Vladimir Oltean's avatar
      net: dsa: mv88e6xxx: compute port vlan membership based on dp->bridge_dev comparison · 65144067
      Vladimir Oltean authored
      
      
      The goal of this change is to reduce mv88e6xxx_port_vlan() to a form
      where dsa_port_bridge_same() can be used, since the dp->bridge_dev
      pointer will be hidden in a future change.
      
      To do that, we observe that the "br" pointer is deduced from a
      dp->bridge_dev in both cases (of a physical switch port as well as a
      virtual bridge). So instead of keeping the "br" pointer, we can just
      keep the "dp" pointer from which "br" gets derived.
      
      In the last iteration over switch ports, we must use another iterator
      variable, "other_dp"since now we use the "dp" variable to keep an
      indirect reference to the bridge. While at it, the old code used to
      filter only the ports which were part of the same switch as "ds".
      There exists a dedicated DSA port iterator for that:
      dsa_switch_for_each_port (which skips the ports in the tree that belong
      to non-local switches), so we can just use that.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      65144067
    • Vladimir Oltean's avatar
      net: dsa: mv88e6xxx: iterate using dsa_switch_for_each_user_port in mv88e6xxx_port_check_hw_vlan · 0493fa79
      Vladimir Oltean authored
      
      
      Avoid a plethora of dsa_to_port() calls (some hidden behind
      dsa_is_*_port and some in plain sight) by keeping two struct dsa_port
      references: one to the port passed as argument, and another to the other
      ports of the switch that we're iterating over.
      
      This isn't called from the DSA initialization path, so there is no risk
      that we have user ports without a dp->slave populated. So the combined
      checks that a port isn't a DSA port, a CPU port, or doesn't have a slave
      net device (therefore is unused), are strictly equivalent to the simple
      check that the port is a user port. This is already handled by the DSA
      iterator.
      
      i gets replaced by other_dp->index, dsa_is_*_port calls get replaced by
      dsa_port_is_*, and dsa_to_port gets replaced by the respective pointer
      directly.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      0493fa79
    • Vladimir Oltean's avatar
      net: dsa: mt7530: iterate using dsa_switch_for_each_user_port in bridging ops · 872bb81d
      Vladimir Oltean authored
      
      
      Avoid repeated calls to dsa_to_port() (some hidden behind dsa_is_user_port
      and some in plain sight) by keeping two struct dsa_port references: one
      to the port passed as argument, and another to the other ports of the
      switch that we're iterating over.
      
      dsa_to_port(ds, i) gets replaced by other_dp, i gets replaced by
      other_port which is derived from other_dp->index, dsa_is_user_port is
      handled by the DSA iterator.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      872bb81d
    • Vladimir Oltean's avatar
      net: dsa: assign a bridge number even without TX forwarding offload · 947c8746
      Vladimir Oltean authored
      
      
      The service where DSA assigns a unique bridge number for each forwarding
      domain is useful even for drivers which do not implement the TX
      forwarding offload feature.
      
      For example, drivers might use the dp->bridge_num for FDB isolation.
      
      So rename ds->num_fwd_offloading_bridges to ds->max_num_bridges, and
      calculate a unique bridge_num for all drivers that set this value.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      947c8746
    • Vladimir Oltean's avatar
      net: dsa: make dp->bridge_num one-based · 3f9bb030
      Vladimir Oltean authored
      I have seen too many bugs already due to the fact that we must encode an
      invalid dp->bridge_num as a negative value, because the natural tendency
      is to check that invalid value using (!dp->bridge_num). Latest example
      can be seen in commit 1bec0f05
      
       ("net: dsa: fix bridge_num not
      getting cleared after ports leaving the bridge").
      
      Convert the existing users to assume that dp->bridge_num == 0 is the
      encoding for invalid, and valid bridge numbers start from 1.
      
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
      Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      3f9bb030
  2. Dec 08, 2021