1. 20 9月, 2022 2 次提交
    • V
      net: dsa: felix: add support for changing DSA master · eca70102
      Vladimir Oltean 提交于
      Changing the DSA master means different things depending on the tagging
      protocol in use.
      
      For NPI mode ("ocelot" and "seville"), there is a single port which can
      be configured as NPI, but DSA only permits changing the CPU port
      affinity of user ports one by one. So changing a user port to a
      different NPI port globally changes what the NPI port is, and breaks the
      user ports still using the old one.
      
      To address this while still permitting the change of the NPI port,
      require that the user ports which are still affine to the old NPI port
      are down, and cannot be brought up until they are all affine to the same
      NPI port.
      
      The tag_8021q mode ("ocelot-8021q") is more flexible, in that each user
      port can be freely assigned to one CPU port or to the other. This works
      by filtering host addresses towards both tag_8021q CPU ports, and then
      restricting the forwarding from a certain user port only to one of the
      two tag_8021q CPU ports.
      
      Additionally, the 2 tag_8021q CPU ports can be placed in a LAG. This
      works by enabling forwarding via PGID_SRC from a certain user port
      towards the logical port ID containing both tag_8021q CPU ports, but
      then restricting forwarding per packet, via the LAG hash codes in
      PGID_AGGR, to either one or the other.
      
      When we change the DSA master to a LAG device, DSA guarantees us that
      the LAG has at least one lower interface as a physical DSA master.
      But DSA masters can come and go as lowers of that LAG, and
      ds->ops->port_change_master() will not get called, because the DSA
      master is still the same (the LAG). So we need to hook into the
      ds->ops->port_lag_{join,leave} calls on the CPU ports and update the
      logical port ID of the LAG that user ports are assigned to.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NPaolo Abeni <pabeni@redhat.com>
      eca70102
    • V
      net: dsa: propagate extack to port_lag_join · 2e359b00
      Vladimir Oltean 提交于
      Drivers could refuse to offload a LAG configuration for a variety of
      reasons, mainly having to do with its TX type. Additionally, since DSA
      masters may now also be LAG interfaces, and this will translate into a
      call to port_lag_join on the CPU ports, there may be extra restrictions
      there. Propagate the netlink extack to this DSA method in order for
      drivers to give a meaningful error message back to the user.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NPaolo Abeni <pabeni@redhat.com>
      2e359b00
  2. 09 9月, 2022 8 次提交
    • V
      net: mscc: ocelot: share the common stat definitions between all drivers · 4d1d157f
      Vladimir Oltean 提交于
      All switch families supported by the ocelot lib (ocelot, felix, seville)
      export the same registers so far. But for example felix also has TSN
      counters, while the others don't.
      
      To reduce the bloat even further, create an OCELOT_COMMON_STATS() macro
      which just lists all stats that are common between switches. The array
      elements are still replicated among all of vsc9959_stats_layout,
      vsc9953_stats_layout and ocelot_stats_layout.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      4d1d157f
    • V
      net: mscc: ocelot: minimize definitions for stats · b69cf1c6
      Vladimir Oltean 提交于
      The current definition of struct ocelot_stat_layout is long-winded (4
      lines per entry, and we have hundreds of entries), so we could make an
      effort to use the C preprocessor and reduce the line count.
      
      Create an implicit correspondence between enum ocelot_reg, which tells
      us the register address (SYS_COUNT_RX_OCTETS etc) and enum ocelot_stat
      which allows us to index the ocelot->stats array (OCELOT_STAT_RX_OCTETS
      etc), and don't require us to specify both when we define what stats
      each switch family has.
      
      Create an OCELOT_STAT() macro that pairs only an enum ocelot_stat to an
      enum ocelot_reg, and an OCELOT_STAT_ETHTOOL() macro which also contains
      a name exported to the unstructured ethtool -S stringset API. For now,
      we define all counters as having the OCELOT_STAT_ETHTOOL() kind, but we
      will add more counters in the future which are not exported to the
      unstructured ethtool -S.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      b69cf1c6
    • V
      net: mscc: ocelot: harmonize names of SYS_COUNT_TX_AGING and OCELOT_STAT_TX_AGED · be5c13f2
      Vladimir Oltean 提交于
      The hardware counter is called C_TX_AGED, so rename SYS_COUNT_TX_AGING
      to SYS_COUNT_TX_AGED. This will become important since we want to
      minimize the way in which we declare struct ocelot_stat_layout elements,
      using the C preprocessor.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      be5c13f2
    • V
      net: mscc: ocelot: add support for all sorts of standardized counters present in DSA · e32036e1
      Vladimir Oltean 提交于
      DSA is integrated with the new standardized ethtool -S --groups option,
      but the felix driver only exports unstructured statistics.
      
      Reuse the array of 64-bit statistics collected by ocelot_check_stats_work(),
      but just export select values from it.
      
      Since ocelot_check_stats_work() runs periodically to avoid 32-bit
      overflow, and the ethtool calling context is sleepable, we update the
      64-bit stats one more time, to provide up-to-date values. The locking
      scheme with a mutex followed by a spinlock is a bit hard to digest, so
      we create and use a ocelot_port_stats_run() helper with a callback that
      populates the ethool stats group the caller is interested in.
      
      The exported stats are:
      ethtool -S swp0 --groups eth-phy
      ethtool -S swp0 --groups eth-mac
      ethtool -S swp0 --groups eth-ctrl
      ethtool -S swp0 --groups rmon
      ethtool --include-statistics --show-pause swp0
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      e32036e1
    • V
      net: dsa: felix: use ocelot's ndo_get_stats64 method · 776b71e5
      Vladimir Oltean 提交于
      Move the logic from the ocelot switchdev driver's ocelot_get_stats64()
      method to the common switch lib and reuse it for the DSA driver.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      776b71e5
    • V
      net: dsa: felix: check the 32-bit PSFP stats against overflow · 25027c84
      Vladimir Oltean 提交于
      The Felix PSFP counters suffer from the same problem as the ocelot
      ndo_get_stats64 ones - they are 32-bit, so they can easily overflow and
      this can easily go undetected.
      
      Add a custom hook in ocelot_check_stats_work() through which driver
      specific actions can be taken, and update the stats for the existing
      PSFP filters from that hook.
      
      Previously, vsc9959_psfp_filter_add() and vsc9959_psfp_filter_del() were
      serialized with respect to each other via rtnl_lock(). However, with the
      new entry point into &psfp->sfi_list coming from the periodic worker, we
      now need an explicit mutex to serialize access to these lists.
      
      We used to keep a struct felix_stream_filter_counters on stack, through
      which vsc9959_psfp_stats_get() - a FLOW_CLS_STATS callback - would
      retrieve data from vsc9959_psfp_counters_get(). We need to become
      smarter about that in 3 ways:
      
      - we need to keep a persistent set of counters for each stream instead
        of keeping them on stack
      
      - we need to promote those counters from u32 to u64, and create a
        procedure that properly keeps 64-bit counters. Since we clear the
        hardware counters anyway, and we poll every 2 seconds, a simple
        increment of a u64 counter with a u32 value will perfectly do the job.
      
      - FLOW_CLS_STATS also expect incremental counters, so we also need to
        zeroize our u64 counters every time sch_flower calls us
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      25027c84
    • V
      net: mscc: ocelot: make access to STAT_VIEW sleepable again · 96980ff7
      Vladimir Oltean 提交于
      To support SPI-controlled switches in the future, access to
      SYS_STAT_CFG_STAT_VIEW needs to be done outside of any spinlock
      protected region, but it still needs to be serialized (by a mutex).
      
      Split the ocelot->stats_lock spinlock into a mutex that serializes
      indirect access to hardware registers (ocelot->stat_view_lock) and a
      spinlock that serializes access to the u64 ocelot->stats array.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      96980ff7
    • V
      net: dsa: felix: add definitions for the stream filter counters · 0a2360c5
      Vladimir Oltean 提交于
      TSN stream (802.1Qci, 802.1CB) filters are also accessed through
      STAT_VIEW, just like the port registers, but these counters are per
      stream, rather than per port. So we don't keep them in
      ocelot_port_update_stats().
      
      What we can do, however, is we can create register definitions for them
      just like we have for the port counters, and delete the last remaining
      user of the SYS_CNT register + a group index (read_gix).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      0a2360c5
  3. 23 8月, 2022 1 次提交
    • V
      net: mscc: ocelot: set up tag_8021q CPU ports independent of user port affinity · 36a0bf44
      Vladimir Oltean 提交于
      This is a partial revert of commit c295f983 ("net: mscc: ocelot:
      switch from {,un}set to {,un}assign for tag_8021q CPU ports"), because
      as it turns out, this isn't how tag_8021q CPU ports under a LAG are
      supposed to work.
      
      Under that scenario, all user ports are "assigned" to the single
      tag_8021q CPU port represented by the logical port corresponding to the
      bonding interface. So one CPU port in a LAG would have is_dsa_8021q_cpu
      set to true (the one whose physical port ID is equal to the logical port
      ID), and the other one to false.
      
      In turn, this makes 2 undesirable things happen:
      
      (1) PGID_CPU contains only the first physical CPU port, rather than both
      (2) only the first CPU port will be added to the private VLANs used by
          ocelot for VLAN-unaware bridging
      
      To make the driver behave in the same way for both bonded CPU ports, we
      need to bring back the old concept of setting up a port as a tag_8021q
      CPU port, and this is what deals with VLAN membership and PGID_CPU
      updating. But we also need the CPU port "assignment" (the user to CPU
      port affinity), and this is what updates the PGID_SRC forwarding rules.
      
      All DSA CPU ports are statically configured for tag_8021q mode when the
      tagging protocol is changed to ocelot-8021q. User ports are "assigned"
      to one CPU port or the other dynamically (this will be handled by a
      future change).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NPaolo Abeni <pabeni@redhat.com>
      36a0bf44
  4. 18 8月, 2022 4 次提交
    • V
      net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset · d4c36765
      Vladimir Oltean 提交于
      With so many counter addresses recently discovered as being wrong, it is
      desirable to at least have a central database of information, rather
      than two: one through the SYS_COUNT_* registers (used for
      ndo_get_stats64), and the other through the offset field of struct
      ocelot_stat_layout elements (used for ethtool -S).
      
      The strategy will be to keep the SYS_COUNT_* definitions as the single
      source of truth, but for that we need to expand our current definitions
      to cover all registers. Then we need to convert the ocelot region
      creation logic, and stats worker, to the read semantics imposed by going
      through SYS_COUNT_* absolute register addresses, rather than offsets
      of 32-bit words relative to SYS_COUNT_RX_OCTETS (which should have been
      SYS_CNT, by the way).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      d4c36765
    • V
      net: mscc: ocelot: make struct ocelot_stat_layout array indexable · 91904600
      Vladimir Oltean 提交于
      The ocelot counters are 32-bit and require periodic reading, every 2
      seconds, by ocelot_port_update_stats(), so that wraparounds are
      detected.
      
      Currently, the counters reported by ocelot_get_stats64() come from the
      32-bit hardware counters directly, rather than from the 64-bit
      accumulated ocelot->stats, and this is a problem for their integrity.
      
      The strategy is to make ocelot_get_stats64() able to cherry-pick
      individual stats from ocelot->stats the way in which it currently reads
      them out from SYS_COUNT_* registers. But currently it can't, because
      ocelot->stats is an opaque u64 array that's used only to feed data into
      ethtool -S.
      
      To solve that problem, we need to make ocelot->stats indexable, and
      associate each element with an element of struct ocelot_stat_layout used
      by ethtool -S.
      
      This makes ocelot_stat_layout a fat (and possibly sparse) array, so we
      need to change the way in which we access it. We no longer need
      OCELOT_STAT_END as a sentinel, because we know the array's size
      (OCELOT_NUM_STATS). We just need to skip the array elements that were
      left unpopulated for the switch revision (ocelot, felix, seville).
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      91904600
    • V
      net: mscc: ocelot: turn stats_lock into a spinlock · 22d842e3
      Vladimir Oltean 提交于
      ocelot_get_stats64() currently runs unlocked and therefore may collide
      with ocelot_port_update_stats() which indirectly accesses the same
      counters. However, ocelot_get_stats64() runs in atomic context, and we
      cannot simply take the sleepable ocelot->stats_lock mutex. We need to
      convert it to an atomic spinlock first. Do that as a preparatory change.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      22d842e3
    • V
      net: mscc: ocelot: fix incorrect ndo_get_stats64 packet counters · 5152de7b
      Vladimir Oltean 提交于
      Reading stats using the SYS_COUNT_* register definitions is only used by
      ocelot_get_stats64() from the ocelot switchdev driver, however,
      currently the bucket definitions are incorrect.
      
      Separately, on both RX and TX, we have the following problems:
      - a 256-1023 bucket which actually tracks the 256-511 packets
      - the 1024-1526 bucket actually tracks the 512-1023 packets
      - the 1527-max bucket actually tracks the 1024-1526 packets
      
      => nobody tracks the packets from the real 1527-max bucket
      
      Additionally, the RX_PAUSE, RX_CONTROL, RX_LONGS and RX_CLASSIFIED_DROPS
      all track the wrong thing. However this doesn't seem to have any
      consequence, since ocelot_get_stats64() doesn't use these.
      
      Even though this problem only manifests itself for the switchdev driver,
      we cannot split the fix for ocelot and for DSA, since it requires fixing
      the bucket definitions from enum ocelot_reg, which makes us necessarily
      adapt the structures from felix and seville as well.
      
      Fixes: 84705fc1 ("net: dsa: felix: introduce support for Seville VSC9953 switch")
      Fixes: 56051948 ("net: dsa: ocelot: add driver for Felix switch family")
      Fixes: a556c76a ("net: mscc: Add initial Ocelot switch support")
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      5152de7b
  5. 01 7月, 2022 1 次提交
  6. 19 6月, 2022 1 次提交
    • X
      net: dsa: felix: update base time of time-aware shaper when adjusting PTP time · 8670dc33
      Xiaoliang Yang 提交于
      When adjusting the PTP clock, the base time of the TAS configuration
      will become unreliable. We need reset the TAS configuration by using a
      new base time.
      
      For example, if the driver gets a base time 0 of Qbv configuration from
      user, and current time is 20000. The driver will set the TAS base time
      to be 20000. After the PTP clock adjustment, the current time becomes
      10000. If the TAS base time is still 20000, it will be a future time,
      and TAS entry list will stop running. Another example, if the current
      time becomes to be 10000000 after PTP clock adjust, a large time offset
      can cause the hardware to hang.
      
      This patch introduces a tas_clock_adjust() function to reset the TAS
      module by using a new base time after the PTP clock adjustment. This can
      avoid issues above.
      
      Due to PTP clock adjustment can occur at any time, it may conflict with
      the TAS configuration. We introduce a new TAS lock to serialize the
      access to the TAS registers.
      Signed-off-by: NXiaoliang Yang <xiaoliang.yang_1@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      8670dc33
  7. 23 5月, 2022 2 次提交
    • V
      net: mscc: ocelot: switch from {,un}set to {,un}assign for tag_8021q CPU ports · c295f983
      Vladimir Oltean 提交于
      There is a desire for the felix driver to gain support for multiple
      tag_8021q CPU ports, but the current model prevents it.
      
      This is because ocelot_apply_bridge_fwd_mask() only takes into
      consideration whether a port is a tag_8021q CPU port, but not whose CPU
      port it is.
      
      We need a model where we can have a direct affinity between an ocelot
      port and a tag_8021q CPU port. This serves as the basis for multiple CPU
      ports.
      
      Declare a "dsa_8021q_cpu" backpointer in struct ocelot_port which
      encodes that affinity. Repurpose the "ocelot_set_dsa_8021q_cpu" API to
      "ocelot_assign_dsa_8021q_cpu" to express the change of paradigm.
      
      Note that this change makes the first practical use of the new
      ocelot_port->index field in ocelot_port_unassign_dsa_8021q_cpu(), where
      we need to remove the old tag_8021q CPU port from the reserved VLAN range.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      c295f983
    • V
      net: dsa: felix: update bridge fwd mask from ocelot lib when changing tag_8021q CPU · a72e23dd
      Vladimir Oltean 提交于
      Add more logic to ocelot_port_{,un}set_dsa_8021q_cpu() from the ocelot
      switch lib by encapsulating the ocelot_apply_bridge_fwd_mask() call that
      felix used to have.
      
      This is necessary because the CPU port change procedure will also need
      to do this, and it's good to reduce code duplication by having an entry
      point in the ocelot switch lib that does all that is needed.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      a72e23dd
  8. 13 5月, 2022 3 次提交
    • V
      net: mscc: ocelot: move ocelot_port_private :: chip_port to ocelot_port :: index · 7e708760
      Vladimir Oltean 提交于
      Currently the ocelot switch lib is unaware of the index of a struct
      ocelot_port, since that is kept in the encapsulating structures of outer
      drivers (struct dsa_port :: index, struct ocelot_port_private :: chip_port).
      
      With the upcoming increase in complexity associated with assigning DSA
      tag_8021q CPU ports to certain user ports, it becomes necessary for the
      switch lib to be able to retrieve the index of a certain ocelot_port.
      
      Therefore, introduce a new u8 to ocelot_port (same size as the chip_port
      used by the ocelot switchdev driver) and rework the existing code to
      populate and use it.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      7e708760
    • V
      net: mscc: ocelot: minimize holes in struct ocelot_port · 6d0be600
      Vladimir Oltean 提交于
      Reorder members of struct ocelot_port to eliminate holes and reduce
      structure size. Pahole says:
      
      Before:
      
      struct ocelot_port {
              struct ocelot *            ocelot;               /*     0     8 */
              struct regmap *            target;               /*     8     8 */
              bool                       vlan_aware;           /*    16     1 */
      
              /* XXX 7 bytes hole, try to pack */
      
              const struct ocelot_bridge_vlan  * pvid_vlan;    /*    24     8 */
              unsigned int               ptp_skbs_in_flight;   /*    32     4 */
              u8                         ptp_cmd;              /*    36     1 */
      
              /* XXX 3 bytes hole, try to pack */
      
              struct sk_buff_head        tx_skbs;              /*    40    96 */
              /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
              u8                         ts_id;                /*   136     1 */
      
              /* XXX 3 bytes hole, try to pack */
      
              phy_interface_t            phy_mode;             /*   140     4 */
              bool                       is_dsa_8021q_cpu;     /*   144     1 */
              bool                       learn_ena;            /*   145     1 */
      
              /* XXX 6 bytes hole, try to pack */
      
              struct net_device *        bond;                 /*   152     8 */
              bool                       lag_tx_active;        /*   160     1 */
      
              /* XXX 1 byte hole, try to pack */
      
              u16                        mrp_ring_id;          /*   162     2 */
      
              /* XXX 4 bytes hole, try to pack */
      
              struct net_device *        bridge;               /*   168     8 */
              int                        bridge_num;           /*   176     4 */
              u8                         stp_state;            /*   180     1 */
      
              /* XXX 3 bytes hole, try to pack */
      
              int                        speed;                /*   184     4 */
      
              /* size: 192, cachelines: 3, members: 18 */
              /* sum members: 161, holes: 7, sum holes: 27 */
              /* padding: 4 */
      };
      
      After:
      
      struct ocelot_port {
              struct ocelot *            ocelot;               /*     0     8 */
              struct regmap *            target;               /*     8     8 */
              struct net_device *        bond;                 /*    16     8 */
              struct net_device *        bridge;               /*    24     8 */
              const struct ocelot_bridge_vlan  * pvid_vlan;    /*    32     8 */
              phy_interface_t            phy_mode;             /*    40     4 */
              unsigned int               ptp_skbs_in_flight;   /*    44     4 */
              struct sk_buff_head        tx_skbs;              /*    48    96 */
              /* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */
              u16                        mrp_ring_id;          /*   144     2 */
              u8                         ptp_cmd;              /*   146     1 */
              u8                         ts_id;                /*   147     1 */
              u8                         stp_state;            /*   148     1 */
              bool                       vlan_aware;           /*   149     1 */
              bool                       is_dsa_8021q_cpu;     /*   150     1 */
              bool                       learn_ena;            /*   151     1 */
              bool                       lag_tx_active;        /*   152     1 */
      
              /* XXX 3 bytes hole, try to pack */
      
              int                        bridge_num;           /*   156     4 */
              int                        speed;                /*   160     4 */
      
              /* size: 168, cachelines: 3, members: 18 */
              /* sum members: 161, holes: 1, sum holes: 3 */
              /* padding: 4 */
              /* last cacheline: 40 bytes */
      };
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      6d0be600
    • V
      net: mscc: ocelot: delete ocelot_port :: xmit_template · 15f6d01e
      Vladimir Oltean 提交于
      This is no longer used since commit 7c4bb540 ("net: dsa: tag_ocelot:
      create separate tagger for Seville").
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      15f6d01e
  9. 07 5月, 2022 1 次提交
  10. 03 5月, 2022 2 次提交
  11. 30 4月, 2022 1 次提交
    • C
      net: ethernet: ocelot: remove the need for num_stats initializer · 2f187bfa
      Colin Foster 提交于
      There is a desire to share the oclot_stats_layout struct outside of the
      current vsc7514 driver. In order to do so, the length of the array needs to
      be known at compile time, and defined in the struct ocelot and struct
      felix_info.
      
      Since the array is defined in a .c file and would be declared in the header
      file via:
      extern struct ocelot_stat_layout[];
      the size of the array will not be known at compile time to outside modules.
      
      To fix this, remove the need for defining the number of stats at compile
      time and allow this number to be determined at initialization.
      Signed-off-by: NColin Foster <colin.foster@in-advantage.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      2f187bfa
  12. 18 3月, 2022 1 次提交
    • V
      net: mscc: ocelot: add port mirroring support using tc-matchall · ccb6ed42
      Vladimir Oltean 提交于
      Ocelot switches perform port-based ingress mirroring if
      ANA:PORT:PORT_CFG field SRC_MIRROR_ENA is set, and egress mirroring if
      the port is in ANA:ANA:EMIRRORPORTS.
      
      Both ingress-mirrored and egress-mirrored frames are copied to the port
      mask from ANA:ANA:MIRRORPORTS.
      
      So the choice of limiting to a single mirror port via ocelot_mirror_get()
      and ocelot_mirror_put() may seem bizarre, but the hardware model doesn't
      map very well to the user space model. If the user wants to mirror the
      ingress of swp1 towards swp2 and the ingress of swp3 towards swp4, we'd
      have to program ANA:ANA:MIRRORPORTS with BIT(2) | BIT(4), and that would
      make swp1 be mirrored towards swp4 too, and swp3 towards swp2. But there
      are no tc-matchall rules to describe those actions.
      
      Now, we could offload a matchall rule with multiple mirred actions, one
      per desired mirror port, and force the user to stick to the multi-action
      rule format for subsequent matchall filters. But both DSA and ocelot
      have the flow_offload_has_one_action() check for the matchall offload,
      plus the fact that it will get cumbersome to cross-check matchall
      mirrors with flower mirrors (which will be added in the next patch).
      
      As a result, we limit the configuration to a single mirror port, with
      the possibility of lifting the restriction in the future.
      
      Frames injected from the CPU don't get egress-mirrored, since they are
      sent with the BYPASS bit in the injection frame header, and this
      bypasses the analyzer module (effectively also the mirroring logic).
      I don't know what to do/say about this.
      
      Functionality was tested with:
      
      tc qdisc add dev swp3 clsact
      tc filter add dev swp3 ingress \
      	matchall skip_sw \
      	action mirred egress mirror dev swp1
      
      and pinging through swp3, while seeing that the ICMP replies are
      mirrored towards swp1.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      ccb6ed42
  13. 14 3月, 2022 1 次提交
    • V
      net: dsa: felix: configure default-prio and dscp priorities · 978777d0
      Vladimir Oltean 提交于
      Follow the established programming model for this driver and provide
      shims in the felix DSA driver which call the implementations from the
      ocelot switch lib. The ocelot switchdev driver wasn't integrated with
      dcbnl due to lack of hardware availability.
      
      The switch doesn't have any fancy QoS classification enabled by default.
      The provided getters will create a default-prio app table entry of 0,
      and no dscp entry. However, the getters have been made to actually
      retrieve the hardware configuration rather than static values, to be
      future proof in case DSA will need this information from more call paths.
      
      For default-prio, there is a single field per port, in ANA_PORT_QOS_CFG,
      called QOS_DEFAULT_VAL.
      
      DSCP classification is enabled per-port, again via ANA_PORT_QOS_CFG
      (field QOS_DSCP_ENA), and individual DSCP values are configured as
      trusted or not through register ANA_DSCP_CFG (replicated 64 times).
      An untrusted DSCP value falls back to other QoS classification methods.
      If trusted, the selected ANA_DSCP_CFG register also holds the QoS class
      in the QOS_DSCP_VAL field.
      
      The hardware also supports DSCP remapping (DSCP value X is translated to
      DSCP value Y before the QoS class is determined based on the app table
      entry for Y) and DSCP packet rewriting. The dcbnl framework, for being
      so flexible in other useless areas, doesn't appear to support this.
      So this functionality has been left out.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      978777d0
  14. 27 2月, 2022 1 次提交
    • V
      net: mscc: ocelot: enforce FDB isolation when VLAN-unaware · 54c31984
      Vladimir Oltean 提交于
      Currently ocelot uses a pvid of 0 for standalone ports and ports under a
      VLAN-unaware bridge, and the pvid of the bridge for ports under a
      VLAN-aware bridge. Standalone ports do not perform learning, but packets
      received on them are still subject to FDB lookups. So if the MAC DA that
      a standalone port receives has been also learned on a VLAN-unaware
      bridge port, ocelot will attempt to forward to that port, even though it
      can't, so it will drop packets.
      
      So there is a desire to avoid that, and isolate the FDBs of different
      bridges from one another, and from standalone ports.
      
      The ocelot switch library has two distinct entry points: the felix DSA
      driver and the ocelot switchdev driver.
      
      We need to code up a minimal bridge_num allocation in the ocelot
      switchdev driver too, this is copied from DSA with the exception that
      ocelot does not care about DSA trees, cross-chip bridging etc. So it
      only looks at its own ports that are already in the same bridge.
      
      The ocelot switchdev driver uses the bridge_num it has allocated itself,
      while the felix driver uses the bridge_num allocated by DSA. They are
      both stored inside ocelot_port->bridge_num by the common function
      ocelot_port_bridge_join() which receives the bridge_num passed by value.
      
      Once we have a bridge_num, we can only use it to enforce isolation
      between VLAN-unaware bridges. As far as I can see, ocelot does not have
      anything like a FID that further makes VLAN 100 from a port be different
      to VLAN 100 from another port with regard to FDB lookup. So we simply
      deny multiple VLAN-aware bridges.
      
      For VLAN-unaware bridges, we crop the 4000-4095 VLAN region and we
      allocate a VLAN for each bridge_num. This will be used as the pvid of
      each port that is under that VLAN-unaware bridge, for as long as that
      bridge is VLAN-unaware.
      
      VID 0 remains only for standalone ports. It is okay if all standalone
      ports use the same VID 0, since they perform no address learning, the
      FDB will contain no entry in VLAN 0, so the packets will always be
      flooded to the only possible destination, the CPU port.
      
      The CPU port module doesn't need to be member of the VLANs to receive
      packets, but if we use the DSA tag_8021q protocol, those packets are
      part of the data plane as far as ocelot is concerned, so there it needs
      to. Just ensure that the DSA tag_8021q CPU port is a member of all
      reserved VLANs when it is created, and is removed when it is deleted.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NDavid S. Miller <davem@davemloft.net>
      54c31984
  15. 25 2月, 2022 1 次提交
    • V
      net: dsa: felix: support FDB entries on offloaded LAG interfaces · 961d8b69
      Vladimir Oltean 提交于
      This adds the logic in the Felix DSA driver and Ocelot switch library.
      For Ocelot switches, the DEST_IDX that is the output of the MAC table
      lookup is a logical port (equal to physical port, if no LAG is used, or
      a dynamically allocated number otherwise). The allocation we have in
      place for LAG IDs is different from DSA's, so we can't use that:
      - DSA allocates a continuous range of LAG IDs starting from 1
      - Ocelot appears to require that physical ports and LAG IDs are in the
        same space of [0, num_phys_ports), and additionally, ports that aren't
        in a LAG must have physical port id == logical port id
      
      The implication is that an FDB entry towards a LAG might need to be
      deleted and reinstalled when the LAG ID changes.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: NJakub Kicinski <kuba@kernel.org>
      961d8b69
  16. 17 2月, 2022 2 次提交
  17. 14 2月, 2022 3 次提交
  18. 08 1月, 2022 1 次提交
  19. 11 12月, 2021 3 次提交
  20. 26 11月, 2021 1 次提交
    • V
      net: dsa: felix: enable cut-through forwarding between ports by default · 8abe1970
      Vladimir Oltean 提交于
      The VSC9959 switch embedded within NXP LS1028A (and that version of
      Ocelot switches only) supports cut-through forwarding - meaning it can
      start the process of looking up the destination ports for a packet, and
      forward towards those ports, before the entire packet has been received
      (as opposed to the store-and-forward mode).
      
      The up side is having lower forwarding latency for large packets. The
      down side is that frames with FCS errors are forwarded instead of being
      dropped. However, erroneous frames do not result in incorrect updates of
      the FDB or incorrect policer updates, since these processes are deferred
      inside the switch to the end of frame. Since the switch starts the
      cut-through forwarding process after all packet headers (including IP,
      if any) have been processed, packets with large headers and small
      payload do not see the benefit of lower forwarding latency.
      
      There are two cases that need special attention.
      
      The first is when a packet is multicast (or flooded) to multiple
      destinations, one of which doesn't have cut-through forwarding enabled.
      The switch deals with this automatically by disabling cut-through
      forwarding for the frame towards all destination ports.
      
      The second is when a packet is forwarded from a port of lower link speed
      towards a port of higher link speed. This is not handled by the hardware
      and needs software intervention.
      
      Since we practically need to update the cut-through forwarding domain
      from paths that aren't serialized by the rtnl_mutex (phylink
      mac_link_down/mac_link_up ops), this means we need to serialize physical
      link events with user space updates of bonding/bridging domains.
      
      Enabling cut-through forwarding is done per {egress port, traffic class}.
      I don't see any reason why this would be a configurable option as long
      as it works without issues, and there doesn't appear to be any user
      space configuration tool to toggle this on/off, so this patch enables
      cut-through forwarding on all eligible ports and traffic classes.
      Signed-off-by: NVladimir Oltean <vladimir.oltean@nxp.com>
      Link: https://lore.kernel.org/r/20211125125808.2383984-2-vladimir.oltean@nxp.comSigned-off-by: NJakub Kicinski <kuba@kernel.org>
      8abe1970