Bluetooth: controller: Avoid race between ULL and LLL when initiating conn

Use an "initiated" flag in the lll_conn struct to guard the processing
of PDUs related to connection initiation (CONNECT_IND,
AUX_CONNECT_RSP). This avoids races between ULL and LLL when creating
a connection.

Signed-off-by: Wolfgang Puffitsch <wopu@demant.com>
This commit is contained in:
Wolfgang Puffitsch 2021-02-20 15:32:05 +01:00 committed by Anas Nashif
commit 5ce5dc055e
8 changed files with 34 additions and 6 deletions

View file

@ -46,6 +46,7 @@ struct lll_conn {
uint8_t data_chan_count:6; uint8_t data_chan_count:6;
uint8_t data_chan_sel:1; uint8_t data_chan_sel:1;
uint8_t role:1; uint8_t role:1;
uint8_t initiated:1;
union { union {
struct { struct {
@ -59,6 +60,7 @@ struct lll_conn {
#if defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_PERIPHERAL)
struct { struct {
uint8_t latency_enabled:1; uint8_t latency_enabled:1;
uint32_t window_widening_periodic_us; uint32_t window_widening_periodic_us;
uint32_t window_widening_max_us; uint32_t window_widening_max_us;
uint32_t window_widening_prepare_us; uint32_t window_widening_prepare_us;

View file

@ -1331,7 +1331,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr, lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
rx_addr, tgt_addr, rx_addr, tgt_addr,
devmatch_ok, &rl_idx) && devmatch_ok, &rl_idx) &&
lll->conn) { lll->conn &&
!lll->conn->initiated) {
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
struct node_rx_pdu *rx; struct node_rx_pdu *rx;
int ret; int ret;
@ -1366,6 +1367,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
ret = lll_stop(lll); ret = lll_stop(lll);
LL_ASSERT(!ret); LL_ASSERT(!ret);
lll->conn->initiated = 1;
rx = ull_pdu_rx_alloc(); rx = ull_pdu_rx_alloc();
rx->hdr.type = NODE_RX_TYPE_CONNECTION; rx->hdr.type = NODE_RX_TYPE_CONNECTION;

View file

@ -25,6 +25,7 @@
#include "lll_vendor.h" #include "lll_vendor.h"
#include "lll_clock.h" #include "lll_clock.h"
#include "lll_chan.h" #include "lll_chan.h"
#include "lll_conn.h"
#include "lll_adv_types.h" #include "lll_adv_types.h"
#include "lll_adv.h" #include "lll_adv.h"
#include "lll_adv_pdu.h" #include "lll_adv_pdu.h"
@ -56,7 +57,9 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
uint8_t devmatch_ok, uint8_t devmatch_id, uint8_t devmatch_ok, uint8_t devmatch_id,
uint8_t irkmatch_ok, uint8_t irkmatch_id, uint8_t irkmatch_ok, uint8_t irkmatch_id,
uint8_t rssi_ready); uint8_t rssi_ready);
#if defined(CONFIG_BT_PERIPHERAL)
static void isr_tx_connect_rsp(void *param); static void isr_tx_connect_rsp(void *param);
#endif /* CONFIG_BT_PERIPHERAL */
static struct pdu_adv *init_connect_rsp_pdu(void) static struct pdu_adv *init_connect_rsp_pdu(void)
{ {
@ -103,6 +106,7 @@ static struct pdu_adv *init_connect_rsp_pdu(void)
return pdu; return pdu;
} }
#if defined(CONFIG_BT_PERIPHERAL)
static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci) static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)
{ {
struct pdu_adv_com_ext_adv *cr_com_hdr; struct pdu_adv_com_ext_adv *cr_com_hdr;
@ -127,6 +131,7 @@ static struct pdu_adv *update_connect_rsp_pdu(struct pdu_adv *pdu_ci)
return pdu_cr; return pdu_cr;
} }
#endif /* CONFIG_BT_PERIPHERAL */
int lll_adv_aux_init(void) int lll_adv_aux_init(void)
{ {
@ -487,7 +492,6 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
struct pdu_adv *pdu_adv; struct pdu_adv *pdu_adv;
struct pdu_adv *pdu_aux; struct pdu_adv *pdu_aux;
struct pdu_adv *pdu_rx; struct pdu_adv *pdu_rx;
struct pdu_adv *pdu_tx;
struct lll_adv *lll; struct lll_adv *lll;
uint8_t *tgt_addr; uint8_t *tgt_addr;
uint8_t tx_addr; uint8_t tx_addr;
@ -566,13 +570,18 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
CONFIG_BT_CTLR_GPIO_PA_OFFSET); CONFIG_BT_CTLR_GPIO_PA_OFFSET);
#endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */ #endif /* CONFIG_BT_CTLR_GPIO_PA_PIN */
return 0; return 0;
#if defined(CONFIG_BT_PERIPHERAL)
} else if ((pdu_rx->type == PDU_ADV_TYPE_AUX_CONNECT_REQ) && } else if ((pdu_rx->type == PDU_ADV_TYPE_AUX_CONNECT_REQ) &&
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) && (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr, lll_adv_connect_ind_check(lll, pdu_rx, tx_addr, addr,
rx_addr, tgt_addr, rx_addr, tgt_addr,
devmatch_ok, &rl_idx)) { devmatch_ok, &rl_idx) &&
lll->conn &&
!lll->conn->initiated) {
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
struct node_rx_pdu *rx; struct node_rx_pdu *rx;
struct pdu_adv *pdu_tx;
if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) { if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) {
rx = ull_pdu_rx_alloc_peek(4); rx = ull_pdu_rx_alloc_peek(4);
@ -637,11 +646,13 @@ static inline int isr_rx_pdu(struct lll_adv_aux *lll_aux,
} }
return 0; return 0;
#endif /* CONFIG_BT_PERIPHERAL */
} }
return -EINVAL; return -EINVAL;
} }
#if defined(CONFIG_BT_PERIPHERAL)
static void isr_tx_connect_rsp(void *param) static void isr_tx_connect_rsp(void *param)
{ {
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
@ -678,9 +689,12 @@ static void isr_tx_connect_rsp(void *param)
/* Stop further LLL radio events */ /* Stop further LLL radio events */
ret = lll_stop(lll); ret = lll_stop(lll);
LL_ASSERT(!ret); LL_ASSERT(!ret);
lll->conn->initiated = 1;
} }
/* Clear radio status and events */ /* Clear radio status and events */
lll_isr_status_reset(); lll_isr_status_reset();
lll_isr_cleanup(lll); lll_isr_cleanup(lll);
} }
#endif /* CONFIG_BT_PERIPHERAL */

View file

@ -768,7 +768,7 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
if (0) { if (0) {
#if defined(CONFIG_BT_CENTRAL) #if defined(CONFIG_BT_CENTRAL)
/* Initiator */ /* Initiator */
} else if ((lll->conn) && } else if (lll->conn && !lll->conn->initiated &&
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) { isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
struct lll_conn *lll_conn; struct lll_conn *lll_conn;
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
@ -925,6 +925,8 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
ret = lll_stop(lll); ret = lll_stop(lll);
LL_ASSERT(!ret); LL_ASSERT(!ret);
lll->conn->initiated = 1;
rx = ull_pdu_rx_alloc(); rx = ull_pdu_rx_alloc();
rx->hdr.type = NODE_RX_TYPE_CONNECTION; rx->hdr.type = NODE_RX_TYPE_CONNECTION;

View file

@ -896,7 +896,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
(pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) && (pdu_rx->len == sizeof(struct pdu_adv_connect_ind)) &&
isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok, isr_rx_ci_check(lll, pdu_adv, pdu_rx, devmatch_ok,
&rl_idx) && &rl_idx) &&
lll->conn) { lll->conn &&
!lll->conn->initiated) {
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
struct node_rx_pdu *rx; struct node_rx_pdu *rx;
int ret; int ret;
@ -930,6 +931,8 @@ static inline int isr_rx_pdu(struct lll_adv *lll,
ret = lll_stop(lll); ret = lll_stop(lll);
LL_ASSERT(!ret); LL_ASSERT(!ret);
lll->conn->initiated = 1;
rx = ull_pdu_rx_alloc(); rx = ull_pdu_rx_alloc();
rx->hdr.type = NODE_RX_TYPE_CONNECTION; rx->hdr.type = NODE_RX_TYPE_CONNECTION;

View file

@ -672,7 +672,7 @@ static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
if (0) { if (0) {
#if defined(CONFIG_BT_CENTRAL) #if defined(CONFIG_BT_CENTRAL)
/* Initiator */ /* Initiator */
} else if ((lll->conn) && } else if (lll->conn && !lll->conn->initiated &&
isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) { isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
struct lll_conn *lll_conn; struct lll_conn *lll_conn;
struct node_rx_ftr *ftr; struct node_rx_ftr *ftr;
@ -829,6 +829,8 @@ static inline uint32_t isr_rx_pdu(struct lll_scan *lll, uint8_t devmatch_ok,
ret = lll_stop(lll); ret = lll_stop(lll);
LL_ASSERT(!ret); LL_ASSERT(!ret);
lll->conn->initiated = 1;
rx = ull_pdu_rx_alloc(); rx = ull_pdu_rx_alloc();
rx->hdr.type = NODE_RX_TYPE_CONNECTION; rx->hdr.type = NODE_RX_TYPE_CONNECTION;

View file

@ -872,6 +872,7 @@ uint8_t ll_adv_enable(uint8_t enable)
/* FIXME: BEGIN: Move to ULL? */ /* FIXME: BEGIN: Move to ULL? */
conn_lll->role = 1; conn_lll->role = 1;
conn_lll->initiated = 0;
conn_lll->data_chan_sel = 0; conn_lll->data_chan_sel = 0;
conn_lll->data_chan_use = 0; conn_lll->data_chan_use = 0;
conn_lll->event_counter = 0; conn_lll->event_counter = 0;

View file

@ -213,6 +213,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
conn_lll->data_chan_sel = 0; conn_lll->data_chan_sel = 0;
conn_lll->data_chan_use = 0; conn_lll->data_chan_use = 0;
conn_lll->role = 0; conn_lll->role = 0;
conn_lll->initiated = 0;
/* FIXME: END: Move to ULL? */ /* FIXME: END: Move to ULL? */
#if defined(CONFIG_BT_CTLR_CONN_META) #if defined(CONFIG_BT_CTLR_CONN_META)
memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta)); memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));