From 79cb61577045d0c924c72858e3a6a8d242c6df99 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 29 May 2019 21:54:38 +0200 Subject: [PATCH] Bluetooth: controller: split: Port Enc setup to be queueable Port the fix for the controller implementation to make start encryption queueable if there is any control procedure in progress. Refer to #15335. Relates to #15335, #15186, #15958 and #14636. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull_adv.c | 10 +- subsys/bluetooth/controller/ll_sw/ull_conn.c | 231 +++++++++++------- .../controller/ll_sw/ull_conn_types.h | 22 +- .../bluetooth/controller/ll_sw/ull_master.c | 32 +-- subsys/bluetooth/controller/ll_sw/ull_slave.c | 7 +- 5 files changed, 178 insertions(+), 124 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index 58af7459822..60c3b154fb1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -564,11 +564,6 @@ u8_t ll_adv_enable(u8_t enable) conn_lll->nesn = 0; conn_lll->empty = 0; -#if defined(CONFIG_BT_CTLR_LE_ENC) - conn_lll->enc_rx = 0; - conn_lll->enc_tx = 0; -#endif /* CONFIG_BT_CTLR_LE_ENC */ - #if defined(CONFIG_BT_CTLR_DATA_LENGTH) conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN; conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN; @@ -627,7 +622,10 @@ u8_t ll_adv_enable(u8_t enable) conn->llcp_terminate.node_rx.hdr.link = link; #if defined(CONFIG_BT_CTLR_LE_ENC) - conn->pause_tx = conn->pause_rx = conn->refresh = 0; + conn_lll->enc_rx = conn_lll->enc_tx = 0U; + conn->llcp_enc.req = conn->llcp_enc.ack = 0U; + conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.refresh = 0U; #endif /* CONFIG_BT_CTLR_LE_ENC */ #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 48eaaf24ee7..c5bae4088d4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -57,6 +57,7 @@ static inline void event_ch_map_prep(struct ll_conn *conn, static void terminate_ind_rx_enqueue(struct ll_conn *conn, u8_t reason); #if defined(CONFIG_BT_CTLR_LE_ENC) +static bool is_enc_req_pause_tx(struct ll_conn *conn); static inline void event_enc_prep(struct ll_conn *conn); static int enc_rsp_send(struct ll_conn *conn); static int start_enc_rsp_send(struct ll_conn *conn, @@ -674,7 +675,7 @@ int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx) case PDU_DATA_LLID_DATA_CONTINUE: case PDU_DATA_LLID_DATA_START: #if defined(CONFIG_BT_CTLR_LE_ENC) - if (conn->pause_rx) { + if (conn->llcp_enc.pause_rx) { conn->llcp_terminate.reason_peer = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL; @@ -687,7 +688,7 @@ int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx) case PDU_DATA_LLID_RESV: default: #if defined(CONFIG_BT_CTLR_LE_ENC) - if (conn->pause_rx) { + if (conn->llcp_enc.pause_rx) { conn->llcp_terminate.reason_peer = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL; } @@ -715,7 +716,7 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy) */ if ((conn->llcp_ack == conn->llcp_req) && #if defined(CONFIG_BT_CTLR_LE_ENC) - !conn->pause_rx) { + !conn->llcp_enc.pause_rx) { #else /* !CONFIG_BT_CTLR_LE_ENC */ 1) { #endif /* !CONFIG_BT_CTLR_LE_ENC */ @@ -736,6 +737,13 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy) ticks_at_expire); #endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) + /* check if procedure is requested */ + } else if (conn->llcp_length.ack != conn->llcp_length.req) { + /* handle DLU state machine */ + event_len_prep(conn); +#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ + #if defined(CONFIG_BT_CTLR_PHY) /* check if PHY Req procedure is requested */ } else if (conn->llcp_phy.ack != conn->llcp_phy.req) { @@ -819,14 +827,6 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy) } } -#if defined(CONFIG_BT_CTLR_DATA_LENGTH) - /* check if procedure is requested */ - if (conn->llcp_length.ack != conn->llcp_length.req) { - /* handle DLU state machine */ - event_len_prep(conn); - } -#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ - /* Terminate Procedure Request */ if (conn->llcp_terminate.ack != conn->llcp_terminate.req) { struct node_tx *tx; @@ -891,7 +891,7 @@ void ull_conn_done(struct node_rx_event_done *done) switch (done->extra.mic_state) { case LLL_CONN_MIC_NONE: #if defined(CONFIG_BT_CTLR_LE_PING) - if (lll->enc_rx || conn->pause_rx) { + if (lll->enc_rx || conn->llcp_enc.pause_rx) { u16_t appto_reload_new; /* check for change in apto */ @@ -1190,42 +1190,43 @@ void ull_conn_tx_demux(u8_t count) void ull_conn_tx_lll_enqueue(struct ll_conn *conn, u8_t count) { - struct node_tx *tx; + bool pause_tx = false; - tx = conn->tx_head; - while (tx && + while (conn->tx_head && (( -#if defined(CONFIG_BT_CTLR_LE_ENC) - !conn->pause_tx && -#endif /* CONFIG_BT_CTLR_LE_ENC */ #if defined(CONFIG_BT_CTLR_DATA_LENGTH) !conn->llcp_length.pause_tx && #endif /* CONFIG_BT_CTLR_DATA_LENGTH */ #if defined(CONFIG_BT_CTLR_PHY) !conn->llcp_phy.pause_tx && #endif /* CONFIG_BT_CTLR_PHY */ - 1) || (tx == conn->tx_ctrl)) && count--) { +#if defined(CONFIG_BT_CTLR_LE_ENC) + !conn->llcp_enc.pause_tx && + !(pause_tx = is_enc_req_pause_tx(conn)) && +#endif /* CONFIG_BT_CTLR_LE_ENC */ + 1) || + (!pause_tx && (conn->tx_head == conn->tx_ctrl))) && count--) { struct node_tx *tx_lll; memq_link_t *link; - tx_lll = tx; + tx_lll = conn->tx_head; - if (tx == conn->tx_ctrl) { - tx = conn->tx_head = conn->tx_head->next; + if (conn->tx_head == conn->tx_ctrl) { + conn->tx_head = conn->tx_head->next; if (conn->tx_ctrl == conn->tx_ctrl_last) { conn->tx_ctrl = NULL; conn->tx_ctrl_last = NULL; } else { - conn->tx_ctrl = tx; + conn->tx_ctrl = conn->tx_head; } /* point to self to indicate a control PDU mem alloc */ tx_lll->next = tx_lll; } else { - if (tx == conn->tx_data) { + if (conn->tx_head == conn->tx_data) { conn->tx_data = conn->tx_data->next; } - tx = conn->tx_head = conn->tx_head->next; + conn->tx_head = conn->tx_head->next; } link = mem_acquire(&mem_link_tx.free); @@ -1510,7 +1511,7 @@ static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx) /* data/ctrl packet is in the head */ conn->tx_head && #if defined(CONFIG_BT_CTLR_LE_ENC) - !conn->pause_tx && + !conn->llcp_enc.pause_tx && #endif /* CONFIG_BT_CTLR_LE_ENC */ #if defined(CONFIG_BT_CTLR_DATA_LENGTH) !conn->llcp_length.pause_tx && @@ -1567,7 +1568,7 @@ static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx) static void ctrl_tx_sec_enqueue(struct ll_conn *conn, struct node_tx *tx) { #if defined(CONFIG_BT_CTLR_LE_ENC) - if (conn->pause_tx) { + if (conn->llcp_enc.pause_tx) { if (!conn->tx_ctrl) { tx->next = conn->tx_head; conn->tx_head = tx; @@ -1583,6 +1584,65 @@ static void ctrl_tx_sec_enqueue(struct ll_conn *conn, struct node_tx *tx) } } +#if defined(CONFIG_BT_CTLR_LE_ENC) +static bool is_enc_req_pause_tx(struct ll_conn *conn) +{ + struct pdu_data *pdu_data_tx; + + pdu_data_tx = (void *)conn->tx_head->pdu; + if ((pdu_data_tx->ll_id == PDU_DATA_LLID_CTRL) && + (pdu_data_tx->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_ENC_REQ)) { + if ((conn->llcp_req != conn->llcp_ack) || +#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) + (conn->llcp_conn_param.ack != conn->llcp_conn_param.req) || +#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */ +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) + (conn->llcp_length.ack != conn->llcp_length.req) || +#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ +#if defined(CONFIG_BT_CTLR_PHY) + (conn->llcp_phy.ack != conn->llcp_phy.req) || +#endif /* CONFIG_BT_CTLR_PHY */ + 0) { + struct node_tx *tx; + + /* if we have control packets enqueued after this PDU + * bring it ahead, and move the enc_req to last of + * ctrl queue. + */ + tx = conn->tx_head; + if ((tx->next != NULL) && + (tx->next == conn->tx_ctrl)) { + conn->tx_head = tx->next; + tx->next = conn->tx_ctrl_last->next; + conn->tx_ctrl_last->next = tx; + conn->tx_data = tx; + if (!conn->tx_data_last) { + conn->tx_data_last = tx; + } + + /* Head now contains a control packet permitted + * to be transmitted to peer. + */ + return false; + } + + /* Head contains ENC_REQ packet deferred due to another + * control procedure in progress. + */ + return true; + } + + conn->llcp.encryption.initiate = 1U; + + conn->llcp_type = LLCP_ENCRYPTION; + conn->llcp_ack -= 2U; + } + + /* Head contains a permitted data or control packet. */ + return false; +} +#endif /* CONFIG_BT_CTLR_LE_ENC */ + static inline void event_conn_upd_init(struct ll_conn *conn, u16_t event_counter, u32_t ticks_at_expire, @@ -2046,9 +2106,9 @@ static inline void event_enc_prep(struct ll_conn *conn) /* master sends encrypted enc start rsp in control priority */ if (!lll->role) { /* calc the Session Key */ - ecb_encrypt(&conn->llcp.encryption.ltk[0], - &conn->llcp.encryption.skd[0], - NULL, &lll->ccm_rx.key[0]); + ecb_encrypt(&conn->llcp_enc.ltk[0], + &conn->llcp.encryption.skd[0], NULL, + &lll->ccm_rx.key[0]); /* copy the Session Key */ memcpy(&lll->ccm_tx.key[0], &lll->ccm_rx.key[0], @@ -2080,7 +2140,7 @@ static inline void event_enc_prep(struct ll_conn *conn) #if defined(CONFIG_BT_CTLR_FAST_ENC) else { #else /* !CONFIG_BT_CTLR_FAST_ENC */ - else if (!conn->pause_tx || conn->refresh) { + else if (!conn->llcp_enc.pause_tx || conn->llcp_enc.refresh) { #endif /* !CONFIG_BT_CTLR_FAST_ENC */ /* place the reject ind packet as next in tx queue */ @@ -2106,7 +2166,7 @@ static inline void event_enc_prep(struct ll_conn *conn) #endif /* !CONFIG_BT_CTLR_FAST_ENC */ /* calc the Session Key */ - ecb_encrypt(&conn->llcp.encryption.ltk[0], + ecb_encrypt(&conn->llcp_enc.ltk[0], &conn->llcp.encryption.skd[0], NULL, &lll->ccm_rx.key[0]); @@ -2120,20 +2180,20 @@ static inline void event_enc_prep(struct ll_conn *conn) sizeof(lll->ccm_tx.iv)); /* initialise counter */ - lll->ccm_rx.counter = 0; - lll->ccm_tx.counter = 0; + lll->ccm_rx.counter = 0U; + lll->ccm_tx.counter = 0U; /* set direction: slave to master = 0, * master to slave = 1 */ - lll->ccm_rx.direction = 1; - lll->ccm_tx.direction = 0; + lll->ccm_rx.direction = 1U; + lll->ccm_tx.direction = 0U; /* enable receive encryption (transmit turned * on when start enc resp from master is * received) */ - lll->enc_rx = 1; + lll->enc_rx = 1U; /* prepare the start enc req */ pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL; @@ -2149,8 +2209,8 @@ static inline void event_enc_prep(struct ll_conn *conn) start_enc_rsp_send(conn, pdu_ctrl_tx); /* resume data packet rx and tx */ - conn->pause_rx = 0; - conn->pause_tx = 0; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; #endif /* !CONFIG_BT_CTLR_FAST_ENC */ } @@ -2518,7 +2578,7 @@ static inline void event_conn_param_app_req(struct ll_conn *conn) #if defined(CONFIG_BT_CTLR_LE_ENC) /* defer until encryption setup is complete */ - if (conn->pause_tx) { + if (conn->llcp_enc.pause_tx) { return; } #endif /* CONFIG_BT_CTLR_LE_ENC */ @@ -2762,7 +2822,7 @@ static inline void event_phy_req_prep(struct ll_conn *conn) conn->phy_pref_flags = conn->llcp_phy.flags; /* pause data packet tx */ - conn->llcp_phy.pause_tx = 1; + conn->llcp_phy.pause_tx = 1U; /* place the phy req packet as next in tx queue */ pdu_ctrl_tx = (void *)tx->pdu; @@ -3116,13 +3176,10 @@ static void enc_req_reused_send(struct ll_conn *conn, struct node_tx **tx) pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_req) + sizeof(struct pdu_data_llctrl_enc_req); pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ; - memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0], - &conn->llcp.encryption.rand[0], + memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0], &conn->llcp_enc.rand[0], sizeof(pdu_ctrl_tx->llctrl.enc_req.rand)); - pdu_ctrl_tx->llctrl.enc_req.ediv[0] = - conn->llcp.encryption.ediv[0]; - pdu_ctrl_tx->llctrl.enc_req.ediv[1] = - conn->llcp.encryption.ediv[1]; + pdu_ctrl_tx->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0]; + pdu_ctrl_tx->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1]; /* * Take advantage of the fact that ivm and skdm fields, which both have @@ -3218,13 +3275,13 @@ static int start_enc_rsp_send(struct ll_conn *conn, static inline bool ctrl_is_unexpected(struct ll_conn *conn, u8_t opcode) { return (!conn->lll.role && - ((!conn->refresh && + ((!conn->llcp_enc.refresh && (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_REQ) && (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) && (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) || - (conn->refresh && + (conn->llcp_enc.refresh && (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) && (opcode != PDU_DATA_LLCTRL_TYPE_ENC_RSP) && @@ -3233,13 +3290,13 @@ static inline bool ctrl_is_unexpected(struct ll_conn *conn, u8_t opcode) (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)))) || (conn->lll.role && - ((!conn->refresh && + ((!conn->llcp_enc.refresh && (opcode != PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP) && (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) && (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) || - (conn->refresh && + (conn->llcp_enc.refresh && (opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) && (opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) && (opcode != PDU_DATA_LLCTRL_TYPE_ENC_REQ) && @@ -3362,7 +3419,7 @@ static int pause_enc_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx, } /* key refresh */ - conn->refresh = 1U; + conn->llcp_enc.refresh = 1U; } else if (!conn->lll.role) { /* acquire tx mem */ tx = mem_acquire(&mem_conn_tx_ctrl.free); @@ -3380,7 +3437,7 @@ static int pause_enc_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx, } /* pause data packet rx */ - conn->pause_rx = 1U; + conn->llcp_enc.pause_rx = 1U; /* disable receive encryption */ conn->lll.enc_rx = 0; @@ -3683,8 +3740,8 @@ static void reject_ext_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx, switch (rej_ext_ind->reject_opcode) { case PDU_DATA_LLCTRL_TYPE_ENC_REQ: /* resume data packet rx and tx */ - conn->pause_rx = 0U; - conn->pause_tx = 0U; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; /* Procedure complete */ conn->procedure_expire = 0U; @@ -4010,7 +4067,7 @@ static int phy_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx, conn->llcp_phy.rx &= p->tx_phys; /* pause data packet tx */ - conn->llcp_phy.pause_tx = 1; + conn->llcp_phy.pause_tx = 1U; pdu_ctrl_tx = (void *)tx->pdu; pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL; @@ -4146,18 +4203,21 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, &pdu_tx->llctrl.enc_req.ivm[0], 4); /* pause data packet tx */ - conn->pause_tx = 1U; + conn->llcp_enc.pause_tx = 1U; /* Start Procedure Timeout (this will not replace terminate * procedure which always gets place before any packets * going out, hence safe by design). */ conn->procedure_expire = conn->procedure_reload; + + /* Reset enc req queued state */ + conn->llcp_enc.ack = conn->llcp_enc.req; break; case PDU_DATA_LLCTRL_TYPE_ENC_RSP: /* pause data packet tx */ - conn->pause_tx = 1U; + conn->llcp_enc.pause_tx = 1U; break; case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ: @@ -4169,10 +4229,10 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ: /* pause data packet tx */ - conn->pause_tx = 1U; + conn->llcp_enc.pause_tx = 1U; /* key refresh */ - conn->refresh = 1U; + conn->llcp_enc.refresh = 1U; /* Start Procedure Timeout (this will not replace terminate * procedure which always gets place before any packets @@ -4187,7 +4247,7 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, enc_req_reused_send(conn, tx); } else { /* pause data packet tx */ - conn->pause_tx = 1U; + conn->llcp_enc.pause_tx = 1U; } break; @@ -4200,8 +4260,8 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, case PDU_DATA_LLCTRL_TYPE_REJECT_IND: /* resume data packet rx and tx */ - conn->pause_rx = 0U; - conn->pause_tx = 0U; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; /* Procedure complete */ conn->procedure_expire = 0U; @@ -4242,13 +4302,13 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, } /* resume data packet tx */ - conn->llcp_phy.pause_tx = 0; + conn->llcp_phy.pause_tx = 0U; break; case PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND: conn->lll.phy_tx_time = conn->llcp.phy_upd_ind.tx; /* resume data packet tx */ - conn->llcp_phy.pause_tx = 0; + conn->llcp_phy.pause_tx = 0U; break; #endif /* CONFIG_BT_CTLR_PHY */ @@ -4328,7 +4388,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, #if defined(CONFIG_BT_CTLR_LE_ENC) /* FIXME: do check in individual case to reduce CPU time */ - if (conn->pause_rx && ctrl_is_unexpected(conn, opcode)) { + if (conn->llcp_enc.pause_rx && ctrl_is_unexpected(conn, opcode)) { conn->llcp_terminate.reason_peer = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL; @@ -4412,7 +4472,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, &pdu_rx->llctrl.enc_req.ivm[0], 4); /* pause rx data packets */ - conn->pause_rx = 1U; + conn->llcp_enc.pause_rx = 1U; /* Start Procedure Timeout (TODO: this shall not replace * terminate procedure). @@ -4434,7 +4494,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, &pdu_rx->llctrl.enc_rsp.ivs[0], 4); /* pause rx data packets */ - conn->pause_rx = 1U; + conn->llcp_enc.pause_rx = 1U; /* Mark for buffer for release */ (*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE; @@ -4442,10 +4502,9 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, break; case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ: - LL_ASSERT((conn->llcp_req == conn->llcp_ack) || - (conn->llcp_type == LLCP_ENCRYPTION)); - if (conn->lll.role || + ((conn->llcp_req != conn->llcp_ack) && + (conn->llcp_type != LLCP_ENCRYPTION)) || !pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ, pdu_rx->len)) { goto ull_conn_rx_unknown_rsp_send; @@ -4471,8 +4530,10 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, if (conn->lll.role) { #if !defined(CONFIG_BT_CTLR_FAST_ENC) - LL_ASSERT((conn->llcp_req == conn->llcp_ack) || - (conn->llcp_type == LLCP_ENCRYPTION)); + if ((conn->llcp_req != conn->llcp_ack) && + (conn->llcp_type != LLCP_ENCRYPTION)) { + goto ull_conn_rx_unknown_rsp_send; + } /* start enc rsp to be scheduled in slave prepare */ conn->llcp.encryption.initiate = 0U; @@ -4487,19 +4548,19 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, } /* resume data packet rx and tx */ - conn->pause_rx = 0U; - conn->pause_tx = 0U; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; #endif /* CONFIG_BT_CTLR_FAST_ENC */ } else { /* resume data packet rx and tx */ - conn->pause_rx = 0U; - conn->pause_tx = 0U; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; } /* enqueue the start enc resp (encryption change/refresh) */ - if (conn->refresh) { - conn->refresh = 0U; + if (conn->llcp_enc.refresh) { + conn->llcp_enc.refresh = 0U; /* key refresh event */ (*rx)->hdr.type = NODE_RX_TYPE_ENC_REFRESH; @@ -4579,8 +4640,8 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, } /* resume data packet rx and tx */ - conn->pause_rx = 0U; - conn->pause_tx = 0U; + conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.pause_tx = 0U; /* Procedure complete */ conn->procedure_expire = 0U; @@ -4719,7 +4780,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, /* postpone CP request event if under * encryption setup */ - if (conn->pause_tx) { + if (conn->llcp_enc.pause_tx) { conn->llcp_conn_param.state = LLCP_CPR_STATE_APP_REQ; @@ -5036,7 +5097,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, /* Procedure complete */ conn->llcp_phy.ack = conn->llcp_phy.req; - conn->llcp_phy.pause_tx = 0; + conn->llcp_phy.pause_tx = 0U; /* Reset packet timing restrictions */ lll->phy_tx_time = lll->phy_tx; @@ -5171,7 +5232,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, conn->llcp_phy.rx &= p->tx_phys; /* pause data packet tx */ - conn->llcp_phy.pause_tx = 1; + conn->llcp_phy.pause_tx = 1U; /* Mark for buffer for release */ (*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE; @@ -5199,7 +5260,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, conn->llcp_phy.rx &= p->tx_phys; /* pause data packet tx */ - conn->llcp_phy.pause_tx = 1; + conn->llcp_phy.pause_tx = 1U; /* Procedure timeout is stopped */ conn->procedure_expire = 0U; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 21d966b47d9..2ecfd2ab7df 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -87,9 +87,6 @@ struct ll_conn { struct { u8_t initiate; u8_t error_code; - u8_t rand[8]; - u8_t ediv[2]; - u8_t ltk[16]; u8_t skd[16]; } encryption; #endif /* CONFIG_BT_CTLR_LE_ENC */ @@ -118,6 +115,19 @@ struct ll_conn { } node_rx; } llcp_terminate; +#if defined(CONFIG_BT_CTLR_LE_ENC) + struct { + u8_t req; + u8_t ack; + u8_t pause_rx:1; + u8_t pause_tx:1; + u8_t refresh:1; + u8_t ediv[2]; + u8_t rand[8]; + u8_t ltk[16]; + } llcp_enc; +#endif /* CONFIG_BT_CTLR_LE_ENC */ + #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) struct { u8_t req; @@ -191,12 +201,6 @@ struct ll_conn { u8_t phy_pref_rx:3; #endif /* CONFIG_BT_CTLR_PHY */ -#if defined(CONFIG_BT_CTLR_LE_ENC) - u8_t pause_rx:1; - u8_t pause_tx:1; - u8_t refresh:1; -#endif /* CONFIG_BT_CTLR_LE_ENC */ - struct node_tx *tx_head; struct node_tx *tx_ctrl; struct node_tx *tx_ctrl_last; diff --git a/subsys/bluetooth/controller/ll_sw/ull_master.c b/subsys/bluetooth/controller/ll_sw/ull_master.c index 6da11d96065..4a173f6b89a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master.c +++ b/subsys/bluetooth/controller/ll_sw/ull_master.c @@ -118,11 +118,6 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, conn_lll->nesn = 0; conn_lll->empty = 0; -#if defined(CONFIG_BT_CTLR_LE_ENC) - conn_lll->enc_rx = 0; - conn_lll->enc_tx = 0; -#endif /* CONFIG_BT_CTLR_LE_ENC */ - #if defined(CONFIG_BT_CTLR_DATA_LENGTH) conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN; conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN; @@ -197,7 +192,10 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, conn->llcp_terminate.node_rx.hdr.link = link; #if defined(CONFIG_BT_CTLR_LE_ENC) - conn->pause_tx = conn->pause_rx = conn->refresh = 0U; + conn_lll->enc_rx = conn_lll->enc_tx = 0U; + conn->llcp_enc.req = conn->llcp_enc.ack = 0U; + conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U; + conn->llcp_enc.refresh = 0U; #endif /* CONFIG_BT_CTLR_LE_ENC */ #if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ) @@ -337,16 +335,14 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk) { struct ll_conn *conn; struct node_tx *tx; - u8_t ret; conn = ll_connected_get(handle); if (!conn) { return BT_HCI_ERR_UNKNOWN_CONN_ID; } - ret = ull_conn_llcp_req(conn); - if (ret) { - return ret; + if (conn->llcp_enc.req != conn->llcp_enc.ack) { + return BT_HCI_ERR_CMD_DISALLOWED; } tx = ll_tx_mem_acquire(); @@ -355,8 +351,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk) pdu_data_tx = (void *)tx->pdu; - memcpy(&conn->llcp.encryption.ltk[0], ltk, - sizeof(conn->llcp.encryption.ltk)); + memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk)); if ((conn->lll.enc_rx == 0) && (conn->lll.enc_tx == 0)) { struct pdu_data_llctrl_enc_req *enc_req; @@ -375,11 +370,11 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk) bt_rand(enc_req->skdm, sizeof(enc_req->skdm)); bt_rand(enc_req->ivm, sizeof(enc_req->ivm)); } else if ((conn->lll.enc_rx != 0) && (conn->lll.enc_tx != 0)) { - memcpy(&conn->llcp.encryption.rand[0], rand, - sizeof(conn->llcp.encryption.rand)); + memcpy(&conn->llcp_enc.rand[0], rand, + sizeof(conn->llcp_enc.rand)); - conn->llcp.encryption.ediv[0] = ediv[0]; - conn->llcp.encryption.ediv[1] = ediv[1]; + conn->llcp_enc.ediv[0] = ediv[0]; + conn->llcp_enc.ediv[1] = ediv[1]; pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL; pdu_data_tx->len = offsetof(struct pdu_data_llctrl, @@ -398,10 +393,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk) return BT_HCI_ERR_CMD_DISALLOWED; } - conn->llcp.encryption.initiate = 1U; - - conn->llcp_type = LLCP_ENCRYPTION; - conn->llcp_req++; + conn->llcp_enc.req++; return 0; } diff --git a/subsys/bluetooth/controller/ll_sw/ull_slave.c b/subsys/bluetooth/controller/ll_sw/ull_slave.c index 6eefdea2329..46d92f7b810 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_slave.c +++ b/subsys/bluetooth/controller/ll_sw/ull_slave.c @@ -393,7 +393,7 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code, } if (error_code) { - if (conn->refresh == 0U) { + if (conn->llcp_enc.refresh == 0U) { ret = ull_conn_llcp_req(conn); if (ret) { return ret; @@ -415,14 +415,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code, conn->llcp_terminate.req++; } } else { - memcpy(&conn->llcp.encryption.ltk[0], ltk, - sizeof(conn->llcp.encryption.ltk)); - ret = ull_conn_llcp_req(conn); if (ret) { return ret; } + memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk)); + conn->llcp.encryption.error_code = 0U; conn->llcp.encryption.initiate = 0U;