nimble/ll: Fix connection update instant calculation

The instant for connection update was calculated at the time PDU was
enqueued in connsm. This caused new conn params to be always applied at
instant regardless if PDU was event dequeued for tx, e.g. in case there
were lots of data PDUs to be send before control PDU.

Currently we calculate instant when PDU is dequeued to make sure this is
the next PDU to be sent and thus instant is valid.
This commit is contained in:
Andrzej Kaczmarek
2023-06-15 15:24:11 +02:00
parent 634e41b166
commit f561b74667
2 changed files with 42 additions and 24 deletions
@@ -109,6 +109,7 @@ union ble_ll_conn_sm_flags {
uint32_t awaiting_host_reply:1;
uint32_t terminate_started:1;
uint32_t conn_update_sched:1;
uint32_t conn_update_use_cp:1;
uint32_t host_expects_upd_event:1;
uint32_t version_ind_sent:1;
uint32_t rxd_version_ind:1;
+41 -24
View File
@@ -383,18 +383,28 @@ conn_param_pdu_exit:
return rsp_opcode;
}
/**
* Called to make a connection update request LL control PDU
*
* Context: Link Layer
*
* @param connsm
* @param rsp
*/
static void
ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld,
struct ble_ll_conn_params *cp)
ble_ll_ctrl_conn_update_init_proc(struct ble_ll_conn_sm *connsm,
struct ble_ll_conn_params *cp)
{
/* This only stores conn params, if any. The caller will enqueue LL Control
* PDU and we will calculate its contents when dequeued so we know that
* instant is in the future.
*/
connsm->csmflags.cfbit.conn_update_sched = 0;
connsm->csmflags.cfbit.conn_update_use_cp = (cp != NULL);
if (cp) {
connsm->conn_cp = *cp;
}
}
static void
ble_ll_ctrl_conn_update_make_ind_pdu(struct ble_ll_conn_sm *connsm,
uint8_t *ctrdata)
{
struct ble_ll_conn_params *cp = NULL;
struct ble_ll_conn_params offset_cp = { };
uint16_t instant;
uint32_t dt;
@@ -404,6 +414,10 @@ ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld,
struct hci_conn_update *hcu;
struct ble_ll_conn_upd_req *req;
if (connsm->csmflags.cfbit.conn_update_use_cp) {
cp = &connsm->conn_cp;
}
/*
* Set instant. We set the instant to the current event counter plus
* the amount of peripheral latency as the peripheral may not be listening
@@ -475,15 +489,12 @@ ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld,
req->instant = instant;
/* XXX: make sure this works for the connection parameter request proc. */
pyld[0] = req->winsize;
put_le16(pyld + 1, req->winoffset);
put_le16(pyld + 3, req->interval);
put_le16(pyld + 5, req->latency);
put_le16(pyld + 7, req->timeout);
put_le16(pyld + 9, instant);
/* Set flag in state machine to denote we have scheduled an update */
connsm->csmflags.cfbit.conn_update_sched = 1;
ctrdata[0] = req->winsize;
put_le16(ctrdata + 1, req->winoffset);
put_le16(ctrdata + 3, req->interval);
put_le16(ctrdata + 5, req->latency);
put_le16(ctrdata + 7, req->timeout);
put_le16(ctrdata + 9, instant);
}
/**
@@ -519,7 +530,7 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *
BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ);
#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL);
ble_ll_ctrl_conn_update_init_proc(connsm, NULL);
connsm->reject_reason = BLE_ERR_SUCCESS;
return BLE_LL_CTRL_CONN_UPDATE_IND;
}
@@ -1912,8 +1923,7 @@ ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp,
switch (connsm->conn_role) {
#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
case BLE_LL_CONN_ROLE_CENTRAL:
/* Create a connection update pdu */
ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req);
ble_ll_ctrl_conn_update_init_proc(connsm, req);
rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
break;
#endif
@@ -1967,7 +1977,7 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
case BLE_LL_CONN_ROLE_CENTRAL:
/* As a central we should send connection update indication in this point */
rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL);
ble_ll_ctrl_conn_update_init_proc(connsm, NULL);
connsm->reject_reason = BLE_ERR_SUCCESS;
break;
#endif
@@ -2467,7 +2477,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data)
switch (ctrl_proc) {
case BLE_LL_CTRL_PROC_CONN_UPDATE:
opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
ble_ll_ctrl_conn_upd_make(connsm, ctrdata, data);
ble_ll_ctrl_conn_update_init_proc(connsm, data);
break;
case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ;
@@ -3116,9 +3126,16 @@ int
ble_ll_ctrl_tx_start(struct ble_ll_conn_sm *connsm, struct os_mbuf *txpdu)
{
uint8_t opcode;
uint8_t *ctrdata;
opcode = txpdu->om_data[0];
ctrdata = &txpdu->om_data[1];
switch (opcode) {
case BLE_LL_CTRL_CONN_UPDATE_IND:
ble_ll_ctrl_conn_update_make_ind_pdu(connsm, ctrdata);
connsm->csmflags.cfbit.conn_update_sched = 1;
break;
case BLE_LL_CTRL_SUBRATE_IND:
connsm->csmflags.cfbit.subrate_trans = 1;
break;