Skip to content

Commit 21408d3

Browse files
nimble/eatt: Collision mitigation handling
TBD
1 parent 3e3a621 commit 21408d3

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

nimble/host/src/ble_eatt.c

Lines changed: 48 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
#if (MYNEWT_VAL(BLE_EATT_AUTO_CONNECT))
203210
void
204211
ble_eatt_auto_conn_cb(struct os_event *ev)
@@ -231,7 +238,8 @@ ble_eatt_alloc(void)
231238
eatt->used_channels = 0;
232239

233240
STAILQ_INIT(&eatt->eatt_tx_q);
234-
241+
os_callout_init(&eatt->collision_co, os_eventq_dflt_get(),
242+
ble_eatt_collision_ev, NULL);
235243
os_callout_init(&eatt->auto_conn_delay, os_eventq_dflt_get(),
236244
ble_eatt_auto_conn_cb, NULL);
237245
ble_npl_event_init(&eatt->setup_ev, ble_eatt_setup_cb, eatt);
@@ -259,25 +267,49 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
259267
{
260268
struct ble_eatt *eatt = arg;
261269
struct ble_gap_conn_desc desc;
262-
uint8_t free_channels;
263270
uint8_t opcode;
271+
uint8_t free_channels;
272+
uint8_t coll_delay;
273+
uint8_t rand_part;
264274
int rc;
265275

266276
switch (event->type) {
267277
case BLE_L2CAP_EVENT_COC_CONNECTED:
268278
eatt = ble_eatt_find_by_conn_handle(event->connect.conn_handle);
279+
269280
BLE_EATT_LOG_DEBUG("eatt: Connected event | conn_handle: %d | scid: %d | dcid: %d\n",
270281
event->connect.conn_handle, event->connect.chan->scid,
271282
event->connect.chan->dcid);
272283

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

278307
eatt->chan = event->connect.chan;
279308
eatt->conn_handle = event->connect.conn_handle;
280309

310+
/* Delete collision callout on successfull connection */
311+
os_callout_stop(&eatt->collision_co);
312+
eatt->collision_ctrl = false;
281313

282314
/* Increase used channel number on connected event */
283315
eatt->used_channels++;
@@ -317,7 +349,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
317349

318350
if (free_channels == 0) {
319351
BLE_EATT_LOG_ERROR("eatt: Accept event | No free channel slots\n");
320-
eatt->no_res_error = BLE_L2CAP_COC_ERR_NO_RESOURCES;
352+
eatt->collision_ctrl = true;
321353
return BLE_HS_ENOMEM;
322354
}
323355
}
@@ -657,9 +689,16 @@ ble_eatt_connect(uint16_t conn_handle, uint8_t chan_num)
657689
}
658690

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

0 commit comments

Comments
 (0)