1. Jul 03, 2023
    • Vladimir Oltean's avatar
      net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode · 6ca3c005
      Vladimir Oltean authored
      According to the synchronization rules for .ndo_get_stats() as seen in
      Documentation/networking/netdevices.rst, acquiring a plain spin_lock()
      should not be illegal, but the bridge driver implementation makes it so.
      
      After running these commands, I am being faced with the following
      lockdep splat:
      
      $ ip link add link swp0 name macsec0 type macsec encrypt on && ip link set swp0 up
      $ ip link add dev br0 type bridge vlan_filtering 1 && ip link set br0 up
      $ ip link set macsec0 master br0 && ip link set macsec0 up
      
        ========================================================
        WARNING: possible irq lock inversion dependency detected
        6.4.0-04295-g31b577b4bd4a #603 Not tainted
        --------------------------------------------------------
        swapper/1/0 just changed the state of lock:
        ffff6bd348724cd8 (&br->lock){+.-.}-{3:3}, at: br_forward_delay_timer_expired+0x34/0x198
        but this lock took another, SOFTIRQ-unsafe lock in the past:
         (&ocelot->stats_lock){+.+.}-{3:3}
      
        and interrupts could create inverse lock ordering between them.
      
        other info that might help us debug this:
        Chain exists of:
          &br->lock --> &br->hash_lock --> &ocelot->stats_lock
      
         Possible interrupt unsafe locking scenario:
      
               CPU0                    CPU1
               ----                    ----
          lock(&ocelot->stats_lock);
                                       local_irq_disable();
                                       lock(&br->lock);
                                       lock(&br->hash_lock);
          <Interrupt>
            lock(&br->lock);
      
         *** DEADLOCK ***
      
      (details about the 3 locks skipped)
      
      swp0 is instantiated by drivers/net/dsa/ocelot/felix.c, and this
      only matters to the extent that its .ndo_get_stats64() method calls
      spin_lock(&ocelot->stats_lock).
      
      Documentation/locking/lockdep-design.rst says:
      
      | A lock is irq-safe means it was ever used in an irq context, while a lock
      | is irq-unsafe means it was ever acquired with irq enabled.
      
      (...)
      
      | Furthermore, the following usage based lock dependencies are not allowed
      | between any two lock-classes::
      |
      |    <hardirq-safe>   ->  <hardirq-unsafe>
      |    <softirq-safe>   ->  <softirq-unsafe>
      
      Lockdep marks br->hash_lock as softirq-safe, because it is sometimes
      taken in softirq context (for example br_fdb_update() which runs in
      NET_RX softirq), and when it's not in softirq context it blocks softirqs
      by using spin_lock_bh().
      
      Lockdep marks ocelot->stats_lock as softirq-unsafe, because it never
      blocks softirqs from running, and it is never taken from softirq
      context. So it can always be interrupted by softirqs.
      
      There is a call path through which a function that holds br->hash_lock:
      fdb_add_hw_addr() will call a function that acquires ocelot->stats_lock:
      ocelot_port_get_stats64(). This can be seen below:
      
      ocelot_port_get_stats64+0x3c/0x1e0
      felix_get_stats64+0x20/0x38
      dsa_slave_get_stats64+0x3c/0x60
      dev_get_stats+0x74/0x2c8
      rtnl_fill_stats+0x4c/0x150
      rtnl_fill_ifinfo+0x5cc/0x7b8
      rtmsg_ifinfo_build_skb+0xe4/0x150
      rtmsg_ifinfo+0x5c/0xb0
      __dev_notify_flags+0x58/0x200
      __dev_set_promiscuity+0xa0/0x1f8
      dev_set_promiscuity+0x30/0x70
      macsec_dev_change_rx_flags+0x68/0x88
      __dev_set_promiscuity+0x1a8/0x1f8
      __dev_set_rx_mode+0x74/0xa8
      dev_uc_add+0x74/0xa0
      fdb_add_hw_addr+0x68/0xd8
      fdb_add_local+0xc4/0x110
      br_fdb_add_local+0x54/0x88
      br_add_if+0x338/0x4a0
      br_add_slave+0x20/0x38
      do_setlink+0x3a4/0xcb8
      rtnl_newlink+0x758/0x9d0
      rtnetlink_rcv_msg+0x2f0/0x550
      netlink_rcv_skb+0x128/0x148
      rtnetlink_rcv+0x24/0x38
      
      the plain English explanation for it is:
      
      The macsec0 bridge port is created without p->flags & BR_PROMISC,
      because it is what br_manage_promisc() decides for a VLAN filtering
      bridge with a single auto port.
      
      As part of the br_add_if() procedure, br_fdb_add_local() is called for
      the MAC address of the device, and this results in a call to
      dev_uc_add() for macsec0 while the softirq-safe br->hash_lock is taken.
      
      Because macsec0 does not have IFF_UNICAST_FLT, dev_uc_add() ends up
      calling __dev_set_promiscuity() for macsec0, which is propagated by its
      implementation, macsec_dev_change_rx_flags(), to the lower device: swp0.
      This triggers the call path:
      
      dev_set_promiscuity(swp0)
      -> rtmsg_ifinfo()
         -> dev_get_stats()
            -> ocelot_port_get_stats64()
      
      with a calling context that lockdep doesn't like (br->hash_lock held).
      
      Normally we don't see this, because even though many drivers that can be
      bridge ports don't support IFF_UNICAST_FLT, we need a driver that
      
      (a) doesn't support IFF_UNICAST_FLT, *and*
      (b) it forwards the IFF_PROMISC flag to another driver, and
      (c) *that* driver implements ndo_get_stats64() using a softirq-unsafe
          spinlock.
      
      Condition (b) is necessary because the first __dev_set_rx_mode() calls
      __dev_set_promiscuity() with "bool notify=false", and thus, the
      rtmsg_ifinfo() code path won't be entered.
      
      The same criteria also hold true for DSA switches which don't report
      IFF_UNICAST_FLT. When the DSA master uses a spin_lock() in its
      ndo_get_stats64() method, the same lockdep splat can be seen.
      
      I think the deadlock possibility is real, even though I didn't reproduce
      it, and I'm thinking of the following situation to support that claim:
      
      fdb_add_hw_addr() runs on a CPU A, in a context with softirqs locally
      disabled and br->hash_lock held, and may end up attempting to acquire
      ocelot->stats_lock.
      
      In parallel, ocelot->stats_lock is currently held by a thread B (say,
      ocelot_check_stats_work()), which is interrupted while holding it by a
      softirq which attempts to lock br->hash_lock.
      
      Thread B cannot make progress because br->hash_lock is held by A. Whereas
      thread A cannot make progress because ocelot->stats_lock is held by B.
      
      When taking the issue at face value, the bridge can avoid that problem
      by simply making the ports promiscuous from a code path with a saner
      calling context (br->hash_lock not held). A bridge port without
      IFF_UNICAST_FLT is going to become promiscuous as soon as we call
      dev_uc_add() on it (which we do unconditionally), so why not be
      preemptive and make it promiscuous right from the beginning, so as to
      not be taken by surprise.
      
      With this, we've broken the links between code that holds br->hash_lock
      or br->lock and code that calls into the ndo_change_rx_flags() or
      ndo_get_stats64() ops of the bridge port.
      
      Fixes: 2796d0c6
      
       ("bridge: Automatically manage port promiscuous mode.")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
      Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
      6ca3c005
  2. Jul 02, 2023
  3. Jul 01, 2023
  4. Jun 30, 2023
  5. Jun 29, 2023
    • Paolo Abeni's avatar
      Merge branch 'fix-ptp-received-on-wrong-port-with-bridged-sja1105-dsa' · 5998bb76
      Paolo Abeni authored
      Vladimir Oltean says:
      
      ====================
      Fix PTP received on wrong port with bridged SJA1105 DSA
      
      Since the changes were made to tag_8021q to support imprecise RX for
      bridged ports, the tag_sja1105 driver still prefers the source port
      information deduced from the VLAN headers for link-local traffic, even
      though the switch can theoretically do better and report the precise
      source port.
      
      The problem is that the tagger doesn't know when to trust one source of
      information over another, because the INCL_SRCPT option (to "tag" link
      local frames) is sometimes enabled and sometimes it isn't.
      
      The first patch makes the switch provide the hardware tag for link local
      traffic under all circumstances, and the second patch makes the tagger
      always use that hardware tag as primary source of information for link
      local packets.
      ====================
      
      Link: https://lore.kernel.org/r/20230627094207.3385231-1-vladimir.oltean@nxp.com
      
      
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      5998bb76
    • Vladimir Oltean's avatar
      net: dsa: tag_sja1105: always prefer source port information from INCL_SRCPT · c1ae02d8
      Vladimir Oltean authored
      Currently the sja1105 tagging protocol prefers using the source port
      information from the VLAN header if that is available, falling back to
      the INCL_SRCPT option if it isn't. The VLAN header is available for all
      frames except for META frames initiated by the switch (containing RX
      timestamps), and thus, the "if (is_link_local)" branch is practically
      dead.
      
      The tag_8021q source port identification has become more loose
      ("imprecise") and will report a plausible rather than exact bridge port,
      when under a bridge (be it VLAN-aware or VLAN-unaware). But link-local
      traffic always needs to know the precise source port. With incorrect
      source port reporting, for example PTP traffic over 2 bridged ports will
      all be seen on sockets opened on the first such port, which is incorrect.
      
      Now that the tagging protocol has been changed to make link-local frames
      always contain source port information, we can reverse the order of the
      checks so that we always give precedence to that information (which is
      always precise) in lieu of the tag_8021q VID which is only precise for a
      standalone port.
      
      Fixes: d7f9787a ("net: dsa: tag_8021q: add support for imprecise RX based on the VBID")
      Fixes: 91495f21
      
       ("net: dsa: tag_8021q: replace the SVL bridging with VLAN-unaware IVL bridging")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      c1ae02d8
    • Vladimir Oltean's avatar
      net: dsa: sja1105: always enable the INCL_SRCPT option · b4638af8
      Vladimir Oltean authored
      Link-local traffic on bridged SJA1105 ports is sometimes tagged by the
      hardware with source port information (when the port is under a VLAN
      aware bridge).
      
      The tag_8021q source port identification has become more loose
      ("imprecise") and will report a plausible rather than exact bridge port,
      when under a bridge (be it VLAN-aware or VLAN-unaware). But link-local
      traffic always needs to know the precise source port.
      
      Modify the driver logic (and therefore: the tagging protocol itself) to
      always include the source port information with link-local packets,
      regardless of whether the port is standalone, under a VLAN-aware or
      VLAN-unaware bridge. This makes it possible for the tagging driver to
      give priority to that information over the tag_8021q VLAN header.
      
      The big drawback with INCL_SRCPT is that it makes it impossible to
      distinguish between an original MAC DA of 01:80:C2:XX:YY:ZZ and
      01:80:C2:AA:BB:ZZ, because the tagger just patches MAC DA bytes 3 and 4
      with zeroes. Only if PTP RX timestamping is enabled, the switch will
      generate a META follow-up frame containing the RX timestamp and the
      original bytes 3 and 4 of the MAC DA. Those will be used to patch up the
      original packet. Nonetheless, in the absence of PTP RX timestamping, we
      have to live with this limitation, since it is more important to have
      the more precise source port information for link-local traffic.
      
      Fixes: d7f9787a ("net: dsa: tag_8021q: add support for imprecise RX based on the VBID")
      Fixes: 91495f21
      
       ("net: dsa: tag_8021q: replace the SVL bridging with VLAN-unaware IVL bridging")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      b4638af8
    • Paolo Abeni's avatar
      Merge branch 'fix-ptp-packet-drops-with-ocelot-8021q-dsa-tag-protocol' · e999c897
      Paolo Abeni authored
      Vladimir Oltean says:
      
      ====================
      Fix PTP packet drops with ocelot-8021q DSA tag protocol
      
      Changes in v2:
      - Distinguish between L2 and L4 PTP packets
      v1 at:
      https://lore.kernel.org/netdev/20230626154003.3153076-1-vladimir.oltean@nxp.com/
      
      Patch 3/3 fixes an issue with the ocelot/felix driver, where it would
      drop PTP traffic on RX unless hardware timestamping for that packet type
      was enabled.
      
      Fixing that requires the driver to know whether it had previously
      configured the hardware to timestamp PTP packets on that port. But it
      cannot correctly determine that today using the existing code structure,
      so patches 1/3 and 2/3 fix the control path of the code such that
      ocelot->ports[port]->trap_proto faithfully reflects whether that
      configuration took place.
      ====================
      
      Link: https://lore.kernel.org/r/20230627163114.3561597-1-vladimir.oltean@nxp.com
      
      
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      e999c897
    • Vladimir Oltean's avatar
      net: dsa: felix: don't drop PTP frames with tag_8021q when RX timestamping is disabled · 2edcfcbb
      Vladimir Oltean authored
      The driver implements a workaround for the fact that it doesn't have an
      IRQ source to tell it whether PTP frames are available through the
      extraction registers, for those frames to be processed and passed
      towards the network stack. That workaround is to configure the switch,
      through felix_hwtstamp_set() -> felix_update_trapping_destinations(),
      to create two copies of PTP packets: one sent over Ethernet to the DSA
      master, and one to be consumed through the aforementioned CPU extraction
      queue registers.
      
      The reason why we want PTP packets to be consumed through the CPU
      extraction registers in the first place is because we want to see their
      hardware RX timestamp. With tag_8021q, that is only visible that way,
      and it isn't visible with the copy of the packet that's transmitted over
      Ethernet.
      
      The problem with the workaround implementation is that it drops the
      packet received over Ethernet, in expectation of its copy being present
      in the CPU extraction registers. However, if felix_hwtstamp_set() hasn't
      run (aka PTP RX timestamping is disabled), the driver will drop the
      original PTP frame and there will be no copy of it in the CPU extraction
      registers. So, the network stack will simply not see any PTP frame.
      
      Look at the port's trapping configuration to see whether the driver has
      previously enabled the CPU extraction registers. If it hasn't, just
      don't RX timestamp the frame and let it be passed up the stack by DSA,
      which is perfectly fine.
      
      Fixes: 0a6f17c6
      
       ("net: dsa: tag_ocelot_8021q: add support for PTP timestamping")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      2edcfcbb
    • Vladimir Oltean's avatar
      net: mscc: ocelot: don't keep PTP configuration of all ports in single structure · 45d0fcb5
      Vladimir Oltean authored
      In a future change, the driver will need to determine whether PTP RX
      timestamping is enabled on a port (including whether traps were set up
      on that port in particular) and that is currently not possible.
      
      The driver supports different RX filters (L2, L4) and kinds of TX
      timestamping (one-step, two-step) on its ports, but it saves all
      configuration in a single struct hwtstamp_config that is global to the
      switch. So, the latest timestamping configuration on one port
      (including a request to disable timestamping) affects what gets reported
      for all ports, even though the configuration itself is still individual
      to each port.
      
      The port timestamping configurations are only coupled because of the
      common structure, so replace the hwtstamp_config with a mask of trapped
      protocols saved per port. We also have the ptp_cmd to distinguish
      between one-step and two-step PTP timestamping, so with those 2 bits of
      information we can fully reconstruct a descriptive struct
      hwtstamp_config for each port, during the SIOCGHWTSTAMP ioctl.
      
      Fixes: 4e3b0468 ("net: mscc: PTP Hardware Clock (PHC) support")
      Fixes: 96ca08c0
      
       ("net: mscc: ocelot: set up traps for PTP packets")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      45d0fcb5
    • Vladimir Oltean's avatar
      net: mscc: ocelot: don't report that RX timestamping is enabled by default · 4fd44b82
      Vladimir Oltean authored
      PTP RX timestamping should be enabled when the user requests it, not by
      default. If it is enabled by default, it can be problematic when the
      ocelot driver is a DSA master, and it sidesteps what DSA tries to avoid
      through __dsa_master_hwtstamp_validate().
      
      Additionally, after the change which made ocelot trap PTP packets only
      to the CPU at ocelot_hwtstamp_set() time, it is no longer even true that
      RX timestamping is enabled by default, because until ocelot_hwtstamp_set()
      is called, the PTP traps are actually not set up. So the rx_filter field
      of ocelot->hwtstamp_config reflects an incorrect reality.
      
      Fixes: 96ca08c0 ("net: mscc: ocelot: set up traps for PTP packets")
      Fixes: 4e3b0468
      
       ("net: mscc: PTP Hardware Clock (PHC) support")
      Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      4fd44b82
    • Paolo Abeni's avatar
      Merge branch 'net-sched-act_ipt-bug-fixes' · 3c4bb45a
      Paolo Abeni authored
      Florian Westphal says:
      
      ====================
      net/sched: act_ipt bug fixes
      
      v3: prefer skb_header() helper in patch 2.  No other changes.
      I've retained Acks and RvB-Tags of v2.
      
      While checking if netfilter could be updated to replace selected
      instances of NF_DROP with kfree_skb_reason+NF_STOLEN to improve
      debugging info via drop monitor I found that act_ipt is incompatible
      with such an approach.  Moreover, it lacks multiple sanity checks
      to avoid certain code paths that make assumptions that the tc layer
      doesn't meet, such as header sanity checks, availability of skb_dst,
      skb_nfct() and so on.
      
      act_ipt test in the tc selftest still pass with this applied.
      
      I think that we should consider removal of this module, while
      this should take care of all problems, its ipv4 only and I don't
      think there are any netfilter targets that lack a native tc
      equivalent, even when ignoring bpf.
      ====================
      
      Link: https://lore.kernel.org/r/20230627123813.3036-1-fw@strlen.de
      
      
      Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
      3c4bb45a