-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bluetooth: host: Allow concurrent advertising with multiple ids #34848
bluetooth: host: Allow concurrent advertising with multiple ids #34848
Conversation
4346318
to
38d95be
Compare
subsys/bluetooth/host/hci_core.h
Outdated
* should be processed or not. | ||
*/ | ||
bool conn_complete_received; | ||
struct bt_hci_evt_le_enh_conn_complete cached_conn_complete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this can lead to a race condition if two advertisers manage to establish a connection before the TERMINATED is received for the first one.
Should this scale by CONFIG_BT_ID_MAX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming that the race condition you are considering is in step 5 and 6 below:
- Start advertising set 0 using identity 0
- Start advertising set 1 using identity 1
- Receive LE Connection Complete for advertising set 0
- Receive LE Connection Complete for advertising set 1
- Receive LE Advertising Set terminated event for advertising set 0
- Receive LE Advertising Set terminated event for advertising set 1
If that sequence occurs, the host has no way of mapping the LE Advertising Set Terminated event to the Connection Complete event. That is, it can't map an identity to the newly established connection.
Therefore, according to errata 14871, the controller should guarantee that the Advertising Set Terminated event follows the Connection Complete event. Hence, the controller should prevent sequences like the one above from happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about the warning in hci_core:1058? will that be raised in such scenario?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this warning (https://github.com/zephyrproject-rtos/zephyr/pull/34848/files#diff-774b3de86adb275da54becf2a0958a2d4dae03d63e47840037ecc575e9d658b4R1058 ) will be printed in case the controller is raising another enhanced connection complete event before the LE Advertising Set Terminated event is processed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea of caching the connection complete event is sound I believe. Since the terminated event contains a connection handle, we can do a lookup from the adv set to the enhanced connection complete event.
The current implementation would not support the scenario above, where we receive 2 connection complete events before the advertising set terminated event, it only supports caching of one such even.
I think this could be implemented as
- Only Enchance Connection Complete Event, store the event in an array (same size as
MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_EXT_ADV_MAX_ADV_SET)
) - On Advertising Set terminated lookup the connection handle to find the matching enhanced connection complete event
- Finalize connection complete
Furthermore, I believe this PR is missing some crucial connection cancellation features, e.g. if the application stops the advertising set before advertising set terminated event, but after the connection complete event (corner case, but can still cause a desync).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Thalley , thanks for your review. I believe I've addressed your comments by doing the following:
- Checking if the advertiser is still running before processing the cached connection complete event to avoid that the application gets a connection complete callback after stopping the advertiser.
- No longer depend on the order of events from the controller. Now the host caches all events that result in a connection being established. The host will compare the connection handles in those two events in order to create the mapping. The cost is some extra RAM usage.
subsys/bluetooth/host/hci_core.h
Outdated
* should be processed or not. | ||
*/ | ||
bool conn_complete_received; | ||
struct bt_hci_evt_le_enh_conn_complete cached_conn_complete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea of caching the connection complete event is sound I believe. Since the terminated event contains a connection handle, we can do a lookup from the adv set to the enhanced connection complete event.
The current implementation would not support the scenario above, where we receive 2 connection complete events before the advertising set terminated event, it only supports caching of one such even.
I think this could be implemented as
- Only Enchance Connection Complete Event, store the event in an array (same size as
MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_EXT_ADV_MAX_ADV_SET)
) - On Advertising Set terminated lookup the connection handle to find the matching enhanced connection complete event
- Finalize connection complete
Furthermore, I believe this PR is missing some crucial connection cancellation features, e.g. if the application stops the advertising set before advertising set terminated event, but after the connection complete event (corner case, but can still cause a desync).
38d95be
to
3635534
Compare
3635534
to
6016c3d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few formatting comments.
Since this may introduce introduce issues with enhanced connections, I would be a lot happier to approve if it was accompanied by some test that validates the change.
6016c3d
to
1e71dd5
Compare
The HCI specification creates additional complexity to allow this configuration: - When a connection gets established, we need to know which identity the HCI_LE_Connection_Complete event corresponds to. - The identity is a property of the advertising set. Therefore we need the advertising handle. - The advertising handle is part of the HCI_LE_Advertising_Set_Terminated event and is not part of the HCI_LE_Connection_Complete event. Therefore the information of both events needs to be combined. By spec the LE_Connection_Complete comes first. Therefore we cache this event until the identity is available. The event is only cached when a connection gets established as that is the only case where we need to resolve the identity. As the caching requires more resources, it is only enabled if the application requires multiple advertising sets and multiple identities. The host maps the HCI_LE_Advertising_Set_Terminated event with the HCI_LE_Connection_Complete event by comparing the connection handles. Signed-off-by: Rubin Gerritsen <rubin.gerritsen@nordicsemi.no>
This will exercise caching of the HCI_LE_Connection_Complete event in the host. Signed-off-by: Rubin Gerritsen <rubin.gerritsen@nordicsemi.no>
1e71dd5
to
7b9c14b
Compare
*/ | ||
bt_hci_le_enh_conn_complete(&bt_dev.cached_conn_complete[i].evt); | ||
} | ||
bt_dev.cached_conn_complete[i].valid = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still seems that in case that the application disables the advertising set after the connection complete event is received, but before the adv terminated event, then we don't clean up the cached connection complete event, as there won't be a adv terminated event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think it's missing handling of a corner case.
@Thalley , I have thought a bit more about the race conditions you have mentioned. I'm not convinced there are race conditions that need to be handled. LE_Set_Advertising_Enable is handled synchronously, Let me try to illustrate this by providing some examples: Case 1: Adv is stopped with success:
Case 2: Adv is stopped but fails because the controller has a pending event:
Case 3: Adv is stopped after the enhanced connection complete event is processed:
Furthermore, when restarting the advertiser will not result in race conditions as the flag BT_ADV_ENABLED is cleared when processing the LE_Advertising_Set_Terminated event. Case 4: Advertiser is restared after fetching both events:
Case 5: Advertiser is restarted after fetching the first event:
From this analysis I conclude that we don't need to validate the advertiser flags when processing these events. That is, remove the check Is there something I've misunderstood or overlooked? |
You might a good point, and I think you are right that it should work. The sentence
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The HCI specification creates additional complexity to allow this
configuration:
identity the HCI_LE_Connection_Complete event corresponds to.
Therefore we need the advertising handle.
HCI_LE_Advertising_Set_Terminated event and is not part of
the HCI_LE_Connection_Complete event. Therefore
the information of both events needs to be combined.
By spec the LE_Connection_Complete comes first. Therefore we cache
this event until the identity is available.
The event is only cached when a connection gets established as
that is the only case where we need to resolve the identity.
As the caching requires more resources, it is only enabled if the
application requires multiple advertising sets and multiple
identities.
The host maps the HCI_LE_Advertising_Set_Terminated event with
the HCI_LE_Connection_Complete event by comparing the connection
handles.
Fixes: #31588