mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-05 00:30:02 +00:00
nimble/host/ble_l2cap_coc: SDUs for faster data rx
Added list of SDUs for faster data rx. This allows to process more data while receiving another.
This commit is contained in:
committed by
Szymon Janc
parent
5ea8badc46
commit
c1a2c99498
@@ -175,6 +175,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
{
|
||||
int rc;
|
||||
struct os_mbuf **om;
|
||||
struct os_mbuf *rx_sdu;
|
||||
struct ble_l2cap_coc_endpoint *rx;
|
||||
uint16_t om_total;
|
||||
|
||||
@@ -186,10 +187,13 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
rx = &chan->coc_rx;
|
||||
BLE_HS_DBG_ASSERT(rx != NULL);
|
||||
|
||||
rx_sdu = rx->sdus[chan->coc_rx.current_sdu_idx];
|
||||
BLE_HS_DBG_ASSERT(rx_sdu != NULL);
|
||||
|
||||
om_total = OS_MBUF_PKTLEN(*om);
|
||||
|
||||
/* First LE frame */
|
||||
if (OS_MBUF_PKTLEN(rx->sdu) == 0) {
|
||||
if (OS_MBUF_PKTLEN(rx_sdu) == 0) {
|
||||
uint16_t sdu_len;
|
||||
|
||||
rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SDU_SIZE);
|
||||
@@ -199,12 +203,15 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
|
||||
sdu_len = get_le16((*om)->om_data);
|
||||
|
||||
BLE_HS_LOG(INFO, "First LE frame received %d, SDU len: %d\n",
|
||||
om_total, sdu_len + 2);
|
||||
|
||||
/* We should receive payload of size sdu_len + 2 bytes of sdu_len field */
|
||||
if (om_total > sdu_len + 2) {
|
||||
BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n",
|
||||
om_total, sdu_len + 2);
|
||||
/* Disconnect peer with invalid behaviour */
|
||||
rx->sdu = NULL;
|
||||
rx_sdu = NULL;
|
||||
rx->data_offset = 0;
|
||||
ble_l2cap_disconnect(chan);
|
||||
return BLE_HS_EBADDATA;
|
||||
@@ -218,12 +225,13 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
return BLE_HS_EBADDATA;
|
||||
}
|
||||
|
||||
BLE_HS_LOG(DEBUG, "sdu_len=%d, received LE frame=%d, credits=%d\n",
|
||||
sdu_len, om_total, rx->credits);
|
||||
BLE_HS_LOG(DEBUG,
|
||||
"sdu_len=%d, received LE frame=%d, credits=%d, current_sdu_idx=%d\n",
|
||||
sdu_len, om_total, rx->credits, chan->coc_rx.current_sdu_idx);
|
||||
|
||||
os_mbuf_adj(*om , BLE_L2CAP_SDU_SIZE);
|
||||
|
||||
rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total - BLE_L2CAP_SDU_SIZE);
|
||||
rc = os_mbuf_appendfrom(rx_sdu, *om, 0, om_total - BLE_L2CAP_SDU_SIZE);
|
||||
if (rc != 0) {
|
||||
/* FIXME: User shall give us big enough buffer.
|
||||
* need to handle it better
|
||||
@@ -238,16 +246,16 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
} else {
|
||||
BLE_HS_LOG(DEBUG, "Continuation...received %d\n", (*om)->om_len);
|
||||
|
||||
if (OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len > rx->data_offset) {
|
||||
if (OS_MBUF_PKTLEN(rx_sdu) + (*om)->om_len > rx->data_offset) {
|
||||
/* Disconnect peer with invalid behaviour */
|
||||
BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n",
|
||||
OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len, rx->data_offset);
|
||||
rx->sdu = NULL;
|
||||
OS_MBUF_PKTLEN(rx_sdu) + (*om)->om_len, rx->data_offset);
|
||||
rx_sdu = NULL;
|
||||
rx->data_offset = 0;
|
||||
ble_l2cap_disconnect(chan);
|
||||
return BLE_HS_EBADDATA;
|
||||
}
|
||||
rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total);
|
||||
rc = os_mbuf_appendfrom(rx_sdu, *om, 0, om_total);
|
||||
if (rc != 0) {
|
||||
/* FIXME: need to handle it better */
|
||||
BLE_HS_LOG(DEBUG, "Could not append data rc=%d\n", rc);
|
||||
@@ -257,17 +265,19 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
|
||||
rx->credits--;
|
||||
|
||||
if (OS_MBUF_PKTLEN(rx->sdu) == rx->data_offset) {
|
||||
struct os_mbuf *sdu_rx = rx->sdu;
|
||||
if (OS_MBUF_PKTLEN(rx_sdu) == rx->data_offset) {
|
||||
struct os_mbuf *sdu_rx = rx_sdu;
|
||||
|
||||
BLE_HS_LOG(DEBUG, "Received sdu_len=%d, credits left=%d\n",
|
||||
OS_MBUF_PKTLEN(rx->sdu), rx->credits);
|
||||
OS_MBUF_PKTLEN(rx_sdu), rx->credits);
|
||||
|
||||
/* Lets get back control to os_mbuf to application.
|
||||
* Since it this callback application might want to set new sdu
|
||||
* we need to prepare space for this. Therefore we need sdu_rx
|
||||
*/
|
||||
rx->sdu = NULL;
|
||||
rx_sdu = NULL;
|
||||
chan->coc_rx.current_sdu_idx =
|
||||
(chan->coc_rx.current_sdu_idx + 1) % BLE_L2CAP_SDU_BUFF_CNT;
|
||||
rx->data_offset = 0;
|
||||
|
||||
ble_l2cap_event_coc_received_data(chan, sdu_rx);
|
||||
@@ -288,8 +298,9 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
|
||||
ble_l2cap_sig_le_credits(chan->conn_handle, chan->scid, rx->credits);
|
||||
}
|
||||
|
||||
BLE_HS_LOG(DEBUG, "Received partial sdu_len=%d, credits left=%d\n",
|
||||
OS_MBUF_PKTLEN(rx->sdu), rx->credits);
|
||||
BLE_HS_LOG(DEBUG,
|
||||
"Received partial sdu_len=%d, credits left=%d, current_sdu_idx=%d\n",
|
||||
OS_MBUF_PKTLEN(rx_sdu), rx->credits, chan->coc_rx.current_sdu_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -324,7 +335,12 @@ ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn, uint16_t psm, uint16_t mtu,
|
||||
chan->my_coc_mps = MYNEWT_VAL(BLE_L2CAP_COC_MPS);
|
||||
chan->rx_fn = ble_l2cap_coc_rx_fn;
|
||||
chan->coc_rx.mtu = mtu;
|
||||
chan->coc_rx.sdu = sdu_rx;
|
||||
chan->coc_rx.sdus[0] = sdu_rx;
|
||||
for (int i = 1; i < BLE_L2CAP_SDU_BUFF_CNT; i++) {
|
||||
chan->coc_rx.sdus[i] = NULL;
|
||||
}
|
||||
chan->coc_rx.current_sdu_idx = 0;
|
||||
chan->coc_rx.next_sdu_alloc_idx = chan->coc_rx.sdus[0] == NULL ? 0 : 1;
|
||||
|
||||
/* Number of credits should allow to send full SDU with on given
|
||||
* L2CAP MTU
|
||||
@@ -391,8 +407,10 @@ ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan
|
||||
chan->scid - BLE_L2CAP_COC_CID_START);
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(chan->coc_rx.sdu);
|
||||
os_mbuf_free_chain(chan->coc_tx.sdu);
|
||||
for (int i = 0; i < BLE_L2CAP_SDU_BUFF_CNT; i++) {
|
||||
os_mbuf_free_chain(chan->coc_rx.sdus[i]);
|
||||
}
|
||||
os_mbuf_free_chain(chan->coc_tx.sdus[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -427,7 +445,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
|
||||
/* If there is no data to send, just return success */
|
||||
tx = &chan->coc_tx;
|
||||
if (!tx->sdu) {
|
||||
if (!tx->sdus[0]) {
|
||||
ble_hs_unlock();
|
||||
return 0;
|
||||
}
|
||||
@@ -438,7 +456,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
BLE_HS_LOG(DEBUG, "Available credits %d\n", tx->credits);
|
||||
|
||||
/* lets calculate data we are going to send */
|
||||
left_to_send = OS_MBUF_PKTLEN(tx->sdu) - tx->data_offset;
|
||||
left_to_send = OS_MBUF_PKTLEN(tx->sdus[0]) - tx->data_offset;
|
||||
|
||||
if (tx->data_offset == 0) {
|
||||
sdu_size_offset = BLE_L2CAP_SDU_SIZE;
|
||||
@@ -458,9 +476,10 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
|
||||
if (tx->data_offset == 0) {
|
||||
/* First packet needs SDU len first. Left to send */
|
||||
uint16_t l = htole16(OS_MBUF_PKTLEN(tx->sdu));
|
||||
uint16_t l = htole16(OS_MBUF_PKTLEN(tx->sdus[0]));
|
||||
|
||||
BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", OS_MBUF_PKTLEN(tx->sdu));
|
||||
BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n",
|
||||
OS_MBUF_PKTLEN(tx->sdus[0]));
|
||||
rc = os_mbuf_append(txom, &l, sizeof(uint16_t));
|
||||
if (rc) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
@@ -473,7 +492,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
* that for first packet we need to decrease data size by 2 bytes for sdu
|
||||
* size
|
||||
*/
|
||||
rc = os_mbuf_appendfrom(txom, tx->sdu, tx->data_offset,
|
||||
rc = os_mbuf_appendfrom(txom, tx->sdus[0], tx->data_offset,
|
||||
len - sdu_size_offset);
|
||||
if (rc) {
|
||||
rc = BLE_HS_ENOMEM;
|
||||
@@ -494,18 +513,19 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
}
|
||||
|
||||
BLE_HS_LOG(DEBUG, "Sent %d bytes, credits=%d, to send %d bytes \n",
|
||||
len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset);
|
||||
len, tx->credits,
|
||||
OS_MBUF_PKTLEN(tx->sdus[0]) - tx->data_offset);
|
||||
|
||||
if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdu)) {
|
||||
if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdus[0])) {
|
||||
BLE_HS_LOG(DEBUG, "Complete package sent\n");
|
||||
os_mbuf_free_chain(tx->sdu);
|
||||
tx->sdu = NULL;
|
||||
os_mbuf_free_chain(tx->sdus[0]);
|
||||
tx->sdus[0] = NULL;
|
||||
tx->data_offset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx->sdu) {
|
||||
if (tx->sdus[0]) {
|
||||
/* Not complete SDU sent, wait for credits */
|
||||
tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
|
||||
ble_hs_unlock();
|
||||
@@ -523,8 +543,8 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
os_mbuf_free_chain(tx->sdu);
|
||||
tx->sdu = NULL;
|
||||
os_mbuf_free_chain(tx->sdus[0]);
|
||||
tx->sdus[0] = NULL;
|
||||
|
||||
os_mbuf_free_chain(txom);
|
||||
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
|
||||
@@ -582,7 +602,14 @@ ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx)
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
chan->coc_rx.sdu = sdu_rx;
|
||||
if (chan->coc_rx.sdus[0] != NULL &&
|
||||
chan->coc_rx.next_sdu_alloc_idx == chan->coc_rx.current_sdu_idx) {
|
||||
return BLE_HS_EBUSY;
|
||||
}
|
||||
|
||||
chan->coc_rx.sdus[chan->coc_rx.next_sdu_alloc_idx] = sdu_rx;
|
||||
chan->coc_rx.next_sdu_alloc_idx =
|
||||
(chan->coc_rx.next_sdu_alloc_idx + 1) % BLE_L2CAP_SDU_BUFF_CNT;
|
||||
|
||||
ble_hs_lock();
|
||||
conn = ble_hs_conn_find_assert(chan->conn_handle);
|
||||
@@ -625,11 +652,11 @@ ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx)
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
if (tx->sdu) {
|
||||
if (tx->sdus[0]) {
|
||||
ble_hs_unlock();
|
||||
return BLE_HS_EBUSY;
|
||||
}
|
||||
tx->sdu = sdu_tx;
|
||||
tx->sdus[0] = sdu_tx;
|
||||
|
||||
|
||||
/* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
|
||||
|
||||
@@ -37,8 +37,14 @@ struct ble_l2cap_chan;
|
||||
|
||||
#define BLE_L2CAP_COC_FLAG_STALLED 0x01
|
||||
|
||||
#define BLE_L2CAP_SDU_BUFF_CNT (MYNEWT_VAL(BLE_L2CAP_COC_SDU_BUFF_COUNT))
|
||||
|
||||
struct ble_l2cap_coc_endpoint {
|
||||
struct os_mbuf *sdu;
|
||||
struct os_mbuf *sdus[BLE_L2CAP_SDU_BUFF_CNT];
|
||||
/* Index for currently used sdu from sdus */
|
||||
uint16_t current_sdu_idx;
|
||||
/* Index indicating free sdus slot to allocate next sdu */
|
||||
uint16_t next_sdu_alloc_idx;
|
||||
uint16_t mtu;
|
||||
uint16_t credits;
|
||||
uint16_t data_offset;
|
||||
|
||||
@@ -79,7 +79,13 @@ syscfg.defs:
|
||||
the required HCI and L2CAP headers fit into the smallest available
|
||||
MSYS blocks.
|
||||
value: 'MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8'
|
||||
|
||||
BLE_L2CAP_COC_SDU_BUFF_COUNT:
|
||||
description: >
|
||||
Defines maximum number of SDU buffers in L2CAP COC endpoints.
|
||||
Provides more currently available credits to receive more data packets.
|
||||
value: 1
|
||||
restrictions:
|
||||
- 'BLE_L2CAP_COC_SDU_BUFF_COUNT > 0'
|
||||
BLE_L2CAP_ENHANCED_COC:
|
||||
description: >
|
||||
Enables LE Enhanced CoC mode.
|
||||
|
||||
Reference in New Issue
Block a user