Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 745ec6f49 -> 6410e4375


MYNEWT-555 BLE Host - Avoid mbuf copy on chr read

When the host receives any form of characteristic read request, an
extraneous mbuf gets allocated. The sequence is:

    1. Allocate new mbuf.
    2. Pass new mbuf to application code so app can fill in
       characteristic value.
    3. Copy characteristic value out of new mbuf into response mbuf
    4. Free new mbuf

The reason for the extra allocation is to simplify reads that specify
non-zero offsets. In the case of a GATT read, the peer may read from
different offsets of the characteristic. In an effort to simplify the
API, I decided the requested offset should be hidden from the
application. Instead, the application always provides the full
characteristic value, and the host copies the requested portion out of
the user-filled mbuf and into the ACL data packet.

The fix is to try to reuse the response to hold the characteristic data.
This can be done if the read request specifies an offset of 0. For
non-zero offsets, the old behavior remains: allocate an extra mbuf and
copy the data.

Additional context:
https://lists.apache.org/thread.html/78358745716cac9512b3c659dfe9b9b7bbb1354ee4c38d6da137bcc0@%3Cdev.mynewt.apache.org%3E


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/6410e437
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/6410e437
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/6410e437

Branch: refs/heads/develop
Commit: 6410e4375caf15bb265cf4a641f8e669e45bbd8c
Parents: 745ec6f
Author: Christopher Collins <[email protected]>
Authored: Sun Jan 22 10:14:04 2017 -0800
Committer: Christopher Collins <[email protected]>
Committed: Sun Jan 22 10:14:04 2017 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_gatts.c | 37 +++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6410e437/net/nimble/host/src/ble_gatts.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatts.c b/net/nimble/host/src/ble_gatts.c
index 075233d..aa09fe7 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -313,28 +313,51 @@ ble_gatts_val_access(uint16_t conn_handle, uint16_t 
attr_handle,
                      struct os_mbuf **om, ble_gatt_access_fn *access_cb,
                      void *cb_arg)
 {
+    uint16_t initial_len;
     int attr_len;
+    int new_om;
     int rc;
 
     switch (gatt_ctxt->op) {
     case BLE_GATT_ACCESS_OP_READ_CHR:
     case BLE_GATT_ACCESS_OP_READ_DSC:
-        gatt_ctxt->om = os_msys_get_pkthdr(0, 0);
-        if (gatt_ctxt->om == NULL) {
-            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        /* A characteristic value is being read.
+         *
+         * If the read specifies an offset of 0:
+         *     just append the characteristic value directly onto the response
+         *     mbuf.
+         *
+         * Else:
+         *     allocate a new mbuf to hold the characteristic data, then append
+         *     the requested portion onto the response mbuf.
+         */
+        if (offset == 0) {
+            new_om = 0;
+            gatt_ctxt->om = *om;
+        } else {
+            new_om = 1;
+            gatt_ctxt->om = os_msys_get_pkthdr(0, 0);
+            if (gatt_ctxt->om == NULL) {
+                return BLE_ATT_ERR_INSUFFICIENT_RES;
+            }
         }
 
+        initial_len = OS_MBUF_PKTLEN(gatt_ctxt->om);
         rc = access_cb(conn_handle, attr_handle, gatt_ctxt, cb_arg);
         if (rc == 0) {
-            attr_len = OS_MBUF_PKTLEN(gatt_ctxt->om) - offset;
+            attr_len = OS_MBUF_PKTLEN(gatt_ctxt->om) - initial_len - offset;
             if (attr_len >= 0) {
-                os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len);
+                if (new_om) {
+                    os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len);
+                }
             } else {
-                return BLE_ATT_ERR_INVALID_OFFSET;
+                rc = BLE_ATT_ERR_INVALID_OFFSET;
             }
         }
 
-        os_mbuf_free_chain(gatt_ctxt->om);
+        if (new_om) {
+            os_mbuf_free_chain(gatt_ctxt->om);
+        }
         return rc;
 
     case BLE_GATT_ACCESS_OP_WRITE_CHR:

Reply via email to