mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] Bluetooth: put the peer's on-air address on air when we cannot resolve
@ 2026-09-08 20:41 Radek Podgorny
  2026-09-09 19:40 ` patchwork-bot+bluetooth
  0 siblings, 1 reply; 2+ messages in thread
From: Radek Podgorny @ 2026-09-08 20:41 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz
  Cc: Luiz Augusto von Dentz, linux-bluetooth, linux-kernel, Radek Podgorny

An identity address only reaches a peer that is advertising an RPA if the
controller resolves it on our behalf. Where it cannot, the host has to put
the peer's on-air address on air itself.

hci_connect_le() still swaps the caller's identity address for the peer's
cached RPA before creating the connection, but __hci_conn_add() resolves
the RPA back to the identity address when it stores it, so the identity is
what goes out. Storing the identity is right when the controller
translates it on the way to the radio; without LL Privacy, or with this
peer absent from the resolving list, nothing does.

A peer advertising an RPA cannot answer its identity address, so the
attempt burns a full create-connection timeout. That is not merely a slow
connect: a controller without extended scanning cannot scan while it is
initiating, so every dead attempt also takes the scanner off the air for
the whole timeout.

Measured on a CYW43438, which reports neither LL Privacy nor extended
advertising (LE features 3f 00 00 08 00 00 00 00), against a peer
advertising a resolvable private address the host holds the IRK for, with
the connection requested on the peer's identity address:

  before: LE Create Connection to the identity address, public type
          1.61s -> 22.07s, then LE Create Connection Cancel
          LE Connection Complete: Unknown Connection Identifier (0x02)
  after:  LE Create Connection to the peer's RPA, random type
          LE Connection Complete: Success

Advertising reports reaching the host per second, same window, same five
unrelated devices on the adapter:

  before   1s:2   [nothing from 2s through 21s]   22s:5  23s:3
  after    0s:11 1s:5 2s:2 3s:5 4s:3 5s:4 ... 21s:2 22s:1 23s:2

One dead connect costs twenty seconds of scanning for every device on the
adapter, not just the one being dialled.

Keep the RPA in conn->dst unless the controller will translate the
identity address: address resolution enabled and the peer's identity
actually programmed into the resolving list. Testing ll_privacy_capable()
alone would not be enough: it reports the feature bit, not whether
resolution is switched on and not whether this peer is in the list.
Resolution is cleared with the other volatile flags on power-off and
switched off again while suspend pauses scanning, and a peer's IRK is only
programmed along the accept list path, so a direct-connect target, a peer
without HCI_CONN_FLAG_ADDRESS_RESOLUTION, and one that did not fit in a
full list are all absent from it.

With the peer programmed, the identity address stays in conn->dst and the
controller translates it: measured on an Intel controller, the host dials
the identity and LE Enhanced Connection Complete reports Resolved Public
with the peer's RPA in the separate peer resolvable private address field.
With the peer absent from the list the same setup dials the RPA itself.

Everything downstream already copes with an RPA in conn->dst: it is what
every outgoing LE connection stored before 14b06c3a88f7, the connection
complete event names the address that was dialled, and
le_conn_complete_evt() resolves it back to the identity once the link is
up. ISO links keep the unconditional conversion: they are created from an
existing ACL or a periodic sync and never dial this address themselves.

Fixes: 14b06c3a88f7 ("Bluetooth: HCI: Always use the identity address when initializing a connection")
Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radek Podgorny <radek@podgorny.cz>
---
Changes in v2:
 - Move the address choice into __hci_conn_add() rather than translating
   at the create-connection command builders, as suggested by Luiz. The
   RPA that hci_connect_le() swaps in is simply kept when the controller
   will not translate the identity address for us, which is how every
   outgoing LE connection stored it before 14b06c3a88f7.
 - Drop the "record when an IRK's RPA was last seen" patch, and with it
   the freshness window and the smp_irk change. hci_find_irk_by_rpa()
   already refreshes irk->rpa on every advertising report the host
   resolves, so the cached address is as current as the scan that led to
   the connect and no timestamp is needed.
 - One patch instead of two, so no cover letter this time.
 - Link to v1: https://lore.kernel.org/linux-bluetooth/20260908012048.3681904-2-radek@podgorny.cz/

Per Documentation/process/generated-content.rst: this was developed with
the help of the Claude coding assistant, as recorded in the Assisted-by
trailer. The prompts described the misdirected create-connection, the
btmon captures taken before and after, and Luiz's review of v1; the
assistant was asked to locate where the dialled address is chosen and to
draft the change and its commit message. The measurements, the hardware
testing and the final wording are the author's own.
---
 net/bluetooth/hci_conn.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 8de98af2fb58..c9466cb2c7c0 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1023,6 +1023,19 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type,
 		if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
 			return ERR_PTR(-ECONNREFUSED);
 		irk = hci_get_irk(hdev, dst, dst_type);
+		/* An identity address only reaches a peer advertising an RPA
+		 * if the controller translates it. Unless address resolution
+		 * is enabled and this peer is programmed into the resolving
+		 * list, keep the RPA the peer is on air with;
+		 * le_conn_complete_evt() resolves it back once the link is
+		 * up.
+		 */
+		if (irk &&
+		    (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION) ||
+		     !hci_bdaddr_list_lookup_with_irk(&hdev->le_resolv_list,
+						      &irk->bdaddr,
+						      irk->addr_type)))
+			irk = NULL;
 		break;
 	case SCO_LINK:
 	case ESCO_LINK:

---
base-commit: 701ca71884b3d101fd25b7adbf972355056ef352
change-id: 20260908-for-upstream-le-connect-on-air-addr-a796ae625007

Best regards,
--  
Radek Podgorny <radek@podgorny.cz>


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] Bluetooth: put the peer's on-air address on air when we cannot resolve
  2026-09-08 20:41 [PATCH v2] Bluetooth: put the peer's on-air address on air when we cannot resolve Radek Podgorny
@ 2026-09-09 19:40 ` patchwork-bot+bluetooth
  0 siblings, 0 replies; 2+ messages in thread
From: patchwork-bot+bluetooth @ 2026-09-09 19:40 UTC (permalink / raw)
  To: Radek Podgorny
  Cc: marcel, luiz.dentz, luiz.von.dentz, linux-bluetooth, linux-kernel

Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 08 Sep 2026 22:41:38 +0200 you wrote:
> An identity address only reaches a peer that is advertising an RPA if the
> controller resolves it on our behalf. Where it cannot, the host has to put
> the peer's on-air address on air itself.
> 
> hci_connect_le() still swaps the caller's identity address for the peer's
> cached RPA before creating the connection, but __hci_conn_add() resolves
> the RPA back to the identity address when it stores it, so the identity is
> what goes out. Storing the identity is right when the controller
> translates it on the way to the radio; without LL Privacy, or with this
> peer absent from the resolving list, nothing does.
> 
> [...]

Here is the summary with links:
  - [v2] Bluetooth: put the peer's on-air address on air when we cannot resolve
    https://git.kernel.org/bluetooth/bluetooth-next/c/e35544d23359

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-09 19:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08 20:41 [PATCH v2] Bluetooth: put the peer's on-air address on air when we cannot resolve Radek Podgorny
2026-09-09 19:40 ` patchwork-bot+bluetooth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®