Skip to content

Commit cafacb8

Browse files
jori-nordicalwa-nordic
authored andcommitted
Bluetooth: host: Send host num completes as early as possible
The Softdevice Controller now sends the disconnect event only after receiving all Host Num Completes for the packets it sent to the host. This is done for security reasons. In our current reassembly logic, it does not really matter when we withhold the num complete. Before this patch, it's the first fragment that is withheld, and after the patch it will be the last fragment that is withheld until the host is done processing. The flow control properties are maintained, just in a different way. Co-authored-by: Aleksander Wasaznik <[email protected]> Signed-off-by: Jonathan Rico <[email protected]> (cherry picked from commit 147ee3d) Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent e5b66a7 commit cafacb8

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

subsys/bluetooth/host/conn.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,12 @@ void bt_conn_reset_rx_state(struct bt_conn *conn)
283283
conn->rx = NULL;
284284
}
285285

286-
static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
287-
uint8_t flags)
286+
static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf, uint8_t flags)
288287
{
289288
uint16_t acl_total_len;
290289

290+
bt_acl_set_ncp_sent(buf, false);
291+
291292
/* Check packet boundary flags */
292293
switch (flags) {
293294
case BT_ACL_START:
@@ -299,7 +300,7 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
299300
LOG_DBG("First, len %u final %u", buf->len,
300301
(buf->len < sizeof(uint16_t)) ? 0 : sys_get_le16(buf->data));
301302

302-
conn->rx = buf;
303+
conn->rx = net_buf_ref(buf);
303304
break;
304305
case BT_ACL_CONT:
305306
if (!conn->rx) {
@@ -329,7 +330,6 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
329330
}
330331

331332
net_buf_add_mem(conn->rx, buf->data, buf->len);
332-
net_buf_unref(buf);
333333
break;
334334
default:
335335
/* BT_ACL_START_NO_FLUSH and BT_ACL_COMPLETE are not allowed on
@@ -346,16 +346,26 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
346346
/* Still not enough data received to retrieve the L2CAP header
347347
* length field.
348348
*/
349+
bt_send_one_host_num_completed_packets(conn->handle);
350+
bt_acl_set_ncp_sent(buf, true);
351+
net_buf_unref(buf);
352+
349353
return;
350354
}
351355

352356
acl_total_len = sys_get_le16(conn->rx->data) + sizeof(struct bt_l2cap_hdr);
353357

354358
if (conn->rx->len < acl_total_len) {
355359
/* L2CAP frame not complete. */
360+
bt_send_one_host_num_completed_packets(conn->handle);
361+
bt_acl_set_ncp_sent(buf, true);
362+
net_buf_unref(buf);
363+
356364
return;
357365
}
358366

367+
net_buf_unref(buf);
368+
359369
if (conn->rx->len > acl_total_len) {
360370
LOG_ERR("ACL len mismatch (%u > %u)", conn->rx->len, acl_total_len);
361371
bt_conn_reset_rx_state(conn);
@@ -366,6 +376,8 @@ static void bt_acl_recv(struct bt_conn *conn, struct net_buf *buf,
366376
buf = conn->rx;
367377
conn->rx = NULL;
368378

379+
__ASSERT(buf->ref == 1, "buf->ref %d", buf->ref);
380+
369381
LOG_DBG("Successfully parsed %u byte L2CAP packet", buf->len);
370382
bt_l2cap_recv(conn, buf, true);
371383
}

subsys/bluetooth/host/conn_internal.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,12 @@ struct acl_data {
151151
struct bt_buf_data buf_data;
152152

153153
/* Index into the bt_conn storage array */
154-
uint8_t index;
154+
uint8_t index;
155+
156+
/** Host has already sent a Host Number of Completed Packets
157+
* for this buffer.
158+
*/
159+
bool host_ncp_sent;
155160

156161
/** ACL connection handle */
157162
uint16_t handle;

subsys/bluetooth/host/hci_core.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ static void handle_vs_event(uint8_t event, struct net_buf *buf,
196196
/* Other possible errors are handled by handle_event_common function */
197197
}
198198

199+
void bt_acl_set_ncp_sent(struct net_buf *packet, bool value)
200+
{
201+
acl(packet)->host_ncp_sent = value;
202+
}
203+
199204
void bt_send_one_host_num_completed_packets(uint16_t handle)
200205
{
201206
if (!IS_ENABLED(CONFIG_BT_HCI_ACL_FLOW_CONTROL)) {
@@ -234,6 +239,10 @@ void bt_hci_host_num_completed_packets(struct net_buf *buf)
234239

235240
net_buf_destroy(buf);
236241

242+
if (acl(buf)->host_ncp_sent) {
243+
return;
244+
}
245+
237246
/* Do nothing if controller to host flow control is not supported */
238247
if (!BT_CMD_TEST(bt_dev.supported_commands, 10, 5)) {
239248
return;

subsys/bluetooth/host/hci_core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,3 +527,6 @@ void bt_hci_le_df_cte_req_failed(struct net_buf *buf);
527527

528528
void bt_hci_le_per_adv_subevent_data_request(struct net_buf *buf);
529529
void bt_hci_le_per_adv_response_report(struct net_buf *buf);
530+
531+
void bt_send_one_host_num_completed_packets(uint16_t handle);
532+
void bt_acl_set_ncp_sent(struct net_buf *packet, bool value);

0 commit comments

Comments
 (0)