You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ja...@apache.org on 2022/09/05 07:46:13 UTC

[mynewt-nimble] 01/02: nimble/host/ble_l2cap_coc: SDUs for faster data rx

This is an automated email from the ASF dual-hosted git repository.

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit c1a2c9949805148520afb852d86afe588061d64e
Author: Jakub Rotkiewicz <ja...@codecoup.pl>
AuthorDate: Wed Jul 27 09:23:42 2022 +0200

    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.
---
 nimble/host/src/ble_l2cap_coc.c      | 93 +++++++++++++++++++++++-------------
 nimble/host/src/ble_l2cap_coc_priv.h |  8 +++-
 nimble/host/syscfg.yml               |  8 +++-
 3 files changed, 74 insertions(+), 35 deletions(-)

diff --git a/nimble/host/src/ble_l2cap_coc.c b/nimble/host/src/ble_l2cap_coc.c
index f74cea28..973ff75f 100644
--- a/nimble/host/src/ble_l2cap_coc.c
+++ b/nimble/host/src/ble_l2cap_coc.c
@@ -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() */
diff --git a/nimble/host/src/ble_l2cap_coc_priv.h b/nimble/host/src/ble_l2cap_coc_priv.h
index 5ebdaa05..37a95b31 100644
--- a/nimble/host/src/ble_l2cap_coc_priv.h
+++ b/nimble/host/src/ble_l2cap_coc_priv.h
@@ -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;
diff --git a/nimble/host/syscfg.yml b/nimble/host/syscfg.yml
index ec55878e..cf35be24 100644
--- a/nimble/host/syscfg.yml
+++ b/nimble/host/syscfg.yml
@@ -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.