Skip to content

Commit 8d56513

Browse files
nimble/eatt: Collision mitigation handling
TBD
1 parent 8145e02 commit 8d56513

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

nimble/host/src/ble_eatt.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,17 @@
3434

3535
struct ble_eatt {
3636
SLIST_ENTRY(ble_eatt) next;
37-
uint16_t conn_handle;
3837
struct ble_l2cap_chan *chan;
39-
uint8_t chan_num;
4038
uint8_t used_channels;
39+
uint16_t conn_handle;
40+
bool collision_ctrl;
4141
uint8_t client_op;
42+
uint8_t chan_num;
4243
uint8_t accept_chans;
4344

4445
/* Packet transmit queue */
4546
STAILQ_HEAD(, os_mbuf_pkthdr) eatt_tx_q;
46-
47+
struct os_callout collision_co;
4748
struct ble_npl_event setup_ev;
4849
struct ble_npl_event wakeup_ev;
4950

@@ -147,6 +148,7 @@ ble_eatt_used_channels(uint16_t conn_handle)
147148
struct ble_eatt *eatt;
148149
size_t used_channels = 0;
149150

151+
150152
SLIST_FOREACH(eatt, &g_ble_eatt_list, next) {
151153
if (eatt->conn_handle == conn_handle) {
152154
used_channels += eatt->used_channels;
@@ -199,6 +201,11 @@ ble_eatt_wakeup_cb(struct ble_npl_event *ev)
199201
}
200202
}
201203

204+
static void
205+
ble_eatt_collision_ev(struct os_event *ev)
206+
{
207+
BLE_EATT_LOG_DEBUG("eatt: Collision delay expired\n");
208+
}
202209

203210
#if (MYNEWT_VAL(BLE_EATT_AUTO_CONNECT))
204211
void
@@ -232,7 +239,7 @@ ble_eatt_alloc(void)
232239
eatt->used_channels = 0;
233240

234241
STAILQ_INIT(&eatt->eatt_tx_q);
235-
242+
os_callout_init(&eatt->collision_co, os_eventq_dflt_get(),
236243
#if (MYNEWT_VAL(BLE_EATT_AUTO_CONNECT))
237244
os_callout_init(&eatt->auto_conn_delay, os_eventq_dflt_get(),
238245
ble_eatt_auto_conn_cb, NULL);
@@ -262,25 +269,49 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
262269
{
263270
struct ble_eatt *eatt = arg;
264271
struct ble_gap_conn_desc desc;
265-
uint8_t free_channels;
266272
uint8_t opcode;
273+
uint8_t free_channels;
274+
uint8_t coll_delay;
275+
uint8_t rand_part;
267276
int rc;
268277

269278
switch (event->type) {
270279
case BLE_L2CAP_EVENT_COC_CONNECTED:
271280
eatt = ble_eatt_find_by_conn_handle(event->connect.conn_handle);
281+
272282
BLE_EATT_LOG_DEBUG("eatt: Connected event | conn_handle: %d | scid: %d | dcid: %d\n",
273283
event->connect.conn_handle, event->connect.chan->scid,
274284
event->connect.chan->dcid);
275285

286+
if (event->connect.status == BLE_HS_ENOMEM && eatt->collision_ctrl) {
287+
BLE_EATT_LOG_DEBUG("eatt: Connection collision\n");
288+
289+
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
290+
assert(rc == 0);
291+
292+
rc = ble_hs_hci_rand(&rand_part, 1);
293+
if (rc != 0) {
294+
return rc;
295+
}
296+
297+
coll_delay = (rand_part % 5) + 2 * (desc.conn_latency + 1) * desc.conn_itvl;
298+
299+
os_callout_reset(&eatt->collision_co, OS_TICKS_PER_SEC / 1000 * coll_delay);
300+
301+
return 0;
302+
}
303+
276304
if (event->connect.status) {
277-
ble_eatt_free(eatt);
305+
eatt->used_channels--;
278306
return 0;
279307
}
280308

281309
eatt->chan = event->connect.chan;
282310
eatt->conn_handle = event->connect.conn_handle;
283311

312+
/* Delete collision callout on successfull connection */
313+
os_callout_stop(&eatt->collision_co);
314+
eatt->collision_ctrl = false;
284315

285316
/* Increase used channel number on connected event */
286317
eatt->used_channels++;
@@ -320,7 +351,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
320351

321352
if (free_channels == 0) {
322353
BLE_EATT_LOG_ERROR("eatt: Accept event | No free channel slots\n");
323-
eatt->no_res_error = BLE_L2CAP_COC_ERR_NO_RESOURCES;
354+
eatt->collision_ctrl = true;
324355
return BLE_HS_ENOMEM;
325356
}
326357
}
@@ -659,9 +690,16 @@ ble_eatt_connect(uint16_t conn_handle, uint8_t chan_num)
659690
}
660691

661692
/*
662-
* Warn about exceeding the number
663-
* of maximum per-conn EATT connections.
693+
* 5.3 Vol 3, Part G, Sec. 5.4 L2CAP collision mitigation
694+
* Peripheral shall wait some time before retrying connection.
695+
* Central may reconnect without any delay.
696+
* To reconnect user has to call ble_eatt_connect again.
664697
*/
698+
if (desc.role == BLE_GAP_ROLE_SLAVE && os_callout_queued(&eatt->collision_co)) {
699+
BLE_EATT_LOG_WARN("ble_eatt_connect: Connection collision\n");
700+
return;
701+
}
702+
665703
if (chan_num == 0 || chan_num > MYNEWT_VAL(BLE_EATT_CHAN_PER_CONN)) {
666704
BLE_EATT_LOG_WARN("ble_eatt_connect | Invalid channel number\n");
667705
return;

0 commit comments

Comments
 (0)