Bluetooth: controller: Thread-safe local RPA access
In order to make sure that the ISR never gets an incomplete or partial local RPA, use pointers to share the local RPA between thread mode and ISRs. Pointer updates are guaranteed to be atomic at least on ARM Cortex-M. Additionally add support for using local RPAs when initiating a connection or sending a scan request. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
a260d6face
commit
296b469c40
3 changed files with 52 additions and 23 deletions
|
@ -1225,16 +1225,20 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
pdu_adv_tx->rx_addr = pdu_adv_rx->tx_addr;
|
||||
pdu_adv_tx->len = sizeof(struct pdu_adv_payload_connect_ind);
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
/*@todo: obtain RPA based on rl_idx if rl_idx != NONE and
|
||||
* own address > 0x01 */
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
if (_radio.scanner.rpa_gen && rl_idx != FILTER_IDX_NONE) {
|
||||
bt_addr_t *lrpa = ctrl_lrpa_get(rl_idx);
|
||||
LL_ASSERT(lrpa);
|
||||
pdu_adv_tx->tx_addr = 1;
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||
lrpa->val, BDADDR_SIZE);
|
||||
} else {
|
||||
#else
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
if (1) {
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
}
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.adv_addr[0],
|
||||
&pdu_adv_rx->payload.adv_ind.addr[0], BDADDR_SIZE);
|
||||
memcpy(&pdu_adv_tx->payload.connect_ind.lldata.
|
||||
|
@ -1437,16 +1441,20 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
pdu_adv_tx->rx_addr = pdu_adv_rx->tx_addr;
|
||||
pdu_adv_tx->len = sizeof(struct pdu_adv_payload_scan_req);
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
/*@todo: obtain RPA based on rl_idx if rl_idx != NONE and
|
||||
* own address > 0x01 */
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.scan_req.scan_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
if (_radio.scanner.rpa_gen && rl_idx != FILTER_IDX_NONE) {
|
||||
bt_addr_t *lrpa = ctrl_lrpa_get(rl_idx);
|
||||
LL_ASSERT(lrpa);
|
||||
pdu_adv_tx->tx_addr = 1;
|
||||
memcpy(&pdu_adv_tx->payload.scan_req.adv_addr[0],
|
||||
lrpa->val, BDADDR_SIZE);
|
||||
} else {
|
||||
#else
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.scan_req.scan_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
#endif
|
||||
if (1) {
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
pdu_adv_tx->tx_addr = _radio.scanner.init_addr_type;
|
||||
memcpy(&pdu_adv_tx->payload.scan_req.scan_addr[0],
|
||||
&_radio.scanner.init_addr[0], BDADDR_SIZE);
|
||||
}
|
||||
memcpy(&pdu_adv_tx->payload.scan_req.adv_addr[0],
|
||||
&pdu_adv_rx->payload.adv_ind.addr[0], BDADDR_SIZE);
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ u8_t wl_anon;
|
|||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
#include "common/rpa.h"
|
||||
|
||||
|
||||
/* Whitelist peer list */
|
||||
static struct {
|
||||
u8_t taken:1;
|
||||
|
@ -57,7 +56,7 @@ static struct rl_dev {
|
|||
u8_t local_irk[16];
|
||||
u8_t pirk_idx;
|
||||
bt_addr_t peer_rpa;
|
||||
bt_addr_t local_rpa;
|
||||
bt_addr_t *local_rpa;
|
||||
|
||||
} rl[CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE];
|
||||
|
||||
|
@ -65,6 +64,8 @@ static u8_t peer_irks[CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE][16];
|
|||
static u8_t peer_irk_rl_ids[CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE];
|
||||
static u8_t peer_irk_count;
|
||||
|
||||
static bt_addr_t local_rpas[CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE];
|
||||
|
||||
BUILD_ASSERT(ARRAY_SIZE(wl) < FILTER_IDX_NONE);
|
||||
BUILD_ASSERT(ARRAY_SIZE(rl) < FILTER_IDX_NONE);
|
||||
|
||||
|
@ -215,6 +216,16 @@ static u32_t filter_remove(struct ll_filter *filter, u8_t addr_type,
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
bt_addr_t *ctrl_lrpa_get(u8_t rl_idx)
|
||||
{
|
||||
LL_ASSERT(rl_idx < ARRAY_SIZE(rl));
|
||||
if (!rl[rl_idx].lirk || !rl[rl_idx].rpas_ready) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rl[rl_idx].local_rpa;
|
||||
}
|
||||
|
||||
u8_t *ctrl_irks_get(u8_t *count)
|
||||
{
|
||||
*count = peer_irk_count;
|
||||
|
@ -498,7 +509,7 @@ void ll_rl_pdu_adv_update(int idx, struct pdu_adv *pdu)
|
|||
if (idx >= 0 && rl[idx].lirk) {
|
||||
LL_ASSERT(rl[idx].rpas_ready);
|
||||
pdu->tx_addr = 1;
|
||||
memcpy(adva, rl[idx].local_rpa.val, BDADDR_SIZE);
|
||||
memcpy(adva, rl[idx].local_rpa->val, BDADDR_SIZE);
|
||||
} else {
|
||||
pdu->tx_addr = ll_adv->own_addr_type & 0x1;
|
||||
ll_addr_get(ll_adv->own_addr_type & 0x1, adva);
|
||||
|
@ -608,9 +619,17 @@ void ll_rl_rpa_update(bool timeout)
|
|||
LL_ASSERT(!err);
|
||||
}
|
||||
if (rl[i].lirk) {
|
||||
err = bt_rpa_create(rl[i].local_irk,
|
||||
&rl[i].local_rpa);
|
||||
bt_addr_t rpa;
|
||||
|
||||
err = bt_rpa_create(rl[i].local_irk, &rpa);
|
||||
LL_ASSERT(!err);
|
||||
/* pointer read/write assumed to be atomic
|
||||
* so that if ISR fires the local_rpa pointer
|
||||
* will always point to a valid full RPA
|
||||
*/
|
||||
rl[i].local_rpa = &rpa;
|
||||
bt_addr_copy(&local_rpas[i], &rpa);
|
||||
rl[i].local_rpa = &local_rpas[i];
|
||||
}
|
||||
|
||||
rl[i].rpas_ready = 1;
|
||||
|
@ -713,6 +732,7 @@ u32_t ll_rl_add(bt_addr_le_t *id_addr, const u8_t pirk[16],
|
|||
}
|
||||
if (rl[i].lirk) {
|
||||
memcpy(rl[i].local_irk, lirk, 16);
|
||||
rl[i].local_rpa = NULL;
|
||||
}
|
||||
rl[i].rpas_ready = 0;
|
||||
/* Default to Network Privacy */
|
||||
|
@ -798,7 +818,7 @@ u32_t ll_rl_lrpa_get(bt_addr_le_t *id_addr, bt_addr_t *lrpa)
|
|||
/* find the device and return the local RPA */
|
||||
i = ll_rl_find(id_addr->type, id_addr->a.val, NULL);
|
||||
if (i < ARRAY_SIZE(rl)) {
|
||||
bt_addr_copy(lrpa, &rl[i].local_rpa);
|
||||
bt_addr_copy(lrpa, rl[i].local_rpa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ void ll_filters_adv_update(u8_t adv_fp);
|
|||
void ll_filters_scan_update(u8_t scan_fp);
|
||||
|
||||
struct ll_filter *ctrl_filter_get(bool whitelist);
|
||||
bt_addr_t *ctrl_lrpa_get(u8_t rl_idx);
|
||||
u8_t *ctrl_irks_get(u8_t *count);
|
||||
u8_t ctrl_rl_idx(bool whitelist, u8_t devmatch_id);
|
||||
u8_t ctrl_rl_irk_idx(u8_t irkmatch_id);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue