2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

Compare commits

...

90 Commits

Author SHA1 Message Date
Linus Torvalds
6439a0e64c Including fixes from Bluetooth.
Current release - fix to a fix:
 
  - usb: asix_devices: fix PHY address mask in MDIO bus initialization
 
 Current release - regressions:
 
  - Bluetooth: fixes for the split between BIS_LINK and PA_LINK
 
  - Revert "net: cadence: macb: sama7g5_emac: Remove USARIO CLKEN flag",
    breaks compatibility with some existing device tree blobs
 
  - dsa: b53: fix reserved register access in b53_fdb_dump()
 
 Current release - new code bugs:
 
  - sched: dualpi2: run probability update timer in BH to avoid deadlock
 
  - eth: libwx: fix the size in RSS hash key population
 
  - pse-pd: pd692x0: improve power budget error paths and handling
 
 Previous releases - regressions:
 
  - tls: fix handling of zero-length records on the rx_list
 
  - hsr: reject HSR frame if skb can't hold tag
 
  - bonding: fix negotiation flapping in 802.3ad passive mode
 
 Previous releases - always broken:
 
  - gso: forbid IPv6 TSO with extensions on devices with only IPV6_CSUM
 
  - sched: make cake_enqueue return NET_XMIT_CN when past buffer_limit,
    avoid packet drops with low buffer_limit, remove unnecessary WARN()
 
  - sched: fix backlog accounting after modifying config of a qdisc
    in the middle of the hierarchy
 
  - mptcp: improve handling of skb extension allocation failures
 
  - eth: mlx5:
    - fixes for the "HW Steering" flow management method
    - fixes for QoS and device buffer management
 
 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAminVEUACgkQMUZtbf5S
 Irtt/g//YoT8G6Wzv3unTf+qYl/pia7936VqW/W51A7UyCZp2bfDi8/r8eIl+bCf
 8KbUH2nSTUPEsngRrzoXhbVAXs6AFe3WKA89efCeal+GFPPA43A5+BZKaXBRE14M
 DgSCo1mYjrVIMENv33LttjQOYjLIBu4finciqIkLj/rOeyRZUURlModQW+aA800K
 QhXKt0BYniL7tg4ChW3/TQMNpRVLnfae6cu/CKjv/rmzdioVZRChC/cGPI0xctpq
 kAIJa49i6dNGtNMWFtS+YaDjTFWS05R9y5bSiylLUnqply9+sWrF1VZIGHXMOcv8
 uzxLIlZhvSQycETMinPf0w02H3PuuqpKH8X+1c77Z7/wHmCn5ht2QVv1BwgFu4hv
 MZm+zRYKZDdkdYCqujD/XmqF/D7t49LIql8WctxwgWus2yTfg089+9H2VHEj2kyl
 S6FBI6f3ZwwLGh6MCAcqswbGc/6QSVFg2ndW6QFxl85Py3fTefV0Y3OknSkXqom/
 2azpWNX6zoKfB6QSW4ZrfPFvuDAV8Ai5OJCTpw/3gkbquUMgx+mN2wf2/t8hPbci
 Qkh5Y9/44gQFY9KaLx8N7Xr1FBTQ4c21QnG67gvflw3mNMdr3ot0isGTCtjty/eC
 abQ+KvQwxy8rVnlunYC8REAAFxQi3AtCiFBE/vioVApNQtsqm68=
 =waf0
 -----END PGP SIGNATURE-----

Merge tag 'net-6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Jakub Kicinski:
 "Including fixes from Bluetooth.

  Current release - fix to a fix:

   - usb: asix_devices: fix PHY address mask in MDIO bus initialization

  Current release - regressions:

   - Bluetooth: fixes for the split between BIS_LINK and PA_LINK

   - Revert "net: cadence: macb: sama7g5_emac: Remove USARIO CLKEN
     flag", breaks compatibility with some existing device tree blobs

   - dsa: b53: fix reserved register access in b53_fdb_dump()

  Current release - new code bugs:

   - sched: dualpi2: run probability update timer in BH to avoid
     deadlock

   - eth: libwx: fix the size in RSS hash key population

   - pse-pd: pd692x0: improve power budget error paths and handling

  Previous releases - regressions:

   - tls: fix handling of zero-length records on the rx_list

   - hsr: reject HSR frame if skb can't hold tag

   - bonding: fix negotiation flapping in 802.3ad passive mode

  Previous releases - always broken:

   - gso: forbid IPv6 TSO with extensions on devices with only IPV6_CSUM

   - sched: make cake_enqueue return NET_XMIT_CN when past buffer_limit,
     avoid packet drops with low buffer_limit, remove unnecessary WARN()

   - sched: fix backlog accounting after modifying config of a qdisc in
     the middle of the hierarchy

   - mptcp: improve handling of skb extension allocation failures

   - eth: mlx5:
       - fixes for the "HW Steering" flow management method
       - fixes for QoS and device buffer management"

* tag 'net-6.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (81 commits)
  netfilter: nf_reject: don't leak dst refcount for loopback packets
  net/mlx5e: Preserve shared buffer capacity during headroom updates
  net/mlx5e: Query FW for buffer ownership
  net/mlx5: Restore missing scheduling node cleanup on vport enable failure
  net/mlx5: Fix QoS reference leak in vport enable error path
  net/mlx5: Destroy vport QoS element when no configuration remains
  net/mlx5e: Preserve tc-bw during parent changes
  net/mlx5: Remove default QoS group and attach vports directly to root TSAR
  net/mlx5: Base ECVF devlink port attrs from 0
  net: pse-pd: pd692x0: Skip power budget configuration when undefined
  net: pse-pd: pd692x0: Fix power budget leak in manager setup error path
  Octeontx2-af: Skip overlap check for SPI field
  selftests: tls: add tests for zero-length records
  tls: fix handling of zero-length records on the rx_list
  net: airoha: ppe: Do not invalid PPE entries in case of SW hash collision
  selftests: bonding: add test for passive LACP mode
  bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
  bonding: update LACP activity flag after setting lacp_active
  Revert "net: cadence: macb: sama7g5_emac: Remove USARIO CLKEN flag"
  ipv6: sr: Fix MAC comparison to be constant-time
  ...
2025-08-21 13:51:15 -04:00
Florian Westphal
91a79b7922 netfilter: nf_reject: don't leak dst refcount for loopback packets
recent patches to add a WARN() when replacing skb dst entry found an
old bug:

WARNING: include/linux/skbuff.h:1165 skb_dst_check_unset include/linux/skbuff.h:1164 [inline]
WARNING: include/linux/skbuff.h:1165 skb_dst_set include/linux/skbuff.h:1210 [inline]
WARNING: include/linux/skbuff.h:1165 nf_reject_fill_skb_dst+0x2a4/0x330 net/ipv4/netfilter/nf_reject_ipv4.c:234
[..]
Call Trace:
 nf_send_unreach+0x17b/0x6e0 net/ipv4/netfilter/nf_reject_ipv4.c:325
 nft_reject_inet_eval+0x4bc/0x690 net/netfilter/nft_reject_inet.c:27
 expr_call_ops_eval net/netfilter/nf_tables_core.c:237 [inline]
 ..

This is because blamed commit forgot about loopback packets.
Such packets already have a dst_entry attached, even at PRE_ROUTING stage.

Instead of checking hook just check if the skb already has a route
attached to it.

Fixes: f53b9b0bdc ("netfilter: introduce support for reject at prerouting stage")
Signed-off-by: Florian Westphal <fw@strlen.de>
Link: https://patch.msgid.link/20250820123707.10671-1-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 10:02:00 -07:00
Jakub Kicinski
1b78236a05 Merge branch 'mlx5-misx-fixes-2025-08-20'
Mark Bloch says:

====================
mlx5 misx fixes 2025-08-20

This patchset provides misc bug fixes from the team to the mlx5
core and Eth drivers.

v1: https://lore.kernel.org/1755095476-414026-1-git-send-email-tariqt@nvidia.com
====================

Link: https://patch.msgid.link/20250820133209.389065-1-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:36 -07:00
Armen Ratner
8b0587a885 net/mlx5e: Preserve shared buffer capacity during headroom updates
When port buffer headroom changes, port_update_shared_buffer()
recalculates the shared buffer size and splits it in a 3:1 ratio
(lossy:lossless) - Currently, the calculation is:
lossless = shared / 4;
lossy = (shared / 4) * 3;

Meaning, the calculation dropped the remainder of shared % 4 due to
integer division, unintentionally reducing the total shared buffer
by up to three cells on each update. Over time, this could shrink
the buffer below usable size.

Fix it by changing the calculation to:
lossless = shared / 4;
lossy = shared - lossless;

This retains all buffer cells while still approximating the
intended 3:1 split, preventing capacity loss over time.

While at it, perform headroom calculations in units of cells rather than
in bytes for more accurate calculations avoiding extra divisions.

Fixes: a440030d89 ("net/mlx5e: Update shared buffer along with device buffer changes")
Signed-off-by: Armen Ratner <armeng@nvidia.com>
Signed-off-by: Maher Sanalla <msanalla@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Alexei Lazar <alazar@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://patch.msgid.link/20250820133209.389065-9-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:33 -07:00
Alexei Lazar
451d2849ea net/mlx5e: Query FW for buffer ownership
The SW currently saves local buffer ownership when setting
the buffer.
This means that the SW assumes it has ownership of the buffer
after the command is set.

If setting the buffer fails and we remain in FW ownership,
the local buffer ownership state incorrectly remains as SW-owned.
This leads to incorrect behavior in subsequent PFC commands,
causing failures.

Instead of saving local buffer ownership in SW,
query the FW for buffer ownership when setting the buffer.
This ensures that the buffer ownership state is accurately
reflected, avoiding the issues caused by incorrect ownership
states.

Fixes: ecdf2dadee ("net/mlx5e: Receive buffer support for DCBX")
Signed-off-by: Alexei Lazar <alazar@nvidia.com>
Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-8-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:32 -07:00
Carolina Jubran
51b17c98e3 net/mlx5: Restore missing scheduling node cleanup on vport enable failure
Restore the __esw_qos_free_node() call removed by the offending commit.

Fixes: 97733d1e00 ("net/mlx5: Add traffic class scheduling support for vport QoS")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-7-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:32 -07:00
Carolina Jubran
3c114fb2af net/mlx5: Fix QoS reference leak in vport enable error path
Add missing esw_qos_put() call when __esw_qos_alloc_node() fails in
mlx5_esw_qos_vport_enable().

Fixes: be034baba8 ("net/mlx5: Make vport QoS enablement more flexible for future extensions")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-6-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:31 -07:00
Carolina Jubran
b697ef4d1d net/mlx5: Destroy vport QoS element when no configuration remains
If a VF has been configured and the user later clears all QoS settings,
the vport element remains in the firmware QoS tree. This leads to
inconsistent behavior compared to VFs that were never configured, since
the FW assumes that unconfigured VFs are outside the QoS hierarchy.
As a result, the bandwidth share across VFs may differ, even though
none of them appear to have any configuration.

Align the driver behavior with the FW expectation by destroying the
vport QoS element when all configurations are removed.

Fixes: c9497c9890 ("net/mlx5: Add support for setting VF min rate")
Fixes: cf7e73770d ("net/mlx5: Manage TC arbiter nodes and implement full support for tc-bw")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://patch.msgid.link/20250820133209.389065-5-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:31 -07:00
Carolina Jubran
e8f973576c net/mlx5e: Preserve tc-bw during parent changes
When changing parent of a node/leaf with tc-bw configured, the code
saves and restores tc-bw values. However, it was reading the converted
hardware bw_share values (where 0 becomes 1) instead of the original
user values, causing incorrect tc-bw calculations after parent change.

Store original tc-bw values in the node structure and use them directly
for save/restore operations.

Fixes: cf7e73770d ("net/mlx5: Manage TC arbiter nodes and implement full support for tc-bw")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-4-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:31 -07:00
Carolina Jubran
330f0f6713 net/mlx5: Remove default QoS group and attach vports directly to root TSAR
Currently, the driver creates a default group (`node0`) and attaches
all vports to it unless the user explicitly sets a parent group. As a
result, when a user configures tx_share on a group and tx_share on
a VF, the expectation is for the group and the VF to share bandwidth
relatively. However, since the VF is not connected to the same parent
(but to the default node), the proportional share logic is not applied
correctly.

To fix this, remove the default group (`node0`) and instead connect
vports directly to the root TSAR when no parent is specified. This
ensures that vports and groups share the same root scheduler and their
tx_share values are compared directly under the same hierarchy.

Fixes: 0fe132eac3 ("net/mlx5: E-switch, Allow to add vports to rate groups")
Signed-off-by: Carolina Jubran <cjubran@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-3-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:30 -07:00
Daniel Jurgens
bc17455bc8 net/mlx5: Base ECVF devlink port attrs from 0
Adjust the vport number by the base ECVF vport number so the port
attributes start at 0. Previously the port attributes would start 1
after the maximum number of host VFs.

Fixes: dc13180824 ("net/mlx5: Enable devlink port for embedded cpu VF vports")
Signed-off-by: Daniel Jurgens <danielj@nvidia.com>
Reviewed-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250820133209.389065-2-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:58:30 -07:00
Kory Maincent
7ef353879f net: pse-pd: pd692x0: Skip power budget configuration when undefined
If the power supply's power budget is not defined in the device tree,
the current code still requests power and configures the PSE manager
with a 0W power limit, which is undesirable behavior.

Skip power budget configuration entirely when the budget is zero,
avoiding unnecessary power requests and preventing invalid 0W limits
from being set on the PSE manager.

Fixes: 359754013e ("net: pse-pd: pd692x0: Add support for PSE PI priority feature")
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20250820133321.841054-1-kory.maincent@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:56:08 -07:00
Kory Maincent
1c67f9c54c net: pse-pd: pd692x0: Fix power budget leak in manager setup error path
Fix a resource leak where manager power budgets were freed on both
success and error paths during manager setup. Power budgets should
only be freed on error paths after regulator registration or during
driver removal.

Refactor cleanup logic by extracting OF node cleanup and power budget
freeing into separate helper functions for better maintainability.

Fixes: 359754013e ("net: pse-pd: pd692x0: Add support for PSE PI priority feature")
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Link: https://patch.msgid.link/20250820132708.837255-1-kory.maincent@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:55:40 -07:00
Hariprasad Kelam
8c5d95988c Octeontx2-af: Skip overlap check for SPI field
Octeontx2/CN10K silicon supports generating a 256-bit key per packet.
The specific fields to be extracted from a packet for key generation
are configurable via a Key Extraction (MKEX) Profile.

The AF driver scans the configured extraction profile to ensure that
fields from upper layers do not overwrite fields from lower layers in
the key.

Example Packet Field Layout:
LA: DMAC + SMAC
LB: VLAN
LC: IPv4/IPv6
LD: TCP/UDP

Valid MKEX Profile Configuration:

LA   -> DMAC   -> key_offset[0-5]
LC   -> SIP    -> key_offset[20-23]
LD   -> SPORT  -> key_offset[30-31]

Invalid MKEX profile configuration:

LA   -> DMAC   -> key_offset[0-5]
LC   -> SIP    -> key_offset[20-23]
LD   -> SPORT  -> key_offset[2-3]  // Overlaps with DMAC field

In another scenario, if the MKEX profile is configured to extract
the SPI field from both AH and ESP headers at the same key offset,
the driver rejecting this configuration. In a regular traffic,
ipsec packet will be having either AH(LD) or ESP (LE). This patch
relaxes the check for the same.

Fixes: 12aa0a3b93 ("octeontx2-af: Harden rule validation.")
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Link: https://patch.msgid.link/20250820063919.1463518-1-hkelam@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:52:54 -07:00
Jakub Kicinski
a61a3e961b selftests: tls: add tests for zero-length records
Test various combinations of zero-length records.
Unfortunately, kernel cannot be coerced into producing those,
so hardcode the ciphertext messages in the test.

Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20250820021952.143068-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:52:31 -07:00
Jakub Kicinski
62708b9452 tls: fix handling of zero-length records on the rx_list
Each recvmsg() call must process either
 - only contiguous DATA records (any number of them)
 - one non-DATA record

If the next record has different type than what has already been
processed we break out of the main processing loop. If the record
has already been decrypted (which may be the case for TLS 1.3 where
we don't know type until decryption) we queue the pending record
to the rx_list. Next recvmsg() will pick it up from there.

Queuing the skb to rx_list after zero-copy decrypt is not possible,
since in that case we decrypted directly to the user space buffer,
and we don't have an skb to queue (darg.skb points to the ciphertext
skb for access to metadata like length).

Only data records are allowed zero-copy, and we break the processing
loop after each non-data record. So we should never zero-copy and
then find out that the record type has changed. The corner case
we missed is when the initial record comes from rx_list, and it's
zero length.

Reported-by: Muhammad Alifa Ramdhan <ramdhan@starlabs.sg>
Reported-by: Billy Jheng Bing-Jhong <billy@starlabs.sg>
Fixes: 84c61fe1a7 ("tls: rx: do not use the standard strparser")
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20250820021952.143068-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-21 07:52:30 -07:00
Lorenzo Bianconi
9f6b606b6b net: airoha: ppe: Do not invalid PPE entries in case of SW hash collision
SW hash computed by airoha_ppe_foe_get_entry_hash routine (used for
foe_flow hlist) can theoretically produce collisions between two
different HW PPE entries.
In airoha_ppe_foe_insert_entry() if the collision occurs we will mark
the second PPE entry in the list as stale (setting the hw hash to 0xffff).
Stale entries are no more updated in airoha_ppe_foe_flow_entry_update
routine and so they are removed by Netfilter.
Fix the problem not marking the second entry as stale in
airoha_ppe_foe_insert_entry routine if we have already inserted the
brand new entry in the PPE table and let Netfilter remove real stale
entries according to their timestamp.
Please note this is just a theoretical issue spotted reviewing the code
and not faced running the system.

Fixes: cd53f62261 ("net: airoha: Add L2 hw acceleration support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250818-airoha-en7581-hash-collision-fix-v1-1-d190c4b53d1c@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-21 11:25:11 +02:00
Paolo Abeni
184fa9d704 Merge branch 'bonding-fix-negotiation-flapping-in-802-3ad-passive-mode'
Hangbin Liu says:

====================
bonding: fix negotiation flapping in 802.3ad passive mode

This patch fixes unstable LACP negotiation when bonding is configured in
passive mode (`lacp_active=off`).

Previously, the actor would stop sending LACPDUs after initial negotiation
succeeded, leading to the partner timing out and restarting the negotiation
cycle. This resulted in continuous LACP state flapping.

The fix ensures the passive actor starts sending periodic LACPDUs after
receiving the first LACPDU from the partner, in accordance with IEEE
802.1AX-2020 section 6.4.1.
====================

Link: https://patch.msgid.link/20250815062000.22220-1-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-21 09:35:24 +02:00
Hangbin Liu
87951b5664 selftests: bonding: add test for passive LACP mode
Add a selftest to verify bonding behavior when `lacp_active` is set to `off`.

The test checks the following:
- The passive LACP bond should not send LACPDUs before receiving a partner's
  LACPDU.
- The transmitted LACPDUs must not include the active flag.
- After transitioning to EXPIRED and DEFAULTED states, the passive side should
  still not initiate LACPDUs.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20250815062000.22220-4-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-21 09:35:21 +02:00
Hangbin Liu
0599640a21 bonding: send LACPDUs periodically in passive mode after receiving partner's LACPDU
When `lacp_active` is set to `off`, the bond operates in passive mode, meaning
it only "speaks when spoken to." However, the current kernel implementation
only sends an LACPDU in response when the partner's state changes.

As a result, once LACP negotiation succeeds, the actor stops sending LACPDUs
until the partner times out and sends an "expired" LACPDU. This causes
continuous LACP state flapping.

According to IEEE 802.1AX-2014, 6.4.13 Periodic Transmission machine. The
values of Partner_Oper_Port_State.LACP_Activity and
Actor_Oper_Port_State.LACP_Activity determine whether periodic transmissions
take place. If either or both parameters are set to Active LACP, then periodic
transmissions occur; if both are set to Passive LACP, then periodic
transmissions do not occur.

To comply with this, we remove the `!bond->params.lacp_active` check in
`ad_periodic_machine()`. Instead, we initialize the actor's port's
`LACP_STATE_LACP_ACTIVITY` state based on `lacp_active` setting.

Additionally, we avoid setting the partner's state to
`LACP_STATE_LACP_ACTIVITY` in the EXPIRED state, since we should not assume
the partner is active by default.

This ensures that in passive mode, the bond starts sending periodic LACPDUs
after receiving one from the partner, and avoids flapping due to inactivity.

Fixes: 3a755cd8b7 ("bonding: add new option lacp_active")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20250815062000.22220-3-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-21 09:35:20 +02:00
Hangbin Liu
b64d035f77 bonding: update LACP activity flag after setting lacp_active
The port's actor_oper_port_state activity flag should be updated immediately
after changing the lacp_active option to reflect the current mode correctly.

Fixes: 3a755cd8b7 ("bonding: add new option lacp_active")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20250815062000.22220-2-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-21 09:35:20 +02:00
Ryan Wanner
c42be53454 Revert "net: cadence: macb: sama7g5_emac: Remove USARIO CLKEN flag"
This reverts commit db400061b5.

This commit can cause a Devicetree ABI break for older DTS files that rely this
flag for RMII configuration. Adding this back in ensures that the older
DTBs will not break.

Fixes: db400061b5 ("net: cadence: macb: sama7g5_emac: Remove USARIO CLKEN flag")
Signed-off-by: Ryan Wanner <Ryan.Wanner@microchip.com>
Link: https://patch.msgid.link/20250819163236.100680-1-Ryan.Wanner@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:33:42 -07:00
Eric Biggers
a458b29021 ipv6: sr: Fix MAC comparison to be constant-time
To prevent timing attacks, MACs need to be compared in constant time.
Use the appropriate helper function for this.

Fixes: bf355b8d2c ("ipv6: sr: add core files for SR HMAC support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Reviewed-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Link: https://patch.msgid.link/20250818202724.15713-1-ebiggers@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:32:30 -07:00
Jakub Acs
7af76e9d18 net, hsr: reject HSR frame if skb can't hold tag
Receiving HSR frame with insufficient space to hold HSR tag in the skb
can result in a crash (kernel BUG):

[   45.390915] skbuff: skb_under_panic: text:ffffffff86f32cac len:26 put:14 head:ffff888042418000 data:ffff888042417ff4 tail:0xe end:0x180 dev:bridge_slave_1
[   45.392559] ------------[ cut here ]------------
[   45.392912] kernel BUG at net/core/skbuff.c:211!
[   45.393276] Oops: invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN NOPTI
[   45.393809] CPU: 1 UID: 0 PID: 2496 Comm: reproducer Not tainted 6.15.0 #12 PREEMPT(undef)
[   45.394433] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
[   45.395273] RIP: 0010:skb_panic+0x15b/0x1d0

<snip registers, remove unreliable trace>

[   45.402911] Call Trace:
[   45.403105]  <IRQ>
[   45.404470]  skb_push+0xcd/0xf0
[   45.404726]  br_dev_queue_push_xmit+0x7c/0x6c0
[   45.406513]  br_forward_finish+0x128/0x260
[   45.408483]  __br_forward+0x42d/0x590
[   45.409464]  maybe_deliver+0x2eb/0x420
[   45.409763]  br_flood+0x174/0x4a0
[   45.410030]  br_handle_frame_finish+0xc7c/0x1bc0
[   45.411618]  br_handle_frame+0xac3/0x1230
[   45.413674]  __netif_receive_skb_core.constprop.0+0x808/0x3df0
[   45.422966]  __netif_receive_skb_one_core+0xb4/0x1f0
[   45.424478]  __netif_receive_skb+0x22/0x170
[   45.424806]  process_backlog+0x242/0x6d0
[   45.425116]  __napi_poll+0xbb/0x630
[   45.425394]  net_rx_action+0x4d1/0xcc0
[   45.427613]  handle_softirqs+0x1a4/0x580
[   45.427926]  do_softirq+0x74/0x90
[   45.428196]  </IRQ>

This issue was found by syzkaller.

The panic happens in br_dev_queue_push_xmit() once it receives a
corrupted skb with ETH header already pushed in linear data. When it
attempts the skb_push() call, there's not enough headroom and
skb_push() panics.

The corrupted skb is put on the queue by HSR layer, which makes a
sequence of unintended transformations when it receives a specific
corrupted HSR frame (with incomplete TAG).

Fix it by dropping and consuming frames that are not long enough to
contain both ethernet and hsr headers.

Alternative fix would be to check for enough headroom before skb_push()
in br_dev_queue_push_xmit().

In the reproducer, this is injected via AF_PACKET, but I don't easily
see why it couldn't be sent over the wire from adjacent network.

Further Details:

In the reproducer, the following network interface chain is set up:

┌────────────────┐   ┌────────────────┐
│ veth0_to_hsr   ├───┤  hsr_slave0    ┼───┐
└────────────────┘   └────────────────┘   │
                                          │ ┌──────┐
                                          ├─┤ hsr0 ├───┐
                                          │ └──────┘   │
┌────────────────┐   ┌────────────────┐   │            │┌────────┐
│ veth1_to_hsr   ┼───┤  hsr_slave1    ├───┘            └┤        │
└────────────────┘   └────────────────┘                ┌┼ bridge │
                                                       ││        │
                                                       │└────────┘
                                                       │
                                        ┌───────┐      │
                                        │  ...  ├──────┘
                                        └───────┘

To trigger the events leading up to crash, reproducer sends a corrupted
HSR frame with incomplete TAG, via AF_PACKET socket on 'veth0_to_hsr'.

The first HSR-layer function to process this frame is
hsr_handle_frame(). It and then checks if the
protocol is ETH_P_PRP or ETH_P_HSR. If it is, it calls
skb_set_network_header(skb, ETH_HLEN + HSR_HLEN), without checking that
the skb is long enough. For the crashing frame it is not, and hence the
skb->network_header and skb->mac_len fields are set incorrectly,
pointing after the end of the linear buffer.

I will call this a BUG#1 and it is what is addressed by this patch. In
the crashing scenario before the fix, the skb continues to go down the
hsr path as follows.

hsr_handle_frame() then calls this sequence
hsr_forward_skb()
  fill_frame_info()
    hsr->proto_ops->fill_frame_info()
      hsr_fill_frame_info()

hsr_fill_frame_info() contains a check that intends to check whether the
skb actually contains the HSR header. But the check relies on the
skb->mac_len field which was erroneously setup due to BUG#1, so the
check passes and the execution continues  back in the hsr_forward_skb():

hsr_forward_skb()
  hsr_forward_do()
    hsr->proto_ops->get_untagged_frame()
      hsr_get_untagged_frame()
        create_stripped_skb_hsr()

In create_stripped_skb_hsr(), a copy of the skb is created and is
further corrupted by operation that attempts to strip the HSR tag in a
call to __pskb_copy().

The skb enters create_stripped_skb_hsr() with ethernet header pushed in
linear buffer. The skb_pull(skb_in, HSR_HLEN) thus pulls 6 bytes of
ethernet header into the headroom, creating skb_in with a headroom of
size 8. The subsequent __pskb_copy() then creates an skb with headroom
of just 2 and skb->len of just 12, this is how it looks after the copy:

gdb) p skb->len
$10 = 12
(gdb) p skb->data
$11 = (unsigned char *) 0xffff888041e45382 "\252\252\252\252\252!\210\373",
(gdb) p skb->head
$12 = (unsigned char *) 0xffff888041e45380 ""

It seems create_stripped_skb_hsr() assumes that ETH header is pulled
in the headroom when it's entered, because it just pulls HSR header on
top. But that is not the case in our code-path and we end up with the
corrupted skb instead. I will call this BUG#2

*I got confused here because it seems that under no conditions can
create_stripped_skb_hsr() work well, the assumption it makes is not true
during the processing of hsr frames - since the skb_push() in
hsr_handle_frame to skb_pull in hsr_deliver_master(). I wonder whether I
missed something here.*

Next, the execution arrives in hsr_deliver_master(). It calls
skb_pull(ETH_HLEN), which just returns NULL - the SKB does not have
enough space for the pull (as it only has 12 bytes in total at this
point).

*The skb_pull() here further suggests that ethernet header is meant
to be pushed through the whole hsr processing and
create_stripped_skb_hsr() should pull it before doing the HSR header
pull.*

hsr_deliver_master() then puts the corrupted skb on the queue, it is
then picked up from there by bridge frame handling layer and finally
lands in br_dev_queue_push_xmit where it panics.

Cc: stable@kernel.org
Fixes: 48b491a5cc ("net: hsr: fix mac_len checks")
Reported-by: syzbot+a81f2759d022496b40ab@syzkaller.appspotmail.com
Signed-off-by: Jakub Acs <acsjakub@amazon.de>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250819082842.94378-1-acsjakub@amazon.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:31:25 -07:00
William Liu
2c2192e5f9 net/sched: Remove unnecessary WARNING condition for empty child qdisc in htb_activate
The WARN_ON trigger based on !cl->leaf.q->q.qlen is unnecessary in
htb_activate. htb_dequeue_tree already accounts for that scenario.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Link: https://patch.msgid.link/20250819033632.579854-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:27:08 -07:00
William Liu
15de71d06a net/sched: Make cake_enqueue return NET_XMIT_CN when past buffer_limit
The following setup can trigger a WARNING in htb_activate due to
the condition: !cl->leaf.q->q.qlen

tc qdisc del dev lo root
tc qdisc add dev lo root handle 1: htb default 1
tc class add dev lo parent 1: classid 1:1 \
       htb rate 64bit
tc qdisc add dev lo parent 1:1 handle f: \
       cake memlimit 1b
ping -I lo -f -c1 -s64 -W0.001 127.0.0.1

This is because the low memlimit leads to a low buffer_limit, which
causes packet dropping. However, cake_enqueue still returns
NET_XMIT_SUCCESS, causing htb_enqueue to call htb_activate with an
empty child qdisc. We should return NET_XMIT_CN when packets are
dropped from the same tin and flow.

I do not believe return value of NET_XMIT_CN is necessary for packet
drops in the case of ack filtering, as that is meant to optimize
performance, not to signal congestion.

Fixes: 046f6fd5da ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20250819033601.579821-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:27:08 -07:00
Tristram Ha
e318cd6714 net: dsa: microchip: Fix KSZ9477 HSR port setup issue
ksz9477_hsr_join() is called once to setup the HSR port membership, but
the port can be enabled later, or disabled and enabled back and the port
membership is not set correctly inside ksz_update_port_member().  The
added code always use the correct HSR port membership for HSR port that
is enabled.

Fixes: 2d61298fdd ("net: dsa: microchip: Enable HSR offloading for KSZ9477")
Reported-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Reviewed-by: Łukasz Majewski <lukma@nabladev.com>
Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Link: https://patch.msgid.link/20250819010457.563286-1-Tristram.Ha@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:25:38 -07:00
Jakub Kicinski
f7b0b97c2d Merge branch 'intel-wired-lan-driver-updates-2025-08-15-ice-ixgbe-igc'
Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2025-08-15 (ice, ixgbe, igc)

For ixgbe:
Jason Xing corrects a condition in which improper decrement can cause
improper budget value.

Maciej extends down states in which XDP cannot transmit and excludes XDP
rings from Tx hang checks.

For igc:
VladikSS moves setting of hardware device information to allow for proper
check of device ID.

v1: https://lore.kernel.org/20250815204205.1407768-1-anthony.l.nguyen@intel.com
====================

Link: https://patch.msgid.link/20250819222000.3504873-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 19:20:50 -07:00
ValdikSS
1468c1f97c igc: fix disabling L1.2 PCI-E link substate on I226 on init
Device ID comparison in igc_is_device_id_i226 is performed before
the ID is set, resulting in always failing check on init.

Before the patch:
* L1.2 is not disabled on init
* L1.2 is properly disabled after suspend-resume cycle

With the patch:
* L1.2 is properly disabled both on init and after suspend-resume

How to test:
Connect to the 1G link with 300+ mbit/s Internet speed, and run
the download speed test, such as:

    curl -o /dev/null http://speedtest.selectel.ru/1GB

Without L1.2 disabled, the speed would be no more than ~200 mbit/s.
With L1.2 disabled, the speed would reach 1 gbit/s.
Note: it's required that the latency between your host and the remote
be around 3-5 ms, the test inside LAN (<1 ms latency) won't trigger the
issue.

Link: https://lore.kernel.org/intel-wired-lan/15248b4f-3271-42dd-8e35-02bfc92b25e1@intel.com
Fixes: 0325143b59 ("igc: disable L1.2 PCI-E link substate to avoid performance issue")
Signed-off-by: ValdikSS <iam@valdikss.org.ru>
Reviewed-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20250819222000.3504873-6-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 18:46:30 -07:00
Maciej Fijalkowski
f3d9f7fa7f ixgbe: fix ndo_xdp_xmit() workloads
Currently ixgbe driver checks periodically in its watchdog subtask if
there is anything to be transmitted (considering both Tx and XDP rings)
under state of carrier not being 'ok'. Such event is interpreted as Tx
hang and therefore results in interface reset.

This is currently problematic for ndo_xdp_xmit() as it is allowed to
produce descriptors when interface is going through reset or its carrier
is turned off.

Furthermore, XDP rings should not really be objects of Tx hang
detection. This mechanism is rather a matter of ndo_tx_timeout() being
called from dev_watchdog against Tx rings exposed to networking stack.

Taking into account issues described above, let us have a two fold fix -
do not respect XDP rings in local ixgbe watchdog and do not produce Tx
descriptors in ndo_xdp_xmit callback when there is some problem with
carrier currently. For now, keep the Tx hang checks in clean Tx irq
routine, but adjust it to not execute for XDP rings.

Cc: Tobias Böhm <tobias.boehm@hetzner-cloud.de>
Reported-by: Marcus Wichelmann <marcus.wichelmann@hetzner-cloud.de>
Closes: https://lore.kernel.org/netdev/eca1880f-253a-4955-afe6-732d7c6926ee@hetzner-cloud.de/
Fixes: 6453073987 ("ixgbe: add initial support for xdp redirect")
Fixes: 33fdc82f08 ("ixgbe: add support for XDP_TX action")
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Marcus Wichelmann <marcus.wichelmann@hetzner-cloud.de>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20250819222000.3504873-5-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 18:46:30 -07:00
Jason Xing
4d4d9ef9df ixgbe: xsk: resolve the negative overflow of budget in ixgbe_xmit_zc
Resolve the budget negative overflow which leads to returning true in
ixgbe_xmit_zc even when the budget of descs are thoroughly consumed.

Before this patch, when the budget is decreased to zero and finishes
sending the last allowed desc in ixgbe_xmit_zc, it will always turn back
and enter into the while() statement to see if it should keep processing
packets, but in the meantime it unexpectedly decreases the value again to
'unsigned int (0--)', namely, UINT_MAX. Finally, the ixgbe_xmit_zc returns
true, showing 'we complete cleaning the budget'. That also means
'clean_complete = true' in ixgbe_poll.

The true theory behind this is if that budget number of descs are consumed,
it implies that we might have more descs to be done. So we should return
false in ixgbe_xmit_zc to tell napi poll to find another chance to start
polling to handle the rest of descs. On the contrary, returning true here
means job done and we know we finish all the possible descs this time and
we don't intend to start a new napi poll.

It is apparently against our expectations. Please also see how
ixgbe_clean_tx_irq() handles the problem: it uses do..while() statement
to make sure the budget can be decreased to zero at most and the negative
overflow never happens.

The patch adds 'likely' because we rarely would not hit the loop condition
since the standard budget is 256.

Fixes: 8221c5eba8 ("ixgbe: add AF_XDP zero-copy Tx support")
Signed-off-by: Jason Xing <kernelxing@tencent.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Priya Singh <priyax.singh@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20250819222000.3504873-4-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-20 18:46:30 -07:00
Jakub Kicinski
51f27beeb7 Merge branch 'fixes-on-the-microchip-s-lan865x-driver'
Parthiban Veerasooran says:

====================
Fixes on the Microchip's LAN865x driver

This patch series includes two bug fixes for the LAN865x Ethernet MAC-PHY
driver:

1. Fix missing transmit queue restart on device reopen
   This patch addresses an issue where the transmit queue is not restarted
   when the network interface is brought back up after being taken down
   (e.g., via ip or ifconfig). As a result, packet transmission hangs
   after the first down/up cycle. The fix ensures netif_start_queue() is
   explicitly called in lan865x_net_open() to properly restart the queue
   on every reopen.

2. Fix missing configuration in the Microchip LAN865x driver for silicon
   revisions B0 and B1, as documented in Microchip Application Note AN1760
   (Rev F, June 2024). These revisions require the MAC to be configured for
   timestamping at the end of the Start of Frame Delimiter (SFD) and the
   Timer Increment register to be set to 40 ns, corresponding to a 25 MHz
   internal clock.

Both patches address issues introduced with the initial driver support and
are marked with the appropriate Fixes: tag.
====================

Link: https://patch.msgid.link/20250818060514.52795-1-parthiban.veerasooran@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:38:29 -07:00
Parthiban Veerasooran
2cd58fec91 microchip: lan865x: fix missing Timer Increment config for Rev.B0/B1
Fix missing configuration for LAN865x silicon revisions B0 and B1 as per
Microchip Application Note AN1760 (Rev F, June 2024).

The Timer Increment register was not being set, which is required for
accurate timestamping. As per the application note, configure the MAC to
set timestamping at the end of the Start of Frame Delimiter (SFD), and
set the Timer Increment register to 40 ns (corresponding to a 25 MHz
internal clock).

Link: https://www.microchip.com/en-us/application-notes/an1760

Fixes: 5cd2340cb6 ("microchip: lan865x: add driver support for Microchip's LAN865X MAC-PHY")
Signed-off-by: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250818060514.52795-3-parthiban.veerasooran@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:38:25 -07:00
Parthiban Veerasooran
1683fd1b2f microchip: lan865x: fix missing netif_start_queue() call on device open
This fixes an issue where the transmit queue is started implicitly only
the very first time the device is registered. When the device is taken
down and brought back up again (using `ip` or `ifconfig`), the transmit
queue is not restarted, causing packet transmission to hang.

Adding an explicit call to netif_start_queue() in lan865x_net_open()
ensures the transmit queue is properly started every time the device
is reopened.

Fixes: 5cd2340cb6 ("microchip: lan865x: add driver support for Microchip's LAN865X MAC-PHY")
Signed-off-by: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
Link: https://patch.msgid.link/20250818060514.52795-2-parthiban.veerasooran@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:38:25 -07:00
Jakub Kicinski
4f953be882 Merge branch 'mlx5-hws-fixes-2025-08-17'
Mark Bloch says:

====================
mlx5 HWS fixes 2025-08-17

The following patch set focuses on hardware steering fixes
found by the team.
====================

Link: https://patch.msgid.link/20250817202323.308604-1-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:18 -07:00
Vlad Dogaru
d2d6f950cb net/mlx5: CT: Use the correct counter offset
Specifying the counter action is not enough, as it is used by multiple
counters that were allocated in a bulk. By omitting the offset, rules
will be associated with a different counter from the same bulk.
Subsequently, the CT subsystem checks the correct counter, assumes that
no traffic has triggered the rule, and ages out the rule. The end result
is intermittent offloading of long lived connections, as rules are aged
out then promptly re-added.

Fix this by specifying the correct offset along with the counter rule.

Fixes: 34eea5b12a ("net/mlx5e: CT: Add initial support for Hardware Steering")
Signed-off-by: Vlad Dogaru <vdogaru@nvidia.com>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-8-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:14 -07:00
Alex Vesker
8a51507320 net/mlx5: HWS, Fix table creation UID
During table creation, caller passes a UID using ft_attr. The UID
value was ignored, which leads to problems when the caller sets the
UID to a non-zero value, such as SHARED_RESOURCE_UID (0xffff) - the
internal FT objects will be created with UID=0.

Fixes: 0869701cba ("net/mlx5: HWS, added FW commands handling")
Signed-off-by: Alex Vesker <valex@nvidia.com>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-7-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:14 -07:00
Yevgeny Kliteynik
7c60952f83 net/mlx5: HWS, don't rehash on every kind of insertion failure
If rule creation failed due to a full queue, due to timeout
in polling for completion, or due to matcher being in resize,
don't try to initiate rehash sequence - rehash would have
failed anyway.

Fixes: 2111bb970c ("net/mlx5: HWS, added backward-compatible API handling")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-6-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:13 -07:00
Yevgeny Kliteynik
1a72298d27 net/mlx5: HWS, prevent rehash from filling up the queues
While moving the rules during rehash, CQ is not drained. The flush
and drain happens only when all the rules of a certain queue have been
moved. This behaviour can lead to accumulating large quantity of rules
that haven't got their completion yet, and eventually will fill up
the queue and will cause the rehash to fail.

Fix this problem by requiring drain once the number of outstanding
completions reaches a certain threshold.

Fixes: ef94799a87 ("net/mlx5: HWS, rework rehash loop")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-5-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:13 -07:00
Yevgeny Kliteynik
4a842b1bf1 net/mlx5: HWS, fix complex rules rehash error flow
Moving rules from matcher to matcher should not fail.
However, if it does fail due to various reasons, the error flow
should allow the kernel to continue functioning (albeit with broken
steering rules) instead of going into series of soft lock-ups or
some other problematic behaviour.

Similar to the simple rules, complex rules rehash logic suffers
from the same problems. This patch fixes the error flow for moving
complex rules:
 - If new rule creation fails before it was even enqeued, do not
   poll for completion
 - If TIMEOUT happened while moving the rule, no point trying
   to poll for completions for other rules. Something is broken,
   completion won't come, just abort the rehash sequence.
 - If some other completion with error received, don't give up.
   Continue handling rest of the rules to minimize the damage.
 - Make sure that the first error code that was received will
   be actually returned to the caller instead of replacing it
   with the generic error code.

All the aforementioned issues stem from the same bad error flow,
so no point fixing them one by one and leaving partially broken
code - fixing them in one patch.

Fixes: 17e0accac5 ("net/mlx5: HWS, support complex matchers")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-4-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:13 -07:00
Yevgeny Kliteynik
615b690612 net/mlx5: HWS, fix simple rules rehash error flow
Moving rules from matcher to matcher should not fail.
However, if it does fail due to various reasons, the error flow
should allow the kernel to continue functioning (albeit with broken
steering rules) instead of going into series of soft lock-ups or
some other problematic behaviour.

This patch fixes the error flow for moving simple rules:
 - If new rule creation fails before it was even enqeued, do not
   poll for completion
 - If TIMEOUT happened while moving the rule, no point trying
   to poll for completions for other rules. Something is broken,
   completion won't come, just abort the rehash sequence.
 - If some other completion with error received, don't give up.
   Continue handling rest of the rules to minimize the damage.
 - Make sure that the first error code that was received will
   be actually returned to the caller instead of replacing it
   with the generic error code.

All the aforementioned issues stem from the same bad error flow,
so no point fixing them one by one and leaving partially broken
code - fixing them in one patch.

Fixes: ef94799a87 ("net/mlx5: HWS, rework rehash loop")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-3-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:13 -07:00
Yevgeny Kliteynik
2462c1b921 net/mlx5: HWS, fix bad parameter in CQ creation
'cqe_sz' valid value should be 0 for 64-byte CQE.

Fixes: 2ca62599aa ("net/mlx5: HWS, added send engine and context handling")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250817202323.308604-2-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 19:35:12 -07:00
D. Wythe
d9cef55ed4 net/smc: fix UAF on smcsk after smc_listen_out()
BPF CI testing report a UAF issue:

  [   16.446633] BUG: kernel NULL pointer dereference, address: 000000000000003  0
  [   16.447134] #PF: supervisor read access in kernel mod  e
  [   16.447516] #PF: error_code(0x0000) - not-present pag  e
  [   16.447878] PGD 0 P4D   0
  [   16.448063] Oops: Oops: 0000 [#1] PREEMPT SMP NOPT  I
  [   16.448409] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Tainted: G           OE      6.13.0-rc3-g89e8a75fda73-dirty #4  2
  [   16.449124] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODUL  E
  [   16.449502] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/201  4
  [   16.450201] Workqueue: smc_hs_wq smc_listen_wor  k
  [   16.450531] RIP: 0010:smc_listen_work+0xc02/0x159  0
  [   16.452158] RSP: 0018:ffffb5ab40053d98 EFLAGS: 0001024  6
  [   16.452526] RAX: 0000000000000001 RBX: 0000000000000002 RCX: 000000000000030  0
  [   16.452994] RDX: 0000000000000280 RSI: 00003513840053f0 RDI: 000000000000000  0
  [   16.453492] RBP: ffffa097808e3800 R08: ffffa09782dba1e0 R09: 000000000000000  5
  [   16.453987] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0978274640  0
  [   16.454497] R13: 0000000000000000 R14: 0000000000000000 R15: ffffa09782d4092  0
  [   16.454996] FS:  0000000000000000(0000) GS:ffffa097bbc00000(0000) knlGS:000000000000000  0
  [   16.455557] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003  3
  [   16.455961] CR2: 0000000000000030 CR3: 0000000102788004 CR4: 0000000000770ef  0
  [   16.456459] PKRU: 5555555  4
  [   16.456654] Call Trace  :
  [   16.456832]  <TASK  >
  [   16.456989]  ? __die+0x23/0x7  0
  [   16.457215]  ? page_fault_oops+0x180/0x4c  0
  [   16.457508]  ? __lock_acquire+0x3e6/0x249  0
  [   16.457801]  ? exc_page_fault+0x68/0x20  0
  [   16.458080]  ? asm_exc_page_fault+0x26/0x3  0
  [   16.458389]  ? smc_listen_work+0xc02/0x159  0
  [   16.458689]  ? smc_listen_work+0xc02/0x159  0
  [   16.458987]  ? lock_is_held_type+0x8f/0x10  0
  [   16.459284]  process_one_work+0x1ea/0x6d  0
  [   16.459570]  worker_thread+0x1c3/0x38  0
  [   16.459839]  ? __pfx_worker_thread+0x10/0x1  0
  [   16.460144]  kthread+0xe0/0x11  0
  [   16.460372]  ? __pfx_kthread+0x10/0x1  0
  [   16.460640]  ret_from_fork+0x31/0x5  0
  [   16.460896]  ? __pfx_kthread+0x10/0x1  0
  [   16.461166]  ret_from_fork_asm+0x1a/0x3  0
  [   16.461453]  </TASK  >
  [   16.461616] Modules linked in: bpf_testmod(OE) [last unloaded: bpf_testmod(OE)  ]
  [   16.462134] CR2: 000000000000003  0
  [   16.462380] ---[ end trace 0000000000000000 ]---
  [   16.462710] RIP: 0010:smc_listen_work+0xc02/0x1590

The direct cause of this issue is that after smc_listen_out_connected(),
newclcsock->sk may be NULL since it will releases the smcsk. Therefore,
if the application closes the socket immediately after accept,
newclcsock->sk can be NULL. A possible execution order could be as
follows:

smc_listen_work                                 | userspace
-----------------------------------------------------------------
lock_sock(sk)                                   |
smc_listen_out_connected()                      |
| \- smc_listen_out                             |
|    | \- release_sock                          |
     | |- sk->sk_data_ready()                   |
                                                | fd = accept();
                                                | close(fd);
                                                |  \- socket->sk = NULL;
/* newclcsock->sk is NULL now */
SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk))

Since smc_listen_out_connected() will not fail, simply swapping the order
of the code can easily fix this issue.

Fixes: 3b2dec2603 ("net/smc: restructure client and server code in af_smc")
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Link: https://patch.msgid.link/20250818054618.41615-1-alibuda@linux.alibaba.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 18:27:16 -07:00
Yao Zi
6d6714bf0c net: stmmac: thead: Enable TX clock before MAC initialization
The clk_tx_i clock must be supplied to the MAC for successful
initialization. On TH1520 SoC, the clock is provided by an internal
divider configured through GMAC_PLLCLK_DIV register when using RGMII
interface. However, currently we don't setup the divider before
initialization of the MAC, resulting in DMA reset failures if the
bootloader/firmware doesn't enable the divider,

[    7.839601] thead-dwmac ffe7060000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0
[    7.938338] thead-dwmac ffe7060000.ethernet eth0: PHY [stmmac-0:02] driver [RTL8211F Gigabit Ethernet] (irq=POLL)
[    8.160746] thead-dwmac ffe7060000.ethernet eth0: Failed to reset the dma
[    8.170118] thead-dwmac ffe7060000.ethernet eth0: stmmac_hw_setup: DMA engine initialization failed
[    8.179384] thead-dwmac ffe7060000.ethernet eth0: __stmmac_open: Hw setup failed

Let's simply write GMAC_PLLCLK_DIV_EN to GMAC_PLLCLK_DIV to enable the
divider before MAC initialization. Note that for reconfiguring the
divisor, the divider must be disabled first and re-enabled later to make
sure the new divisor take effect.

The exact clock rate doesn't affect MAC's initialization according to my
test. It's set to the speed required by RGMII when the linkspeed is
1Gbps and could be reclocked later after link is up if necessary.

Fixes: 33a1a01e3a ("net: stmmac: Add glue layer for T-HEAD TH1520 SoC")
Signed-off-by: Yao Zi <ziyao@disroot.org>
Reviewed-by: Drew Fustini <fustini@kernel.org>
Link: https://patch.msgid.link/20250815104803.55294-1-ziyao@disroot.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 18:15:53 -07:00
Jordan Rhee
75a9a46d67 gve: prevent ethtool ops after shutdown
A crash can occur if an ethtool operation is invoked
after shutdown() is called.

shutdown() is invoked during system shutdown to stop DMA operations
without performing expensive deallocations. It is discouraged to
unregister the netdev in this path, so the device may still be visible
to userspace and kernel helpers.

In gve, shutdown() tears down most internal data structures. If an
ethtool operation is dispatched after shutdown(), it will dereference
freed or NULL pointers, leading to a kernel panic. While graceful
shutdown normally quiesces userspace before invoking the reboot
syscall, forced shutdowns (as observed on GCP VMs) can still trigger
this path.

Fix by calling netif_device_detach() in shutdown().
This marks the device as detached so the ethtool ioctl handler
will skip dispatching operations to the driver.

Fixes: 974365e518 ("gve: Implement suspend/resume/shutdown")
Signed-off-by: Jordan Rhee <jordanrhee@google.com>
Signed-off-by: Jeroen de Borst <jeroendb@google.com>
Link: https://patch.msgid.link/20250818211245.1156919-1-jeroendb@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 18:04:07 -07:00
Yuichiro Tsuji
24ef2f53c0 net: usb: asix_devices: Fix PHY address mask in MDIO bus initialization
Syzbot reported shift-out-of-bounds exception on MDIO bus initialization.

The PHY address should be masked to 5 bits (0-31). Without this
mask, invalid PHY addresses could be used, potentially causing issues
with MDIO bus operations.

Fix this by masking the PHY address with 0x1f (31 decimal) to ensure
it stays within the valid range.

Fixes: 4faff70959 ("net: usb: asix_devices: add phy_mask for ax88772 mdio bus")
Reported-by: syzbot+20537064367a0f98d597@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=20537064367a0f98d597
Tested-by: syzbot+20537064367a0f98d597@syzkaller.appspotmail.com
Signed-off-by: Yuichiro Tsuji <yuichtsu@amazon.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250818084541.1958-1-yuichtsu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 17:52:29 -07:00
Horatiu Vultur
bc1a59cff9 phy: mscc: Fix timestamping for vsc8584
There was a problem when we received frames and the frames were
timestamped. The driver is configured to store the nanosecond part of
the timestmap in the ptp reserved bits and it would take the second part
by reading the LTC. The problem is that when reading the LTC we are in
atomic context and to read the second part will go over mdio bus which
might sleep, so we get an error.
The fix consists in actually put all the frames in a queue and start the
aux work and in that work to read the LTC and then calculate the full
received time.

Fixes: 7d272e63e0 ("net: phy: mscc: timestamping and PHC support")
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20250818081029.1300780-1-horatiu.vultur@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 17:52:02 -07:00
Victor Nogueira
f179f5bc15 net/sched: sch_dualpi2: Run prob update timer in softirq to avoid deadlock
When a user creates a dualpi2 qdisc it automatically sets a timer. This
timer will run constantly and update the qdisc's probability field.
The issue is that the timer acquires the qdisc root lock and runs in
hardirq. The qdisc root lock is also acquired in dev.c whenever a packet
arrives for this qdisc. Since the dualpi2 timer callback runs in hardirq,
it may interrupt the packet processing running in softirq. If that happens
and it runs on the same CPU, it will acquire the same lock and cause a
deadlock. The following splat shows up when running a kernel compiled with
lock debugging:

[  +0.000224] WARNING: inconsistent lock state
[  +0.000224] 6.16.0+ #10 Not tainted
[  +0.000169] --------------------------------
[  +0.000029] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
[  +0.000000] ping/156 [HC0[0]:SC0[2]:HE1:SE0] takes:
[  +0.000000] ffff897841242110 (&sch->root_lock_key){?.-.}-{3:3}, at: __dev_queue_xmit+0x86d/0x1140
[  +0.000000] {IN-HARDIRQ-W} state was registered at:
[  +0.000000]   lock_acquire.part.0+0xb6/0x220
[  +0.000000]   _raw_spin_lock+0x31/0x80
[  +0.000000]   dualpi2_timer+0x6f/0x270
[  +0.000000]   __hrtimer_run_queues+0x1c5/0x360
[  +0.000000]   hrtimer_interrupt+0x115/0x260
[  +0.000000]   __sysvec_apic_timer_interrupt+0x6d/0x1a0
[  +0.000000]   sysvec_apic_timer_interrupt+0x6e/0x80
[  +0.000000]   asm_sysvec_apic_timer_interrupt+0x1a/0x20
[  +0.000000]   pv_native_safe_halt+0xf/0x20
[  +0.000000]   default_idle+0x9/0x10
[  +0.000000]   default_idle_call+0x7e/0x1e0
[  +0.000000]   do_idle+0x1e8/0x250
[  +0.000000]   cpu_startup_entry+0x29/0x30
[  +0.000000]   rest_init+0x151/0x160
[  +0.000000]   start_kernel+0x6f3/0x700
[  +0.000000]   x86_64_start_reservations+0x24/0x30
[  +0.000000]   x86_64_start_kernel+0xc8/0xd0
[  +0.000000]   common_startup_64+0x13e/0x148
[  +0.000000] irq event stamp: 6884
[  +0.000000] hardirqs last  enabled at (6883): [<ffffffffa75700b3>] neigh_resolve_output+0x223/0x270
[  +0.000000] hardirqs last disabled at (6882): [<ffffffffa7570078>] neigh_resolve_output+0x1e8/0x270
[  +0.000000] softirqs last  enabled at (6880): [<ffffffffa757006b>] neigh_resolve_output+0x1db/0x270
[  +0.000000] softirqs last disabled at (6884): [<ffffffffa755b533>] __dev_queue_xmit+0x73/0x1140
[  +0.000000]
              other info that might help us debug this:
[  +0.000000]  Possible unsafe locking scenario:

[  +0.000000]        CPU0
[  +0.000000]        ----
[  +0.000000]   lock(&sch->root_lock_key);
[  +0.000000]   <Interrupt>
[  +0.000000]     lock(&sch->root_lock_key);
[  +0.000000]
               *** DEADLOCK ***

[  +0.000000] 4 locks held by ping/156:
[  +0.000000]  #0: ffff897842332e08 (sk_lock-AF_INET){+.+.}-{0:0}, at: raw_sendmsg+0x41e/0xf40
[  +0.000000]  #1: ffffffffa816f880 (rcu_read_lock){....}-{1:3}, at: ip_output+0x2c/0x190
[  +0.000000]  #2: ffffffffa816f880 (rcu_read_lock){....}-{1:3}, at: ip_finish_output2+0xad/0x950
[  +0.000000]  #3: ffffffffa816f840 (rcu_read_lock_bh){....}-{1:3}, at: __dev_queue_xmit+0x73/0x1140

I am able to reproduce it consistently when running the following:

tc qdisc add dev lo handle 1: root dualpi2
ping -f 127.0.0.1

To fix it, make the timer run in softirq.

Fixes: 320d031ad6 ("sched: Struct definition and parsing of dualpi2 qdisc")
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Link: https://patch.msgid.link/20250815135317.664993-1-victor@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 17:49:01 -07:00
Lubomir Rintel
4a73a36cb7 cdc_ncm: Flag Intel OEM version of Fibocom L850-GL as WWAN
This lets NetworkManager/ModemManager know that this is a modem and
needs to be connected first.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Link: https://patch.msgid.link/20250814154214.250103-1-lkundrak@v3.sk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-19 17:16:37 -07:00
MD Danish Anwar
01792bc3e5 net: ti: icssg-prueth: Fix HSR and switch offload Enablement during firwmare reload.
To enable HSR / Switch offload, certain configurations are needed.
Currently they are done inside icssg_change_mode(). This function only
gets called if we move from one mode to another without bringing the
links up / down.

Once in HSR / Switch mode, if we bring the links down and bring it back
up again. The callback sequence is,

- emac_ndo_stop()
	Firmwares are stopped
- emac_ndo_open()
	Firmwares are loaded

In this path icssg_change_mode() doesn't get called and as a result the
configurations needed for HSR / Switch is not done.

To fix this, put all these configurations in a separate function
icssg_enable_fw_offload() and call this from both icssg_change_mode()
and emac_ndo_open()

Fixes: 56375086d0 ("net: ti: icssg-prueth: Enable HSR Tx duplication, Tx Tag and Rx Tag offload")
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Link: https://patch.msgid.link/20250814105106.1491871-1-danishanwar@ti.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-19 12:26:18 +02:00
Qingfang Deng
0417adf367 ppp: fix race conditions in ppp_fill_forward_path
ppp_fill_forward_path() has two race conditions:

1. The ppp->channels list can change between list_empty() and
   list_first_entry(), as ppp_lock() is not held. If the only channel
   is deleted in ppp_disconnect_channel(), list_first_entry() may
   access an empty head or a freed entry, and trigger a panic.

2. pch->chan can be NULL. When ppp_unregister_channel() is called,
   pch->chan is set to NULL before pch is removed from ppp->channels.

Fix these by using a lockless RCU approach:
- Use list_first_or_null_rcu() to safely test and access the first list
  entry.
- Convert list modifications on ppp->channels to their RCU variants and
  add synchronize_net() after removal.
- Check for a NULL pch->chan before dereferencing it.

Fixes: f6efc675c9 ("net: ppp: resolve forwarding path for bridge pppoe devices")
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20250814012559.3705-2-dqfext@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-19 11:25:32 +02:00
Qingfang Deng
62c30c5443 net: ethernet: mtk_ppe: add RCU lock around dev_fill_forward_path
Ensure ndo_fill_forward_path() is called with RCU lock held.

Fixes: 2830e31477 ("net: ethernet: mtk-ppe: fix traffic offload with bridged wlan")
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20250814012559.3705-1-dqfext@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2025-08-19 11:25:32 +02:00
Michael Chan
4611d88a37 bnxt_en: Fix lockdep warning during rmmod
The commit under the Fixes tag added a netdev_assert_locked() in
bnxt_free_ntp_fltrs().  The lock should be held during normal run-time
but the assert will be triggered (see below) during bnxt_remove_one()
which should not need the lock.  The netdev is already unregistered by
then.  Fix it by calling netdev_assert_locked_or_invisible() which will
not assert if the netdev is unregistered.

WARNING: CPU: 5 PID: 2241 at ./include/net/netdev_lock.h:17 bnxt_free_ntp_fltrs+0xf8/0x100 [bnxt_en]
Modules linked in: rpcrdma rdma_cm iw_cm ib_cm configfs ib_core bnxt_en(-) bridge stp llc x86_pkg_temp_thermal xfs tg3 [last unloaded: bnxt_re]
CPU: 5 UID: 0 PID: 2241 Comm: rmmod Tainted: G S      W           6.16.0 #2 PREEMPT(voluntary)
Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN
Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.4.3 01/17/2017
RIP: 0010:bnxt_free_ntp_fltrs+0xf8/0x100 [bnxt_en]
Code: 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 48 8b 47 60 be ff ff ff ff 48 8d b8 28 0c 00 00 e8 d0 cf 41 c3 85 c0 0f 85 2e ff ff ff <0f> 0b e9 27 ff ff ff 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 0018:ffffa92082387da0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff9e5b593d8000 RCX: 0000000000000001
RDX: 0000000000000001 RSI: ffffffff83dc9a70 RDI: ffffffff83e1a1cf
RBP: ffff9e5b593d8c80 R08: 0000000000000000 R09: ffffffff8373a2b3
R10: 000000008100009f R11: 0000000000000001 R12: 0000000000000001
R13: ffffffffc01c4478 R14: dead000000000122 R15: dead000000000100
FS:  00007f3a8a52c740(0000) GS:ffff9e631ad1c000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055bb289419c8 CR3: 000000011274e001 CR4: 00000000003706f0
Call Trace:
 <TASK>
 bnxt_remove_one+0x57/0x180 [bnxt_en]
 pci_device_remove+0x39/0xc0
 device_release_driver_internal+0xa5/0x130
 driver_detach+0x42/0x90
 bus_remove_driver+0x61/0xc0
 pci_unregister_driver+0x38/0x90
 bnxt_exit+0xc/0x7d0 [bnxt_en]

Fixes: 004b500801 ("eth: bnxt: remove most dependencies on RTNL")
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250816183850.4125033-1-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:51:22 -07:00
Jonas Gorski
89eb9a62ae net: dsa: b53: fix reserved register access in b53_fdb_dump()
When BCM5325 support was added in c45655386e ("net: dsa: b53: add
support for FDB operations on 5325/5365"), the register used for ARL access
was made conditional on the chip.

But in b53_fdb_dump(), instead of the register argument the page
argument was replaced, causing it to write to a reserved page 0x50 on
!BCM5325*. Writing to this page seems to completely lock the switch up:

[   89.680000] b53-switch spi0.1 lan2: Link is Down
[   89.680000] WARNING: CPU: 1 PID: 26 at drivers/net/phy/phy.c:1350 _phy_state_machine+0x1bc/0x454
[   89.720000] phy_check_link_status+0x0/0x114: returned: -5
[   89.730000] Modules linked in: nft_fib_inet nf_flow_table_inet nft_reject_ipv6 nft_reject_ipv4 nft_reject_inet nft_reject nft_redir nft_quota nft_numgen nft_nat nft_masq nft_log nft_limit nft_hash nft_flow_offload nft_fib_ipv6 nft_fib_ipv4 nft_fib nft_ct nft_chain_nat nf_tables nf_nat nf_flow_table nf_conntrack nfnetlink nf_reject_ipv6 nf_reject_ipv4 nf_log_syslog nf_defrag_ipv6 nf_defrag_ipv4 cls_flower sch_tbf sch_ingress sch_htb sch_hfsc em_u32 cls_u32 cls_route cls_matchall cls_fw cls_flow cls_basic act_skbedit act_mirred act_gact vrf md5 crc32c_cryptoapi
[   89.780000] CPU: 1 UID: 0 PID: 26 Comm: kworker/u10:0 Tainted: G        W           6.16.0-rc1+ #0 NONE
[   89.780000] Tainted: [W]=WARN
[   89.780000] Hardware name: Netgear DGND3700 v1
[   89.780000] Workqueue: events_power_efficient phy_state_machine
[   89.780000] Stack : 809c762c 8006b050 00000001 820a9ce3 0000114c 000affff 805d22d0 8200ba00
[   89.780000]         82005000 6576656e 74735f70 6f776572 5f656666 10008b00 820a9cb8 82088700
[   89.780000]         00000000 00000000 809c762c 820a9a98 00000000 00000000 ffffefff 80a7a76c
[   89.780000]         80a70000 820a9af8 80a70000 80a70000 80a70000 00000000 809c762c 820a9dd4
[   89.780000]         00000000 805d1494 80a029e4 80a70000 00000003 00000000 00000004 81a60004
[   89.780000]         ...
[   89.780000] Call Trace:
[   89.780000] [<800228b8>] show_stack+0x38/0x118
[   89.780000] [<8001afc4>] dump_stack_lvl+0x6c/0xac
[   89.780000] [<80046b90>] __warn+0x9c/0x114
[   89.780000] [<80046da8>] warn_slowpath_fmt+0x1a0/0x1b0
[   89.780000] [<805d1494>] _phy_state_machine+0x1bc/0x454
[   89.780000] [<805d22fc>] phy_state_machine+0x2c/0x70
[   89.780000] [<80066b08>] process_one_work+0x1e8/0x3e0
[   89.780000] [<80067a1c>] worker_thread+0x354/0x4e4
[   89.780000] [<800706cc>] kthread+0x130/0x274
[   89.780000] [<8001d808>] ret_from_kernel_thread+0x14/0x1c

And any further accesses fail:

[  120.790000] b53-switch spi0.1: timeout waiting for ARL to finish: 0x81
[  120.800000] b53-switch spi0.1: port 2 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145
[  121.010000] b53-switch spi0.1: timeout waiting for ARL to finish: 0xbf
[  121.020000] b53-switch spi0.1: port 3 failed to add 2c:b0:5d:27:9a:bd vid 3 to fdb: -145

Restore the correct page B53_ARLIO_PAGE again, and move the offset
argument to the correct place.

*On BCM5325, this became a write to the MIB page of Port 1. Still
a reserved offset, but likely less brokenness from that write.

Fixes: c45655386e ("net: dsa: b53: add support for FDB operations on 5325/5365")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20250815201809.549195-1-jonas.gorski@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:46:04 -07:00
Jakub Kicinski
8cd3709b39 Merge branch 'mptcp-misc-fixes-for-v6-17-rc'
Matthieu Baerts says:

====================
mptcp: misc fixes for v6.17-rc

Here are various fixes:

- Patch 1: Better handling SKB extension allocation failures.
  A fix for v5.7.

- Patches 2, 3: Avoid resetting MPTCP limits when flushing MPTCP
  endpoints. With a validation in the selftests. Fixes for v5.7.

- Patches 4, 5, 6: Disallow '0' as ADD_ADDR retransmission timeout.
  With a preparation patch, and a validation in the selftests.
  Fixes for v5.11.

- Patches 8, 9: Fix C23 extension warnings in the selftests,
  spotted by GCC. Fixes for v6.16.
====================

Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-0-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:40:04 -07:00
Matthieu Baerts (NGI0)
3259889fd3 selftests: mptcp: sockopt: fix C23 extension warning
GCC was complaining about the new label:

  mptcp_inq.c:79:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions]
     79 |         int err = getaddrinfo(node, service, hints, res);
        |         ^

  mptcp_sockopt.c:166:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions]
    166 |         int err = getaddrinfo(node, service, hints, res);
        |         ^

Simply declare 'err' before the label to avoid this warning.

Fixes: dd367e81b7 ("selftests: mptcp: sockopt: use IPPROTO_MPTCP for getaddrinfo")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-8-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:59 -07:00
Matthieu Baerts (NGI0)
2eefbed30d selftests: mptcp: connect: fix C23 extension warning
GCC was complaining about the new label:

  mptcp_connect.c:187:2: warning: label followed by a declaration is a C23 extension [-Wc23-extensions]
    187 |         int err = getaddrinfo(node, service, hints, res);
        |         ^

Simply declare 'err' before the label to avoid this warning.

Fixes: a862771d1a ("selftests: mptcp: use IPPROTO_MPTCP for getaddrinfo")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-7-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:59 -07:00
Geliang Tang
f92199f551 selftests: mptcp: disable add_addr retrans in endpoint_tests
To prevent test instability in the "delete re-add signal" test caused by
ADD_ADDR retransmissions, disable retransmissions for this test by setting
net.mptcp.add_addr_timeout to 0.

Suggested-by: Matthieu Baerts <matttbe@kernel.org>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-6-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Geliang Tang
f5ce071462 mptcp: disable add_addr retransmission when timeout is 0
When add_addr_timeout was set to 0, this caused the ADD_ADDR to be
retransmitted immediately, which looks like a buggy behaviour. Instead,
interpret 0 as "no retransmissions needed".

The documentation is updated to explicitly state that setting the timeout
to 0 disables retransmission.

Fixes: 93f323b9cc ("mptcp: add a new sysctl add_addr_timeout")
Cc: stable@vger.kernel.org
Suggested-by: Matthieu Baerts <matttbe@kernel.org>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-5-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Geliang Tang
5d13349472 mptcp: remove duplicate sk_reset_timer call
sk_reset_timer() was called twice in mptcp_pm_alloc_anno_list.

Simplify the code by using a 'goto' statement to eliminate the
duplication.

Note that this is not a fix, but it will help backporting the following
patch. The same "Fixes" tag has been added for this reason.

Fixes: 93f323b9cc ("mptcp: add a new sysctl add_addr_timeout")
Cc: stable@vger.kernel.org
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-4-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Matthieu Baerts (NGI0)
452690be7d selftests: mptcp: pm: check flush doesn't reset limits
This modification is linked to the parent commit where the received
ADD_ADDR limit was accidentally reset when the endpoints were flushed.

To validate that, the test is now flushing endpoints after having set
new limits, and before checking them.

The 'Fixes' tag here below is the same as the one from the previous
commit: this patch here is not fixing anything wrong in the selftests,
but it validates the previous fix for an issue introduced by this commit
ID.

Fixes: 01cacb00b3 ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-3-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Matthieu Baerts (NGI0)
68fc0f4b0d mptcp: pm: kernel: flush: do not reset ADD_ADDR limit
A flush of the MPTCP endpoints should not affect the MPTCP limits. In
other words, 'ip mptcp endpoint flush' should not change 'ip mptcp
limits'.

But it was the case: the MPTCP_PM_ATTR_RCV_ADD_ADDRS (add_addr_accepted)
limit was reset by accident. Removing the reset of this counter during a
flush fixes this issue.

Fixes: 01cacb00b3 ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Reported-by: Thomas Dreibholz <dreibh@simula.no>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/579
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-2-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Christoph Paasch
ccab044697 mptcp: drop skb if MPTCP skb extension allocation fails
When skb_ext_add(skb, SKB_EXT_MPTCP) fails in mptcp_incoming_options(),
we used to return true, letting the segment proceed through the TCP
receive path without a DSS mapping. Such segments can leave inconsistent
mapping state and trigger a mid-stream fallback to TCP, which in testing
collapsed (by artificially forcing failures in skb_ext_add) throughput
to zero.

Return false instead so the TCP input path drops the skb (see
tcp_data_queue() and step-7 processing). This is the safer choice
under memory pressure: it preserves MPTCP correctness and provides
backpressure to the sender.

Control packets remain unaffected: ACK updates and DATA_FIN handling
happen before attempting the extension allocation, and tcp_reset()
continues to ignore the return value.

With this change, MPTCP continues to work at high throughput if we
artificially inject failures into skb_ext_add.

Fixes: 6787b7e350 ("mptcp: avoid processing packet if a subflow reset")
Cc: stable@vger.kernel.org
Signed-off-by: Christoph Paasch <cpaasch@openai.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-1-521fe9957892@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:39:58 -07:00
Minhong He
84967deee9 ipv6: sr: validate HMAC algorithm ID in seg6_hmac_info_add
The seg6_genl_sethmac() directly uses the algorithm ID provided by the
userspace without verifying whether it is an HMAC algorithm supported
by the system.
If an unsupported HMAC algorithm ID is configured, packets using SRv6 HMAC
will be dropped during encapsulation or decapsulation.

Fixes: 4f4853dc1c ("ipv6: sr: implement API to control SR HMAC structure")
Signed-off-by: Minhong He <heminhong@kylinos.cn>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250815063845.85426-1-heminhong@kylinos.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:35:50 -07:00
Jakub Ramaseuski
864e339697 net: gso: Forbid IPv6 TSO with extensions on devices with only IPV6_CSUM
When performing Generic Segmentation Offload (GSO) on an IPv6 packet that
contains extension headers, the kernel incorrectly requests checksum offload
if the egress device only advertises NETIF_F_IPV6_CSUM feature, which has
a strict contract: it supports checksum offload only for plain TCP or UDP
over IPv6 and explicitly does not support packets with extension headers.
The current GSO logic violates this contract by failing to disable the feature
for packets with extension headers, such as those used in GREoIPv6 tunnels.

This violation results in the device being asked to perform an operation
it cannot support, leading to a `skb_warn_bad_offload` warning and a collapse
of network throughput. While device TSO/USO is correctly bypassed in favor
of software GSO for these packets, the GSO stack must be explicitly told not
to request checksum offload.

Mask NETIF_F_IPV6_CSUM, NETIF_F_TSO6 and NETIF_F_GSO_UDP_L4
in gso_features_check if the IPv6 header contains extension headers to compute
checksum in software.

The exception is a BIG TCP extension, which, as stated in commit
68e068cabd ("net: reenable NETIF_F_IPV6_CSUM offload for BIG TCP packets"):
"The feature is only enabled on devices that support BIG TCP TSO.
The header is only present for PF_PACKET taps like tcpdump,
and not transmitted by physical devices."

kernel log output (truncated):
WARNING: CPU: 1 PID: 5273 at net/core/dev.c:3535 skb_warn_bad_offload+0x81/0x140
...
Call Trace:
 <TASK>
 skb_checksum_help+0x12a/0x1f0
 validate_xmit_skb+0x1a3/0x2d0
 validate_xmit_skb_list+0x4f/0x80
 sch_direct_xmit+0x1a2/0x380
 __dev_xmit_skb+0x242/0x670
 __dev_queue_xmit+0x3fc/0x7f0
 ip6_finish_output2+0x25e/0x5d0
 ip6_finish_output+0x1fc/0x3f0
 ip6_tnl_xmit+0x608/0xc00 [ip6_tunnel]
 ip6gre_tunnel_xmit+0x1c0/0x390 [ip6_gre]
 dev_hard_start_xmit+0x63/0x1c0
 __dev_queue_xmit+0x6d0/0x7f0
 ip6_finish_output2+0x214/0x5d0
 ip6_finish_output+0x1fc/0x3f0
 ip6_xmit+0x2ca/0x6f0
 ip6_finish_output+0x1fc/0x3f0
 ip6_xmit+0x2ca/0x6f0
 inet6_csk_xmit+0xeb/0x150
 __tcp_transmit_skb+0x555/0xa80
 tcp_write_xmit+0x32a/0xe90
 tcp_sendmsg_locked+0x437/0x1110
 tcp_sendmsg+0x2f/0x50
...
skb linear:   00000000: e4 3d 1a 7d ec 30 e4 3d 1a 7e 5d 90 86 dd 60 0e
skb linear:   00000010: 00 0a 1b 34 3c 40 20 11 00 00 00 00 00 00 00 00
skb linear:   00000020: 00 00 00 00 00 12 20 11 00 00 00 00 00 00 00 00
skb linear:   00000030: 00 00 00 00 00 11 2f 00 04 01 04 01 01 00 00 00
skb linear:   00000040: 86 dd 60 0e 00 0a 1b 00 06 40 20 23 00 00 00 00
skb linear:   00000050: 00 00 00 00 00 00 00 00 00 12 20 23 00 00 00 00
skb linear:   00000060: 00 00 00 00 00 00 00 00 00 11 bf 96 14 51 13 f9
skb linear:   00000070: ae 27 a0 a8 2b e3 80 18 00 40 5b 6f 00 00 01 01
skb linear:   00000080: 08 0a 42 d4 50 d5 4b 70 f8 1a

Fixes: 04c20a9356 ("net: skip offload for NETIF_F_IPV6_CSUM if ipv6 header contains extension")
Reported-by: Tianhao Zhao <tizhao@redhat.com>
Suggested-by: Michal Schmidt <mschmidt@redhat.com>
Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Signed-off-by: Jakub Ramaseuski <jramaseu@redhat.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20250814105119.1525687-1-jramaseu@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-18 17:20:06 -07:00
Jakub Kicinski
715c7a36d5 selftests: tls: make the new data_steal test less flaky
The CI has hit a couple of cases of:

  RUN           global.data_steal ...
 tls.c:2762:data_steal:Expected recv(cfd, buf2, sizeof(buf2), MSG_DONTWAIT) (20000) == -1 (-1)
 data_steal: Test terminated by timeout
          FAIL  global.data_steal

Looks like the 2msec sleep is not long enough. Make the sleep longer,
and then instead of second sleep wait for the thieving process to exit.
That way we can be sure it called recv() before us.

While at it also avoid trying to steal more than a record, this seems
to be causing issues in manual testing as well.

Fixes: d7e82594a4 ("selftests: tls: test TCP stealing data from under the TLS socket")
Link: https://patch.msgid.link/20250814194323.2014650-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 18:07:27 -07:00
Chandra Mohan Sundar
12da2b92ad net: libwx: Fix the size in RSS hash key population
While trying to fill a random RSS key, the size of the pointer
is being used rather than the actual size of the RSS key.

Fix by passing an appropriate value of the RSS key.
This issue was reported by static coverity analyser.

Fixes: eb4898fde1 ("net: libwx: add wangxun vf common api")
Signed-off-by: Chandra Mohan Sundar <chandramohan.explore@gmail.com>
Link: https://patch.msgid.link/20250814163014.613004-1-chandramohan.explore@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 12:38:53 -07:00
Jakub Kicinski
79116acb75 bluetooth pull request for net:
- hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
  - hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
  - hci_core: Fix using {cis,bis}_capable for current settings
  - hci_core: Fix using ll_privacy_capable for current settings
  - hci_core: Fix not accounting for BIS/CIS/PA links separately
  - hci_conn: do return error from hci_enhanced_setup_sync()
  - hci_event: fix MTU for BN == 0 in CIS Established
  - hci_sync: Fix scan state after PA Sync has been established
  - hci_sync: Avoid adding default advertising on startup
  - hci_sync: Prevent unintended PA sync when SID is 0xFF
  - ISO: Fix getname not returning broadcast fields
  - btmtk: Fix wait_on_bit_timeout interruption during shutdown
  - btnxpuart: Uses threaded IRQ for host wakeup handling
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCgA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmifQh4ZHGx1aXoudm9u
 LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKSpyD/4+a98UD/FMiu2MuowbCJvK
 EWneAUc9l0j/bhVSaTnRzpXM6gov/SNdSFr9dLrTeYY75X+ky1YDFca/deP2fZzl
 v+2H306yIw73k4DAEqkzOQk+YRpi/N7+rruytlZd7TC29zwer1IEg2Rv6hMqmZQt
 bkFiEcR2HpIFaXGDAmsKmXEQ3xsNnbHpeuqQIYPC0uzTYDdW8O+vV/etgHeycfzc
 dGDJOX+3oEAYCi3NtJY/DZLlIhKneLHRn7qGpDAXUWTRvzHESdzmOzSQ9wD0fVqD
 pMMJv0dmaubH32JHafnIGixGb6LwhHWbse2yaei2uWfwukQJAzflfMwkManVsEBa
 SM5mNXS586xeLfahLy1FmlbOaL5e7enL8Bhd4jZJGtIb1WRMZBsXCNKX0cZUKn8B
 mNrM1zqQUvBrmS9G5KC2lAfgco0mqxoSKipgctJLamzNR2z6Yz4No0MLTzh89MnV
 0waBToTn8sXidN/ENzOrxq6GGFZmaV0x3UXickwcbxLKC30+r3nXR4j0xK56N2ly
 2sM+wU9CkXitQIW8PUWcYAWZ1k3/7ixv5/pIGVHnozQEcHiBX0OOmReauF3LWZjC
 pWZU0/T7vduS4/3ThSBQNOjjWp3uhyKYCbbumMQsTVSsJ5MOgvf7IqLcVWAVi3Eg
 1lbQkLQNC3uaosoV/JJfRg==
 =ZtN+
 -----END PGP SIGNATURE-----

Merge tag 'for-net-2025-08-15' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
 - hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
 - hci_core: Fix using {cis,bis}_capable for current settings
 - hci_core: Fix using ll_privacy_capable for current settings
 - hci_core: Fix not accounting for BIS/CIS/PA links separately
 - hci_conn: do return error from hci_enhanced_setup_sync()
 - hci_event: fix MTU for BN == 0 in CIS Established
 - hci_sync: Fix scan state after PA Sync has been established
 - hci_sync: Avoid adding default advertising on startup
 - hci_sync: Prevent unintended PA sync when SID is 0xFF
 - ISO: Fix getname not returning broadcast fields
 - btmtk: Fix wait_on_bit_timeout interruption during shutdown
 - btnxpuart: Uses threaded IRQ for host wakeup handling

* tag 'for-net-2025-08-15' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately
  Bluetooth: btnxpuart: Uses threaded IRQ for host wakeup handling
  Bluetooth: hci_conn: do return error from hci_enhanced_setup_sync()
  Bluetooth: hci_event: fix MTU for BN == 0 in CIS Established
  Bluetooth: hci_sync: Prevent unintended PA sync when SID is 0xFF
  Bluetooth: hci_core: Fix using ll_privacy_capable for current settings
  Bluetooth: hci_core: Fix using {cis,bis}_capable for current settings
  Bluetooth: btmtk: Fix wait_on_bit_timeout interruption during shutdown
  Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
  Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
  Bluetooth: ISO: Fix getname not returning broadcast fields
  Bluetooth: hci_sync: Fix scan state after PA Sync has been established
  Bluetooth: hci_sync: Avoid adding default advertising on startup
====================

Link: https://patch.msgid.link/20250815142229.253052-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 10:56:11 -07:00
Jakub Kicinski
0894731887 Merge branch 'mlxsw-spectrum-forward-packets-with-an-ipv4-link-local-source-ip'
Petr Machata says:

====================
mlxsw: spectrum: Forward packets with an IPv4 link-local source IP

By default, Spectrum devices do not forward IPv4 packets with a link-local
source IP (i.e., 169.254.0.0/16). This behavior does not align with the
kernel which does forward them. Fix the issue and add a selftest.
====================

Link: https://patch.msgid.link/cover.1755174341.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 10:44:50 -07:00
Ido Schimmel
5e0b2177bd selftest: forwarding: router: Add a test case for IPv4 link-local source IP
Add a test case which checks that packets with an IPv4 link-local source
IP are forwarded and not dropped.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Link: https://patch.msgid.link/3c2e0b17d99530f57bef5ddff9af284fa0c9b667.1755174341.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 10:44:48 -07:00
Ido Schimmel
f604d3aaf6 mlxsw: spectrum: Forward packets with an IPv4 link-local source IP
By default, the device does not forward IPv4 packets with a link-local
source IP (i.e., 169.254.0.0/16). This behavior does not align with the
kernel which does forward them.

Fix by instructing the device to forward such packets instead of
dropping them.

Fixes: ca360db4b8 ("mlxsw: spectrum: Disable DIP_LINK_LOCAL check in hardware pipeline")
Reported-by: Zoey Mertes <zoey@cloudflare.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Link: https://patch.msgid.link/6721e6b2c96feb80269e72ce8d0b426e2f32d99c.1755174341.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-15 10:44:48 -07:00
Luiz Augusto von Dentz
9d4b01a0bf Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately
This fixes the likes of hci_conn_num(CIS_LINK) returning the total of
ISO connection which includes BIS_LINK as well, so this splits the
iso_num into each link type and introduces hci_iso_num that can be used
in places where the total number of ISO connection still needs to be
used.

Fixes: 23205562ff ("Bluetooth: separate CIS_LINK and BIS_LINK link types")
Fixes: a7bcffc673 ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 10:13:41 -04:00
Neeraj Sanjay Kale
e489317d2f Bluetooth: btnxpuart: Uses threaded IRQ for host wakeup handling
This replaces devm_request_irq() with devm_request_threaded_irq().

On iMX93 11x11 EVK platform, the BT chip's BT_WAKE_OUT pin is connected
to an I2C GPIO expander instead of directly been connected to iMX GPIO.

When I2C GPIO expander's (PCAL6524) host driver receives an interrupt on
it's INTR line, the driver's interrupt handler needs to query the
interrupt source with PCAL6524 first, and then call the actual interrupt
handler, in this case the IRQ handler in BTNXPUART.

In order to handle interrupts when such I2C GPIO expanders are between
the host and interrupt source, devm_request_threaded_irq() is needed.

This commit also removes the IRQF_TRIGGER_FALLING flag, to allow setting
the IRQ trigger type from the device tree setting instead of hardcoding
in the driver.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Reviewed-by: Sherry Sun <sherry.sun@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 10:13:26 -04:00
Sergey Shtylyov
0eaf7c7e85 Bluetooth: hci_conn: do return error from hci_enhanced_setup_sync()
The commit e07a06b4eb ("Bluetooth: Convert SCO configure_datapath to
hci_sync") missed to update the *return* statement under the *case* of
BT_CODEC_TRANSPARENT in hci_enhanced_setup_sync(), which led to returning
success (0) instead of the negative error code (-EINVAL).  However, the
result of hci_enhanced_setup_sync() seems to be ignored anyway, since NULL
gets passed to hci_cmd_sync_queue() as the last argument in that case and
the only function interested in that result is specified by that argument.

Fixes: e07a06b4eb ("Bluetooth: Convert SCO configure_datapath to hci_sync")
Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 10:13:09 -04:00
Pauli Virtanen
0b3725dbf6 Bluetooth: hci_event: fix MTU for BN == 0 in CIS Established
BN == 0x00 in CIS Established means no isochronous data for the
corresponding direction (Core v6.1 pp. 2394). In this case SDU MTU
should be 0.

However, the specification does not say the Max_PDU_C_To_P or P_To_C are
then zero.  Intel AX210 in Framed CIS mode sets nonzero Max_PDU for
direction with zero BN.  This causes failure later when we try to LE
Setup ISO Data Path for disabled direction, which is disallowed (Core
v6.1 pp. 2750).

Fix by setting SDU MTU to 0 if BN == 0.

Fixes: 2be22f1941 ("Bluetooth: hci_event: Fix parsing of CIS Established Event")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Yang Li
4d19cd228b Bluetooth: hci_sync: Prevent unintended PA sync when SID is 0xFF
After LE Extended Scan times out, conn->sid remains 0xFF,
so the PA sync creation process should be aborted.

Btmon snippet from PA sync with SID=0xFF:

< HCI Command: LE Set Extended.. (0x08|0x0042) plen 6  #74726 [hci0] 863.107927
        Extended scan: Enabled (0x01)
        Filter duplicates: Enabled (0x01)
        Duration: 0 msec (0x0000)
        Period: 0.00 sec (0x0000)
> HCI Event: Command Complete (0x0e) plen 4            #74727 [hci0] 863.109389
      LE Set Extended Scan Enable (0x08|0x0042) ncmd 1
        Status: Success (0x00)
< HCI Command: LE Periodic Ad.. (0x08|0x0044) plen 14  #74728 [hci0] 865.141168
        Options: 0x0000
        Use advertising SID, Advertiser Address Type and address
        Reporting initially enabled
        SID: 0xff
        Adv address type: Random (0x01)
        Adv address: 0D:D7:2C:E7:42:46 (Non-Resolvable)
        Skip: 0x0000
        Sync timeout: 20000 msec (0x07d0)
        Sync CTE type: 0x0000
> HCI Event: Command Status (0x0f) plen 4              #74729 [hci0] 865.143223
      LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1
        Status: Success (0x00)

Fixes: e2d471b780 ("Bluetooth: ISO: Fix not using SID from adv report")
Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
3dcf7175f2 Bluetooth: hci_core: Fix using ll_privacy_capable for current settings
ll_privacy_capable only indicates that the controller supports the
feature but it doesnt' check that LE is enabled so it end up being
marked as active in the current settings when it shouldn't.

Fixes: ad383c2c65 ("Bluetooth: hci_sync: Enable advertising when LL privacy is enabled")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
709788b154 Bluetooth: hci_core: Fix using {cis,bis}_capable for current settings
{cis,bis}_capable only indicates the controller supports the feature
since it doesn't check that LE is enabled so it shall not be used for
current setting, instead this introduces {cis,bis}_enabled macros that
can be used to indicate that these features are currently enabled.

Fixes: 26afbd826e ("Bluetooth: Add initial implementation of CIS connections")
Fixes: eca0ae4aea ("Bluetooth: Add initial implementation of BIS connections")
Fixes: ae75336131 ("Bluetooth: Check for ISO support in controller")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Jiande Lu
099799fa9b Bluetooth: btmtk: Fix wait_on_bit_timeout interruption during shutdown
During the shutdown process, an interrupt occurs that
prematurely terminates the wait for the expected event.
This change replaces TASK_INTERRUPTIBLE with
TASK_UNINTERRUPTIBLE in the wait_on_bit_timeout call to ensure
the shutdown process completes as intended without being
interrupted by signals.

Fixes: d019930b00 ("Bluetooth: btmtk: move btusb_mtk_hci_wmt_sync to btmtk.c")
Signed-off-by: Jiande Lu <jiande.lu@mediatek.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
3ba486c5f3 Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
This fixes Broadcaster/Broadcast Source not sending HCI_OP_LE_TERM_BIG
because HCI_CONN_PER_ADV where not being set.

Fixes: a7bcffc673 ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
d36349ea73 Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
Connections with type of PA_LINK shall be considered temporary just to
track the lifetime of PA Sync setup, once the BIG Sync is established
and connection are created with BIS_LINK the existing PA_LINK
connection shall not longer use bis_cleanup otherwise it terminates the
PA Sync when that shall be left to BIS_LINK connection to do it.

Fixes: a7bcffc673 ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
aee29c18a3 Bluetooth: ISO: Fix getname not returning broadcast fields
getname shall return iso_bc fields for both BIS_LINK and PA_LINK since
the likes of bluetoothd do use the getpeername to retrieve the SID both
when enumerating the broadcasters and when synchronizing.

Fixes: a7bcffc673 ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Luiz Augusto von Dentz
ca88be1a27 Bluetooth: hci_sync: Fix scan state after PA Sync has been established
Passive scanning is used to program the address of the peer to be
synchronized, so once HCI_EV_LE_PA_SYNC_ESTABLISHED is received it
needs to be updated after clearing HCI_PA_SYNC then call
hci_update_passive_scan_sync to return it to its original state.

Fixes: 6d0417e4e1 ("Bluetooth: hci_conn: Fix not setting conn_timeout for Broadcast Receiver")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Yang Li
de5d7d3f27 Bluetooth: hci_sync: Avoid adding default advertising on startup
list_empty(&hdev->adv_instances) is always true during startup,
so an advertising instance is added by default.

Call trace:
  dump_backtrace+0x94/0xec
  show_stack+0x18/0x24
  dump_stack_lvl+0x48/0x60
  dump_stack+0x18/0x24
  hci_setup_ext_adv_instance_sync+0x17c/0x328
  hci_powered_update_adv_sync+0xb4/0x12c
  hci_powered_update_sync+0x54/0x70
  hci_power_on_sync+0xe4/0x278
  hci_set_powered_sync+0x28/0x34
  set_powered_sync+0x40/0x58
  hci_cmd_sync_work+0x94/0x100
  process_one_work+0x168/0x444
  worker_thread+0x378/0x3f4
  kthread+0x108/0x10c
  ret_from_fork+0x10/0x20

Link: https://github.com/bluez/bluez/issues/1442
Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2025-08-15 09:44:49 -04:00
Justin Lai
065c31f2c6 rtase: Fix Rx descriptor CRC error bit definition
The CRC error bit is located at bit 17 in the Rx descriptor, but the
driver was incorrectly using bit 16. Fix it.

Fixes: a36e9f5cfe ("rtase: Add support for a pci table in this module")
Signed-off-by: Justin Lai <justinlai0215@realtek.com>
Link: https://patch.msgid.link/20250813071631.7566-1-justinlai0215@realtek.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:53:12 -07:00
William Liu
8c06cbdcba selftests/tc-testing: Check backlog stats in gso_skb case
Add tests to ensure proper backlog accounting in hhf, codel, pie, fq,
fq_pie, and fq_codel qdiscs. We check for the bug pattern originally
found in fq, fq_pie, and fq_codel, which was an underflow in the tbf
parent backlog stats upon child qdisc removal.

Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Link: https://patch.msgid.link/20250812235808.45281-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:52:29 -07:00
William Liu
52bf272636 net/sched: Fix backlog accounting in qdisc_dequeue_internal
This issue applies for the following qdiscs: hhf, fq, fq_codel, and
fq_pie, and occurs in their change handlers when adjusting to the new
limit. The problem is the following in the values passed to the
subsequent qdisc_tree_reduce_backlog call given a tbf parent:

   When the tbf parent runs out of tokens, skbs of these qdiscs will
   be placed in gso_skb. Their peek handlers are qdisc_peek_dequeued,
   which accounts for both qlen and backlog. However, in the case of
   qdisc_dequeue_internal, ONLY qlen is accounted for when pulling
   from gso_skb. This means that these qdiscs are missing a
   qdisc_qstats_backlog_dec when dropping packets to satisfy the
   new limit in their change handlers.

   One can observe this issue with the following (with tc patched to
   support a limit of 0):

   export TARGET=fq
   tc qdisc del dev lo root
   tc qdisc add dev lo root handle 1: tbf rate 8bit burst 100b latency 1ms
   tc qdisc replace dev lo handle 3: parent 1:1 $TARGET limit 1000
   echo ''; echo 'add child'; tc -s -d qdisc show dev lo
   ping -I lo -f -c2 -s32 -W0.001 127.0.0.1 2>&1 >/dev/null
   echo ''; echo 'after ping'; tc -s -d qdisc show dev lo
   tc qdisc change dev lo handle 3: parent 1:1 $TARGET limit 0
   echo ''; echo 'after limit drop'; tc -s -d qdisc show dev lo
   tc qdisc replace dev lo handle 2: parent 1:1 sfq
   echo ''; echo 'post graft'; tc -s -d qdisc show dev lo

   The second to last show command shows 0 packets but a positive
   number (74) of backlog bytes. The problem becomes clearer in the
   last show command, where qdisc_purge_queue triggers
   qdisc_tree_reduce_backlog with the positive backlog and causes an
   underflow in the tbf parent's backlog (4096 Mb instead of 0).

To fix this issue, the codepath for all clients of qdisc_dequeue_internal
has been simplified: codel, pie, hhf, fq, fq_pie, and fq_codel.
qdisc_dequeue_internal handles the backlog adjustments for all cases that
do not directly use the dequeue handler.

The old fq_codel_change limit adjustment loop accumulated the arguments to
the subsequent qdisc_tree_reduce_backlog call through the cstats field.
However, this is confusing and error prone as fq_codel_dequeue could also
potentially mutate this field (which qdisc_dequeue_internal calls in the
non gso_skb case), so we have unified the code here with other qdiscs.

Fixes: 2d3cbfd6d5 ("net_sched: Flush gso_skb list too during ->change()")
Fixes: 4b549a2ef4 ("fq_codel: Fair Queue Codel AQM")
Fixes: 10239edf86 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc")
Signed-off-by: William Liu <will@willsroot.io>
Reviewed-by: Savino Dicanosa <savy@syst3mfailure.io>
Link: https://patch.msgid.link/20250812235725.45243-1-will@willsroot.io
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:52:29 -07:00
Wang Liang
d1547bf460 net: bridge: fix soft lockup in br_multicast_query_expired()
When set multicast_query_interval to a large value, the local variable
'time' in br_multicast_send_query() may overflow. If the time is smaller
than jiffies, the timer will expire immediately, and then call mod_timer()
again, which creates a loop and may trigger the following soft lockup
issue.

  watchdog: BUG: soft lockup - CPU#1 stuck for 221s! [rb_consumer:66]
  CPU: 1 UID: 0 PID: 66 Comm: rb_consumer Not tainted 6.16.0+ #259 PREEMPT(none)
  Call Trace:
   <IRQ>
   __netdev_alloc_skb+0x2e/0x3a0
   br_ip6_multicast_alloc_query+0x212/0x1b70
   __br_multicast_send_query+0x376/0xac0
   br_multicast_send_query+0x299/0x510
   br_multicast_query_expired.constprop.0+0x16d/0x1b0
   call_timer_fn+0x3b/0x2a0
   __run_timers+0x619/0x950
   run_timer_softirq+0x11c/0x220
   handle_softirqs+0x18e/0x560
   __irq_exit_rcu+0x158/0x1a0
   sysvec_apic_timer_interrupt+0x76/0x90
   </IRQ>

This issue can be reproduced with:
  ip link add br0 type bridge
  echo 1 > /sys/class/net/br0/bridge/multicast_querier
  echo 0xffffffffffffffff >
  	/sys/class/net/br0/bridge/multicast_query_interval
  ip link set dev br0 up

The multicast_startup_query_interval can also cause this issue. Similar to
the commit 99b4061095 ("net: bridge: mcast: add and enforce query
interval minimum"), add check for the query interval maximum to fix this
issue.

Link: https://lore.kernel.org/netdev/20250806094941.1285944-1-wangliang74@huawei.com/
Link: https://lore.kernel.org/netdev/20250812091818.542238-1-wangliang74@huawei.com/
Fixes: d902eee43f ("bridge: Add multicast count/interval sysfs entries")
Suggested-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Wang Liang <wangliang74@huawei.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20250813021054.1643649-1-wangliang74@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:49:33 -07:00
Suraj Gupta
fd980bf6e9 net: xilinx: axienet: Fix RX skb ring management in DMAengine mode
Submit multiple descriptors in axienet_rx_cb() to fill Rx skb ring. This
ensures the ring "catches up" on previously missed allocations.

Increment Rx skb ring head pointer after BD is successfully allocated.
Previously, head pointer was incremented before verifying if descriptor is
successfully allocated and has valid entries, which could lead to ring
state inconsistency if descriptor setup failed.

These changes improve reliability by maintaining adequate descriptor
availability and ensuring proper ring buffer state management.

Fixes: 6a91b846af ("net: axienet: Introduce dmaengine support")
Signed-off-by: Suraj Gupta <suraj.gupta2@amd.com>
Link: https://patch.msgid.link/20250813135559.1555652-1-suraj.gupta2@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:38:44 -07:00
Alexandra Winter
1548549e17 MAINTAINERS: update s390/net
Remove Thorsten Winkler as maintainer and add Aswin Karuvally as reviewer.

Thank you Thorsten for your support, welcome Aswin!

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Acked-by: Thorsten Winkler <twinkler@linux.ibm.com>
Acked-by: Aswin Karuvally <aswin@linux.ibm.com>
Link: https://patch.msgid.link/20250813111633.241111-1-wintera@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2025-08-14 17:36:15 -07:00
92 changed files with 1434 additions and 397 deletions

View File

@ -12,6 +12,8 @@ add_addr_timeout - INTEGER (seconds)
resent to an MPTCP peer that has not acknowledged a previous resent to an MPTCP peer that has not acknowledged a previous
ADD_ADDR message. ADD_ADDR message.
Do not retransmit if set to 0.
The default value matches TCP_RTO_MAX. This is a per-namespace The default value matches TCP_RTO_MAX. This is a per-namespace
sysctl. sysctl.

View File

@ -22174,7 +22174,7 @@ F: arch/s390/mm
S390 NETWORK DRIVERS S390 NETWORK DRIVERS
M: Alexandra Winter <wintera@linux.ibm.com> M: Alexandra Winter <wintera@linux.ibm.com>
M: Thorsten Winkler <twinkler@linux.ibm.com> R: Aswin Karuvally <aswin@linux.ibm.com>
L: linux-s390@vger.kernel.org L: linux-s390@vger.kernel.org
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Supported S: Supported

View File

@ -642,12 +642,7 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
* WMT command. * WMT command.
*/ */
err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT, err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT,
TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); TASK_UNINTERRUPTIBLE, HCI_INIT_TIMEOUT);
if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted");
clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags);
goto err_free_wc;
}
if (err) { if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out"); bt_dev_err(hdev, "Execution of wmt command timed out");

View File

@ -543,10 +543,10 @@ static int ps_setup(struct hci_dev *hdev)
} }
if (psdata->wakeup_source) { if (psdata->wakeup_source) {
ret = devm_request_irq(&serdev->dev, psdata->irq_handler, ret = devm_request_threaded_irq(&serdev->dev, psdata->irq_handler,
ps_host_wakeup_irq_handler, NULL, ps_host_wakeup_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_FALLING, IRQF_ONESHOT,
dev_name(&serdev->dev), nxpdev); dev_name(&serdev->dev), nxpdev);
if (ret) if (ret)
bt_dev_info(hdev, "error setting wakeup IRQ handler, ignoring\n"); bt_dev_info(hdev, "error setting wakeup IRQ handler, ignoring\n");
disable_irq(psdata->irq_handler); disable_irq(psdata->irq_handler);

View File

@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
static void ad_mux_machine(struct port *port, bool *update_slave_arr); static void ad_mux_machine(struct port *port, bool *update_slave_arr);
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port); static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
static void ad_tx_machine(struct port *port); static void ad_tx_machine(struct port *port);
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params); static void ad_periodic_machine(struct port *port);
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr); static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
static void ad_agg_selection_logic(struct aggregator *aggregator, static void ad_agg_selection_logic(struct aggregator *aggregator,
bool *update_slave_arr); bool *update_slave_arr);
static void ad_clear_agg(struct aggregator *aggregator); static void ad_clear_agg(struct aggregator *aggregator);
static void ad_initialize_agg(struct aggregator *aggregator); static void ad_initialize_agg(struct aggregator *aggregator);
static void ad_initialize_port(struct port *port, int lacp_fast); static void ad_initialize_port(struct port *port, const struct bond_params *bond_params);
static void ad_enable_collecting(struct port *port); static void ad_enable_collecting(struct port *port);
static void ad_disable_distributing(struct port *port, static void ad_disable_distributing(struct port *port,
bool *update_slave_arr); bool *update_slave_arr);
@ -1307,10 +1307,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
* case of EXPIRED even if LINK_DOWN didn't arrive for * case of EXPIRED even if LINK_DOWN didn't arrive for
* the port. * the port.
*/ */
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
port->sm_vars &= ~AD_PORT_MATCHED; port->sm_vars &= ~AD_PORT_MATCHED;
/* Based on IEEE 8021AX-2014, Figure 6-18 - Receive
* machine state diagram, the statue should be
* Partner_Oper_Port_State.Synchronization = FALSE;
* Partner_Oper_Port_State.LACP_Timeout = Short Timeout;
* start current_while_timer(Short Timeout);
* Actor_Oper_Port_State.Expired = TRUE;
*/
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT; port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT;
port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY;
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
port->actor_oper_port_state |= LACP_STATE_EXPIRED; port->actor_oper_port_state |= LACP_STATE_EXPIRED;
port->sm_vars |= AD_PORT_CHURNED; port->sm_vars |= AD_PORT_CHURNED;
@ -1417,11 +1423,10 @@ static void ad_tx_machine(struct port *port)
/** /**
* ad_periodic_machine - handle a port's periodic state machine * ad_periodic_machine - handle a port's periodic state machine
* @port: the port we're looking at * @port: the port we're looking at
* @bond_params: bond parameters we will use
* *
* Turn ntt flag on priodically to perform periodic transmission of lacpdu's. * Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
*/ */
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params) static void ad_periodic_machine(struct port *port)
{ {
periodic_states_t last_state; periodic_states_t last_state;
@ -1430,8 +1435,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params *bond_para
/* check if port was reinitialized */ /* check if port was reinitialized */
if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) || if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) || (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) {
!bond_params->lacp_active) {
port->sm_periodic_state = AD_NO_PERIODIC; port->sm_periodic_state = AD_NO_PERIODIC;
} }
/* check if state machine should change state */ /* check if state machine should change state */
@ -1955,16 +1959,16 @@ static void ad_initialize_agg(struct aggregator *aggregator)
/** /**
* ad_initialize_port - initialize a given port's parameters * ad_initialize_port - initialize a given port's parameters
* @port: the port we're looking at * @port: the port we're looking at
* @lacp_fast: boolean. whether fast periodic should be used * @bond_params: bond parameters we will use
*/ */
static void ad_initialize_port(struct port *port, int lacp_fast) static void ad_initialize_port(struct port *port, const struct bond_params *bond_params)
{ {
static const struct port_params tmpl = { static const struct port_params tmpl = {
.system_priority = 0xffff, .system_priority = 0xffff,
.key = 1, .key = 1,
.port_number = 1, .port_number = 1,
.port_priority = 0xff, .port_priority = 0xff,
.port_state = 1, .port_state = 0,
}; };
static const struct lacpdu lacpdu = { static const struct lacpdu lacpdu = {
.subtype = 0x01, .subtype = 0x01,
@ -1982,12 +1986,14 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
port->actor_port_priority = 0xff; port->actor_port_priority = 0xff;
port->actor_port_aggregator_identifier = 0; port->actor_port_aggregator_identifier = 0;
port->ntt = false; port->ntt = false;
port->actor_admin_port_state = LACP_STATE_AGGREGATION | port->actor_admin_port_state = LACP_STATE_AGGREGATION;
LACP_STATE_LACP_ACTIVITY; port->actor_oper_port_state = LACP_STATE_AGGREGATION;
port->actor_oper_port_state = LACP_STATE_AGGREGATION | if (bond_params->lacp_active) {
LACP_STATE_LACP_ACTIVITY; port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY;
port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
}
if (lacp_fast) if (bond_params->lacp_fast)
port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT; port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT;
memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
@ -2201,7 +2207,7 @@ void bond_3ad_bind_slave(struct slave *slave)
/* port initialization */ /* port initialization */
port = &(SLAVE_AD_INFO(slave)->port); port = &(SLAVE_AD_INFO(slave)->port);
ad_initialize_port(port, bond->params.lacp_fast); ad_initialize_port(port, &bond->params);
port->slave = slave; port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave)->id; port->actor_port_number = SLAVE_AD_INFO(slave)->id;
@ -2513,7 +2519,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
} }
ad_rx_machine(NULL, port); ad_rx_machine(NULL, port);
ad_periodic_machine(port, &bond->params); ad_periodic_machine(port);
ad_port_selection_logic(port, &update_slave_arr); ad_port_selection_logic(port, &update_slave_arr);
ad_mux_machine(port, &update_slave_arr); ad_mux_machine(port, &update_slave_arr);
ad_tx_machine(port); ad_tx_machine(port);
@ -2883,6 +2889,31 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
spin_unlock_bh(&bond->mode_lock); spin_unlock_bh(&bond->mode_lock);
} }
/**
* bond_3ad_update_lacp_active - change the lacp active
* @bond: bonding struct
*
* Update actor_oper_port_state when lacp_active is modified.
*/
void bond_3ad_update_lacp_active(struct bonding *bond)
{
struct port *port = NULL;
struct list_head *iter;
struct slave *slave;
int lacp_active;
lacp_active = bond->params.lacp_active;
spin_lock_bh(&bond->mode_lock);
bond_for_each_slave(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave)->port);
if (lacp_active)
port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
else
port->actor_oper_port_state &= ~LACP_STATE_LACP_ACTIVITY;
}
spin_unlock_bh(&bond->mode_lock);
}
size_t bond_3ad_stats_size(void) size_t bond_3ad_stats_size(void)
{ {
return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */ return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */

View File

@ -1660,6 +1660,7 @@ static int bond_option_lacp_active_set(struct bonding *bond,
netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n", netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n",
newval->string, newval->value); newval->string, newval->value);
bond->params.lacp_active = newval->value; bond->params.lacp_active = newval->value;
bond_3ad_update_lacp_active(bond);
return 0; return 0;
} }

View File

@ -2078,7 +2078,7 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
/* Start search operation */ /* Start search operation */
reg = ARL_SRCH_STDN; reg = ARL_SRCH_STDN;
b53_write8(priv, offset, B53_ARL_SRCH_CTL, reg); b53_write8(priv, B53_ARLIO_PAGE, offset, reg);
do { do {
ret = b53_arl_search_wait(priv); ret = b53_arl_search_wait(priv);

View File

@ -2457,6 +2457,12 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)
dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); dev->dev_ops->cfg_port_member(dev, i, val | cpu_port);
} }
/* HSR ports are setup once so need to use the assigned membership
* when the port is enabled.
*/
if (!port_member && p->stp_state == BR_STATE_FORWARDING &&
(dev->hsr_ports & BIT(port)))
port_member = dev->hsr_ports;
dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
} }

View File

@ -736,10 +736,8 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
continue; continue;
} }
if (commit_done || !airoha_ppe_foe_compare_entry(e, hwe)) { if (!airoha_ppe_foe_compare_entry(e, hwe))
e->hash = 0xffff;
continue; continue;
}
airoha_ppe_foe_commit_entry(ppe, &e->data, hash); airoha_ppe_foe_commit_entry(ppe, &e->data, hash);
commit_done = true; commit_done = true;

View File

@ -5332,7 +5332,7 @@ static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool all)
{ {
int i; int i;
netdev_assert_locked(bp->dev); netdev_assert_locked_or_invisible(bp->dev);
/* Under netdev instance lock and all our NAPIs have been disabled. /* Under netdev instance lock and all our NAPIs have been disabled.
* It's safe to delete the hash table. * It's safe to delete the hash table.

View File

@ -5113,7 +5113,8 @@ static const struct macb_config sama7g5_gem_config = {
static const struct macb_config sama7g5_emac_config = { static const struct macb_config sama7g5_emac_config = {
.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII |
MACB_CAPS_MIIONRGMII | MACB_CAPS_GEM_HAS_PTP, MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_MIIONRGMII |
MACB_CAPS_GEM_HAS_PTP,
.dma_burst_length = 16, .dma_burst_length = 16,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,

View File

@ -2870,6 +2870,8 @@ static void gve_shutdown(struct pci_dev *pdev)
struct gve_priv *priv = netdev_priv(netdev); struct gve_priv *priv = netdev_priv(netdev);
bool was_up = netif_running(priv->dev); bool was_up = netif_running(priv->dev);
netif_device_detach(netdev);
rtnl_lock(); rtnl_lock();
netdev_lock(netdev); netdev_lock(netdev);
if (was_up && gve_close(priv->dev)) { if (was_up && gve_close(priv->dev)) {

View File

@ -7149,6 +7149,13 @@ static int igc_probe(struct pci_dev *pdev,
adapter->port_num = hw->bus.func; adapter->port_num = hw->bus.func;
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
/* PCI config space info */
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
hw->revision_id = pdev->revision;
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_device_id = pdev->subsystem_device;
/* Disable ASPM L1.2 on I226 devices to avoid packet loss */ /* Disable ASPM L1.2 on I226 devices to avoid packet loss */
if (igc_is_device_id_i226(hw)) if (igc_is_device_id_i226(hw))
pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
@ -7175,13 +7182,6 @@ static int igc_probe(struct pci_dev *pdev,
netdev->mem_start = pci_resource_start(pdev, 0); netdev->mem_start = pci_resource_start(pdev, 0);
netdev->mem_end = pci_resource_end(pdev, 0); netdev->mem_end = pci_resource_end(pdev, 0);
/* PCI config space info */
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
hw->revision_id = pdev->revision;
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_device_id = pdev->subsystem_device;
/* Copy the default MAC and PHY function pointers */ /* Copy the default MAC and PHY function pointers */
memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops));
memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops));

View File

@ -968,10 +968,6 @@ static void ixgbe_update_xoff_rx_lfc(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
clear_bit(__IXGBE_HANG_CHECK_ARMED, clear_bit(__IXGBE_HANG_CHECK_ARMED,
&adapter->tx_ring[i]->state); &adapter->tx_ring[i]->state);
for (i = 0; i < adapter->num_xdp_queues; i++)
clear_bit(__IXGBE_HANG_CHECK_ARMED,
&adapter->xdp_ring[i]->state);
} }
static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter) static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
@ -1214,7 +1210,7 @@ static void ixgbe_pf_handle_tx_hang(struct ixgbe_ring *tx_ring,
struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev); struct ixgbe_adapter *adapter = netdev_priv(tx_ring->netdev);
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
e_err(drv, "Detected Tx Unit Hang%s\n" e_err(drv, "Detected Tx Unit Hang\n"
" Tx Queue <%d>\n" " Tx Queue <%d>\n"
" TDH, TDT <%x>, <%x>\n" " TDH, TDT <%x>, <%x>\n"
" next_to_use <%x>\n" " next_to_use <%x>\n"
@ -1222,16 +1218,14 @@ static void ixgbe_pf_handle_tx_hang(struct ixgbe_ring *tx_ring,
"tx_buffer_info[next_to_clean]\n" "tx_buffer_info[next_to_clean]\n"
" time_stamp <%lx>\n" " time_stamp <%lx>\n"
" jiffies <%lx>\n", " jiffies <%lx>\n",
ring_is_xdp(tx_ring) ? " (XDP)" : "",
tx_ring->queue_index, tx_ring->queue_index,
IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)), IXGBE_READ_REG(hw, IXGBE_TDH(tx_ring->reg_idx)),
IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)), IXGBE_READ_REG(hw, IXGBE_TDT(tx_ring->reg_idx)),
tx_ring->next_to_use, next, tx_ring->next_to_use, next,
tx_ring->tx_buffer_info[next].time_stamp, jiffies); tx_ring->tx_buffer_info[next].time_stamp, jiffies);
if (!ring_is_xdp(tx_ring)) netif_stop_subqueue(tx_ring->netdev,
netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
tx_ring->queue_index);
} }
/** /**
@ -1451,6 +1445,9 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
total_bytes); total_bytes);
adapter->tx_ipsec += total_ipsec; adapter->tx_ipsec += total_ipsec;
if (ring_is_xdp(tx_ring))
return !!budget;
if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) { if (check_for_tx_hang(tx_ring) && ixgbe_check_tx_hang(tx_ring)) {
if (adapter->hw.mac.type == ixgbe_mac_e610) if (adapter->hw.mac.type == ixgbe_mac_e610)
ixgbe_handle_mdd_event(adapter, tx_ring); ixgbe_handle_mdd_event(adapter, tx_ring);
@ -1468,9 +1465,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
return true; return true;
} }
if (ring_is_xdp(tx_ring))
return !!budget;
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index); txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
if (!__netif_txq_completed_wake(txq, total_packets, total_bytes, if (!__netif_txq_completed_wake(txq, total_packets, total_bytes,
@ -7974,12 +7968,9 @@ static void ixgbe_check_hang_subtask(struct ixgbe_adapter *adapter)
return; return;
/* Force detection of hung controller */ /* Force detection of hung controller */
if (netif_carrier_ok(adapter->netdev)) { if (netif_carrier_ok(adapter->netdev))
for (i = 0; i < adapter->num_tx_queues; i++) for (i = 0; i < adapter->num_tx_queues; i++)
set_check_for_tx_hang(adapter->tx_ring[i]); set_check_for_tx_hang(adapter->tx_ring[i]);
for (i = 0; i < adapter->num_xdp_queues; i++)
set_check_for_tx_hang(adapter->xdp_ring[i]);
}
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
/* /*
@ -8199,13 +8190,6 @@ static bool ixgbe_ring_tx_pending(struct ixgbe_adapter *adapter)
return true; return true;
} }
for (i = 0; i < adapter->num_xdp_queues; i++) {
struct ixgbe_ring *ring = adapter->xdp_ring[i];
if (ring->next_to_use != ring->next_to_clean)
return true;
}
return false; return false;
} }
@ -11005,6 +10989,10 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state))) if (unlikely(test_bit(__IXGBE_DOWN, &adapter->state)))
return -ENETDOWN; return -ENETDOWN;
if (!netif_carrier_ok(adapter->netdev) ||
!netif_running(adapter->netdev))
return -ENETDOWN;
if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
return -EINVAL; return -EINVAL;

View File

@ -398,7 +398,7 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
dma_addr_t dma; dma_addr_t dma;
u32 cmd_type; u32 cmd_type;
while (budget-- > 0) { while (likely(budget)) {
if (unlikely(!ixgbe_desc_unused(xdp_ring))) { if (unlikely(!ixgbe_desc_unused(xdp_ring))) {
work_done = false; work_done = false;
break; break;
@ -433,6 +433,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
xdp_ring->next_to_use++; xdp_ring->next_to_use++;
if (xdp_ring->next_to_use == xdp_ring->count) if (xdp_ring->next_to_use == xdp_ring->count)
xdp_ring->next_to_use = 0; xdp_ring->next_to_use = 0;
budget--;
} }
if (tx_desc) { if (tx_desc) {

View File

@ -606,8 +606,8 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
if (!npc_check_field(rvu, blkaddr, NPC_LB, intf)) if (!npc_check_field(rvu, blkaddr, NPC_LB, intf))
*features &= ~BIT_ULL(NPC_OUTER_VID); *features &= ~BIT_ULL(NPC_OUTER_VID);
/* Set SPI flag only if AH/ESP and IPSEC_SPI are in the key */ /* Allow extracting SPI field from AH and ESP headers at same offset */
if (npc_check_field(rvu, blkaddr, NPC_IPSEC_SPI, intf) && if (npc_is_field_present(rvu, NPC_IPSEC_SPI, intf) &&
(*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH)))) (*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH))))
*features |= BIT_ULL(NPC_IPSEC_SPI); *features |= BIT_ULL(NPC_IPSEC_SPI);

View File

@ -101,7 +101,9 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
return -1; return -1;
rcu_read_lock();
err = dev_fill_forward_path(dev, addr, &stack); err = dev_fill_forward_path(dev, addr, &stack);
rcu_read_unlock();
if (err) if (err)
return err; return err;

View File

@ -26,7 +26,6 @@ struct mlx5e_dcbx {
u8 cap; u8 cap;
/* Buffer configuration */ /* Buffer configuration */
bool manual_buffer;
u32 cable_len; u32 cable_len;
u32 xoff; u32 xoff;
u16 port_buff_cell_sz; u16 port_buff_cell_sz;

View File

@ -272,8 +272,8 @@ static int port_update_shared_buffer(struct mlx5_core_dev *mdev,
/* Total shared buffer size is split in a ratio of 3:1 between /* Total shared buffer size is split in a ratio of 3:1 between
* lossy and lossless pools respectively. * lossy and lossless pools respectively.
*/ */
lossy_epool_size = (shared_buffer_size / 4) * 3;
lossless_ipool_size = shared_buffer_size / 4; lossless_ipool_size = shared_buffer_size / 4;
lossy_epool_size = shared_buffer_size - lossless_ipool_size;
mlx5e_port_set_sbpr(mdev, 0, MLX5_EGRESS_DIR, MLX5_LOSSY_POOL, 0, mlx5e_port_set_sbpr(mdev, 0, MLX5_EGRESS_DIR, MLX5_LOSSY_POOL, 0,
lossy_epool_size); lossy_epool_size);
@ -288,14 +288,12 @@ static int port_set_buffer(struct mlx5e_priv *priv,
u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
int sz = MLX5_ST_SZ_BYTES(pbmc_reg); int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
u32 new_headroom_size = 0; u32 current_headroom_cells = 0;
u32 current_headroom_size; u32 new_headroom_cells = 0;
void *in; void *in;
int err; int err;
int i; int i;
current_headroom_size = port_buffer->headroom_size;
in = kzalloc(sz, GFP_KERNEL); in = kzalloc(sz, GFP_KERNEL);
if (!in) if (!in)
return -ENOMEM; return -ENOMEM;
@ -306,12 +304,14 @@ static int port_set_buffer(struct mlx5e_priv *priv,
for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
current_headroom_cells += MLX5_GET(bufferx_reg, buffer, size);
u64 size = port_buffer->buffer[i].size; u64 size = port_buffer->buffer[i].size;
u64 xoff = port_buffer->buffer[i].xoff; u64 xoff = port_buffer->buffer[i].xoff;
u64 xon = port_buffer->buffer[i].xon; u64 xon = port_buffer->buffer[i].xon;
new_headroom_size += size;
do_div(size, port_buff_cell_sz); do_div(size, port_buff_cell_sz);
new_headroom_cells += size;
do_div(xoff, port_buff_cell_sz); do_div(xoff, port_buff_cell_sz);
do_div(xon, port_buff_cell_sz); do_div(xon, port_buff_cell_sz);
MLX5_SET(bufferx_reg, buffer, size, size); MLX5_SET(bufferx_reg, buffer, size, size);
@ -320,10 +320,8 @@ static int port_set_buffer(struct mlx5e_priv *priv,
MLX5_SET(bufferx_reg, buffer, xon_threshold, xon); MLX5_SET(bufferx_reg, buffer, xon_threshold, xon);
} }
new_headroom_size /= port_buff_cell_sz; err = port_update_shared_buffer(priv->mdev, current_headroom_cells,
current_headroom_size /= port_buff_cell_sz; new_headroom_cells);
err = port_update_shared_buffer(priv->mdev, current_headroom_size,
new_headroom_size);
if (err) if (err)
goto out; goto out;

View File

@ -173,6 +173,8 @@ static void mlx5_ct_fs_hmfs_fill_rule_actions(struct mlx5_ct_fs_hmfs *fs_hmfs,
memset(rule_actions, 0, NUM_CT_HMFS_RULES * sizeof(*rule_actions)); memset(rule_actions, 0, NUM_CT_HMFS_RULES * sizeof(*rule_actions));
rule_actions[0].action = mlx5_fc_get_hws_action(fs_hmfs->ctx, attr->counter); rule_actions[0].action = mlx5_fc_get_hws_action(fs_hmfs->ctx, attr->counter);
rule_actions[0].counter.offset =
attr->counter->id - attr->counter->bulk->base_id;
/* Modify header is special, it may require extra arguments outside the action itself. */ /* Modify header is special, it may require extra arguments outside the action itself. */
if (mh_action->mh_data) { if (mh_action->mh_data) {
rule_actions[1].modify_header.offset = mh_action->mh_data->offset; rule_actions[1].modify_header.offset = mh_action->mh_data->offset;

View File

@ -362,6 +362,7 @@ static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev, static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
struct ieee_pfc *pfc) struct ieee_pfc *pfc)
{ {
u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
u32 old_cable_len = priv->dcbx.cable_len; u32 old_cable_len = priv->dcbx.cable_len;
@ -389,7 +390,14 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
if (MLX5_BUFFER_SUPPORTED(mdev)) { if (MLX5_BUFFER_SUPPORTED(mdev)) {
pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en; pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
if (priv->dcbx.manual_buffer) ret = mlx5_query_port_buffer_ownership(mdev,
&buffer_ownership);
if (ret)
netdev_err(dev,
"%s, Failed to get buffer ownership: %d\n",
__func__, ret);
if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED)
ret = mlx5e_port_manual_buffer_config(priv, changed, ret = mlx5e_port_manual_buffer_config(priv, changed,
dev->mtu, &pfc_new, dev->mtu, &pfc_new,
NULL, NULL); NULL, NULL);
@ -982,7 +990,6 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
if (!changed) if (!changed)
return 0; return 0;
priv->dcbx.manual_buffer = true;
err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL, err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
buffer_size, prio2buffer); buffer_size, prio2buffer);
return err; return err;
@ -1252,7 +1259,6 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
priv->dcbx.cap |= DCB_CAP_DCBX_HOST; priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv); priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
priv->dcbx.manual_buffer = false;
priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN; priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
mlx5e_ets_init(priv); mlx5e_ets_init(priv);

View File

@ -47,10 +47,12 @@ static void mlx5_esw_offloads_pf_vf_devlink_port_attrs_set(struct mlx5_eswitch *
devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum,
vport_num - 1, external); vport_num - 1, external);
} else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) {
u16 base_vport = mlx5_core_ec_vf_vport_base(dev);
memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len);
dl_port->attrs.switch_id.id_len = ppid.id_len; dl_port->attrs.switch_id.id_len = ppid.id_len;
devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum, devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum,
vport_num - 1, false); vport_num - base_vport, false);
} }
} }

View File

@ -102,6 +102,8 @@ struct mlx5_esw_sched_node {
u8 level; u8 level;
/* Valid only when this node represents a traffic class. */ /* Valid only when this node represents a traffic class. */
u8 tc; u8 tc;
/* Valid only for a TC arbiter node or vport TC arbiter. */
u32 tc_bw[DEVLINK_RATE_TCS_MAX];
}; };
static void esw_qos_node_attach_to_parent(struct mlx5_esw_sched_node *node) static void esw_qos_node_attach_to_parent(struct mlx5_esw_sched_node *node)
@ -462,6 +464,7 @@ static int
esw_qos_vport_create_sched_element(struct mlx5_esw_sched_node *vport_node, esw_qos_vport_create_sched_element(struct mlx5_esw_sched_node *vport_node,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *parent = vport_node->parent;
u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
struct mlx5_core_dev *dev = vport_node->esw->dev; struct mlx5_core_dev *dev = vport_node->esw->dev;
void *attr; void *attr;
@ -477,7 +480,7 @@ esw_qos_vport_create_sched_element(struct mlx5_esw_sched_node *vport_node,
attr = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes); attr = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes);
MLX5_SET(vport_element, attr, vport_number, vport_node->vport->vport); MLX5_SET(vport_element, attr, vport_number, vport_node->vport->vport);
MLX5_SET(scheduling_context, sched_ctx, parent_element_id, MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
vport_node->parent->ix); parent ? parent->ix : vport_node->esw->qos.root_tsar_ix);
MLX5_SET(scheduling_context, sched_ctx, max_average_bw, MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
vport_node->max_rate); vport_node->max_rate);
@ -608,10 +611,7 @@ static void
esw_qos_tc_arbiter_get_bw_shares(struct mlx5_esw_sched_node *tc_arbiter_node, esw_qos_tc_arbiter_get_bw_shares(struct mlx5_esw_sched_node *tc_arbiter_node,
u32 *tc_bw) u32 *tc_bw)
{ {
struct mlx5_esw_sched_node *vports_tc_node; memcpy(tc_bw, tc_arbiter_node->tc_bw, sizeof(tc_arbiter_node->tc_bw));
list_for_each_entry(vports_tc_node, &tc_arbiter_node->children, entry)
tc_bw[vports_tc_node->tc] = vports_tc_node->bw_share;
} }
static void static void
@ -628,6 +628,7 @@ esw_qos_set_tc_arbiter_bw_shares(struct mlx5_esw_sched_node *tc_arbiter_node,
u8 tc = vports_tc_node->tc; u8 tc = vports_tc_node->tc;
u32 bw_share; u32 bw_share;
tc_arbiter_node->tc_bw[tc] = tc_bw[tc];
bw_share = tc_bw[tc] * fw_max_bw_share; bw_share = tc_bw[tc] * fw_max_bw_share;
bw_share = esw_qos_calc_bw_share(bw_share, divider, bw_share = esw_qos_calc_bw_share(bw_share, divider,
fw_max_bw_share); fw_max_bw_share);
@ -786,48 +787,15 @@ static int esw_qos_create(struct mlx5_eswitch *esw, struct netlink_ext_ack *exta
return err; return err;
} }
if (MLX5_CAP_QOS(dev, log_esw_max_sched_depth)) {
esw->qos.node0 = __esw_qos_create_vports_sched_node(esw, NULL, extack);
} else {
/* The eswitch doesn't support scheduling nodes.
* Create a software-only node0 using the root TSAR to attach vport QoS to.
*/
if (!__esw_qos_alloc_node(esw,
esw->qos.root_tsar_ix,
SCHED_NODE_TYPE_VPORTS_TSAR,
NULL))
esw->qos.node0 = ERR_PTR(-ENOMEM);
else
list_add_tail(&esw->qos.node0->entry,
&esw->qos.domain->nodes);
}
if (IS_ERR(esw->qos.node0)) {
err = PTR_ERR(esw->qos.node0);
esw_warn(dev, "E-Switch create rate node 0 failed (%d)\n", err);
goto err_node0;
}
refcount_set(&esw->qos.refcnt, 1); refcount_set(&esw->qos.refcnt, 1);
return 0; return 0;
err_node0:
if (mlx5_destroy_scheduling_element_cmd(esw->dev, SCHEDULING_HIERARCHY_E_SWITCH,
esw->qos.root_tsar_ix))
esw_warn(esw->dev, "E-Switch destroy root TSAR failed.\n");
return err;
} }
static void esw_qos_destroy(struct mlx5_eswitch *esw) static void esw_qos_destroy(struct mlx5_eswitch *esw)
{ {
int err; int err;
if (esw->qos.node0->ix != esw->qos.root_tsar_ix)
__esw_qos_destroy_node(esw->qos.node0, NULL);
else
__esw_qos_free_node(esw->qos.node0);
esw->qos.node0 = NULL;
err = mlx5_destroy_scheduling_element_cmd(esw->dev, err = mlx5_destroy_scheduling_element_cmd(esw->dev,
SCHEDULING_HIERARCHY_E_SWITCH, SCHEDULING_HIERARCHY_E_SWITCH,
esw->qos.root_tsar_ix); esw->qos.root_tsar_ix);
@ -990,13 +958,16 @@ esw_qos_vport_tc_enable(struct mlx5_vport *vport, enum sched_node_type type,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
int err, new_level, max_level; struct mlx5_esw_sched_node *parent = vport_node->parent;
int err;
if (type == SCHED_NODE_TYPE_TC_ARBITER_TSAR) { if (type == SCHED_NODE_TYPE_TC_ARBITER_TSAR) {
int new_level, max_level;
/* Increase the parent's level by 2 to account for both the /* Increase the parent's level by 2 to account for both the
* TC arbiter and the vports TC scheduling element. * TC arbiter and the vports TC scheduling element.
*/ */
new_level = vport_node->parent->level + 2; new_level = (parent ? parent->level : 2) + 2;
max_level = 1 << MLX5_CAP_QOS(vport_node->esw->dev, max_level = 1 << MLX5_CAP_QOS(vport_node->esw->dev,
log_esw_max_sched_depth); log_esw_max_sched_depth);
if (new_level > max_level) { if (new_level > max_level) {
@ -1033,9 +1004,7 @@ esw_qos_vport_tc_enable(struct mlx5_vport *vport, enum sched_node_type type,
err_sched_nodes: err_sched_nodes:
if (type == SCHED_NODE_TYPE_RATE_LIMITER) { if (type == SCHED_NODE_TYPE_RATE_LIMITER) {
esw_qos_node_destroy_sched_element(vport_node, NULL); esw_qos_node_destroy_sched_element(vport_node, NULL);
list_add_tail(&vport_node->entry, esw_qos_node_attach_to_parent(vport_node);
&vport_node->parent->children);
vport_node->level = vport_node->parent->level + 1;
} else { } else {
esw_qos_tc_arbiter_scheduling_teardown(vport_node, NULL); esw_qos_tc_arbiter_scheduling_teardown(vport_node, NULL);
} }
@ -1083,7 +1052,6 @@ err_out:
static void esw_qos_vport_disable(struct mlx5_vport *vport, struct netlink_ext_ack *extack) static void esw_qos_vport_disable(struct mlx5_vport *vport, struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node; struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
struct mlx5_esw_sched_node *parent = vport_node->parent;
enum sched_node_type curr_type = vport_node->type; enum sched_node_type curr_type = vport_node->type;
if (curr_type == SCHED_NODE_TYPE_VPORT) if (curr_type == SCHED_NODE_TYPE_VPORT)
@ -1092,8 +1060,9 @@ static void esw_qos_vport_disable(struct mlx5_vport *vport, struct netlink_ext_a
esw_qos_vport_tc_disable(vport, extack); esw_qos_vport_tc_disable(vport, extack);
vport_node->bw_share = 0; vport_node->bw_share = 0;
memset(vport_node->tc_bw, 0, sizeof(vport_node->tc_bw));
list_del_init(&vport_node->entry); list_del_init(&vport_node->entry);
esw_qos_normalize_min_rate(parent->esw, parent, extack); esw_qos_normalize_min_rate(vport_node->esw, vport_node->parent, extack);
trace_mlx5_esw_vport_qos_destroy(vport_node->esw->dev, vport); trace_mlx5_esw_vport_qos_destroy(vport_node->esw->dev, vport);
} }
@ -1103,25 +1072,23 @@ static int esw_qos_vport_enable(struct mlx5_vport *vport,
struct mlx5_esw_sched_node *parent, struct mlx5_esw_sched_node *parent,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
int err; int err;
esw_assert_qos_lock_held(vport->dev->priv.eswitch); esw_assert_qos_lock_held(vport->dev->priv.eswitch);
esw_qos_node_set_parent(vport->qos.sched_node, parent); esw_qos_node_set_parent(vport_node, parent);
if (type == SCHED_NODE_TYPE_VPORT) { if (type == SCHED_NODE_TYPE_VPORT)
err = esw_qos_vport_create_sched_element(vport->qos.sched_node, err = esw_qos_vport_create_sched_element(vport_node, extack);
extack); else
} else {
err = esw_qos_vport_tc_enable(vport, type, extack); err = esw_qos_vport_tc_enable(vport, type, extack);
}
if (err) if (err)
return err; return err;
vport->qos.sched_node->type = type; vport_node->type = type;
esw_qos_normalize_min_rate(parent->esw, parent, extack); esw_qos_normalize_min_rate(vport_node->esw, parent, extack);
trace_mlx5_esw_vport_qos_create(vport->dev, vport, trace_mlx5_esw_vport_qos_create(vport->dev, vport, vport_node->max_rate,
vport->qos.sched_node->max_rate, vport_node->bw_share);
vport->qos.sched_node->bw_share);
return 0; return 0;
} }
@ -1132,6 +1099,7 @@ static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_t
{ {
struct mlx5_eswitch *esw = vport->dev->priv.eswitch; struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
struct mlx5_esw_sched_node *sched_node; struct mlx5_esw_sched_node *sched_node;
struct mlx5_eswitch *parent_esw;
int err; int err;
esw_assert_qos_lock_held(esw); esw_assert_qos_lock_held(esw);
@ -1139,10 +1107,14 @@ static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_t
if (err) if (err)
return err; return err;
parent = parent ?: esw->qos.node0; parent_esw = parent ? parent->esw : esw;
sched_node = __esw_qos_alloc_node(parent->esw, 0, type, parent); sched_node = __esw_qos_alloc_node(parent_esw, 0, type, parent);
if (!sched_node) if (!sched_node) {
esw_qos_put(esw);
return -ENOMEM; return -ENOMEM;
}
if (!parent)
list_add_tail(&sched_node->entry, &esw->qos.domain->nodes);
sched_node->max_rate = max_rate; sched_node->max_rate = max_rate;
sched_node->min_rate = min_rate; sched_node->min_rate = min_rate;
@ -1150,6 +1122,7 @@ static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_t
vport->qos.sched_node = sched_node; vport->qos.sched_node = sched_node;
err = esw_qos_vport_enable(vport, type, parent, extack); err = esw_qos_vport_enable(vport, type, parent, extack);
if (err) { if (err) {
__esw_qos_free_node(sched_node);
esw_qos_put(esw); esw_qos_put(esw);
vport->qos.sched_node = NULL; vport->qos.sched_node = NULL;
} }
@ -1157,6 +1130,19 @@ static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_t
return err; return err;
} }
static void mlx5_esw_qos_vport_disable_locked(struct mlx5_vport *vport)
{
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
esw_assert_qos_lock_held(esw);
if (!vport->qos.sched_node)
return;
esw_qos_vport_disable(vport, NULL);
mlx5_esw_qos_vport_qos_free(vport);
esw_qos_put(esw);
}
void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport) void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
{ {
struct mlx5_eswitch *esw = vport->dev->priv.eswitch; struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
@ -1168,11 +1154,9 @@ void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
goto unlock; goto unlock;
parent = vport->qos.sched_node->parent; parent = vport->qos.sched_node->parent;
WARN(parent != esw->qos.node0, "Disabling QoS on port before detaching it from node"); WARN(parent, "Disabling QoS on port before detaching it from node");
esw_qos_vport_disable(vport, NULL); mlx5_esw_qos_vport_disable_locked(vport);
mlx5_esw_qos_vport_qos_free(vport);
esw_qos_put(esw);
unlock: unlock:
esw_qos_unlock(esw); esw_qos_unlock(esw);
} }
@ -1262,13 +1246,13 @@ static int esw_qos_vport_update(struct mlx5_vport *vport,
struct mlx5_esw_sched_node *parent, struct mlx5_esw_sched_node *parent,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *curr_parent = vport->qos.sched_node->parent; struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
enum sched_node_type curr_type = vport->qos.sched_node->type; struct mlx5_esw_sched_node *curr_parent = vport_node->parent;
enum sched_node_type curr_type = vport_node->type;
u32 curr_tc_bw[DEVLINK_RATE_TCS_MAX] = {0}; u32 curr_tc_bw[DEVLINK_RATE_TCS_MAX] = {0};
int err; int err;
esw_assert_qos_lock_held(vport->dev->priv.eswitch); esw_assert_qos_lock_held(vport->dev->priv.eswitch);
parent = parent ?: curr_parent;
if (curr_type == type && curr_parent == parent) if (curr_type == type && curr_parent == parent)
return 0; return 0;
@ -1276,10 +1260,8 @@ static int esw_qos_vport_update(struct mlx5_vport *vport,
if (err) if (err)
return err; return err;
if (curr_type == SCHED_NODE_TYPE_TC_ARBITER_TSAR && curr_type == type) { if (curr_type == SCHED_NODE_TYPE_TC_ARBITER_TSAR && curr_type == type)
esw_qos_tc_arbiter_get_bw_shares(vport->qos.sched_node, esw_qos_tc_arbiter_get_bw_shares(vport_node, curr_tc_bw);
curr_tc_bw);
}
esw_qos_vport_disable(vport, extack); esw_qos_vport_disable(vport, extack);
@ -1290,8 +1272,8 @@ static int esw_qos_vport_update(struct mlx5_vport *vport,
} }
if (curr_type == SCHED_NODE_TYPE_TC_ARBITER_TSAR && curr_type == type) { if (curr_type == SCHED_NODE_TYPE_TC_ARBITER_TSAR && curr_type == type) {
esw_qos_set_tc_arbiter_bw_shares(vport->qos.sched_node, esw_qos_set_tc_arbiter_bw_shares(vport_node, curr_tc_bw,
curr_tc_bw, extack); extack);
} }
return err; return err;
@ -1306,16 +1288,16 @@ static int esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw
esw_assert_qos_lock_held(esw); esw_assert_qos_lock_held(esw);
curr_parent = vport->qos.sched_node->parent; curr_parent = vport->qos.sched_node->parent;
parent = parent ?: esw->qos.node0;
if (curr_parent == parent) if (curr_parent == parent)
return 0; return 0;
/* Set vport QoS type based on parent node type if different from /* Set vport QoS type based on parent node type if different from
* default QoS; otherwise, use the vport's current QoS type. * default QoS; otherwise, use the vport's current QoS type.
*/ */
if (parent->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR) if (parent && parent->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR)
type = SCHED_NODE_TYPE_RATE_LIMITER; type = SCHED_NODE_TYPE_RATE_LIMITER;
else if (curr_parent->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR) else if (curr_parent &&
curr_parent->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR)
type = SCHED_NODE_TYPE_VPORT; type = SCHED_NODE_TYPE_VPORT;
else else
type = vport->qos.sched_node->type; type = vport->qos.sched_node->type;
@ -1654,9 +1636,10 @@ static bool esw_qos_validate_unsupported_tc_bw(struct mlx5_eswitch *esw,
static bool esw_qos_vport_validate_unsupported_tc_bw(struct mlx5_vport *vport, static bool esw_qos_vport_validate_unsupported_tc_bw(struct mlx5_vport *vport,
u32 *tc_bw) u32 *tc_bw)
{ {
struct mlx5_eswitch *esw = vport->qos.sched_node ? struct mlx5_esw_sched_node *node = vport->qos.sched_node;
vport->qos.sched_node->parent->esw : struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
vport->dev->priv.eswitch;
esw = (node && node->parent) ? node->parent->esw : esw;
return esw_qos_validate_unsupported_tc_bw(esw, tc_bw); return esw_qos_validate_unsupported_tc_bw(esw, tc_bw);
} }
@ -1673,6 +1656,21 @@ static bool esw_qos_tc_bw_disabled(u32 *tc_bw)
return true; return true;
} }
static void esw_vport_qos_prune_empty(struct mlx5_vport *vport)
{
struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
esw_assert_qos_lock_held(vport->dev->priv.eswitch);
if (!vport_node)
return;
if (vport_node->parent || vport_node->max_rate ||
vport_node->min_rate || !esw_qos_tc_bw_disabled(vport_node->tc_bw))
return;
mlx5_esw_qos_vport_disable_locked(vport);
}
int mlx5_esw_qos_init(struct mlx5_eswitch *esw) int mlx5_esw_qos_init(struct mlx5_eswitch *esw)
{ {
if (esw->qos.domain) if (esw->qos.domain)
@ -1706,6 +1704,10 @@ int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void
esw_qos_lock(esw); esw_qos_lock(esw);
err = mlx5_esw_qos_set_vport_min_rate(vport, tx_share, extack); err = mlx5_esw_qos_set_vport_min_rate(vport, tx_share, extack);
if (err)
goto out;
esw_vport_qos_prune_empty(vport);
out:
esw_qos_unlock(esw); esw_qos_unlock(esw);
return err; return err;
} }
@ -1727,6 +1729,10 @@ int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *
esw_qos_lock(esw); esw_qos_lock(esw);
err = mlx5_esw_qos_set_vport_max_rate(vport, tx_max, extack); err = mlx5_esw_qos_set_vport_max_rate(vport, tx_max, extack);
if (err)
goto out;
esw_vport_qos_prune_empty(vport);
out:
esw_qos_unlock(esw); esw_qos_unlock(esw);
return err; return err;
} }
@ -1763,7 +1769,8 @@ int mlx5_esw_devlink_rate_leaf_tc_bw_set(struct devlink_rate *rate_leaf,
if (disable) { if (disable) {
if (vport_node->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR) if (vport_node->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR)
err = esw_qos_vport_update(vport, SCHED_NODE_TYPE_VPORT, err = esw_qos_vport_update(vport, SCHED_NODE_TYPE_VPORT,
NULL, extack); vport_node->parent, extack);
esw_vport_qos_prune_empty(vport);
goto unlock; goto unlock;
} }
@ -1775,7 +1782,7 @@ int mlx5_esw_devlink_rate_leaf_tc_bw_set(struct devlink_rate *rate_leaf,
} else { } else {
err = esw_qos_vport_update(vport, err = esw_qos_vport_update(vport,
SCHED_NODE_TYPE_TC_ARBITER_TSAR, SCHED_NODE_TYPE_TC_ARBITER_TSAR,
NULL, extack); vport_node->parent, extack);
} }
if (!err) if (!err)
esw_qos_set_tc_arbiter_bw_shares(vport_node, tc_bw, extack); esw_qos_set_tc_arbiter_bw_shares(vport_node, tc_bw, extack);
@ -1924,14 +1931,20 @@ int mlx5_esw_devlink_rate_leaf_parent_set(struct devlink_rate *devlink_rate,
void *priv, void *parent_priv, void *priv, void *parent_priv,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_sched_node *node; struct mlx5_esw_sched_node *node = parent ? parent_priv : NULL;
struct mlx5_vport *vport = priv; struct mlx5_vport *vport = priv;
int err;
if (!parent) err = mlx5_esw_qos_vport_update_parent(vport, node, extack);
return mlx5_esw_qos_vport_update_parent(vport, NULL, extack); if (!err) {
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
node = parent_priv; esw_qos_lock(esw);
return mlx5_esw_qos_vport_update_parent(vport, node, extack); esw_vport_qos_prune_empty(vport);
esw_qos_unlock(esw);
}
return err;
} }
static bool esw_qos_is_node_empty(struct mlx5_esw_sched_node *node) static bool esw_qos_is_node_empty(struct mlx5_esw_sched_node *node)

View File

@ -373,11 +373,6 @@ struct mlx5_eswitch {
refcount_t refcnt; refcount_t refcnt;
u32 root_tsar_ix; u32 root_tsar_ix;
struct mlx5_qos_domain *domain; struct mlx5_qos_domain *domain;
/* Contains all vports with QoS enabled but no explicit node.
* Cannot be NULL if QoS is enabled, but may be a fake node
* referencing the root TSAR if the esw doesn't support nodes.
*/
struct mlx5_esw_sched_node *node0;
} qos; } qos;
struct mlx5_esw_bridge_offloads *br_offloads; struct mlx5_esw_bridge_offloads *br_offloads;

View File

@ -367,6 +367,8 @@ int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state); int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state);
int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state); int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state);
int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev,
u8 *buffer_ownership);
int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio); int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio);
int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio); int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio);

View File

@ -968,6 +968,26 @@ int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
return err; return err;
} }
int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev,
u8 *buffer_ownership)
{
u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {};
int err;
if (!MLX5_CAP_PCAM_FEATURE(mdev, buffer_ownership)) {
*buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
return 0;
}
err = mlx5_query_pfcc_reg(mdev, out, sizeof(out));
if (err)
return err;
*buffer_ownership = MLX5_GET(pfcc_reg, out, buf_ownership);
return 0;
}
int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio) int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio)
{ {
int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);

View File

@ -74,9 +74,9 @@ static void hws_bwc_matcher_init_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
static int static int
hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher) hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
{ {
bool move_error = false, poll_error = false, drain_error = false;
struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx; struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
struct mlx5hws_matcher *matcher = bwc_matcher->matcher; struct mlx5hws_matcher *matcher = bwc_matcher->matcher;
int drain_error = 0, move_error = 0, poll_error = 0;
u16 bwc_queues = mlx5hws_bwc_queues(ctx); u16 bwc_queues = mlx5hws_bwc_queues(ctx);
struct mlx5hws_rule_attr rule_attr; struct mlx5hws_rule_attr rule_attr;
struct mlx5hws_bwc_rule *bwc_rule; struct mlx5hws_bwc_rule *bwc_rule;
@ -84,6 +84,7 @@ hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
struct list_head *rules_list; struct list_head *rules_list;
u32 pending_rules; u32 pending_rules;
int i, ret = 0; int i, ret = 0;
bool drain;
mlx5hws_bwc_rule_fill_attr(bwc_matcher, 0, 0, &rule_attr); mlx5hws_bwc_rule_fill_attr(bwc_matcher, 0, 0, &rule_attr);
@ -99,23 +100,37 @@ hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
ret = mlx5hws_matcher_resize_rule_move(matcher, ret = mlx5hws_matcher_resize_rule_move(matcher,
bwc_rule->rule, bwc_rule->rule,
&rule_attr); &rule_attr);
if (unlikely(ret && !move_error)) { if (unlikely(ret)) {
mlx5hws_err(ctx, if (!move_error) {
"Moving BWC rule: move failed (%d), attempting to move rest of the rules\n", mlx5hws_err(ctx,
ret); "Moving BWC rule: move failed (%d), attempting to move rest of the rules\n",
move_error = true; ret);
move_error = ret;
}
/* Rule wasn't queued, no need to poll */
continue;
} }
pending_rules++; pending_rules++;
drain = pending_rules >=
hws_bwc_get_burst_th(ctx, rule_attr.queue_id);
ret = mlx5hws_bwc_queue_poll(ctx, ret = mlx5hws_bwc_queue_poll(ctx,
rule_attr.queue_id, rule_attr.queue_id,
&pending_rules, &pending_rules,
false); drain);
if (unlikely(ret && !poll_error)) { if (unlikely(ret)) {
mlx5hws_err(ctx, if (ret == -ETIMEDOUT) {
"Moving BWC rule: poll failed (%d), attempting to move rest of the rules\n", mlx5hws_err(ctx,
ret); "Moving BWC rule: timeout polling for completions (%d), aborting rehash\n",
poll_error = true; ret);
return ret;
}
if (!poll_error) {
mlx5hws_err(ctx,
"Moving BWC rule: polling for completions failed (%d), attempting to move rest of the rules\n",
ret);
poll_error = ret;
}
} }
} }
@ -126,17 +141,30 @@ hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
rule_attr.queue_id, rule_attr.queue_id,
&pending_rules, &pending_rules,
true); true);
if (unlikely(ret && !drain_error)) { if (unlikely(ret)) {
mlx5hws_err(ctx, if (ret == -ETIMEDOUT) {
"Moving BWC rule: drain failed (%d), attempting to move rest of the rules\n", mlx5hws_err(ctx,
ret); "Moving bwc rule: timeout draining completions (%d), aborting rehash\n",
drain_error = true; ret);
return ret;
}
if (!drain_error) {
mlx5hws_err(ctx,
"Moving bwc rule: drain failed (%d), attempting to move rest of the rules\n",
ret);
drain_error = ret;
}
} }
} }
} }
if (move_error || poll_error || drain_error) /* Return the first error that happened */
ret = -EINVAL; if (unlikely(move_error))
return move_error;
if (unlikely(poll_error))
return poll_error;
if (unlikely(drain_error))
return drain_error;
return ret; return ret;
} }
@ -1035,6 +1063,21 @@ int mlx5hws_bwc_rule_create_simple(struct mlx5hws_bwc_rule *bwc_rule,
return 0; /* rule inserted successfully */ return 0; /* rule inserted successfully */
} }
/* Rule insertion could fail due to queue being full, timeout, or
* matcher in resize. In such cases, no point in trying to rehash.
*/
if (ret == -EBUSY || ret == -ETIMEDOUT || ret == -EAGAIN) {
mutex_unlock(queue_lock);
mlx5hws_err(ctx,
"BWC rule insertion failed - %s (%d)\n",
ret == -EBUSY ? "queue is full" :
ret == -ETIMEDOUT ? "timeout" :
ret == -EAGAIN ? "matcher in resize" : "N/A",
ret);
hws_bwc_rule_cnt_dec(bwc_rule);
return ret;
}
/* At this point the rule wasn't added. /* At this point the rule wasn't added.
* It could be because there was collision, or some other problem. * It could be because there was collision, or some other problem.
* Try rehash by size and insert rule again - last chance. * Try rehash by size and insert rule again - last chance.

View File

@ -1328,11 +1328,11 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher)
{ {
struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx; struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
struct mlx5hws_matcher *matcher = bwc_matcher->matcher; struct mlx5hws_matcher *matcher = bwc_matcher->matcher;
bool move_error = false, poll_error = false;
u16 bwc_queues = mlx5hws_bwc_queues(ctx); u16 bwc_queues = mlx5hws_bwc_queues(ctx);
struct mlx5hws_bwc_rule *tmp_bwc_rule; struct mlx5hws_bwc_rule *tmp_bwc_rule;
struct mlx5hws_rule_attr rule_attr; struct mlx5hws_rule_attr rule_attr;
struct mlx5hws_table *isolated_tbl; struct mlx5hws_table *isolated_tbl;
int move_error = 0, poll_error = 0;
struct mlx5hws_rule *tmp_rule; struct mlx5hws_rule *tmp_rule;
struct list_head *rules_list; struct list_head *rules_list;
u32 expected_completions = 1; u32 expected_completions = 1;
@ -1391,11 +1391,15 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher)
ret = mlx5hws_matcher_resize_rule_move(matcher, ret = mlx5hws_matcher_resize_rule_move(matcher,
tmp_rule, tmp_rule,
&rule_attr); &rule_attr);
if (unlikely(ret && !move_error)) { if (unlikely(ret)) {
mlx5hws_err(ctx, if (!move_error) {
"Moving complex BWC rule failed (%d), attempting to move rest of the rules\n", mlx5hws_err(ctx,
ret); "Moving complex BWC rule: move failed (%d), attempting to move rest of the rules\n",
move_error = true; ret);
move_error = ret;
}
/* Rule wasn't queued, no need to poll */
continue;
} }
expected_completions = 1; expected_completions = 1;
@ -1403,11 +1407,19 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher)
rule_attr.queue_id, rule_attr.queue_id,
&expected_completions, &expected_completions,
true); true);
if (unlikely(ret && !poll_error)) { if (unlikely(ret)) {
mlx5hws_err(ctx, if (ret == -ETIMEDOUT) {
"Moving complex BWC rule: poll failed (%d), attempting to move rest of the rules\n", mlx5hws_err(ctx,
ret); "Moving complex BWC rule: timeout polling for completions (%d), aborting rehash\n",
poll_error = true; ret);
return ret;
}
if (!poll_error) {
mlx5hws_err(ctx,
"Moving complex BWC rule: polling for completions failed (%d), attempting to move rest of the rules\n",
ret);
poll_error = ret;
}
} }
/* Done moving the rule to the new matcher, /* Done moving the rule to the new matcher,
@ -1422,8 +1434,11 @@ mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher)
} }
} }
if (move_error || poll_error) /* Return the first error that happened */
ret = -EINVAL; if (unlikely(move_error))
return move_error;
if (unlikely(poll_error))
return poll_error;
return ret; return ret;
} }

View File

@ -55,6 +55,7 @@ int mlx5hws_cmd_flow_table_create(struct mlx5_core_dev *mdev,
MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE); MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type); MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type);
MLX5_SET(create_flow_table_in, in, uid, ft_attr->uid);
ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context); ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level); MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level);

View File

@ -36,6 +36,7 @@ struct mlx5hws_cmd_set_fte_attr {
struct mlx5hws_cmd_ft_create_attr { struct mlx5hws_cmd_ft_create_attr {
u8 type; u8 type;
u8 level; u8 level;
u16 uid;
bool rtc_valid; bool rtc_valid;
bool decap_en; bool decap_en;
bool reformat_en; bool reformat_en;

View File

@ -267,6 +267,7 @@ static int mlx5_cmd_hws_create_flow_table(struct mlx5_flow_root_namespace *ns,
tbl_attr.type = MLX5HWS_TABLE_TYPE_FDB; tbl_attr.type = MLX5HWS_TABLE_TYPE_FDB;
tbl_attr.level = ft_attr->level; tbl_attr.level = ft_attr->level;
tbl_attr.uid = ft_attr->uid;
tbl = mlx5hws_table_create(ctx, &tbl_attr); tbl = mlx5hws_table_create(ctx, &tbl_attr);
if (!tbl) { if (!tbl) {
mlx5_core_err(ns->dev, "Failed creating hws flow_table\n"); mlx5_core_err(ns->dev, "Failed creating hws flow_table\n");

View File

@ -85,6 +85,7 @@ static int hws_matcher_create_end_ft_isolated(struct mlx5hws_matcher *matcher)
ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev,
tbl, tbl,
0,
&matcher->end_ft_id); &matcher->end_ft_id);
if (ret) { if (ret) {
mlx5hws_err(tbl->ctx, "Isolated matcher: failed to create end flow table\n"); mlx5hws_err(tbl->ctx, "Isolated matcher: failed to create end flow table\n");
@ -112,7 +113,9 @@ static int hws_matcher_create_end_ft(struct mlx5hws_matcher *matcher)
if (mlx5hws_matcher_is_isolated(matcher)) if (mlx5hws_matcher_is_isolated(matcher))
ret = hws_matcher_create_end_ft_isolated(matcher); ret = hws_matcher_create_end_ft_isolated(matcher);
else else
ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev,
tbl,
0,
&matcher->end_ft_id); &matcher->end_ft_id);
if (ret) { if (ret) {

View File

@ -75,6 +75,7 @@ struct mlx5hws_context_attr {
struct mlx5hws_table_attr { struct mlx5hws_table_attr {
enum mlx5hws_table_type type; enum mlx5hws_table_type type;
u32 level; u32 level;
u16 uid;
}; };
enum mlx5hws_matcher_flow_src { enum mlx5hws_matcher_flow_src {

View File

@ -964,7 +964,6 @@ static int hws_send_ring_open_cq(struct mlx5_core_dev *mdev,
return -ENOMEM; return -ENOMEM;
MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index); MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index);
MLX5_SET(cqc, cqc_data, cqe_sz, queue->num_entries);
MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries)); MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries));
err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq); err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq);

View File

@ -9,6 +9,7 @@ u32 mlx5hws_table_get_id(struct mlx5hws_table *tbl)
} }
static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl, static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl,
u16 uid,
struct mlx5hws_cmd_ft_create_attr *ft_attr) struct mlx5hws_cmd_ft_create_attr *ft_attr)
{ {
ft_attr->type = tbl->fw_ft_type; ft_attr->type = tbl->fw_ft_type;
@ -16,7 +17,9 @@ static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl,
ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1; ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1;
else else
ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1; ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1;
ft_attr->rtc_valid = true; ft_attr->rtc_valid = true;
ft_attr->uid = uid;
} }
static void hws_table_set_cap_attr(struct mlx5hws_table *tbl, static void hws_table_set_cap_attr(struct mlx5hws_table *tbl,
@ -119,12 +122,12 @@ static int hws_table_connect_to_default_miss_tbl(struct mlx5hws_table *tbl, u32
int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev,
struct mlx5hws_table *tbl, struct mlx5hws_table *tbl,
u32 *ft_id) u16 uid, u32 *ft_id)
{ {
struct mlx5hws_cmd_ft_create_attr ft_attr = {0}; struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
int ret; int ret;
hws_table_init_next_ft_attr(tbl, &ft_attr); hws_table_init_next_ft_attr(tbl, uid, &ft_attr);
hws_table_set_cap_attr(tbl, &ft_attr); hws_table_set_cap_attr(tbl, &ft_attr);
ret = mlx5hws_cmd_flow_table_create(mdev, &ft_attr, ft_id); ret = mlx5hws_cmd_flow_table_create(mdev, &ft_attr, ft_id);
@ -189,7 +192,10 @@ static int hws_table_init(struct mlx5hws_table *tbl)
} }
mutex_lock(&ctx->ctrl_lock); mutex_lock(&ctx->ctrl_lock);
ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, &tbl->ft_id); ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev,
tbl,
tbl->uid,
&tbl->ft_id);
if (ret) { if (ret) {
mlx5hws_err(tbl->ctx, "Failed to create flow table object\n"); mlx5hws_err(tbl->ctx, "Failed to create flow table object\n");
mutex_unlock(&ctx->ctrl_lock); mutex_unlock(&ctx->ctrl_lock);
@ -239,6 +245,7 @@ struct mlx5hws_table *mlx5hws_table_create(struct mlx5hws_context *ctx,
tbl->ctx = ctx; tbl->ctx = ctx;
tbl->type = attr->type; tbl->type = attr->type;
tbl->level = attr->level; tbl->level = attr->level;
tbl->uid = attr->uid;
ret = hws_table_init(tbl); ret = hws_table_init(tbl);
if (ret) { if (ret) {

View File

@ -18,6 +18,7 @@ struct mlx5hws_table {
enum mlx5hws_table_type type; enum mlx5hws_table_type type;
u32 fw_ft_type; u32 fw_ft_type;
u32 level; u32 level;
u16 uid;
struct list_head matchers_list; struct list_head matchers_list;
struct list_head tbl_list_node; struct list_head tbl_list_node;
struct mlx5hws_default_miss default_miss; struct mlx5hws_default_miss default_miss;
@ -47,7 +48,7 @@ u32 mlx5hws_table_get_res_fw_ft_type(enum mlx5hws_table_type tbl_type,
int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev,
struct mlx5hws_table *tbl, struct mlx5hws_table *tbl,
u32 *ft_id); u16 uid, u32 *ft_id);
void mlx5hws_table_destroy_default_ft(struct mlx5hws_table *tbl, void mlx5hws_table_destroy_default_ft(struct mlx5hws_table *tbl,
u32 ft_id); u32 ft_id);

View File

@ -2375,6 +2375,8 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
ROUTER_EXP, false), ROUTER_EXP, false),
MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD, MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD,
ROUTER_EXP, false), ROUTER_EXP, false),
MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_LINK_LOCAL, FORWARD,
ROUTER_EXP, false),
/* Multicast Router Traps */ /* Multicast Router Traps */
MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false), MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false),
MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false), MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false),

View File

@ -94,6 +94,7 @@ enum {
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_SIP_BC = 0x16A, MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_SIP_BC = 0x16A,
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_DIP_LOCAL_NET = 0x16B, MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_DIP_LOCAL_NET = 0x16B,
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_DIP_LINK_LOCAL = 0x16C, MLXSW_TRAP_ID_DISCARD_ING_ROUTER_DIP_LINK_LOCAL = 0x16C,
MLXSW_TRAP_ID_DISCARD_ING_ROUTER_SIP_LINK_LOCAL = 0x16D,
MLXSW_TRAP_ID_DISCARD_ROUTER_IRIF_EN = 0x178, MLXSW_TRAP_ID_DISCARD_ROUTER_IRIF_EN = 0x178,
MLXSW_TRAP_ID_DISCARD_ROUTER_ERIF_EN = 0x179, MLXSW_TRAP_ID_DISCARD_ROUTER_ERIF_EN = 0x179,
MLXSW_TRAP_ID_DISCARD_ROUTER_LPM4 = 0x17B, MLXSW_TRAP_ID_DISCARD_ROUTER_LPM4 = 0x17B,

View File

@ -32,6 +32,10 @@
/* MAC Specific Addr 1 Top Reg */ /* MAC Specific Addr 1 Top Reg */
#define LAN865X_REG_MAC_H_SADDR1 0x00010023 #define LAN865X_REG_MAC_H_SADDR1 0x00010023
/* MAC TSU Timer Increment Register */
#define LAN865X_REG_MAC_TSU_TIMER_INCR 0x00010077
#define MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS 0x0028
struct lan865x_priv { struct lan865x_priv {
struct work_struct multicast_work; struct work_struct multicast_work;
struct net_device *netdev; struct net_device *netdev;
@ -311,6 +315,8 @@ static int lan865x_net_open(struct net_device *netdev)
phy_start(netdev->phydev); phy_start(netdev->phydev);
netif_start_queue(netdev);
return 0; return 0;
} }
@ -344,6 +350,21 @@ static int lan865x_probe(struct spi_device *spi)
goto free_netdev; goto free_netdev;
} }
/* LAN865x Rev.B0/B1 configuration parameters from AN1760
* As per the Configuration Application Note AN1760 published in the
* link, https://www.microchip.com/en-us/application-notes/an1760
* Revision F (DS60001760G - June 2024), configure the MAC to set time
* stamping at the end of the Start of Frame Delimiter (SFD) and set the
* Timer Increment reg to 40 ns to be used as a 25 MHz internal clock.
*/
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_TSU_TIMER_INCR,
MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS);
if (ret) {
dev_err(&spi->dev, "Failed to config TSU Timer Incr reg: %d\n",
ret);
goto oa_tc6_exit;
}
/* As per the point s3 in the below errata, SPI receive Ethernet frame /* As per the point s3 in the below errata, SPI receive Ethernet frame
* transfer may halt when starting the next frame in the same data block * transfer may halt when starting the next frame in the same data block
* (chunk) as the end of a previous frame. The RFA field should be * (chunk) as the end of a previous frame. The RFA field should be

View File

@ -241,7 +241,7 @@ union rtase_rx_desc {
#define RTASE_RX_RES BIT(20) #define RTASE_RX_RES BIT(20)
#define RTASE_RX_RUNT BIT(19) #define RTASE_RX_RUNT BIT(19)
#define RTASE_RX_RWT BIT(18) #define RTASE_RX_RWT BIT(18)
#define RTASE_RX_CRC BIT(16) #define RTASE_RX_CRC BIT(17)
#define RTASE_RX_V6F BIT(31) #define RTASE_RX_V6F BIT(31)
#define RTASE_RX_V4F BIT(30) #define RTASE_RX_V4F BIT(30)
#define RTASE_RX_UDPT BIT(29) #define RTASE_RX_UDPT BIT(29)

View File

@ -152,7 +152,7 @@ static int thead_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat) static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat)
{ {
struct thead_dwmac *dwmac = plat->bsp_priv; struct thead_dwmac *dwmac = plat->bsp_priv;
u32 reg; u32 reg, div;
switch (plat->mac_interface) { switch (plat->mac_interface) {
case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_MII:
@ -164,6 +164,13 @@ static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat)
case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_TXID:
/* use pll */ /* use pll */
div = clk_get_rate(plat->stmmac_clk) / rgmii_clock(SPEED_1000);
reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) |
FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div);
writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV);
writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV);
writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL); writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL);
reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN | reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN |
GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN; GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN;

View File

@ -203,6 +203,44 @@ static void prueth_emac_stop(struct prueth *prueth)
} }
} }
static void icssg_enable_fw_offload(struct prueth *prueth)
{
struct prueth_emac *emac;
int mac;
for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) {
emac = prueth->emac[mac];
if (prueth->is_hsr_offload_mode) {
if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM)
icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE);
else
icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE);
}
if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) {
if (netif_running(emac->ndev)) {
icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
ICSSG_FDB_ENTRY_BLOCK,
true);
icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID,
BIT(emac->port_id) | DEFAULT_PORT_MASK,
BIT(emac->port_id) | DEFAULT_UNTAG_MASK,
true);
if (prueth->is_hsr_offload_mode)
icssg_vtbl_modify(emac, DEFAULT_VID,
DEFAULT_PORT_MASK,
DEFAULT_UNTAG_MASK, true);
icssg_set_pvid(prueth, emac->port_vlan, emac->port_id);
if (prueth->is_switch_mode)
icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
}
}
}
}
static int prueth_emac_common_start(struct prueth *prueth) static int prueth_emac_common_start(struct prueth *prueth)
{ {
struct prueth_emac *emac; struct prueth_emac *emac;
@ -753,6 +791,7 @@ static int emac_ndo_open(struct net_device *ndev)
ret = prueth_emac_common_start(prueth); ret = prueth_emac_common_start(prueth);
if (ret) if (ret)
goto free_rx_irq; goto free_rx_irq;
icssg_enable_fw_offload(prueth);
} }
flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
@ -1360,8 +1399,7 @@ static int prueth_emac_restart(struct prueth *prueth)
static void icssg_change_mode(struct prueth *prueth) static void icssg_change_mode(struct prueth *prueth)
{ {
struct prueth_emac *emac; int ret;
int mac, ret;
ret = prueth_emac_restart(prueth); ret = prueth_emac_restart(prueth);
if (ret) { if (ret) {
@ -1369,35 +1407,7 @@ static void icssg_change_mode(struct prueth *prueth)
return; return;
} }
for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { icssg_enable_fw_offload(prueth);
emac = prueth->emac[mac];
if (prueth->is_hsr_offload_mode) {
if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM)
icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE);
else
icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE);
}
if (netif_running(emac->ndev)) {
icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
ICSSG_FDB_ENTRY_BLOCK,
true);
icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID,
BIT(emac->port_id) | DEFAULT_PORT_MASK,
BIT(emac->port_id) | DEFAULT_UNTAG_MASK,
true);
if (prueth->is_hsr_offload_mode)
icssg_vtbl_modify(emac, DEFAULT_VID,
DEFAULT_PORT_MASK,
DEFAULT_UNTAG_MASK, true);
icssg_set_pvid(prueth, emac->port_vlan, emac->port_id);
if (prueth->is_switch_mode)
icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
}
}
} }
static int prueth_netdevice_port_link(struct net_device *ndev, static int prueth_netdevice_port_link(struct net_device *ndev,

View File

@ -192,7 +192,7 @@ void wx_setup_vfmrqc_vf(struct wx *wx)
u8 i, j; u8 i, j;
/* Fill out hash function seeds */ /* Fill out hash function seeds */
netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key)); netdev_rss_key_fill(wx->rss_key, WX_RSS_KEY_SIZE);
for (i = 0; i < WX_RSS_KEY_SIZE / 4; i++) for (i = 0; i < WX_RSS_KEY_SIZE / 4; i++)
wr32(wx, WX_VXRSSRK(i), wx->rss_key[i]); wr32(wx, WX_VXRSSRK(i), wx->rss_key[i]);

View File

@ -1160,6 +1160,7 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result)
struct axienet_local *lp = data; struct axienet_local *lp = data;
struct sk_buff *skb; struct sk_buff *skb;
u32 *app_metadata; u32 *app_metadata;
int i;
skbuf_dma = axienet_get_rx_desc(lp, lp->rx_ring_tail++); skbuf_dma = axienet_get_rx_desc(lp, lp->rx_ring_tail++);
skb = skbuf_dma->skb; skb = skbuf_dma->skb;
@ -1178,7 +1179,10 @@ static void axienet_dma_rx_cb(void *data, const struct dmaengine_result *result)
u64_stats_add(&lp->rx_packets, 1); u64_stats_add(&lp->rx_packets, 1);
u64_stats_add(&lp->rx_bytes, rx_len); u64_stats_add(&lp->rx_bytes, rx_len);
u64_stats_update_end(&lp->rx_stat_sync); u64_stats_update_end(&lp->rx_stat_sync);
axienet_rx_submit_desc(lp->ndev);
for (i = 0; i < CIRC_SPACE(lp->rx_ring_head, lp->rx_ring_tail,
RX_BUF_NUM_DEFAULT); i++)
axienet_rx_submit_desc(lp->ndev);
dma_async_issue_pending(lp->rx_chan); dma_async_issue_pending(lp->rx_chan);
} }
@ -1457,7 +1461,6 @@ static void axienet_rx_submit_desc(struct net_device *ndev)
if (!skbuf_dma) if (!skbuf_dma)
return; return;
lp->rx_ring_head++;
skb = netdev_alloc_skb(ndev, lp->max_frm_size); skb = netdev_alloc_skb(ndev, lp->max_frm_size);
if (!skb) if (!skb)
return; return;
@ -1482,6 +1485,7 @@ static void axienet_rx_submit_desc(struct net_device *ndev)
skbuf_dma->desc = dma_rx_desc; skbuf_dma->desc = dma_rx_desc;
dma_rx_desc->callback_param = lp; dma_rx_desc->callback_param = lp;
dma_rx_desc->callback_result = axienet_dma_rx_cb; dma_rx_desc->callback_result = axienet_dma_rx_cb;
lp->rx_ring_head++;
dmaengine_submit(dma_rx_desc); dmaengine_submit(dma_rx_desc);
return; return;

View File

@ -362,6 +362,13 @@ struct vsc85xx_hw_stat {
u16 mask; u16 mask;
}; };
struct vsc8531_skb_cb {
u32 ns;
};
#define VSC8531_SKB_CB(skb) \
((struct vsc8531_skb_cb *)((skb)->cb))
struct vsc8531_private { struct vsc8531_private {
int rate_magic; int rate_magic;
u16 supp_led_modes; u16 supp_led_modes;
@ -410,6 +417,11 @@ struct vsc8531_private {
*/ */
struct mutex ts_lock; struct mutex ts_lock;
struct mutex phc_lock; struct mutex phc_lock;
/* list of skbs that were received and need timestamp information but it
* didn't received it yet
*/
struct sk_buff_head rx_skbs_list;
}; };
/* Shared structure between the PHYs of the same package. /* Shared structure between the PHYs of the same package.

View File

@ -2335,6 +2335,13 @@ static int vsc85xx_probe(struct phy_device *phydev)
return vsc85xx_dt_led_modes_get(phydev, default_mode); return vsc85xx_dt_led_modes_get(phydev, default_mode);
} }
static void vsc85xx_remove(struct phy_device *phydev)
{
struct vsc8531_private *priv = phydev->priv;
skb_queue_purge(&priv->rx_skbs_list);
}
/* Microsemi VSC85xx PHYs */ /* Microsemi VSC85xx PHYs */
static struct phy_driver vsc85xx_driver[] = { static struct phy_driver vsc85xx_driver[] = {
{ {
@ -2589,6 +2596,7 @@ static struct phy_driver vsc85xx_driver[] = {
.config_intr = &vsc85xx_config_intr, .config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend, .suspend = &genphy_suspend,
.resume = &genphy_resume, .resume = &genphy_resume,
.remove = &vsc85xx_remove,
.probe = &vsc8574_probe, .probe = &vsc8574_probe,
.set_wol = &vsc85xx_wol_set, .set_wol = &vsc85xx_wol_set,
.get_wol = &vsc85xx_wol_get, .get_wol = &vsc85xx_wol_get,
@ -2614,6 +2622,7 @@ static struct phy_driver vsc85xx_driver[] = {
.config_intr = &vsc85xx_config_intr, .config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend, .suspend = &genphy_suspend,
.resume = &genphy_resume, .resume = &genphy_resume,
.remove = &vsc85xx_remove,
.probe = &vsc8574_probe, .probe = &vsc8574_probe,
.set_wol = &vsc85xx_wol_set, .set_wol = &vsc85xx_wol_set,
.get_wol = &vsc85xx_wol_get, .get_wol = &vsc85xx_wol_get,
@ -2639,6 +2648,7 @@ static struct phy_driver vsc85xx_driver[] = {
.config_intr = &vsc85xx_config_intr, .config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend, .suspend = &genphy_suspend,
.resume = &genphy_resume, .resume = &genphy_resume,
.remove = &vsc85xx_remove,
.probe = &vsc8584_probe, .probe = &vsc8584_probe,
.get_tunable = &vsc85xx_get_tunable, .get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable, .set_tunable = &vsc85xx_set_tunable,
@ -2662,6 +2672,7 @@ static struct phy_driver vsc85xx_driver[] = {
.config_intr = &vsc85xx_config_intr, .config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend, .suspend = &genphy_suspend,
.resume = &genphy_resume, .resume = &genphy_resume,
.remove = &vsc85xx_remove,
.probe = &vsc8584_probe, .probe = &vsc8584_probe,
.get_tunable = &vsc85xx_get_tunable, .get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable, .set_tunable = &vsc85xx_set_tunable,
@ -2685,6 +2696,7 @@ static struct phy_driver vsc85xx_driver[] = {
.config_intr = &vsc85xx_config_intr, .config_intr = &vsc85xx_config_intr,
.suspend = &genphy_suspend, .suspend = &genphy_suspend,
.resume = &genphy_resume, .resume = &genphy_resume,
.remove = &vsc85xx_remove,
.probe = &vsc8584_probe, .probe = &vsc8584_probe,
.get_tunable = &vsc85xx_get_tunable, .get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable, .set_tunable = &vsc85xx_set_tunable,

View File

@ -1194,9 +1194,7 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
{ {
struct vsc8531_private *vsc8531 = struct vsc8531_private *vsc8531 =
container_of(mii_ts, struct vsc8531_private, mii_ts); container_of(mii_ts, struct vsc8531_private, mii_ts);
struct skb_shared_hwtstamps *shhwtstamps = NULL;
struct vsc85xx_ptphdr *ptphdr; struct vsc85xx_ptphdr *ptphdr;
struct timespec64 ts;
unsigned long ns; unsigned long ns;
if (!vsc8531->ptp->configured) if (!vsc8531->ptp->configured)
@ -1206,27 +1204,52 @@ static bool vsc85xx_rxtstamp(struct mii_timestamper *mii_ts,
type == PTP_CLASS_NONE) type == PTP_CLASS_NONE)
return false; return false;
vsc85xx_gettime(&vsc8531->ptp->caps, &ts);
ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter); ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter);
if (!ptphdr) if (!ptphdr)
return false; return false;
shhwtstamps = skb_hwtstamps(skb);
memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
ns = ntohl(ptphdr->rsrvd2); ns = ntohl(ptphdr->rsrvd2);
/* nsec is in reserved field */ VSC8531_SKB_CB(skb)->ns = ns;
if (ts.tv_nsec < ns) skb_queue_tail(&vsc8531->rx_skbs_list, skb);
ts.tv_sec--;
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ns); ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0);
netif_rx(skb);
return true; return true;
} }
static long vsc85xx_do_aux_work(struct ptp_clock_info *info)
{
struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps);
struct skb_shared_hwtstamps *shhwtstamps = NULL;
struct phy_device *phydev = ptp->phydev;
struct vsc8531_private *priv = phydev->priv;
struct sk_buff_head received;
struct sk_buff *rx_skb;
struct timespec64 ts;
unsigned long flags;
__skb_queue_head_init(&received);
spin_lock_irqsave(&priv->rx_skbs_list.lock, flags);
skb_queue_splice_tail_init(&priv->rx_skbs_list, &received);
spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags);
vsc85xx_gettime(info, &ts);
while ((rx_skb = __skb_dequeue(&received)) != NULL) {
shhwtstamps = skb_hwtstamps(rx_skb);
memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns)
ts.tv_sec--;
shhwtstamps->hwtstamp = ktime_set(ts.tv_sec,
VSC8531_SKB_CB(rx_skb)->ns);
netif_rx(rx_skb);
}
return -1;
}
static const struct ptp_clock_info vsc85xx_clk_caps = { static const struct ptp_clock_info vsc85xx_clk_caps = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "VSC85xx timer", .name = "VSC85xx timer",
@ -1240,6 +1263,7 @@ static const struct ptp_clock_info vsc85xx_clk_caps = {
.adjfine = &vsc85xx_adjfine, .adjfine = &vsc85xx_adjfine,
.gettime64 = &vsc85xx_gettime, .gettime64 = &vsc85xx_gettime,
.settime64 = &vsc85xx_settime, .settime64 = &vsc85xx_settime,
.do_aux_work = &vsc85xx_do_aux_work,
}; };
static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev) static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev)
@ -1567,6 +1591,7 @@ int vsc8584_ptp_probe(struct phy_device *phydev)
mutex_init(&vsc8531->phc_lock); mutex_init(&vsc8531->phc_lock);
mutex_init(&vsc8531->ts_lock); mutex_init(&vsc8531->ts_lock);
skb_queue_head_init(&vsc8531->rx_skbs_list);
/* Retrieve the shared load/save GPIO. Request it as non exclusive as /* Retrieve the shared load/save GPIO. Request it as non exclusive as
* the same GPIO can be requested by all the PHYs of the same package. * the same GPIO can be requested by all the PHYs of the same package.

View File

@ -33,6 +33,7 @@
#include <linux/ppp_channel.h> #include <linux/ppp_channel.h>
#include <linux/ppp-comp.h> #include <linux/ppp-comp.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/rculist.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/ip.h> #include <linux/ip.h>
@ -1598,11 +1599,14 @@ static int ppp_fill_forward_path(struct net_device_path_ctx *ctx,
if (ppp->flags & SC_MULTILINK) if (ppp->flags & SC_MULTILINK)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (list_empty(&ppp->channels)) pch = list_first_or_null_rcu(&ppp->channels, struct channel, clist);
if (!pch)
return -ENODEV;
chan = READ_ONCE(pch->chan);
if (!chan)
return -ENODEV; return -ENODEV;
pch = list_first_entry(&ppp->channels, struct channel, clist);
chan = pch->chan;
if (!chan->ops->fill_forward_path) if (!chan->ops->fill_forward_path)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -2994,7 +2998,7 @@ ppp_unregister_channel(struct ppp_channel *chan)
*/ */
down_write(&pch->chan_sem); down_write(&pch->chan_sem);
spin_lock_bh(&pch->downl); spin_lock_bh(&pch->downl);
pch->chan = NULL; WRITE_ONCE(pch->chan, NULL);
spin_unlock_bh(&pch->downl); spin_unlock_bh(&pch->downl);
up_write(&pch->chan_sem); up_write(&pch->chan_sem);
ppp_disconnect_channel(pch); ppp_disconnect_channel(pch);
@ -3515,7 +3519,7 @@ ppp_connect_channel(struct channel *pch, int unit)
hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */
if (hdrlen > ppp->dev->hard_header_len) if (hdrlen > ppp->dev->hard_header_len)
ppp->dev->hard_header_len = hdrlen; ppp->dev->hard_header_len = hdrlen;
list_add_tail(&pch->clist, &ppp->channels); list_add_tail_rcu(&pch->clist, &ppp->channels);
++ppp->n_channels; ++ppp->n_channels;
pch->ppp = ppp; pch->ppp = ppp;
refcount_inc(&ppp->file.refcnt); refcount_inc(&ppp->file.refcnt);
@ -3545,10 +3549,11 @@ ppp_disconnect_channel(struct channel *pch)
if (ppp) { if (ppp) {
/* remove it from the ppp unit's list */ /* remove it from the ppp unit's list */
ppp_lock(ppp); ppp_lock(ppp);
list_del(&pch->clist); list_del_rcu(&pch->clist);
if (--ppp->n_channels == 0) if (--ppp->n_channels == 0)
wake_up_interruptible(&ppp->file.rwait); wake_up_interruptible(&ppp->file.rwait);
ppp_unlock(ppp); ppp_unlock(ppp);
synchronize_net();
if (refcount_dec_and_test(&ppp->file.refcnt)) if (refcount_dec_and_test(&ppp->file.refcnt))
ppp_destroy_interface(ppp); ppp_destroy_interface(ppp);
err = 0; err = 0;

View File

@ -1041,6 +1041,10 @@ pd692x0_configure_managers(struct pd692x0_priv *priv, int nmanagers)
int pw_budget; int pw_budget;
pw_budget = regulator_get_unclaimed_power_budget(supply); pw_budget = regulator_get_unclaimed_power_budget(supply);
if (!pw_budget)
/* Do nothing if no power budget */
continue;
/* Max power budget per manager */ /* Max power budget per manager */
if (pw_budget > 6000000) if (pw_budget > 6000000)
pw_budget = 6000000; pw_budget = 6000000;
@ -1162,12 +1166,44 @@ pd692x0_write_ports_matrix(struct pd692x0_priv *priv,
return 0; return 0;
} }
static void pd692x0_of_put_managers(struct pd692x0_priv *priv,
struct pd692x0_manager *manager,
int nmanagers)
{
int i, j;
for (i = 0; i < nmanagers; i++) {
for (j = 0; j < manager[i].nports; j++)
of_node_put(manager[i].port_node[j]);
of_node_put(manager[i].node);
}
}
static void pd692x0_managers_free_pw_budget(struct pd692x0_priv *priv)
{
int i;
for (i = 0; i < PD692X0_MAX_MANAGERS; i++) {
struct regulator *supply;
if (!priv->manager_reg[i] || !priv->manager_pw_budget[i])
continue;
supply = priv->manager_reg[i]->supply;
if (!supply)
continue;
regulator_free_power_budget(supply,
priv->manager_pw_budget[i]);
}
}
static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev) static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev)
{ {
struct pd692x0_manager *manager __free(kfree) = NULL; struct pd692x0_manager *manager __free(kfree) = NULL;
struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); struct pd692x0_priv *priv = to_pd692x0_priv(pcdev);
struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS]; struct pd692x0_matrix port_matrix[PD692X0_MAX_PIS];
int ret, i, j, nmanagers; int ret, nmanagers;
/* Should we flash the port matrix */ /* Should we flash the port matrix */
if (priv->fw_state != PD692X0_FW_OK && if (priv->fw_state != PD692X0_FW_OK &&
@ -1185,31 +1221,27 @@ static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev)
nmanagers = ret; nmanagers = ret;
ret = pd692x0_register_managers_regulator(priv, manager, nmanagers); ret = pd692x0_register_managers_regulator(priv, manager, nmanagers);
if (ret) if (ret)
goto out; goto err_of_managers;
ret = pd692x0_configure_managers(priv, nmanagers); ret = pd692x0_configure_managers(priv, nmanagers);
if (ret) if (ret)
goto out; goto err_of_managers;
ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix); ret = pd692x0_set_ports_matrix(priv, manager, nmanagers, port_matrix);
if (ret) if (ret)
goto out; goto err_managers_req_pw;
ret = pd692x0_write_ports_matrix(priv, port_matrix); ret = pd692x0_write_ports_matrix(priv, port_matrix);
if (ret) if (ret)
goto out; goto err_managers_req_pw;
out: pd692x0_of_put_managers(priv, manager, nmanagers);
for (i = 0; i < nmanagers; i++) { return 0;
struct regulator *supply = priv->manager_reg[i]->supply;
regulator_free_power_budget(supply, err_managers_req_pw:
priv->manager_pw_budget[i]); pd692x0_managers_free_pw_budget(priv);
err_of_managers:
for (j = 0; j < manager[i].nports; j++) pd692x0_of_put_managers(priv, manager, nmanagers);
of_node_put(manager[i].port_node[j]);
of_node_put(manager[i].node);
}
return ret; return ret;
} }
@ -1748,6 +1780,7 @@ static void pd692x0_i2c_remove(struct i2c_client *client)
{ {
struct pd692x0_priv *priv = i2c_get_clientdata(client); struct pd692x0_priv *priv = i2c_get_clientdata(client);
pd692x0_managers_free_pw_budget(priv);
firmware_upload_unregister(priv->fwl); firmware_upload_unregister(priv->fwl);
} }

View File

@ -676,7 +676,7 @@ static int ax88772_init_mdio(struct usbnet *dev)
priv->mdio->read = &asix_mdio_bus_read; priv->mdio->read = &asix_mdio_bus_read;
priv->mdio->write = &asix_mdio_bus_write; priv->mdio->write = &asix_mdio_bus_write;
priv->mdio->name = "Asix MDIO Bus"; priv->mdio->name = "Asix MDIO Bus";
priv->mdio->phy_mask = ~(BIT(priv->phy_addr) | BIT(AX_EMBD_PHY_ADDR)); priv->mdio->phy_mask = ~(BIT(priv->phy_addr & 0x1f) | BIT(AX_EMBD_PHY_ADDR));
/* mii bus name is usb-<usb bus number>-<usb device number> */ /* mii bus name is usb-<usb bus number>-<usb device number> */
snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
dev->udev->bus->busnum, dev->udev->devnum); dev->udev->bus->busnum, dev->udev->devnum);

View File

@ -2087,6 +2087,13 @@ static const struct usb_device_id cdc_devs[] = {
.driver_info = (unsigned long)&wwan_info, .driver_info = (unsigned long)&wwan_info,
}, },
/* Intel modem (label from OEM reads Fibocom L850-GL) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x8087, 0x095a,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&wwan_info,
},
/* DisplayLink docking stations */ /* DisplayLink docking stations */
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_VENDOR, | USB_DEVICE_ID_MATCH_VENDOR,

View File

@ -647,7 +647,7 @@ static inline void sco_exit(void)
#if IS_ENABLED(CONFIG_BT_LE) #if IS_ENABLED(CONFIG_BT_LE)
int iso_init(void); int iso_init(void);
int iso_exit(void); int iso_exit(void);
bool iso_enabled(void); bool iso_inited(void);
#else #else
static inline int iso_init(void) static inline int iso_init(void)
{ {
@ -659,7 +659,7 @@ static inline int iso_exit(void)
return 0; return 0;
} }
static inline bool iso_enabled(void) static inline bool iso_inited(void)
{ {
return false; return false;
} }

View File

@ -129,7 +129,9 @@ struct hci_conn_hash {
struct list_head list; struct list_head list;
unsigned int acl_num; unsigned int acl_num;
unsigned int sco_num; unsigned int sco_num;
unsigned int iso_num; unsigned int cis_num;
unsigned int bis_num;
unsigned int pa_num;
unsigned int le_num; unsigned int le_num;
unsigned int le_num_peripheral; unsigned int le_num_peripheral;
}; };
@ -1014,9 +1016,13 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
h->sco_num++; h->sco_num++;
break; break;
case CIS_LINK: case CIS_LINK:
h->cis_num++;
break;
case BIS_LINK: case BIS_LINK:
h->bis_num++;
break;
case PA_LINK: case PA_LINK:
h->iso_num++; h->pa_num++;
break; break;
} }
} }
@ -1042,9 +1048,13 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
h->sco_num--; h->sco_num--;
break; break;
case CIS_LINK: case CIS_LINK:
h->cis_num--;
break;
case BIS_LINK: case BIS_LINK:
h->bis_num--;
break;
case PA_LINK: case PA_LINK:
h->iso_num--; h->pa_num--;
break; break;
} }
} }
@ -1061,9 +1071,11 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
case ESCO_LINK: case ESCO_LINK:
return h->sco_num; return h->sco_num;
case CIS_LINK: case CIS_LINK:
return h->cis_num;
case BIS_LINK: case BIS_LINK:
return h->bis_num;
case PA_LINK: case PA_LINK:
return h->iso_num; return h->pa_num;
default: default:
return 0; return 0;
} }
@ -1073,7 +1085,15 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
{ {
struct hci_conn_hash *c = &hdev->conn_hash; struct hci_conn_hash *c = &hdev->conn_hash;
return c->acl_num + c->sco_num + c->le_num + c->iso_num; return c->acl_num + c->sco_num + c->le_num + c->cis_num + c->bis_num +
c->pa_num;
}
static inline unsigned int hci_iso_count(struct hci_dev *hdev)
{
struct hci_conn_hash *c = &hdev->conn_hash;
return c->cis_num + c->bis_num;
} }
static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn) static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
@ -1915,6 +1935,8 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
!hci_dev_test_flag(dev, HCI_RPA_EXPIRED)) !hci_dev_test_flag(dev, HCI_RPA_EXPIRED))
#define adv_rpa_valid(adv) (bacmp(&adv->random_addr, BDADDR_ANY) && \ #define adv_rpa_valid(adv) (bacmp(&adv->random_addr, BDADDR_ANY) && \
!adv->rpa_expired) !adv->rpa_expired)
#define le_enabled(dev) (lmp_le_capable(dev) && \
hci_dev_test_flag(dev, HCI_LE_ENABLED))
#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \ #define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M)) ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
@ -1932,6 +1954,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED)) ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED))
#define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY) #define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY)
#define ll_privacy_enabled(dev) (le_enabled(dev) && ll_privacy_capable(dev))
#define privacy_mode_capable(dev) (ll_privacy_capable(dev) && \ #define privacy_mode_capable(dev) (ll_privacy_capable(dev) && \
((dev)->commands[39] & 0x04)) ((dev)->commands[39] & 0x04))
@ -1981,14 +2004,23 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
/* CIS Master/Slave and BIS support */ /* CIS Master/Slave and BIS support */
#define iso_capable(dev) (cis_capable(dev) || bis_capable(dev)) #define iso_capable(dev) (cis_capable(dev) || bis_capable(dev))
#define iso_enabled(dev) (le_enabled(dev) && iso_capable(dev))
#define cis_capable(dev) \ #define cis_capable(dev) \
(cis_central_capable(dev) || cis_peripheral_capable(dev)) (cis_central_capable(dev) || cis_peripheral_capable(dev))
#define cis_enabled(dev) (le_enabled(dev) && cis_capable(dev))
#define cis_central_capable(dev) \ #define cis_central_capable(dev) \
((dev)->le_features[3] & HCI_LE_CIS_CENTRAL) ((dev)->le_features[3] & HCI_LE_CIS_CENTRAL)
#define cis_central_enabled(dev) \
(le_enabled(dev) && cis_central_capable(dev))
#define cis_peripheral_capable(dev) \ #define cis_peripheral_capable(dev) \
((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL) ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL)
#define cis_peripheral_enabled(dev) \
(le_enabled(dev) && cis_peripheral_capable(dev))
#define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER) #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER)
#define sync_recv_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) #define bis_enabled(dev) (le_enabled(dev) && bis_capable(dev))
#define sync_recv_capable(dev) \
((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER)
#define sync_recv_enabled(dev) (le_enabled(dev) && sync_recv_capable(dev))
#define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \
(!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG))) (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))

View File

@ -307,6 +307,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
struct slave *slave); struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond); int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond);
void bond_3ad_update_lacp_active(struct bonding *bond);
void bond_3ad_update_ad_actor_settings(struct bonding *bond); void bond_3ad_update_ad_actor_settings(struct bonding *bond);
int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats); int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
size_t bond_3ad_stats_size(void); size_t bond_3ad_stats_size(void);

View File

@ -1038,12 +1038,17 @@ static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool dir
skb = __skb_dequeue(&sch->gso_skb); skb = __skb_dequeue(&sch->gso_skb);
if (skb) { if (skb) {
sch->q.qlen--; sch->q.qlen--;
qdisc_qstats_backlog_dec(sch, skb);
return skb; return skb;
} }
if (direct) if (direct) {
return __qdisc_dequeue_head(&sch->q); skb = __qdisc_dequeue_head(&sch->q);
else if (skb)
qdisc_qstats_backlog_dec(sch, skb);
return skb;
} else {
return sch->dequeue(sch); return sch->dequeue(sch);
}
} }
static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)

View File

@ -339,7 +339,8 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
case BT_CODEC_TRANSPARENT: case BT_CODEC_TRANSPARENT:
if (!find_next_esco_param(conn, esco_param_msbc, if (!find_next_esco_param(conn, esco_param_msbc,
ARRAY_SIZE(esco_param_msbc))) ARRAY_SIZE(esco_param_msbc)))
return false; return -EINVAL;
param = &esco_param_msbc[conn->attempt - 1]; param = &esco_param_msbc[conn->attempt - 1];
cp.tx_coding_format.id = 0x03; cp.tx_coding_format.id = 0x03;
cp.rx_coding_format.id = 0x03; cp.rx_coding_format.id = 0x03;
@ -830,7 +831,17 @@ static void bis_cleanup(struct hci_conn *conn)
/* Check if ISO connection is a BIS and terminate advertising /* Check if ISO connection is a BIS and terminate advertising
* set and BIG if there are no other connections using it. * set and BIG if there are no other connections using it.
*/ */
bis = hci_conn_hash_lookup_big(hdev, conn->iso_qos.bcast.big); bis = hci_conn_hash_lookup_big_state(hdev,
conn->iso_qos.bcast.big,
BT_CONNECTED,
HCI_ROLE_MASTER);
if (bis)
return;
bis = hci_conn_hash_lookup_big_state(hdev,
conn->iso_qos.bcast.big,
BT_CONNECT,
HCI_ROLE_MASTER);
if (bis) if (bis)
return; return;
@ -2249,7 +2260,7 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
* the start periodic advertising and create BIG commands have * the start periodic advertising and create BIG commands have
* been queued * been queued
*/ */
hci_conn_hash_list_state(hdev, bis_mark_per_adv, PA_LINK, hci_conn_hash_list_state(hdev, bis_mark_per_adv, BIS_LINK,
BT_BOUND, &data); BT_BOUND, &data);
/* Queue start periodic advertising and create BIG */ /* Queue start periodic advertising and create BIG */

View File

@ -6745,8 +6745,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
qos->ucast.out.latency = qos->ucast.out.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency),
1000); 1000);
qos->ucast.in.sdu = le16_to_cpu(ev->c_mtu); qos->ucast.in.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
qos->ucast.out.sdu = le16_to_cpu(ev->p_mtu); qos->ucast.out.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
qos->ucast.in.phy = ev->c_phy; qos->ucast.in.phy = ev->c_phy;
qos->ucast.out.phy = ev->p_phy; qos->ucast.out.phy = ev->p_phy;
break; break;
@ -6760,8 +6760,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
qos->ucast.in.latency = qos->ucast.in.latency =
DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency),
1000); 1000);
qos->ucast.out.sdu = le16_to_cpu(ev->c_mtu); qos->ucast.out.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
qos->ucast.in.sdu = le16_to_cpu(ev->p_mtu); qos->ucast.in.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
qos->ucast.out.phy = ev->c_phy; qos->ucast.out.phy = ev->c_phy;
qos->ucast.in.phy = ev->p_phy; qos->ucast.in.phy = ev->p_phy;
break; break;
@ -6957,9 +6957,14 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
continue; continue;
} }
if (ev->status != 0x42) if (ev->status != 0x42) {
/* Mark PA sync as established */ /* Mark PA sync as established */
set_bit(HCI_CONN_PA_SYNC, &bis->flags); set_bit(HCI_CONN_PA_SYNC, &bis->flags);
/* Reset cleanup callback of PA Sync so it doesn't
* terminate the sync when deleting the connection.
*/
conn->cleanup = NULL;
}
bis->sync_handle = conn->sync_handle; bis->sync_handle = conn->sync_handle;
bis->iso_qos.bcast.big = ev->handle; bis->iso_qos.bcast.big = ev->handle;

View File

@ -3344,7 +3344,7 @@ static int hci_powered_update_adv_sync(struct hci_dev *hdev)
* advertising data. This also applies to the case * advertising data. This also applies to the case
* where BR/EDR was toggled during the AUTO_OFF phase. * where BR/EDR was toggled during the AUTO_OFF phase.
*/ */
if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || if (hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
list_empty(&hdev->adv_instances)) { list_empty(&hdev->adv_instances)) {
if (ext_adv_capable(hdev)) { if (ext_adv_capable(hdev)) {
err = hci_setup_ext_adv_instance_sync(hdev, 0x00); err = hci_setup_ext_adv_instance_sync(hdev, 0x00);
@ -4531,14 +4531,14 @@ static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
{ {
struct hci_cp_le_set_host_feature cp; struct hci_cp_le_set_host_feature cp;
if (!cis_capable(hdev)) if (!iso_capable(hdev))
return 0; return 0;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
/* Connected Isochronous Channels (Host Support) */ /* Connected Isochronous Channels (Host Support) */
cp.bit_number = 32; cp.bit_number = 32;
cp.bit_value = 1; cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00;
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE, return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE,
sizeof(cp), &cp, HCI_CMD_TIMEOUT); sizeof(cp), &cp, HCI_CMD_TIMEOUT);
@ -6985,8 +6985,6 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
hci_dev_lock(hdev); hci_dev_lock(hdev);
hci_dev_clear_flag(hdev, HCI_PA_SYNC);
if (!hci_conn_valid(hdev, conn)) if (!hci_conn_valid(hdev, conn))
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
@ -7047,10 +7045,13 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
/* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update
* it. * it.
*/ */
if (conn->sid == HCI_SID_INVALID) if (conn->sid == HCI_SID_INVALID) {
__hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, err = __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL,
HCI_EV_LE_EXT_ADV_REPORT, HCI_EV_LE_EXT_ADV_REPORT,
conn->conn_timeout, NULL); conn->conn_timeout, NULL);
if (err == -ETIMEDOUT)
goto done;
}
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.options = qos->bcast.options; cp.options = qos->bcast.options;
@ -7080,6 +7081,12 @@ static int hci_le_pa_create_sync(struct hci_dev *hdev, void *data)
__hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC_CANCEL, __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC_CANCEL,
0, NULL, HCI_CMD_TIMEOUT); 0, NULL, HCI_CMD_TIMEOUT);
done:
hci_dev_clear_flag(hdev, HCI_PA_SYNC);
/* Update passive scan since HCI_PA_SYNC flag has been cleared */
hci_update_passive_scan_sync(hdev);
return err; return err;
} }

View File

@ -1347,7 +1347,7 @@ static int iso_sock_getname(struct socket *sock, struct sockaddr *addr,
bacpy(&sa->iso_bdaddr, &iso_pi(sk)->dst); bacpy(&sa->iso_bdaddr, &iso_pi(sk)->dst);
sa->iso_bdaddr_type = iso_pi(sk)->dst_type; sa->iso_bdaddr_type = iso_pi(sk)->dst_type;
if (hcon && hcon->type == BIS_LINK) { if (hcon && (hcon->type == BIS_LINK || hcon->type == PA_LINK)) {
sa->iso_bc->bc_sid = iso_pi(sk)->bc_sid; sa->iso_bc->bc_sid = iso_pi(sk)->bc_sid;
sa->iso_bc->bc_num_bis = iso_pi(sk)->bc_num_bis; sa->iso_bc->bc_num_bis = iso_pi(sk)->bc_num_bis;
memcpy(sa->iso_bc->bc_bis, iso_pi(sk)->bc_bis, memcpy(sa->iso_bc->bc_bis, iso_pi(sk)->bc_bis,
@ -2483,11 +2483,11 @@ static const struct net_proto_family iso_sock_family_ops = {
.create = iso_sock_create, .create = iso_sock_create,
}; };
static bool iso_inited; static bool inited;
bool iso_enabled(void) bool iso_inited(void)
{ {
return iso_inited; return inited;
} }
int iso_init(void) int iso_init(void)
@ -2496,7 +2496,7 @@ int iso_init(void)
BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr)); BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr));
if (iso_inited) if (inited)
return -EALREADY; return -EALREADY;
err = proto_register(&iso_proto, 0); err = proto_register(&iso_proto, 0);
@ -2524,7 +2524,7 @@ int iso_init(void)
iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs, iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs,
NULL, &iso_debugfs_fops); NULL, &iso_debugfs_fops);
iso_inited = true; inited = true;
return 0; return 0;
@ -2535,7 +2535,7 @@ error:
int iso_exit(void) int iso_exit(void)
{ {
if (!iso_inited) if (!inited)
return -EALREADY; return -EALREADY;
bt_procfs_cleanup(&init_net, "iso"); bt_procfs_cleanup(&init_net, "iso");
@ -2549,7 +2549,7 @@ int iso_exit(void)
proto_unregister(&iso_proto); proto_unregister(&iso_proto);
iso_inited = false; inited = false;
return 0; return 0;
} }

View File

@ -922,19 +922,19 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED)) if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED))
settings |= MGMT_SETTING_WIDEBAND_SPEECH; settings |= MGMT_SETTING_WIDEBAND_SPEECH;
if (cis_central_capable(hdev)) if (cis_central_enabled(hdev))
settings |= MGMT_SETTING_CIS_CENTRAL; settings |= MGMT_SETTING_CIS_CENTRAL;
if (cis_peripheral_capable(hdev)) if (cis_peripheral_enabled(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL; settings |= MGMT_SETTING_CIS_PERIPHERAL;
if (bis_capable(hdev)) if (bis_enabled(hdev))
settings |= MGMT_SETTING_ISO_BROADCASTER; settings |= MGMT_SETTING_ISO_BROADCASTER;
if (sync_recv_capable(hdev)) if (sync_recv_enabled(hdev))
settings |= MGMT_SETTING_ISO_SYNC_RECEIVER; settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
if (ll_privacy_capable(hdev)) if (ll_privacy_enabled(hdev))
settings |= MGMT_SETTING_LL_PRIVACY; settings |= MGMT_SETTING_LL_PRIVACY;
return settings; return settings;
@ -4513,7 +4513,7 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
} }
if (IS_ENABLED(CONFIG_BT_LE)) { if (IS_ENABLED(CONFIG_BT_LE)) {
flags = iso_enabled() ? BIT(0) : 0; flags = iso_inited() ? BIT(0) : 0;
memcpy(rp->features[idx].uuid, iso_socket_uuid, 16); memcpy(rp->features[idx].uuid, iso_socket_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags); rp->features[idx].flags = cpu_to_le32(flags);
idx++; idx++;

View File

@ -4818,6 +4818,14 @@ void br_multicast_set_query_intvl(struct net_bridge_mcast *brmctx,
intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MIN; intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MIN;
} }
if (intvl_jiffies > BR_MULTICAST_QUERY_INTVL_MAX) {
br_info(brmctx->br,
"trying to set multicast query interval above maximum, setting to %lu (%ums)\n",
jiffies_to_clock_t(BR_MULTICAST_QUERY_INTVL_MAX),
jiffies_to_msecs(BR_MULTICAST_QUERY_INTVL_MAX));
intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MAX;
}
brmctx->multicast_query_interval = intvl_jiffies; brmctx->multicast_query_interval = intvl_jiffies;
} }
@ -4834,6 +4842,14 @@ void br_multicast_set_startup_query_intvl(struct net_bridge_mcast *brmctx,
intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN; intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN;
} }
if (intvl_jiffies > BR_MULTICAST_STARTUP_QUERY_INTVL_MAX) {
br_info(brmctx->br,
"trying to set multicast startup query interval above maximum, setting to %lu (%ums)\n",
jiffies_to_clock_t(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX),
jiffies_to_msecs(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX));
intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MAX;
}
brmctx->multicast_startup_query_interval = intvl_jiffies; brmctx->multicast_startup_query_interval = intvl_jiffies;
} }

View File

@ -31,6 +31,8 @@
#define BR_MULTICAST_DEFAULT_HASH_MAX 4096 #define BR_MULTICAST_DEFAULT_HASH_MAX 4096
#define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000) #define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000)
#define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN #define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN
#define BR_MULTICAST_QUERY_INTVL_MAX msecs_to_jiffies(86400000) /* 24 hours */
#define BR_MULTICAST_STARTUP_QUERY_INTVL_MAX BR_MULTICAST_QUERY_INTVL_MAX
#define BR_HWDOM_MAX BITS_PER_LONG #define BR_HWDOM_MAX BITS_PER_LONG

View File

@ -3779,6 +3779,18 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb,
features &= ~NETIF_F_TSO_MANGLEID; features &= ~NETIF_F_TSO_MANGLEID;
} }
/* NETIF_F_IPV6_CSUM does not support IPv6 extension headers,
* so neither does TSO that depends on it.
*/
if (features & NETIF_F_IPV6_CSUM &&
(skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 ||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
vlan_get_protocol(skb) == htons(ETH_P_IPV6))) &&
skb_transport_header_was_set(skb) &&
skb_network_header_len(skb) != sizeof(struct ipv6hdr) &&
!ipv6_has_hopopt_jumbo(skb))
features &= ~(NETIF_F_IPV6_CSUM | NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4);
return features; return features;
} }

View File

@ -63,8 +63,14 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
skb_push(skb, ETH_HLEN); skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) || if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) ||
protocol == htons(ETH_P_HSR)) protocol == htons(ETH_P_HSR)) {
if (!pskb_may_pull(skb, ETH_HLEN + HSR_HLEN)) {
kfree_skb(skb);
goto finish_consume;
}
skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
}
skb_reset_mac_len(skb); skb_reset_mac_len(skb);
/* Only the frames received over the interlink port will assign a /* Only the frames received over the interlink port will assign a

View File

@ -247,8 +247,7 @@ void nf_send_reset(struct net *net, struct sock *sk, struct sk_buff *oldskb,
if (!oth) if (!oth)
return; return;
if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && if (!skb_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0)
nf_reject_fill_skb_dst(oldskb) < 0)
return; return;
if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
@ -321,8 +320,7 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
if (iph->frag_off & htons(IP_OFFSET)) if (iph->frag_off & htons(IP_OFFSET))
return; return;
if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
nf_reject_fill_skb_dst(skb_in) < 0)
return; return;
if (skb_csum_unnecessary(skb_in) || if (skb_csum_unnecessary(skb_in) ||

View File

@ -293,7 +293,7 @@ void nf_send_reset6(struct net *net, struct sock *sk, struct sk_buff *oldskb,
fl6.fl6_sport = otcph->dest; fl6.fl6_sport = otcph->dest;
fl6.fl6_dport = otcph->source; fl6.fl6_dport = otcph->source;
if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) { if (!skb_dst(oldskb)) {
nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
if (!dst) if (!dst)
return; return;
@ -397,8 +397,7 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
skb_in->dev = net->loopback_dev; skb_in->dev = net->loopback_dev;
if ((hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_INGRESS) && if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
nf_reject6_fill_skb_dst(skb_in) < 0)
return; return;
icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);

View File

@ -35,6 +35,7 @@
#include <net/xfrm.h> #include <net/xfrm.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/utils.h>
#include <net/seg6.h> #include <net/seg6.h>
#include <net/genetlink.h> #include <net/genetlink.h>
#include <net/seg6_hmac.h> #include <net/seg6_hmac.h>
@ -280,7 +281,7 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb)
if (seg6_hmac_compute(hinfo, srh, &ipv6_hdr(skb)->saddr, hmac_output)) if (seg6_hmac_compute(hinfo, srh, &ipv6_hdr(skb)->saddr, hmac_output))
return false; return false;
if (memcmp(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN) != 0) if (crypto_memneq(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN))
return false; return false;
return true; return true;
@ -304,6 +305,9 @@ int seg6_hmac_info_add(struct net *net, u32 key, struct seg6_hmac_info *hinfo)
struct seg6_pernet_data *sdata = seg6_pernet(net); struct seg6_pernet_data *sdata = seg6_pernet(net);
int err; int err;
if (!__hmac_get_algo(hinfo->alg_id))
return -EINVAL;
err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node, err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node,
rht_params); rht_params);

View File

@ -1118,7 +1118,9 @@ static bool add_addr_hmac_valid(struct mptcp_sock *msk,
return hmac == mp_opt->ahmac; return hmac == mp_opt->ahmac;
} }
/* Return false if a subflow has been reset, else return true */ /* Return false in case of error (or subflow has been reset),
* else return true.
*/
bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
{ {
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
@ -1222,7 +1224,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
mpext = skb_ext_add(skb, SKB_EXT_MPTCP); mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
if (!mpext) if (!mpext)
return true; return false;
memset(mpext, 0, sizeof(*mpext)); memset(mpext, 0, sizeof(*mpext));

View File

@ -274,6 +274,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
add_timer); add_timer);
struct mptcp_sock *msk = entry->sock; struct mptcp_sock *msk = entry->sock;
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
unsigned int timeout;
pr_debug("msk=%p\n", msk); pr_debug("msk=%p\n", msk);
@ -291,6 +292,10 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
goto out; goto out;
} }
timeout = mptcp_get_add_addr_timeout(sock_net(sk));
if (!timeout)
goto out;
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
if (!mptcp_pm_should_add_signal_addr(msk)) { if (!mptcp_pm_should_add_signal_addr(msk)) {
@ -302,7 +307,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX) if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
sk_reset_timer(sk, timer, sk_reset_timer(sk, timer,
jiffies + mptcp_get_add_addr_timeout(sock_net(sk))); jiffies + timeout);
spin_unlock_bh(&msk->pm.lock); spin_unlock_bh(&msk->pm.lock);
@ -344,6 +349,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
struct mptcp_pm_add_entry *add_entry = NULL; struct mptcp_pm_add_entry *add_entry = NULL;
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
unsigned int timeout;
lockdep_assert_held(&msk->pm.lock); lockdep_assert_held(&msk->pm.lock);
@ -353,9 +359,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk))) if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
return false; return false;
sk_reset_timer(sk, &add_entry->add_timer, goto reset_timer;
jiffies + mptcp_get_add_addr_timeout(net));
return true;
} }
add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC); add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC);
@ -369,8 +373,10 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
add_entry->retrans_times = 0; add_entry->retrans_times = 0;
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0); timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
sk_reset_timer(sk, &add_entry->add_timer, reset_timer:
jiffies + mptcp_get_add_addr_timeout(net)); timeout = mptcp_get_add_addr_timeout(net);
if (timeout)
sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
return true; return true;
} }

View File

@ -1085,7 +1085,6 @@ static void __flush_addrs(struct list_head *list)
static void __reset_counters(struct pm_nl_pernet *pernet) static void __reset_counters(struct pm_nl_pernet *pernet)
{ {
WRITE_ONCE(pernet->add_addr_signal_max, 0); WRITE_ONCE(pernet->add_addr_signal_max, 0);
WRITE_ONCE(pernet->add_addr_accept_max, 0);
WRITE_ONCE(pernet->local_addr_max, 0); WRITE_ONCE(pernet->local_addr_max, 0);
pernet->addrs = 0; pernet->addrs = 0;
} }

View File

@ -1750,7 +1750,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
ktime_t now = ktime_get(); ktime_t now = ktime_get();
struct cake_tin_data *b; struct cake_tin_data *b;
struct cake_flow *flow; struct cake_flow *flow;
u32 idx; u32 idx, tin;
/* choose flow to insert into */ /* choose flow to insert into */
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret); idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
@ -1760,6 +1760,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
__qdisc_drop(skb, to_free); __qdisc_drop(skb, to_free);
return ret; return ret;
} }
tin = (u32)(b - q->tins);
idx--; idx--;
flow = &b->flows[idx]; flow = &b->flows[idx];
@ -1927,13 +1928,22 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->buffer_max_used = q->buffer_used; q->buffer_max_used = q->buffer_used;
if (q->buffer_used > q->buffer_limit) { if (q->buffer_used > q->buffer_limit) {
bool same_flow = false;
u32 dropped = 0; u32 dropped = 0;
u32 drop_id;
while (q->buffer_used > q->buffer_limit) { while (q->buffer_used > q->buffer_limit) {
dropped++; dropped++;
cake_drop(sch, to_free); drop_id = cake_drop(sch, to_free);
if ((drop_id >> 16) == tin &&
(drop_id & 0xFFFF) == idx)
same_flow = true;
} }
b->drop_overlimit += dropped; b->drop_overlimit += dropped;
if (same_flow)
return NET_XMIT_CN;
} }
return NET_XMIT_SUCCESS; return NET_XMIT_SUCCESS;
} }

View File

@ -101,9 +101,9 @@ static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
static int codel_change(struct Qdisc *sch, struct nlattr *opt, static int codel_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct codel_sched_data *q = qdisc_priv(sch); struct codel_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_CODEL_MAX + 1]; struct nlattr *tb[TCA_CODEL_MAX + 1];
unsigned int qlen, dropped = 0;
int err; int err;
err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt, err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt,
@ -142,15 +142,17 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt,
WRITE_ONCE(q->params.ecn, WRITE_ONCE(q->params.ecn,
!!nla_get_u32(tb[TCA_CODEL_ECN])); !!nla_get_u32(tb[TCA_CODEL_ECN]));
qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, true); struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb); if (!skb)
qdisc_qstats_backlog_dec(sch, skb); break;
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_qdisc_drop(skb, sch); rtnl_qdisc_drop(skb, sch);
} }
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); sch_tree_unlock(sch);
return 0; return 0;

View File

@ -927,7 +927,8 @@ static int dualpi2_init(struct Qdisc *sch, struct nlattr *opt,
q->sch = sch; q->sch = sch;
dualpi2_reset_default(sch); dualpi2_reset_default(sch);
hrtimer_setup(&q->pi2_timer, dualpi2_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); hrtimer_setup(&q->pi2_timer, dualpi2_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_ABS_PINNED_SOFT);
if (opt && nla_len(opt)) { if (opt && nla_len(opt)) {
err = dualpi2_change(sch, opt, extack); err = dualpi2_change(sch, opt, extack);
@ -937,7 +938,7 @@ static int dualpi2_init(struct Qdisc *sch, struct nlattr *opt,
} }
hrtimer_start(&q->pi2_timer, next_pi2_timeout(q), hrtimer_start(&q->pi2_timer, next_pi2_timeout(q),
HRTIMER_MODE_ABS_PINNED); HRTIMER_MODE_ABS_PINNED_SOFT);
return 0; return 0;
} }

View File

@ -1013,11 +1013,11 @@ static int fq_load_priomap(struct fq_sched_data *q,
static int fq_change(struct Qdisc *sch, struct nlattr *opt, static int fq_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct fq_sched_data *q = qdisc_priv(sch); struct fq_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_FQ_MAX + 1]; struct nlattr *tb[TCA_FQ_MAX + 1];
int err, drop_count = 0;
unsigned drop_len = 0;
u32 fq_log; u32 fq_log;
int err;
err = nla_parse_nested_deprecated(tb, TCA_FQ_MAX, opt, fq_policy, err = nla_parse_nested_deprecated(tb, TCA_FQ_MAX, opt, fq_policy,
NULL); NULL);
@ -1135,16 +1135,18 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
err = fq_resize(sch, fq_log); err = fq_resize(sch, fq_log);
sch_tree_lock(sch); sch_tree_lock(sch);
} }
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, false); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
if (!skb) if (!skb)
break; break;
drop_len += qdisc_pkt_len(skb);
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);
drop_count++;
} }
qdisc_tree_reduce_backlog(sch, drop_count, drop_len); qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); sch_tree_unlock(sch);
return err; return err;

View File

@ -366,6 +366,7 @@ static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct fq_codel_sched_data *q = qdisc_priv(sch); struct fq_codel_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_FQ_CODEL_MAX + 1]; struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
u32 quantum = 0; u32 quantum = 0;
@ -443,13 +444,14 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
q->memory_usage > q->memory_limit) { q->memory_usage > q->memory_limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, false); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
q->cstats.drop_len += qdisc_pkt_len(skb); if (!skb)
break;
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);
q->cstats.drop_count++;
} }
qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len); qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
q->cstats.drop_count = 0;
q->cstats.drop_len = 0;
sch_tree_unlock(sch); sch_tree_unlock(sch);
return 0; return 0;

View File

@ -287,10 +287,9 @@ begin:
static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct fq_pie_sched_data *q = qdisc_priv(sch); struct fq_pie_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_FQ_PIE_MAX + 1]; struct nlattr *tb[TCA_FQ_PIE_MAX + 1];
unsigned int len_dropped = 0;
unsigned int num_dropped = 0;
int err; int err;
err = nla_parse_nested(tb, TCA_FQ_PIE_MAX, opt, fq_pie_policy, extack); err = nla_parse_nested(tb, TCA_FQ_PIE_MAX, opt, fq_pie_policy, extack);
@ -368,11 +367,14 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, false); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
len_dropped += qdisc_pkt_len(skb); if (!skb)
num_dropped += 1; break;
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);
} }
qdisc_tree_reduce_backlog(sch, num_dropped, len_dropped); qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); sch_tree_unlock(sch);
return 0; return 0;

View File

@ -508,9 +508,9 @@ static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = {
static int hhf_change(struct Qdisc *sch, struct nlattr *opt, static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct hhf_sched_data *q = qdisc_priv(sch); struct hhf_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_HHF_MAX + 1]; struct nlattr *tb[TCA_HHF_MAX + 1];
unsigned int qlen, prev_backlog;
int err; int err;
u64 non_hh_quantum; u64 non_hh_quantum;
u32 new_quantum = q->quantum; u32 new_quantum = q->quantum;
@ -561,15 +561,17 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
usecs_to_jiffies(us)); usecs_to_jiffies(us));
} }
qlen = sch->q.qlen;
prev_backlog = sch->qstats.backlog;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, false); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
if (!skb)
break;
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);
} }
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
prev_backlog - sch->qstats.backlog);
sch_tree_unlock(sch); sch_tree_unlock(sch);
return 0; return 0;

View File

@ -592,7 +592,7 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
*/ */
static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) static inline void htb_activate(struct htb_sched *q, struct htb_class *cl)
{ {
WARN_ON(cl->level || !cl->leaf.q || !cl->leaf.q->q.qlen); WARN_ON(cl->level || !cl->leaf.q);
if (!cl->prio_activity) { if (!cl->prio_activity) {
cl->prio_activity = 1 << cl->prio; cl->prio_activity = 1 << cl->prio;

View File

@ -141,9 +141,9 @@ static const struct nla_policy pie_policy[TCA_PIE_MAX + 1] = {
static int pie_change(struct Qdisc *sch, struct nlattr *opt, static int pie_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
unsigned int dropped_pkts = 0, dropped_bytes = 0;
struct pie_sched_data *q = qdisc_priv(sch); struct pie_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_PIE_MAX + 1]; struct nlattr *tb[TCA_PIE_MAX + 1];
unsigned int qlen, dropped = 0;
int err; int err;
err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy, err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy,
@ -193,15 +193,17 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt,
nla_get_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR])); nla_get_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR]));
/* Drop excess packets if new limit is lower */ /* Drop excess packets if new limit is lower */
qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = qdisc_dequeue_internal(sch, true); struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb); if (!skb)
qdisc_qstats_backlog_dec(sch, skb); break;
dropped_pkts++;
dropped_bytes += qdisc_pkt_len(skb);
rtnl_qdisc_drop(skb, sch); rtnl_qdisc_drop(skb, sch);
} }
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);
sch_tree_unlock(sch); sch_tree_unlock(sch);
return 0; return 0;

View File

@ -2568,8 +2568,9 @@ static void smc_listen_work(struct work_struct *work)
goto out_decl; goto out_decl;
} }
smc_listen_out_connected(new_smc);
SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini); SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini);
/* smc_listen_out() will release smcsk */
smc_listen_out_connected(new_smc);
goto out_free; goto out_free;
out_unlock: out_unlock:

View File

@ -1808,6 +1808,9 @@ int decrypt_skb(struct sock *sk, struct scatterlist *sgout)
return tls_decrypt_sg(sk, NULL, sgout, &darg); return tls_decrypt_sg(sk, NULL, sgout, &darg);
} }
/* All records returned from a recvmsg() call must have the same type.
* 0 is not a valid content type. Use it as "no type reported, yet".
*/
static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm, static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm,
u8 *control) u8 *control)
{ {
@ -2051,8 +2054,10 @@ int tls_sw_recvmsg(struct sock *sk,
if (err < 0) if (err < 0)
goto end; goto end;
/* process_rx_list() will set @control if it processed any records */
copied = err; copied = err;
if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more) if (len <= copied || rx_more ||
(control && control != TLS_RECORD_TYPE_DATA))
goto end; goto end;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);

View File

@ -10,7 +10,8 @@ TEST_PROGS := \
mode-2-recovery-updelay.sh \ mode-2-recovery-updelay.sh \
bond_options.sh \ bond_options.sh \
bond-eth-type-change.sh \ bond-eth-type-change.sh \
bond_macvlan_ipvlan.sh bond_macvlan_ipvlan.sh \
bond_passive_lacp.sh
TEST_FILES := \ TEST_FILES := \
lag_lib.sh \ lag_lib.sh \

View File

@ -0,0 +1,105 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Test if a bond interface works with lacp_active=off.
# shellcheck disable=SC2034
REQUIRE_MZ=no
NUM_NETIFS=0
lib_dir=$(dirname "$0")
# shellcheck disable=SC1091
source "$lib_dir"/../../../net/forwarding/lib.sh
# shellcheck disable=SC2317
check_port_state()
{
local netns=$1
local port=$2
local state=$3
ip -n "${netns}" -d -j link show "$port" | \
jq -e ".[].linkinfo.info_slave_data.ad_actor_oper_port_state_str | index(\"${state}\") != null" > /dev/null
}
check_pkt_count()
{
RET=0
local ns="$1"
local iface="$2"
# wait 65s, one per 30s
slowwait_for_counter 65 2 tc_rule_handle_stats_get \
"dev ${iface} egress" 101 ".packets" "-n ${ns}" &> /dev/null
}
setup() {
setup_ns c_ns s_ns
# shellcheck disable=SC2154
ip -n "${c_ns}" link add eth0 type veth peer name eth0 netns "${s_ns}"
ip -n "${c_ns}" link add eth1 type veth peer name eth1 netns "${s_ns}"
# Add tc filter to count the pkts
tc -n "${c_ns}" qdisc add dev eth0 clsact
tc -n "${c_ns}" filter add dev eth0 egress handle 101 protocol 0x8809 matchall action pass
tc -n "${s_ns}" qdisc add dev eth1 clsact
tc -n "${s_ns}" filter add dev eth1 egress handle 101 protocol 0x8809 matchall action pass
ip -n "${s_ns}" link add bond0 type bond mode 802.3ad lacp_active on lacp_rate fast
ip -n "${s_ns}" link set eth0 master bond0
ip -n "${s_ns}" link set eth1 master bond0
ip -n "${c_ns}" link add bond0 type bond mode 802.3ad lacp_active off lacp_rate fast
ip -n "${c_ns}" link set eth0 master bond0
ip -n "${c_ns}" link set eth1 master bond0
}
trap cleanup_all_ns EXIT
setup
# The bond will send 2 lacpdu pkts during init time, let's wait at least 2s
# after interface up
ip -n "${c_ns}" link set bond0 up
sleep 2
# 1. The passive side shouldn't send LACPDU.
check_pkt_count "${c_ns}" "eth0" && RET=1
log_test "802.3ad lacp_active off" "init port"
ip -n "${s_ns}" link set bond0 up
# 2. The passive side should not have the 'active' flag.
RET=0
slowwait 2 check_port_state "${c_ns}" "eth0" "active" && RET=1
log_test "802.3ad lacp_active off" "port state active"
# 3. The active side should have the 'active' flag.
RET=0
slowwait 2 check_port_state "${s_ns}" "eth0" "active" || RET=1
log_test "802.3ad lacp_active on" "port state active"
# 4. Make sure the connection is not expired.
RET=0
slowwait 5 check_port_state "${s_ns}" "eth0" "distributing"
slowwait 10 check_port_state "${s_ns}" "eth0" "expired" && RET=1
log_test "bond 802.3ad lacp_active off" "port connection"
# After testing, disconnect one port on each side to check the state.
ip -n "${s_ns}" link set eth0 nomaster
ip -n "${s_ns}" link set eth0 up
ip -n "${c_ns}" link set eth1 nomaster
ip -n "${c_ns}" link set eth1 up
# Due to Periodic Machine and Rx Machine state change, the bond will still
# send lacpdu pkts in a few seconds. sleep at lease 5s to make sure
# negotiation finished
sleep 5
# 5. The active side should keep sending LACPDU.
check_pkt_count "${s_ns}" "eth1" || RET=1
log_test "bond 802.3ad lacp_active on" "port pkt after disconnect"
# 6. The passive side shouldn't send LACPDU anymore.
check_pkt_count "${c_ns}" "eth0" && RET=1
log_test "bond 802.3ad lacp_active off" "port pkt after disconnect"
exit "$EXIT_STATUS"

View File

@ -6,6 +6,7 @@ CONFIG_MACVLAN=y
CONFIG_IPVLAN=y CONFIG_IPVLAN=y
CONFIG_NET_ACT_GACT=y CONFIG_NET_ACT_GACT=y
CONFIG_NET_CLS_FLOWER=y CONFIG_NET_CLS_FLOWER=y
CONFIG_NET_CLS_MATCHALL=m
CONFIG_NET_SCH_INGRESS=y CONFIG_NET_SCH_INGRESS=y
CONFIG_NLMON=y CONFIG_NLMON=y
CONFIG_VETH=y CONFIG_VETH=y

View File

@ -18,6 +18,8 @@
# | 2001:db8:1::1/64 2001:db8:2::1/64 | # | 2001:db8:1::1/64 2001:db8:2::1/64 |
# | | # | |
# +-----------------------------------------------------------------+ # +-----------------------------------------------------------------+
#
#shellcheck disable=SC2034 # SC doesn't see our uses of global variables
ALL_TESTS=" ALL_TESTS="
ping_ipv4 ping_ipv4
@ -27,6 +29,7 @@ ALL_TESTS="
ipv4_sip_equal_dip ipv4_sip_equal_dip
ipv6_sip_equal_dip ipv6_sip_equal_dip
ipv4_dip_link_local ipv4_dip_link_local
ipv4_sip_link_local
" "
NUM_NETIFS=4 NUM_NETIFS=4
@ -330,6 +333,32 @@ ipv4_dip_link_local()
tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
} }
ipv4_sip_link_local()
{
local sip=169.254.1.1
RET=0
# Disable rpfilter to prevent packets to be dropped because of it.
sysctl_set net.ipv4.conf.all.rp_filter 0
sysctl_set net.ipv4.conf."$rp1".rp_filter 0
tc filter add dev "$rp2" egress protocol ip pref 1 handle 101 \
flower src_ip "$sip" action pass
$MZ "$h1" -t udp "sp=54321,dp=12345" -c 5 -d 1msec -b "$rp1mac" \
-A "$sip" -B 198.51.100.2 -q
tc_check_packets "dev $rp2 egress" 101 5
check_err $? "Packets were dropped"
log_test "IPv4 source IP is link-local"
tc filter del dev "$rp2" egress protocol ip pref 1 handle 101 flower
sysctl_restore net.ipv4.conf."$rp1".rp_filter
sysctl_restore net.ipv4.conf.all.rp_filter
}
trap cleanup EXIT trap cleanup EXIT
setup_prepare setup_prepare

View File

@ -183,9 +183,10 @@ static void xgetaddrinfo(const char *node, const char *service,
struct addrinfo *hints, struct addrinfo *hints,
struct addrinfo **res) struct addrinfo **res)
{ {
again: int err;
int err = getaddrinfo(node, service, hints, res);
again:
err = getaddrinfo(node, service, hints, res);
if (err) { if (err) {
const char *errstr; const char *errstr;

View File

@ -75,9 +75,10 @@ static void xgetaddrinfo(const char *node, const char *service,
struct addrinfo *hints, struct addrinfo *hints,
struct addrinfo **res) struct addrinfo **res)
{ {
again: int err;
int err = getaddrinfo(node, service, hints, res);
again:
err = getaddrinfo(node, service, hints, res);
if (err) { if (err) {
const char *errstr; const char *errstr;

View File

@ -3842,6 +3842,7 @@ endpoint_tests()
# remove and re-add # remove and re-add
if reset_with_events "delete re-add signal" && if reset_with_events "delete re-add signal" &&
mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=0
pm_nl_set_limits $ns1 0 3 pm_nl_set_limits $ns1 0 3
pm_nl_set_limits $ns2 3 3 pm_nl_set_limits $ns2 3 3
pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal

View File

@ -162,9 +162,10 @@ static void xgetaddrinfo(const char *node, const char *service,
struct addrinfo *hints, struct addrinfo *hints,
struct addrinfo **res) struct addrinfo **res)
{ {
again: int err;
int err = getaddrinfo(node, service, hints, res);
again:
err = getaddrinfo(node, service, hints, res);
if (err) { if (err) {
const char *errstr; const char *errstr;

View File

@ -198,6 +198,7 @@ set_limits 1 9 2>/dev/null
check "get_limits" "${default_limits}" "subflows above hard limit" check "get_limits" "${default_limits}" "subflows above hard limit"
set_limits 8 8 set_limits 8 8
flush_endpoint ## to make sure it doesn't affect the limits
check "get_limits" "$(format_limits 8 8)" "set limits" check "get_limits" "$(format_limits 8 8)" "set limits"
flush_endpoint flush_endpoint

View File

@ -181,13 +181,12 @@ static int tls_send_cmsg(int fd, unsigned char record_type,
return sendmsg(fd, &msg, flags); return sendmsg(fd, &msg, flags);
} }
static int tls_recv_cmsg(struct __test_metadata *_metadata, static int __tls_recv_cmsg(struct __test_metadata *_metadata,
int fd, unsigned char record_type, int fd, unsigned char *ctype,
void *data, size_t len, int flags) void *data, size_t len, int flags)
{ {
char cbuf[CMSG_SPACE(sizeof(char))]; char cbuf[CMSG_SPACE(sizeof(char))];
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
unsigned char ctype;
struct msghdr msg; struct msghdr msg;
struct iovec vec; struct iovec vec;
int n; int n;
@ -206,7 +205,20 @@ static int tls_recv_cmsg(struct __test_metadata *_metadata,
EXPECT_NE(cmsg, NULL); EXPECT_NE(cmsg, NULL);
EXPECT_EQ(cmsg->cmsg_level, SOL_TLS); EXPECT_EQ(cmsg->cmsg_level, SOL_TLS);
EXPECT_EQ(cmsg->cmsg_type, TLS_GET_RECORD_TYPE); EXPECT_EQ(cmsg->cmsg_type, TLS_GET_RECORD_TYPE);
ctype = *((unsigned char *)CMSG_DATA(cmsg)); if (ctype)
*ctype = *((unsigned char *)CMSG_DATA(cmsg));
return n;
}
static int tls_recv_cmsg(struct __test_metadata *_metadata,
int fd, unsigned char record_type,
void *data, size_t len, int flags)
{
unsigned char ctype;
int n;
n = __tls_recv_cmsg(_metadata, fd, &ctype, data, len, flags);
EXPECT_EQ(ctype, record_type); EXPECT_EQ(ctype, record_type);
return n; return n;
@ -2164,6 +2176,284 @@ TEST_F(tls, rekey_poll_delay)
} }
} }
struct raw_rec {
unsigned int plain_len;
unsigned char plain_data[100];
unsigned int cipher_len;
unsigned char cipher_data[128];
};
/* TLS 1.2, AES_CCM, data, seqno:0, plaintext: 'Hello world' */
static const struct raw_rec id0_data_l11 = {
.plain_len = 11,
.plain_data = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f,
0x72, 0x6c, 0x64,
},
.cipher_len = 40,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xa2, 0x33,
0xde, 0x8d, 0x94, 0xf0, 0x29, 0x6c, 0xb1, 0xaf,
0x6a, 0x75, 0xb2, 0x93, 0xad, 0x45, 0xd5, 0xfd,
0x03, 0x51, 0x57, 0x8f, 0xf9, 0xcc, 0x3b, 0x42,
},
};
/* TLS 1.2, AES_CCM, ctrl, seqno:0, plaintext: '' */
static const struct raw_rec id0_ctrl_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x16, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x38, 0x7b,
0xa6, 0x1c, 0xdd, 0xa7, 0x19, 0x33, 0xab, 0xae,
0x88, 0xe1, 0xd2, 0x08, 0x4f,
},
};
/* TLS 1.2, AES_CCM, data, seqno:0, plaintext: '' */
static const struct raw_rec id0_data_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x37, 0x90,
0x70, 0x45, 0x89, 0xfb, 0x5c, 0xc7, 0x89, 0x03,
0x68, 0x80, 0xd3, 0xd8, 0xcc,
},
};
/* TLS 1.2, AES_CCM, data, seqno:1, plaintext: 'Hello world' */
static const struct raw_rec id1_data_l11 = {
.plain_len = 11,
.plain_data = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f,
0x72, 0x6c, 0x64,
},
.cipher_len = 40,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x1a, 0x9c,
0xd0, 0xa8, 0x9a, 0xd6, 0x69, 0xd6, 0x1a, 0xe3,
0xb5, 0x1f, 0x0d, 0x2c, 0xe2, 0x97, 0x46, 0xff,
0x2b, 0xcc, 0x5a, 0xc4, 0xa3, 0xb9, 0xef, 0xba,
},
};
/* TLS 1.2, AES_CCM, ctrl, seqno:1, plaintext: '' */
static const struct raw_rec id1_ctrl_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x16, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x3e, 0xf0, 0xfe,
0xee, 0xd9, 0xe2, 0x5d, 0xc7, 0x11, 0x4c, 0xe6,
0xb4, 0x7e, 0xef, 0x40, 0x2b,
},
};
/* TLS 1.2, AES_CCM, data, seqno:1, plaintext: '' */
static const struct raw_rec id1_data_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xce, 0xfc, 0x86,
0xc8, 0xf0, 0x55, 0xf9, 0x47, 0x3f, 0x74, 0xdc,
0xc9, 0xbf, 0xfe, 0x5b, 0xb1,
},
};
/* TLS 1.2, AES_CCM, ctrl, seqno:2, plaintext: 'Hello world' */
static const struct raw_rec id2_ctrl_l11 = {
.plain_len = 11,
.plain_data = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f,
0x72, 0x6c, 0x64,
},
.cipher_len = 40,
.cipher_data = {
0x16, 0x03, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xe5, 0x3d, 0x19,
0x3d, 0xca, 0xb8, 0x16, 0xb6, 0xff, 0x79, 0x87,
0x2a, 0x04, 0x11, 0x3d, 0xf8, 0x64, 0x5f, 0x36,
0x8b, 0xa8, 0xee, 0x4c, 0x6d, 0x62, 0xa5, 0x00,
},
};
/* TLS 1.2, AES_CCM, data, seqno:2, plaintext: 'Hello world' */
static const struct raw_rec id2_data_l11 = {
.plain_len = 11,
.plain_data = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f,
0x72, 0x6c, 0x64,
},
.cipher_len = 40,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xe5, 0x3d, 0x19,
0x3d, 0xca, 0xb8, 0x16, 0xb6, 0xff, 0x79, 0x87,
0x8e, 0xa1, 0xd0, 0xcd, 0x33, 0xb5, 0x86, 0x2b,
0x17, 0xf1, 0x52, 0x2a, 0x55, 0x62, 0x65, 0x11,
},
};
/* TLS 1.2, AES_CCM, ctrl, seqno:2, plaintext: '' */
static const struct raw_rec id2_ctrl_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x16, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xdc, 0x5c, 0x0e,
0x41, 0xdd, 0xba, 0xd3, 0xcc, 0xcf, 0x6d, 0xd9,
0x06, 0xdb, 0x79, 0xe5, 0x5d,
},
};
/* TLS 1.2, AES_CCM, data, seqno:2, plaintext: '' */
static const struct raw_rec id2_data_l0 = {
.plain_len = 0,
.plain_data = {
},
.cipher_len = 29,
.cipher_data = {
0x17, 0x03, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xc3, 0xca, 0x26,
0x22, 0xe4, 0x25, 0xfb, 0x5f, 0x6d, 0xbf, 0x83,
0x30, 0x48, 0x69, 0x1a, 0x47,
},
};
FIXTURE(zero_len)
{
int fd, cfd;
bool notls;
};
FIXTURE_VARIANT(zero_len)
{
const struct raw_rec *recs[4];
ssize_t recv_ret[4];
};
FIXTURE_VARIANT_ADD(zero_len, data_data_data)
{
.recs = { &id0_data_l11, &id1_data_l11, &id2_data_l11, },
.recv_ret = { 33, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, data_0ctrl_data)
{
.recs = { &id0_data_l11, &id1_ctrl_l0, &id2_data_l11, },
.recv_ret = { 11, 0, 11, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, 0data_0data_0data)
{
.recs = { &id0_data_l0, &id1_data_l0, &id2_data_l0, },
.recv_ret = { -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, 0data_0data_ctrl)
{
.recs = { &id0_data_l0, &id1_data_l0, &id2_ctrl_l11, },
.recv_ret = { 0, 11, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, 0data_0data_0ctrl)
{
.recs = { &id0_data_l0, &id1_data_l0, &id2_ctrl_l0, },
.recv_ret = { 0, 0, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, 0ctrl_0ctrl_0ctrl)
{
.recs = { &id0_ctrl_l0, &id1_ctrl_l0, &id2_ctrl_l0, },
.recv_ret = { 0, 0, 0, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, 0data_0data_data)
{
.recs = { &id0_data_l0, &id1_data_l0, &id2_data_l11, },
.recv_ret = { 11, -EAGAIN, },
};
FIXTURE_VARIANT_ADD(zero_len, data_0data_0data)
{
.recs = { &id0_data_l11, &id1_data_l0, &id2_data_l0, },
.recv_ret = { 11, -EAGAIN, },
};
FIXTURE_SETUP(zero_len)
{
struct tls_crypto_info_keys tls12;
int ret;
tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_CCM_128,
&tls12, 0);
ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls);
if (self->notls)
return;
/* Don't install keys on fd, we'll send raw records */
ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len);
ASSERT_EQ(ret, 0);
}
FIXTURE_TEARDOWN(zero_len)
{
close(self->fd);
close(self->cfd);
}
TEST_F(zero_len, test)
{
const struct raw_rec *const *rec;
unsigned char buf[128];
int rec_off;
int i;
for (i = 0; i < 4 && variant->recs[i]; i++)
EXPECT_EQ(send(self->fd, variant->recs[i]->cipher_data,
variant->recs[i]->cipher_len, 0),
variant->recs[i]->cipher_len);
rec = &variant->recs[0];
rec_off = 0;
for (i = 0; i < 4; i++) {
int j, ret;
ret = variant->recv_ret[i] >= 0 ? variant->recv_ret[i] : -1;
EXPECT_EQ(__tls_recv_cmsg(_metadata, self->cfd, NULL,
buf, sizeof(buf), MSG_DONTWAIT), ret);
if (ret == -1)
EXPECT_EQ(errno, -variant->recv_ret[i]);
if (variant->recv_ret[i] == -EAGAIN)
break;
for (j = 0; j < ret; j++) {
while (rec_off == (*rec)->plain_len) {
rec++;
rec_off = 0;
}
EXPECT_EQ(buf[j], (*rec)->plain_data[rec_off]);
rec_off++;
}
}
};
FIXTURE(tls_err) FIXTURE(tls_err)
{ {
int fd, cfd; int fd, cfd;
@ -2748,17 +3038,18 @@ TEST(data_steal) {
pid = fork(); pid = fork();
ASSERT_GE(pid, 0); ASSERT_GE(pid, 0);
if (!pid) { if (!pid) {
EXPECT_EQ(recv(cfd, buf, sizeof(buf), MSG_WAITALL), EXPECT_EQ(recv(cfd, buf, sizeof(buf) / 2, MSG_WAITALL),
sizeof(buf)); sizeof(buf) / 2);
exit(!__test_passed(_metadata)); exit(!__test_passed(_metadata));
} }
usleep(2000); usleep(10000);
ASSERT_EQ(setsockopt(fd, SOL_TLS, TLS_TX, &tls, tls.len), 0); ASSERT_EQ(setsockopt(fd, SOL_TLS, TLS_TX, &tls, tls.len), 0);
ASSERT_EQ(setsockopt(cfd, SOL_TLS, TLS_RX, &tls, tls.len), 0); ASSERT_EQ(setsockopt(cfd, SOL_TLS, TLS_RX, &tls, tls.len), 0);
EXPECT_EQ(send(fd, buf, sizeof(buf), 0), sizeof(buf)); EXPECT_EQ(send(fd, buf, sizeof(buf), 0), sizeof(buf));
usleep(2000); EXPECT_EQ(wait(&status), pid);
EXPECT_EQ(status, 0);
EXPECT_EQ(recv(cfd, buf2, sizeof(buf2), MSG_DONTWAIT), -1); EXPECT_EQ(recv(cfd, buf2, sizeof(buf2), MSG_DONTWAIT), -1);
/* Don't check errno, the error will be different depending /* Don't check errno, the error will be different depending
* on what random bytes TLS interpreted as the record length. * on what random bytes TLS interpreted as the record length.
@ -2766,9 +3057,6 @@ TEST(data_steal) {
close(fd); close(fd);
close(cfd); close(cfd);
EXPECT_EQ(wait(&status), pid);
EXPECT_EQ(status, 0);
} }
static void __attribute__((constructor)) fips_check(void) { static void __attribute__((constructor)) fips_check(void) {

View File

@ -185,6 +185,204 @@
"$IP addr del 10.10.10.10/24 dev $DUMMY || true" "$IP addr del 10.10.10.10/24 dev $DUMMY || true"
] ]
}, },
{
"id": "34c0",
"name": "Test TBF with HHF Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"hhf"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 hhf limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 hhf limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "fd68",
"name": "Test TBF with CODEL Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"codel"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 codel limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 codel limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "514e",
"name": "Test TBF with PIE Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"pie"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 pie limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 pie limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "6c97",
"name": "Test TBF with FQ Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"fq"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 fq limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 fq limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "5d0b",
"name": "Test TBF with FQ_CODEL Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"fq_codel"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 fq_codel limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 fq_codel limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{
"id": "21c3",
"name": "Test TBF with FQ_PIE Backlog Accounting in gso_skb case against underflow",
"category": [
"qdisc",
"tbf",
"fq_pie"
],
"plugins": {
"requires": [
"nsPlugin"
]
},
"setup": [
"$IP link set dev $DUMMY up || true",
"$IP addr add 10.10.11.10/24 dev $DUMMY || true",
"$TC qdisc add dev $DUMMY root handle 1: tbf rate 8bit burst 100b latency 100ms",
"$TC qdisc replace dev $DUMMY handle 2: parent 1:1 fq_pie limit 1000",
[
"ping -I $DUMMY -c2 10.10.11.11",
1
],
"$TC qdisc change dev $DUMMY handle 2: parent 1:1 fq_pie limit 1"
],
"cmdUnderTest": "$TC qdisc del dev $DUMMY handle 2: parent 1:1",
"expExitCode": "0",
"verifyCmd": "$TC -s qdisc show dev $DUMMY",
"matchPattern": "backlog 0b 0p",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
},
{ {
"id": "a4bb", "id": "a4bb",
"name": "Test FQ_CODEL with HTB parent - force packet drop with empty queue", "name": "Test FQ_CODEL with HTB parent - force packet drop with empty queue",