Bluetooth: Defer RL update if there's an ongoing connection

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2017-10-05 22:01:55 +03:00 committed by Johan Hedberg
commit e25d925242
5 changed files with 56 additions and 12 deletions

View file

@ -731,6 +731,21 @@ static void update_conn_param(struct bt_conn *conn)
CONN_UPDATE_TIMEOUT);
}
#if defined(CONFIG_BT_SMP)
static void update_pending_id(struct bt_keys *keys)
{
if (atomic_test_and_clear_bit(keys->flags, BT_KEYS_ID_PENDING_ADD)) {
bt_id_add(keys);
return;
}
if (atomic_test_and_clear_bit(keys->flags, BT_KEYS_ID_PENDING_DEL)) {
bt_id_del(keys);
return;
}
}
#endif
static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
{
u16_t handle = sys_le16_to_cpu(evt->handle);
@ -741,6 +756,12 @@ static void le_enh_conn_complete(struct bt_hci_evt_le_enh_conn_complete *evt)
BT_DBG("status %u handle %u role %u %s", evt->status, handle,
evt->role, bt_addr_le_str(&evt->peer_addr));
#if defined(CONFIG_BT_SMP)
if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_ID_PENDING)) {
bt_keys_foreach(BT_KEYS_IRK, update_pending_id);
}
#endif
if (evt->status) {
/*
* if there was an error we are only interested in pending
@ -2316,12 +2337,13 @@ static int hci_id_add(const bt_addr_le_t *addr, u8_t val[16])
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_ADD_DEV_TO_RL, buf, NULL);
}
int bt_id_add(const bt_addr_le_t *addr, u8_t val[16])
int bt_id_add(struct bt_keys *keys)
{
bool adv_enabled, scan_enabled;
struct bt_conn *conn;
int err;
BT_DBG("addr %s", bt_addr_le_str(addr));
BT_DBG("addr %s", bt_addr_le_str(&keys->addr));
/* Nothing to be done if host-side resolving is used */
if (!bt_dev.le.rl_size || bt_dev.le.rl_entries > bt_dev.le.rl_size) {
@ -2329,6 +2351,14 @@ int bt_id_add(const bt_addr_le_t *addr, u8_t val[16])
return 0;
}
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (conn) {
atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING);
atomic_set_bit(keys->flags, BT_KEYS_ID_PENDING_ADD);
bt_conn_unref(conn);
return -EAGAIN;
}
adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING);
if (adv_enabled) {
set_advertise_enable(false);
@ -2362,7 +2392,7 @@ int bt_id_add(const bt_addr_le_t *addr, u8_t val[16])
goto done;
}
err = hci_id_add(addr, val);
err = hci_id_add(&keys->addr, keys->irk.val);
if (err) {
BT_ERR("Failed to add IRK to controller");
goto done;
@ -2389,14 +2419,15 @@ static void keys_add_id(struct bt_keys *keys)
hci_id_add(&keys->addr, keys->irk.val);
}
int bt_id_del(const bt_addr_le_t *addr)
int bt_id_del(struct bt_keys *keys)
{
struct bt_hci_cp_le_rem_dev_from_rl *cp;
bool adv_enabled, scan_enabled;
struct bt_conn *conn;
struct net_buf *buf;
int err;
BT_DBG("addr %s", bt_addr_le_str(addr));
BT_DBG("addr %s", bt_addr_le_str(&keys->addr));
if (!bt_dev.le.rl_size ||
bt_dev.le.rl_entries > bt_dev.le.rl_size + 1) {
@ -2404,6 +2435,14 @@ int bt_id_del(const bt_addr_le_t *addr)
return 0;
}
conn = bt_conn_lookup_state_le(NULL, BT_CONN_CONNECT);
if (conn) {
atomic_set_bit(bt_dev.flags, BT_DEV_ID_PENDING);
atomic_set_bit(keys->flags, BT_KEYS_ID_PENDING_DEL);
bt_conn_unref(conn);
return -EAGAIN;
}
adv_enabled = atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING);
if (adv_enabled) {
set_advertise_enable(false);
@ -2423,6 +2462,7 @@ int bt_id_del(const bt_addr_le_t *addr)
/* We checked size + 1 earlier, so here we know we can fit again */
if (bt_dev.le.rl_entries > bt_dev.le.rl_size) {
bt_dev.le.rl_entries--;
keys->keys &= ~BT_KEYS_IRK;
bt_keys_foreach(BT_KEYS_IRK, keys_add_id);
goto done;
}
@ -2434,7 +2474,7 @@ int bt_id_del(const bt_addr_le_t *addr)
}
cp = net_buf_add(buf, sizeof(*cp));
bt_addr_le_copy(&cp->peer_id_addr, addr);
bt_addr_le_copy(&cp->peer_id_addr, &keys->addr);
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_REM_DEV_FROM_RL, buf, NULL);
if (err) {

View file

@ -43,6 +43,8 @@ enum {
BT_DEV_RPA_VALID,
BT_DEV_ID_PENDING,
#if defined(CONFIG_BT_BREDR)
BT_DEV_ISCAN,
BT_DEV_PSCAN,
@ -184,5 +186,7 @@ int bt_send(struct net_buf *buf);
u16_t bt_hci_get_cmd_opcode(struct net_buf *buf);
int bt_id_add(const bt_addr_le_t *addr, u8_t val[16]);
int bt_id_del(const bt_addr_le_t *addr);
/* Don't require everyone to include keys.h */
struct bt_keys;
int bt_id_add(struct bt_keys *keys);
int bt_id_del(struct bt_keys *keys);

View file

@ -168,9 +168,7 @@ void bt_keys_clear(struct bt_keys *keys)
BT_DBG("keys for %s", bt_addr_le_str(&keys->addr));
if (keys->keys & BT_KEYS_IRK) {
/* Clear so bt_id_del doesn't try to re-add to controller */
keys->keys &= ~BT_KEYS_IRK;
bt_id_del(&keys->addr);
bt_id_del(keys);
}
memset(keys, 0, sizeof(*keys));

View file

@ -22,6 +22,8 @@ enum {
enum {
BT_KEYS_AUTHENTICATED,
BT_KEYS_DEBUG,
BT_KEYS_ID_PENDING_ADD,
BT_KEYS_ID_PENDING_DEL,
/* Total number of flags - must be at the end of the enum */
BT_KEYS_NUM_FLAGS,

View file

@ -3041,7 +3041,7 @@ static u8_t smp_ident_addr_info(struct bt_smp *smp, struct net_buf *buf)
}
}
bt_id_add(&keys->addr, keys->irk.val);
bt_id_add(keys);
}
smp->remote_dist &= ~BT_SMP_DIST_ID_KEY;