Skip to content

[WIP]host/eatt: Collision mitigation #1995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/bttester/src/btp/btp_gatt.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ struct btp_gatt_set_mult_val_cmd {
uint8_t data[0];
} __packed;

#define BTP_GATT_EATT_CONNECT 0x1f
struct btp_gatt_eatt_conn_cmd {
ble_addr_t address;
uint8_t num_channels;
} __packed;

/* GATT events */
#define BTP_GATT_EV_NOTIFICATION 0x80
struct btp_gatt_notification_ev {
Expand Down
21 changes: 21 additions & 0 deletions apps/bttester/src/btp_gatt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1950,6 +1950,21 @@ set_mult(const void *cmd, uint16_t cmd_len,
return BTP_STATUS_SUCCESS;
}

static uint8_t
eatt_conn(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
uint16_t conn_handle;
const struct btp_gatt_eatt_conn_cmd *cp = cmd;

ble_gap_conn_find_handle_by_addr(&cp->address, &conn_handle);

ble_eatt_connect(conn_handle, cp->num_channels);

return BTP_STATUS_SUCCESS;
}


static uint8_t
change_database(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
Expand Down Expand Up @@ -2001,6 +2016,7 @@ supported_commands(const void *cmd, uint16_t cmd_len,
tester_set_bit(rp->data, BTP_GATT_GET_ATTRIBUTES);
tester_set_bit(rp->data, BTP_GATT_GET_ATTRIBUTE_VALUE);
tester_set_bit(rp->data, BTP_GATT_CHANGE_DATABASE);
tester_set_bit(rp->data, BTP_GATT_EATT_CONNECT);

*rsp_len = sizeof(*rp) + 4;

Expand Down Expand Up @@ -2137,6 +2153,11 @@ static const struct btp_handler handlers[] = {
.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
.func = set_mult,
},
{
.opcode = BTP_GATT_EATT_CONNECT,
.expect_len = sizeof(struct btp_gatt_eatt_conn_cmd),
.func = eatt_conn,
}
};

int
Expand Down
2 changes: 1 addition & 1 deletion apps/bttester/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ syscfg.vals.!BTTESTER_NODEFAULT:
BLE_L2CAP_COC_MAX_NUM: 5
BLE_L2CAP_SIG_MAX_PROCS: 2
BLE_L2CAP_ENHANCED_COC: 1
BLE_EATT_CHAN_NUM: 5
BLE_EATT_CHAN_NUM: 1
# Some testcases require MPS < MTU
BLE_L2CAP_COC_MPS: 100
BLE_RPA_TIMEOUT: 30
Expand Down
2 changes: 2 additions & 0 deletions nimble/host/include/host/ble_att.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ uint16_t ble_att_preferred_mtu(void);
*/
int ble_att_set_preferred_mtu(uint16_t mtu);

void ble_eatt_connect(uint16_t conn_handle, uint16_t num_channels);

#ifdef __cplusplus
}
#endif
Expand Down
72 changes: 61 additions & 11 deletions nimble/host/src/ble_eatt.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ SLIST_HEAD(ble_eatt_list, ble_eatt);
static struct ble_eatt_list g_ble_eatt_list;
static ble_eatt_att_rx_fn ble_eatt_att_rx_cb;

static uint8_t retry_cnt;
static uint8_t prev_conn_result;

#define BLE_EATT_DATABUF_SIZE ( \
MYNEWT_VAL(BLE_EATT_MTU) + \
2 + \
Expand Down Expand Up @@ -214,6 +217,38 @@ ble_eatt_free(struct ble_eatt *eatt)
os_memblock_put(&ble_eatt_conn_pool, eatt);
}

static void
ble_eatt_retry(uint16_t conn_handle, struct ble_eatt *eatt)
{
struct ble_gap_conn_desc desc;
int rc;

if (retry_cnt > 2) {
ble_eatt_free(eatt);
return;
}

rc = ble_gap_conn_find(conn_handle, &desc);
assert(rc == 0);

/*
* 5.3 Vol 3, Part G, Sec. 5.4 L2CAP collision mitigation
* Peripheral shall wait some time before retrying connection
* We are waiting here for 500 ms
*/
if (desc.role == BLE_GAP_ROLE_SLAVE) {
BLE_EATT_LOG_DEBUG("eatt: Collision - wait before reconnect\n");
os_time_delay(500 * OS_TICKS_PER_SEC / 1000);
}

eatt->conn_handle = conn_handle;

retry_cnt++;

/* Setup EATT */
ble_npl_eventq_put(ble_hs_evq_get(), &eatt->setup_ev);
}

static int
ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
{
Expand All @@ -225,9 +260,15 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
switch (event->type) {
case BLE_L2CAP_EVENT_COC_CONNECTED:
BLE_EATT_LOG_DEBUG("eatt: Connected \n");
if (event->connect.status) {
ble_eatt_free(eatt);
BLE_EATT_LOG_DEBUG("eatt: Conneted status: %d \n", event->connect.status);
if (event->connect.status == 6 &&
prev_conn_result == BLE_L2CAP_COC_ERR_NO_RESOURCES) {
BLE_EATT_LOG_DEBUG("eatt: Limited resources error\n");
prev_conn_result = BLE_L2CAP_COC_ERR_NO_RESOURCES;
ble_eatt_retry(event->connect.conn_handle, eatt);
return 0;
} else if (event->connect.status) {
ble_eatt_free(eatt);
}
eatt->chan = event->connect.chan;
break;
Expand All @@ -239,22 +280,25 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
BLE_EATT_LOG_DEBUG("eatt: Accept request\n");
eatt = ble_eatt_find_by_conn_handle(event->accept.conn_handle);
if (eatt) {
BLE_EATT_LOG_DEBUG("eatt: Accept no mem 1\n");
/* For now we accept only one additional coc channel per ACL
* TODO: improve it
*/
prev_conn_result = BLE_L2CAP_COC_ERR_NO_RESOURCES;
return BLE_HS_ENOMEM;
}

eatt = ble_eatt_alloc();
if (!eatt) {
BLE_EATT_LOG_DEBUG("eatt: Accept no mem 2\n");
return BLE_HS_ENOMEM;
}

eatt->conn_handle = event->accept.conn_handle;
event->accept.chan->cb_arg = eatt;

rc = ble_eatt_prepare_rx_sdu(event->accept.chan);
if (rc) {
BLE_EATT_LOG_DEBUG("eatt: Accept no mem 3\n");
ble_eatt_free(eatt);
return rc;
}
Expand Down Expand Up @@ -341,7 +385,9 @@ ble_eatt_setup_cb(struct ble_npl_event *ev)
BLE_EATT_LOG_ERROR("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n",
eatt->conn_handle, rc);
os_mbuf_free_chain(om);
ble_eatt_free(eatt);
if (rc != BLE_L2CAP_COC_ERR_NO_RESOURCES) {
ble_eatt_free(eatt);
}
}
}

Expand Down Expand Up @@ -509,16 +555,14 @@ ble_eatt_start(uint16_t conn_handle)

rc = ble_gap_conn_find(conn_handle, &desc);
assert(rc == 0);
if (desc.role != BLE_GAP_ROLE_MASTER) {
/* Let master to create ecoc.
* TODO: Slave could setup after some timeout
*/
return;
}

eatt = ble_eatt_alloc();
eatt = ble_eatt_find_by_conn_handle(conn_handle);
if (!eatt) {
eatt = ble_eatt_alloc();
if (!eatt) {
BLE_EATT_LOG_ERROR("eatt: %s, ERROR %d ", __func__, rc);
return;
}
}

eatt->conn_handle = conn_handle;
Expand All @@ -527,6 +571,12 @@ ble_eatt_start(uint16_t conn_handle)
ble_npl_eventq_put(ble_hs_evq_get(), &eatt->setup_ev);
}

void
ble_eatt_connect(uint16_t conn_handle, uint16_t num_channels)
{
ble_eatt_start(conn_handle);
}

void
ble_eatt_init(ble_eatt_att_rx_fn att_rx_cb)
{
Expand Down