mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-05 08:40:01 +00:00
nimble/ll: Fix continuation events handling
We should only start counting continuation events if a valid non-empty PDU was rxd/txd in a connection event. Also we should ignore any valid PDUs prior to subrated event. This fixes LL/CON/PER/BV-143-C and LL/CON/CEN/BV-145-C.
This commit is contained in:
@@ -310,7 +310,8 @@ struct ble_ll_conn_sm
|
||||
uint16_t subrate_base_event;
|
||||
uint16_t subrate_factor;
|
||||
uint16_t cont_num;
|
||||
uint16_t last_pdu_event;
|
||||
uint16_t cont_num_left;
|
||||
uint8_t has_nonempty_pdu;
|
||||
|
||||
union {
|
||||
struct ble_ll_conn_subrate_params subrate_trans;
|
||||
|
||||
@@ -1436,9 +1436,15 @@ conn_tx_pdu:
|
||||
}
|
||||
STATS_INC(ble_ll_conn_stats, tx_empty_pdus);
|
||||
} else if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
|
||||
connsm->has_nonempty_pdu = 1;
|
||||
#endif
|
||||
STATS_INC(ble_ll_conn_stats, tx_ctrl_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, tx_ctrl_bytes, cur_txlen);
|
||||
} else {
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
|
||||
connsm->has_nonempty_pdu = 1;
|
||||
#endif
|
||||
STATS_INC(ble_ll_conn_stats, tx_l2cap_pdus);
|
||||
STATS_INCN(ble_ll_conn_stats, tx_l2cap_bytes, cur_txlen);
|
||||
}
|
||||
@@ -1918,7 +1924,8 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
|
||||
connsm->subrate_base_event = 0;
|
||||
connsm->subrate_factor = 1;
|
||||
connsm->cont_num = 0;
|
||||
connsm->last_pdu_event = 0;
|
||||
connsm->cont_num_left = 0;
|
||||
connsm->has_nonempty_pdu = 0;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
@@ -2271,10 +2278,25 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
|
||||
base_event_cntr = connsm->subrate_base_event;
|
||||
subrate_factor = connsm->subrate_factor;
|
||||
|
||||
if ((connsm->cont_num > 0) &&
|
||||
(connsm->event_cntr + 1 == connsm->subrate_base_event +
|
||||
connsm->subrate_factor) &&
|
||||
(connsm->event_cntr - connsm->last_pdu_event < connsm->cont_num)) {
|
||||
/* We need to restore remaining continuation events counter if a non-empty
|
||||
* PDU was txd/rxd in this connection event. Also we need to set counter to
|
||||
* 0 in case there was no valid PDU at subrated event, since we should not
|
||||
* use continuation events in such case (i.e. ignore any valid PDUs prior
|
||||
* to subrated event).
|
||||
*
|
||||
* Note that has_nonempty_pdu flag is also cleared here since LL may move to
|
||||
* next connection event due to scheduling conflict and there will be no
|
||||
* start callback for new event.
|
||||
*/
|
||||
if (connsm->has_nonempty_pdu) {
|
||||
connsm->cont_num_left = connsm->cont_num;
|
||||
connsm->has_nonempty_pdu = 0;
|
||||
} else if (connsm->event_cntr == connsm->subrate_base_event) {
|
||||
connsm->cont_num_left = 0;
|
||||
}
|
||||
|
||||
if (connsm->cont_num_left > 0) {
|
||||
connsm->cont_num_left--;
|
||||
next_is_subrated = 0;
|
||||
}
|
||||
#else
|
||||
@@ -3344,11 +3366,6 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
acl_len = rxbuf[1];
|
||||
llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
|
||||
connsm->last_pdu_event = connsm->event_cntr;
|
||||
#endif
|
||||
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
|
||||
STATS_INC(ble_ll_conn_stats, mic_failures);
|
||||
@@ -3428,6 +3445,10 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
goto conn_rx_data_pdu_end;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
|
||||
connsm->has_nonempty_pdu = 1;
|
||||
#endif
|
||||
|
||||
if (llid == BLE_LL_LLID_CTRL) {
|
||||
/* Process control frame */
|
||||
STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
|
||||
|
||||
Reference in New Issue
Block a user