You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/07/23 02:47:34 UTC

[07/11] incubator-mynewt-core git commit: BLE Host - Use mbufs instead of flat bufs.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/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 8edc5e3..9c645a9 100644
--- a/net/nimble/host/src/ble_gatts.c
+++ b/net/nimble/host/src/ble_gatts.c
@@ -66,11 +66,13 @@ STATS_NAME_END(ble_gatts_stats)
 
 static int
 ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
-                     uint8_t *uuid128, uint8_t op,
-                     struct ble_att_svr_access_ctxt *ctxt, void *arg)
+                     uint8_t op, uint16_t offset, struct os_mbuf **om,
+                     void *arg)
 {
     const struct ble_gatt_svc_def *svc;
     uint16_t uuid16;
+    uint8_t *buf;
+    int rc;
 
     STATS_INC(ble_gatts_stats, svc_def_reads);
 
@@ -80,11 +82,16 @@ ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
 
     uuid16 = ble_uuid_128_to_16(svc->uuid128);
     if (uuid16 != 0) {
-        htole16(ctxt->read.buf, uuid16);
-        ctxt->read.len = 2;
+        buf = os_mbuf_extend(*om, 2);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+        htole16(buf, uuid16);
     } else {
-        ctxt->read.data = svc->uuid128;
-        ctxt->read.len = 16;
+        rc = os_mbuf_append(*om, svc->uuid128, 16);
+        if (rc != 0) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
     }
 
     return 0;
@@ -92,11 +99,12 @@ ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle,
 
 static int
 ble_gatts_inc_access(uint16_t conn_handle, uint16_t attr_handle,
-                     uint8_t *uuid128, uint8_t op,
-                     struct ble_att_svr_access_ctxt *ctxt, void *arg)
+                     uint8_t op, uint16_t offset, struct os_mbuf **om,
+                     void *arg)
 {
     const struct ble_gatts_svc_entry *entry;
     uint16_t uuid16;
+    uint8_t *buf;
 
     STATS_INC(ble_gatts_stats, svc_inc_reads);
 
@@ -104,16 +112,21 @@ ble_gatts_inc_access(uint16_t conn_handle, uint16_t attr_handle,
 
     entry = arg;
 
-    htole16(ctxt->read.buf + 0, entry->handle);
-    htole16(ctxt->read.buf + 2, entry->end_group_handle);
+    buf = os_mbuf_extend(*om, 4);
+    if (buf == NULL) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+    htole16(buf + 0, entry->handle);
+    htole16(buf + 2, entry->end_group_handle);
 
     /* Only include the service UUID if it has a 16-bit representation. */
     uuid16 = ble_uuid_128_to_16(entry->svc->uuid128);
     if (uuid16 != 0) {
-        htole16(ctxt->read.buf + 4, uuid16);
-        ctxt->read.len = 6;
-    } else {
-        ctxt->read.len = 4;
+        buf = os_mbuf_extend(*om, 2);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+        htole16(buf, uuid16);
     }
 
     return 0;
@@ -208,11 +221,12 @@ ble_gatts_chr_properties(const struct ble_gatt_chr_def *chr)
 
 static int
 ble_gatts_chr_def_access(uint16_t conn_handle, uint16_t attr_handle,
-                         uint8_t *uuid128, uint8_t op,
-                         struct ble_att_svr_access_ctxt *ctxt, void *arg)
+                         uint8_t op, uint16_t offset, struct os_mbuf **om,
+                         void *arg)
 {
     const struct ble_gatt_chr_def *chr;
     uint16_t uuid16;
+    uint8_t *buf;
 
     STATS_INC(ble_gatts_stats, chr_def_reads);
 
@@ -220,18 +234,29 @@ ble_gatts_chr_def_access(uint16_t conn_handle, uint16_t attr_handle,
 
     chr = arg;
 
-    ctxt->read.buf[0] = ble_gatts_chr_properties(chr);
+    buf = os_mbuf_extend(*om, 3);
+    if (buf == NULL) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    buf[0] = ble_gatts_chr_properties(chr);
 
     /* The value attribute is always immediately after the declaration. */
-    htole16(ctxt->read.buf + 1, attr_handle + 1);
+    htole16(buf + 1, attr_handle + 1);
 
     uuid16 = ble_uuid_128_to_16(chr->uuid128);
     if (uuid16 != 0) {
-        htole16(ctxt->read.buf + 3, uuid16);
-        ctxt->read.len = 5;
+        buf = os_mbuf_extend(*om, 2);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+        htole16(buf, uuid16);
     } else {
-        memcpy(ctxt->read.buf + 3, chr->uuid128, 16);
-        ctxt->read.len = 19;
+        buf = os_mbuf_extend(*om, 16);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+        memcpy(buf, chr->uuid128, 16);
     }
 
     return 0;
@@ -287,9 +312,50 @@ ble_gatts_chr_inc_val_stat(uint8_t gatt_op)
 }
 
 static int
+ble_gatts_val_access(uint16_t conn_handle, uint16_t attr_handle,
+                     uint16_t offset, struct ble_gatt_access_ctxt *gatt_ctxt,
+                     struct os_mbuf **om, ble_gatt_access_fn *access_cb,
+                     void *cb_arg)
+{
+    int attr_len;
+    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;
+        }
+
+        rc = access_cb(conn_handle, attr_handle, gatt_ctxt, cb_arg);
+        if (rc == 0) {
+            attr_len = OS_MBUF_PKTLEN(gatt_ctxt->om) - offset;
+            if (attr_len > 0) {
+                os_mbuf_appendfrom(*om, gatt_ctxt->om, offset, attr_len);
+            }
+        }
+
+        os_mbuf_free_chain(gatt_ctxt->om);
+        return rc;
+
+    case BLE_GATT_ACCESS_OP_WRITE_CHR:
+    case BLE_GATT_ACCESS_OP_WRITE_DSC:
+        gatt_ctxt->om = *om;
+        rc = access_cb(conn_handle, attr_handle, gatt_ctxt, cb_arg);
+        *om = gatt_ctxt->om;
+        return rc;
+
+    default:
+        BLE_HS_DBG_ASSERT(0);
+        return BLE_ATT_ERR_UNLIKELY;
+    }
+}
+
+static int
 ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle,
-                         uint8_t *uuid128, uint8_t att_op,
-                         struct ble_att_svr_access_ctxt *att_ctxt, void *arg)
+                         uint8_t att_op, uint16_t offset,
+                         struct os_mbuf **om, void *arg)
 {
     const struct ble_gatt_chr_def *chr_def;
     struct ble_gatt_access_ctxt gatt_ctxt;
@@ -299,23 +365,13 @@ ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle,
     BLE_HS_DBG_ASSERT(chr_def != NULL && chr_def->access_cb != NULL);
 
     gatt_ctxt.op = ble_gatts_chr_op(att_op);
-    ble_gatts_chr_inc_val_stat(gatt_ctxt.op);
-
     gatt_ctxt.chr = chr_def;
-    gatt_ctxt.att = att_ctxt;
-    rc = chr_def->access_cb(conn_handle, attr_handle, &gatt_ctxt,
-                            chr_def->arg);
-    if (rc != 0) {
-        return rc;
-    }
-
-    if (gatt_ctxt.op == BLE_GATT_ACCESS_OP_WRITE_CHR &&
-        ble_gatts_chr_clt_cfg_allowed(chr_def)) {
 
-        ble_gatts_chr_updated(attr_handle - 1);
-    }
+    ble_gatts_chr_inc_val_stat(gatt_ctxt.op);
+    rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om,
+                              chr_def->access_cb, chr_def->arg);
 
-    return 0;
+    return rc;
 }
 
 static int
@@ -406,40 +462,24 @@ ble_gatts_dsc_inc_stat(uint8_t gatt_op)
 
 static int
 ble_gatts_dsc_access(uint16_t conn_handle, uint16_t attr_handle,
-                     uint8_t *uuid128, uint8_t att_op,
-                     struct ble_att_svr_access_ctxt *att_ctxt, void *arg)
+                     uint8_t att_op, uint16_t offset, struct os_mbuf **om,
+                     void *arg)
 {
-    struct ble_gatt_access_ctxt gatt_ctxt;
     const struct ble_gatt_dsc_def *dsc_def;
+    struct ble_gatt_access_ctxt gatt_ctxt;
     int rc;
 
     dsc_def = arg;
     BLE_HS_DBG_ASSERT(dsc_def != NULL && dsc_def->access_cb != NULL);
 
     gatt_ctxt.op = ble_gatts_dsc_op(att_op);
-    switch (gatt_ctxt.op) {
-    case BLE_GATT_ACCESS_OP_READ_DSC:
-        break;
-
-    case BLE_GATT_ACCESS_OP_WRITE_DSC:
-        break;
-
-    default:
-        BLE_HS_DBG_ASSERT(0);
-        return BLE_HS_EUNKNOWN;
-    }
+    gatt_ctxt.dsc = dsc_def;
 
     ble_gatts_dsc_inc_stat(gatt_ctxt.op);
+    rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om,
+                              dsc_def->access_cb, dsc_def->arg);
 
-    gatt_ctxt.dsc = dsc_def;
-    gatt_ctxt.att = att_ctxt;
-    rc = dsc_def->access_cb(conn_handle, attr_handle, &gatt_ctxt,
-                            dsc_def->arg);
-    if (rc != 0) {
-        return rc;
-    }
-
-    return 0;
+    return rc;
 }
 
 static int
@@ -561,8 +601,8 @@ ble_gatts_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
  */
 static int
 ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
-                                uint8_t att_op,
-                                struct ble_att_svr_access_ctxt *ctxt,
+                                uint8_t att_op, uint16_t offset,
+                                struct os_mbuf *om,
                                 struct ble_store_value_cccd *out_cccd,
                                 uint8_t *out_prev_clt_cfg_flags,
                                 uint8_t *out_cur_clt_cfg_flags)
@@ -571,8 +611,7 @@ ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
     uint16_t chr_val_handle;
     uint16_t flags;
     uint8_t gatt_op;
-
-    static uint8_t buf[2];
+    uint8_t *buf;
 
     /* Assume nothing needs to be persisted. */
     out_cccd->chr_val_handle = 0;
@@ -602,18 +641,23 @@ ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
     switch (gatt_op) {
     case BLE_GATT_ACCESS_OP_READ_DSC:
         STATS_INC(ble_gatts_stats, dsc_reads);
+        buf = os_mbuf_extend(om, 2);
+        if (buf == NULL) {
+            return BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
         htole16(buf, clt_cfg->flags & ~BLE_GATTS_CLT_CFG_F_RESERVED);
-        ctxt->read.data = buf;
-        ctxt->read.len = sizeof buf;
         break;
 
     case BLE_GATT_ACCESS_OP_WRITE_DSC:
         STATS_INC(ble_gatts_stats, dsc_writes);
-        if (ctxt->write.len != 2) {
+        if (OS_MBUF_PKTLEN(om) != 2) {
             return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
         }
 
-        flags = le16toh(ctxt->write.data);
+        om = os_mbuf_pullup(om, 2);
+        BLE_HS_DBG_ASSERT(om != NULL);
+
+        flags = le16toh(om->om_data);
         if ((flags & ~clt_cfg->allowed) != 0) {
             return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
         }
@@ -643,8 +687,7 @@ ble_gatts_clt_cfg_access_locked(struct ble_hs_conn *conn, uint16_t attr_handle,
 
 static int
 ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
-                         uint8_t *uuid128, uint8_t op,
-                         struct ble_att_svr_access_ctxt *ctxt,
+                         uint8_t op, uint16_t offset, struct os_mbuf **om,
                          void *arg)
 {
     struct ble_store_value_cccd cccd_value;
@@ -661,9 +704,8 @@ ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle,
     if (conn == NULL) {
         rc = BLE_ATT_ERR_UNLIKELY;
     } else {
-        rc = ble_gatts_clt_cfg_access_locked(conn, attr_handle, op, ctxt,
-                                             &cccd_value,
-                                             &prev_flags,
+        rc = ble_gatts_clt_cfg_access_locked(conn, attr_handle, op, offset,
+                                             *om, &cccd_value, &prev_flags,
                                              &cur_flags);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_hs.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index 5a40804..3d37c47 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -165,7 +165,7 @@ ble_hs_process_tx_data_queue(void)
     }
 }
 
-static void
+void
 ble_hs_process_rx_data_queue(void)
 {
     struct os_mbuf *om;
@@ -343,16 +343,19 @@ ble_hs_start(void)
  * @return                      0 on success; nonzero on failure.
  */
 int
-ble_hs_rx_data(struct os_mbuf *om)
+ble_hs_rx_data(struct os_mbuf **om)
 {
     int rc;
 
-    rc = os_mqueue_put(&ble_hs_rx_q, &ble_hs_evq, om);
-    if (rc != 0) {
-        return BLE_HS_EOS;
+    rc = os_mqueue_put(&ble_hs_rx_q, &ble_hs_evq, *om);
+    if (rc == 0) {
+        *om = NULL;
+    } else {
+        rc = BLE_HS_EOS;
     }
     os_eventq_put(ble_hs_parent_evq, &ble_hs_event_co.cf_c.c_ev);
 
+    os_mbuf_free_chain(*om);
     return 0;
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_hs_mbuf.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_mbuf.c b/net/nimble/host/src/ble_hs_mbuf.c
new file mode 100644
index 0000000..7b8f47f
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_mbuf.c
@@ -0,0 +1,171 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "host/ble_hs.h"
+#include "ble_hs_priv.h"
+
+/**
+ * Allocates an mbuf for use by the nimble host.
+ */
+static struct os_mbuf *
+ble_hs_mbuf_gen_pkt(uint16_t leading_space)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = os_msys_get_pkthdr(0, 0);
+    if (om == NULL) {
+        return NULL;
+    }
+
+    if (om->om_omp->omp_databuf_len < leading_space) {
+        rc = os_mbuf_free_chain(om);
+        BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+        return NULL;
+    }
+
+    om->om_data += leading_space;
+
+    return om;
+}
+
+/**
+ * Allocates an mbuf with no leading space.
+ *
+ * @return                  An empty mbuf on success; null on memory
+ *                              exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_bare_pkt(void)
+{
+    return ble_hs_mbuf_gen_pkt(0);
+}
+
+/**
+ * Allocates an mbuf suitable for an HCI ACM data packet.
+ *
+ * @return                  An empty mbuf on success; null on memory
+ *                              exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_acm_pkt(void)
+{
+    return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ);
+}
+
+/**
+ * Allocates an mbuf suitable for an L2CAP data packet.  The resulting packet
+ * has sufficient leading space for:
+ *     o ACM data header
+ *     o L2CAP B-frame header
+ *
+ * @return                  An empty mbuf on success; null on memory
+ *                              exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_l2cap_pkt(void)
+{
+    return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ + BLE_L2CAP_HDR_SZ);
+}
+
+/**
+ * Allocates an mbuf suitable for an ATT command packet.  The resulting packet
+ * has sufficient leading space for:
+ *     o ACM data header
+ *     o L2CAP B-frame header
+ *     o Largest ATT command base (prepare write request / response).
+ *
+ * @return                  An empty mbuf on success; null on memory
+ *                              exhaustion.
+ */
+struct os_mbuf *
+ble_hs_mbuf_att_pkt(void)
+{
+    /* Prepare write request and response are the larget ATT commands which
+     * contain attribute data.
+     */
+     return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ +
+                                BLE_L2CAP_HDR_SZ +
+                                BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
+}
+
+struct os_mbuf *
+ble_hs_mbuf_from_flat(const void *buf, uint16_t len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_mbuf_att_pkt();
+    if (om == NULL) {
+        return NULL;
+    }
+
+    rc = os_mbuf_copyinto(om, 0, buf, len);
+    if (rc != 0) {
+        os_mbuf_free_chain(om);
+        return NULL;
+    }
+
+    return om;
+}
+
+int
+ble_hs_mbuf_to_flat(const struct os_mbuf *om, void *flat, uint16_t max_len,
+                    uint16_t *out_copy_len)
+{
+    uint16_t copy_len;
+    int rc;
+
+    if (OS_MBUF_PKTLEN(om) <= max_len) {
+        copy_len = OS_MBUF_PKTLEN(om);
+    } else {
+        copy_len = max_len;
+    }
+
+    rc = os_mbuf_copydata(om, 0, copy_len, flat);
+    if (rc != 0) {
+        return BLE_HS_EUNKNOWN;
+    }
+
+    if (copy_len > max_len) {
+        rc = BLE_HS_EMSGSIZE;
+    } else {
+        rc = 0;
+    }
+
+    if (out_copy_len != NULL) {
+        *out_copy_len = copy_len;
+    }
+    return rc;
+}
+
+int
+ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len)
+{
+    if (OS_MBUF_PKTLEN(*om) < base_len) {
+        return BLE_HS_EBADDATA;
+    }
+
+    *om = os_mbuf_pullup(*om, base_len);
+    if (*om == NULL) {
+        return BLE_HS_ENOMEM;
+    }
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_hs_mbuf_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_mbuf_priv.h b/net/nimble/host/src/ble_hs_mbuf_priv.h
new file mode 100644
index 0000000..f0ea9b5
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_mbuf_priv.h
@@ -0,0 +1,11 @@
+#ifndef H_BLE_HS_MBUF_PRIV_
+#define H_BLE_HS_MBUF_PRIV_
+
+struct os_mbuf;
+
+struct os_mbuf *ble_hs_mbuf_bare_pkt(void);
+struct os_mbuf *ble_hs_mbuf_acm_pkt(void);
+struct os_mbuf *ble_hs_mbuf_l2cap_pkt(void);
+int ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_hs_misc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
index 616b0b5..216196b 100644
--- a/net/nimble/host/src/ble_hs_misc.c
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -45,47 +45,6 @@ ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
     return 0;
 }
 
-/**
- * Allocates an mbuf for use by the nimble host.
- */
-struct os_mbuf *
-ble_hs_misc_pkthdr(void)
-{
-    struct os_mbuf *om;
-    int rc;
-
-    om = os_msys_get_pkthdr(0, 0);
-    if (om == NULL) {
-        return NULL;
-    }
-
-    /* Make room in the buffer for various headers.  XXX Check this number. */
-    if (om->om_omp->omp_databuf_len < 8) {
-        rc = os_mbuf_free_chain(om);
-        BLE_HS_DBG_ASSERT_EVAL(rc == 0);
-        return NULL;
-    }
-
-    om->om_data += 8;
-
-    return om;
-}
-
-int
-ble_hs_misc_pullup_base(struct os_mbuf **om, int base_len)
-{
-    if (OS_MBUF_PKTLEN(*om) < base_len) {
-        return BLE_HS_EBADDATA;
-    }
-
-    *om = os_mbuf_pullup(*om, base_len);
-    if (*om == NULL) {
-        return BLE_HS_ENOMEM;
-    }
-
-    return 0;
-}
-
 int
 ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
                            struct ble_hs_conn **out_conn,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_hs_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_priv.h b/net/nimble/host/src/ble_hs_priv.h
index a6bb882..79ef6b9 100644
--- a/net/nimble/host/src/ble_hs_priv.h
+++ b/net/nimble/host/src/ble_hs_priv.h
@@ -31,6 +31,7 @@
 #include "ble_hs_conn_priv.h"
 #include "ble_hs_atomic_priv.h"
 #include "ble_hs_endian_priv.h"
+#include "ble_hs_mbuf_priv.h"
 #include "ble_hs_startup_priv.h"
 #include "ble_l2cap_priv.h"
 #include "ble_l2cap_sig_priv.h"
@@ -66,7 +67,7 @@ extern struct os_mbuf_pool ble_hs_mbuf_pool;
 extern const uint8_t ble_hs_misc_null_addr[6];
 
 void ble_hs_process_tx_data_queue(void);
-int ble_hs_rx_data(struct os_mbuf *om);
+void ble_hs_process_rx_data_queue(void);
 int ble_hs_tx_data(struct os_mbuf *om);
 
 int ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
@@ -88,10 +89,6 @@ void ble_hs_unlock(void);
 void ble_hs_heartbeat_sched(int32_t ticks);
 void ble_hs_notifications_sched(void);
 
-struct os_mbuf *ble_hs_misc_pkthdr(void);
-
-int ble_hs_misc_pullup_base(struct os_mbuf **om, int base_len);
-
 #if LOG_LEVEL <= LOG_LEVEL_DEBUG
 
 #define BLE_HS_LOG_CMD(is_tx, cmd_type, cmd_name, conn_handle,                \

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_l2cap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_l2cap.c
index da66bf1..7f284f5 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -79,7 +79,7 @@ ble_l2cap_chan_free(struct ble_l2cap_chan *chan)
 }
 
 uint16_t
-ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan)
+ble_l2cap_chan_mtu(const struct ble_l2cap_chan *chan)
 {
     uint16_t mtu;
 
@@ -120,14 +120,16 @@ struct os_mbuf *
 ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, uint16_t len)
 {
     struct ble_l2cap_hdr hdr;
+    struct os_mbuf *om2;
 
     htole16(&hdr.blh_len, len);
     htole16(&hdr.blh_cid, cid);
 
-    om = os_mbuf_prepend(om, sizeof hdr);
-    if (om == NULL) {
+    om2 = os_mbuf_prepend(om, sizeof hdr);
+    if (om2 == NULL) {
         return NULL;
     }
+    BLE_HS_DBG_ASSERT(om2 == om);
 
     memcpy(om->om_data, &hdr, sizeof hdr);
 
@@ -276,18 +278,22 @@ err:
  */
 int
 ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
-             struct os_mbuf *om)
+             struct os_mbuf **txom)
 {
+    struct os_mbuf *om;
     int rc;
 
+    /* Consume mbuf from caller. */
+    om = *txom;
+    *txom = NULL;
+
     om = ble_l2cap_prepend_hdr(om, chan->blc_cid, OS_MBUF_PKTLEN(om));
     if (om == NULL) {
         rc = BLE_HS_ENOMEM;
         goto err;
     }
 
-    rc = host_hci_data_tx(conn, om);
-    om = NULL;
+    rc = host_hci_data_tx(conn, &om);
     if (rc != 0) {
         goto err;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_l2cap_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_priv.h b/net/nimble/host/src/ble_l2cap_priv.h
index 9cbf879..3eaf245 100644
--- a/net/nimble/host/src/ble_l2cap_priv.h
+++ b/net/nimble/host/src/ble_l2cap_priv.h
@@ -94,7 +94,7 @@ struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
 struct ble_l2cap_chan *ble_l2cap_chan_alloc(void);
 void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
 
-uint16_t ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan);
+uint16_t ble_l2cap_chan_mtu(const struct ble_l2cap_chan *chan);
 
 
 int ble_l2cap_rx(struct ble_hs_conn *conn,
@@ -103,7 +103,7 @@ int ble_l2cap_rx(struct ble_hs_conn *conn,
                  ble_l2cap_rx_fn **out_rx_cb,
                  struct os_mbuf **out_rx_buf);
 int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
-                 struct os_mbuf *om);
+                 struct os_mbuf **txom);
 
 int ble_l2cap_init(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_l2cap_sig.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c
index dd418f2..4838067 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -300,7 +300,7 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle,
 
     l2cap_result = 0; /* Silence spurious gcc warning. */
 
-    rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+    rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_UPDATE_REQ_SZ);
     if (rc != 0) {
         return rc;
     }
@@ -373,7 +373,7 @@ ble_l2cap_sig_update_rsp_rx(uint16_t conn_handle,
         return BLE_HS_ENOENT;
     }
 
-    rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+    rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_UPDATE_RSP_SZ);
     if (rc != 0) {
         cb_status = rc;
         goto done;
@@ -482,7 +482,7 @@ ble_l2cap_sig_rx(uint16_t conn_handle, struct os_mbuf **om)
     ble_hs_log_mbuf(*om);
     BLE_HS_LOG(DEBUG, "\n");
 
-    rc = ble_hs_misc_pullup_base(om, BLE_L2CAP_SIG_HDR_SZ);
+    rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SIG_HDR_SZ);
     if (rc != 0) {
         return rc;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_l2cap_sig_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig_cmd.c b/net/nimble/host/src/ble_l2cap_sig_cmd.c
index a93833c..6b08a2b 100644
--- a/net/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/net/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -27,18 +27,21 @@ ble_l2cap_sig_init_cmd(uint8_t op, uint8_t id, uint8_t payload_len,
     struct ble_l2cap_sig_hdr hdr;
     struct os_mbuf *txom;
     void *v;
+    int rc;
 
     *out_om = NULL;
     *out_payload_buf = NULL;
 
-    txom = ble_hs_misc_pkthdr();
+    txom = ble_hs_mbuf_l2cap_pkt();
     if (txom == NULL) {
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto err;
     }
 
     v = os_mbuf_extend(txom, BLE_L2CAP_SIG_HDR_SZ + payload_len);
     if (v == NULL) {
-        return BLE_HS_ENOMEM;
+        rc = BLE_HS_ENOMEM;
+        goto err;
     }
 
     hdr.op = op;
@@ -51,6 +54,10 @@ ble_l2cap_sig_init_cmd(uint8_t op, uint8_t id, uint8_t payload_len,
     *out_payload_buf = (uint8_t *)v + BLE_L2CAP_SIG_HDR_SZ;
 
     return 0;
+
+err:
+    os_mbuf_free(txom);
+    return rc;
 }
 
 static void
@@ -113,14 +120,21 @@ ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
     rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_REJECT, id,
                                 BLE_L2CAP_SIG_REJECT_MIN_SZ + data_len, &txom,
                                 &payload_buf);
+    if (rc != 0) {
+        return rc;
+    }
 
     cmd.reason = reason;
     ble_l2cap_sig_reject_write(payload_buf, txom->om_len, &cmd,
                                data, data_len);
 
     STATS_INC(ble_l2cap_stats, sig_rx);
-    rc = ble_l2cap_tx(conn, chan, txom);
-    return rc;
+    rc = ble_l2cap_tx(conn, chan, &txom);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
 }
 
 int
@@ -189,7 +203,7 @@ ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
     ble_l2cap_sig_update_req_write(payload_buf, BLE_L2CAP_SIG_UPDATE_REQ_SZ,
                                    req);
 
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_l2cap_tx(conn, chan, &txom);
     if (rc != 0) {
         return rc;
     }
@@ -241,7 +255,7 @@ ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
     ble_l2cap_sig_update_rsp_write(payload_buf, BLE_L2CAP_SIG_UPDATE_RSP_SZ,
                                    &rsp);
 
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_l2cap_tx(conn, chan, &txom);
     if (rc != 0) {
         return rc;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_sm.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm.c b/net/nimble/host/src/ble_sm.c
index 6f77db2..ae2e5f8 100644
--- a/net/nimble/host/src/ble_sm.c
+++ b/net/nimble/host/src/ble_sm.c
@@ -1285,7 +1285,7 @@ ble_sm_random_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_RANDOM_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_RANDOM_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1335,7 +1335,7 @@ ble_sm_confirm_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *prev;
     uint8_t ioact;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CONFIRM_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CONFIRM_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1496,7 +1496,7 @@ ble_sm_pair_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *prev;
     struct ble_hs_conn *conn;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
     if (res->app_status != 0) {
         return;
     }
@@ -1553,7 +1553,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *prev;
     uint8_t ioact;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_CMD_SZ);
     if (res->app_status != 0) {
         res->enc_cb = 1;
         return;
@@ -1616,7 +1616,7 @@ ble_sm_sec_req_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_hs_conn *conn;
     int authreq_mitm;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_SEC_REQ_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_SEC_REQ_SZ);
     if (res->app_status != 0) {
         return;
     }
@@ -1841,7 +1841,7 @@ ble_sm_enc_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ENC_INFO_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ENC_INFO_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1877,7 +1877,7 @@ ble_sm_master_id_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_MASTER_ID_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_MASTER_ID_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1914,7 +1914,7 @@ ble_sm_id_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ID_INFO_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ID_INFO_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1951,7 +1951,7 @@ ble_sm_id_addr_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_ID_ADDR_INFO_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_ID_ADDR_INFO_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -1989,7 +1989,7 @@ ble_sm_sign_info_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_SIGN_INFO_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_SIGN_INFO_SZ);
     if (res->app_status != 0) {
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
         res->enc_cb = 1;
@@ -2030,7 +2030,7 @@ ble_sm_fail_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
 
     res->enc_cb = 1;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PAIR_FAIL_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PAIR_FAIL_SZ);
     if (res->app_status == 0) {
         ble_sm_pair_fail_parse((*om)->om_data, (*om)->om_len, &cmd);
         BLE_SM_LOG_CMD(0, "fail", conn_handle, ble_sm_pair_fail_log, &cmd);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_sm_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm_cmd.c b/net/nimble/host/src/ble_sm_cmd.c
index 5f5026f..86b0c7b 100644
--- a/net/nimble/host/src/ble_sm_cmd.c
+++ b/net/nimble/host/src/ble_sm_cmd.c
@@ -28,12 +28,17 @@
 #if NIMBLE_OPT(SM)
 
 static int
-ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
+ble_sm_tx(uint16_t conn_handle, struct os_mbuf **txom)
 {
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
+    struct os_mbuf *om;
     int rc;
 
+    /* Consume mbuf from caller. */
+    om = *txom;
+    *txom = NULL;
+
     BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
 
     STATS_INC(ble_l2cap_stats, sm_tx);
@@ -41,7 +46,7 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
     rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
                                          &conn, &chan);
     if (rc == 0) {
-        rc = ble_l2cap_tx(conn, chan, txom);
+        rc = ble_l2cap_tx(conn, chan, &om);
     }
 
     return rc;
@@ -53,7 +58,7 @@ ble_sm_init_req(uint16_t initial_sz, struct os_mbuf **out_txom)
     void *buf;
     int rc;
 
-    *out_txom = ble_hs_misc_pkthdr();
+    *out_txom = ble_hs_mbuf_l2cap_pkt();
     if (*out_txom == NULL) {
         rc = BLE_HS_ENOMEM;
         goto err;
@@ -157,8 +162,10 @@ ble_sm_pair_cmd_tx(uint16_t conn_handle, int is_req,
                    ble_sm_pair_cmd_log, cmd);
     BLE_HS_DBG_ASSERT(ble_sm_pair_cmd_is_valid(cmd));
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -204,7 +211,6 @@ ble_sm_pair_confirm_tx(uint16_t conn_handle, struct ble_sm_pair_confirm *cmd)
     struct os_mbuf *txom;
     int rc;
 
-
     rc = ble_sm_init_req(BLE_SM_PAIR_CONFIRM_SZ, &txom);
     if (rc != 0) {
         rc = BLE_HS_ENOMEM;
@@ -214,8 +220,10 @@ ble_sm_pair_confirm_tx(uint16_t conn_handle, struct ble_sm_pair_confirm *cmd)
     ble_sm_pair_confirm_write(txom->om_data, txom->om_len, cmd);
     BLE_SM_LOG_CMD(1, "confirm", conn_handle, ble_sm_pair_confirm_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -267,8 +275,10 @@ ble_sm_pair_random_tx(uint16_t conn_handle, struct ble_sm_pair_random *cmd)
     ble_sm_pair_random_write(txom->om_data, txom->om_len, cmd);
     BLE_SM_LOG_CMD(1, "random", conn_handle, ble_sm_pair_random_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -327,8 +337,10 @@ ble_sm_pair_fail_tx(uint16_t conn_handle, uint8_t reason)
     ble_sm_pair_fail_write(txom->om_data, txom->om_len, &cmd);
     BLE_SM_LOG_CMD(1, "fail", conn_handle, ble_sm_pair_fail_log, &cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -376,8 +388,10 @@ ble_sm_enc_info_tx(uint16_t conn_handle, struct ble_sm_enc_info *cmd)
 
     BLE_SM_LOG_CMD(1, "enc info", conn_handle, ble_sm_enc_info_log, cmd);
     
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -434,8 +448,10 @@ ble_sm_master_id_tx(uint16_t conn_handle, struct ble_sm_master_id *cmd)
 
     BLE_SM_LOG_CMD(1, "master id", conn_handle, ble_sm_master_id_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -487,8 +503,10 @@ ble_sm_id_info_tx(uint16_t conn_handle, struct ble_sm_id_info *cmd)
 
     ble_sm_id_info_write(txom->om_data, txom->om_len, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -543,8 +561,10 @@ ble_sm_id_addr_info_tx(uint16_t conn_handle, struct ble_sm_id_addr_info *cmd)
 
     ble_sm_id_addr_info_write(txom->om_data, txom->om_len, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -593,8 +613,10 @@ ble_sm_sign_info_tx(uint16_t conn_handle, struct ble_sm_sign_info *cmd)
 
     ble_sm_sign_info_write(txom->om_data, txom->om_len, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -648,8 +670,10 @@ ble_sm_sec_req_tx(uint16_t conn_handle, struct ble_sm_sec_req *cmd)
 
     BLE_SM_LOG_CMD(1, "sec req", conn_handle, ble_sm_sec_req_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -713,8 +737,10 @@ ble_sm_public_key_tx(uint16_t conn_handle, struct ble_sm_public_key *cmd)
 
     BLE_SM_LOG_CMD(1, "public key", conn_handle, ble_sm_public_key_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);
@@ -774,8 +800,10 @@ ble_sm_dhkey_check_tx(uint16_t conn_handle, struct ble_sm_dhkey_check *cmd)
 
     BLE_SM_LOG_CMD(1, "dhkey check", conn_handle, ble_sm_dhkey_check_log, cmd);
 
-    rc = ble_sm_tx(conn_handle, txom);
-    txom = NULL;
+    rc = ble_sm_tx(conn_handle, &txom);
+    if (rc != 0) {
+        goto done;
+    }
 
 done:
     os_mbuf_free_chain(txom);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/ble_sm_sc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm_sc.c b/net/nimble/host/src/ble_sm_sc.c
index c2980b6..455da90 100644
--- a/net/nimble/host/src/ble_sm_sc.c
+++ b/net/nimble/host/src/ble_sm_sc.c
@@ -482,7 +482,7 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *prev;
     int rc;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_PUBLIC_KEY_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_PUBLIC_KEY_SZ);
     if (res->app_status != 0) {
         res->enc_cb = 1;
         return;
@@ -693,7 +693,7 @@ ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
 
-    res->app_status = ble_hs_misc_pullup_base(om, BLE_SM_DHKEY_CHECK_SZ);
+    res->app_status = ble_hs_mbuf_pullup_base(om, BLE_SM_DHKEY_CHECK_SZ);
     if (res->app_status != 0) {
         res->enc_cb = 1;
         res->sm_err = BLE_SM_ERR_UNSPECIFIED;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/host_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci.c b/net/nimble/host/src/host_hci.c
index 86e77c5..887c6fa 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -758,11 +758,18 @@ static struct os_mbuf *
 host_hci_data_hdr_prepend(struct os_mbuf *om, uint16_t handle, uint8_t pb_flag)
 {
     struct hci_data_hdr hci_hdr;
+    struct os_mbuf *om2;
 
     hci_hdr.hdh_handle_pb_bc = host_hci_handle_pb_bc_join(handle, pb_flag, 0);
     htole16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
 
-    om = os_mbuf_prepend(om, sizeof hci_hdr);
+    om2 = os_mbuf_prepend(om, sizeof hci_hdr);
+    if (om2 == NULL) {
+        return NULL;
+    }
+    BLE_HS_DBG_ASSERT(om2 == om);
+
+    om = os_mbuf_pullup(om, sizeof hci_hdr);
     if (om == NULL) {
         return NULL;
     }
@@ -805,7 +812,7 @@ host_hci_split_frag(struct os_mbuf *om, struct os_mbuf **out_frag)
         return BLE_HS_EDONE;
     }
 
-    frag = os_msys_get_pkthdr(host_hci_buffer_sz, 0);
+    frag = ble_hs_mbuf_acm_pkt();
     if (frag == NULL) {
         rc = BLE_HS_ENOMEM;
         goto err;
@@ -836,13 +843,18 @@ err:
  * fragments.
  */
 int
-host_hci_data_tx(struct ble_hs_conn *connection, struct os_mbuf *om)
+host_hci_data_tx(struct ble_hs_conn *connection, struct os_mbuf **txom)
 {
     struct os_mbuf *frag;
+    struct os_mbuf *om;
     uint8_t pb;
     int done;
     int rc;
 
+    /* Consume mbuf from caller. */
+    om = *txom;
+    *txom = NULL;
+
     /* The first fragment uses the first-non-flush packet boundary value.
      * After sending the first fragment, pb gets set appropriately for all
      * subsequent fragments in this packet.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_att_clt_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_clt_test.c b/net/nimble/host/src/test/ble_att_clt_test.c
index dcb402e..869fb19 100644
--- a/net/nimble/host/src/test/ble_att_clt_test.c
+++ b/net/nimble/host/src/test/ble_att_clt_test.c
@@ -63,14 +63,17 @@ ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle,
                                      struct ble_att_write_req *req,
                                      void *value, int value_len, int is_req)
 {
+    struct os_mbuf *om;
     int rc;
 
+    om = ble_hs_test_util_om_from_flat(value, value_len);
     if (is_req) {
-        rc = ble_att_clt_tx_write_req(conn_handle, req, value, value_len);
+        rc = ble_att_clt_tx_write_req(conn_handle, req, &om);
     } else {
-        rc = ble_att_clt_tx_write_cmd(conn_handle, req, value, value_len);
+        rc = ble_att_clt_tx_write_cmd(conn_handle, req, &om);
     }
     TEST_ASSERT(rc == 0);
+    TEST_ASSERT(om == NULL);
 }
 
 TEST_CASE(ble_att_clt_test_tx_find_info)
@@ -212,9 +215,10 @@ ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
 
     req.bapc_handle = handle;
     req.bapc_offset = offset;
-    rc = ble_att_clt_tx_prep_write(conn_handle, &req, attr_data,
-                                   attr_data_len);
+    om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+    rc = ble_att_clt_tx_prep_write(conn_handle, &req, &om);
     TEST_ASSERT(rc == 0);
+    TEST_ASSERT(om == NULL);
 
     ble_hs_test_util_tx_all();
     om = ble_hs_test_util_prev_tx_dequeue_pullup();
@@ -259,16 +263,19 @@ ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
                                int status)
 {
     struct ble_att_prep_write_cmd req;
+    struct os_mbuf *om;
     uint16_t conn_handle;
     int rc;
 
     conn_handle = ble_att_clt_test_misc_init();
 
+    om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len);
+
     req.bapc_handle = handle;
     req.bapc_offset = offset;
-    rc = ble_att_clt_tx_prep_write(conn_handle, &req, attr_data,
-                                   attr_data_len);
+    rc = ble_att_clt_tx_prep_write(conn_handle, &req, &om);
     TEST_ASSERT(rc == status);
+    TEST_ASSERT(om == NULL);
 }
 
 TEST_CASE(ble_att_clt_test_tx_write)
@@ -504,6 +511,8 @@ TEST_CASE(ble_att_clt_test_tx_exec_write)
 
 TEST_SUITE(ble_att_clt_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_att_clt_test_tx_find_info();
     ble_att_clt_test_rx_find_info();
     ble_att_clt_test_tx_read();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c
index d8393a8..e5968d5 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -27,19 +27,19 @@
 #include "ble_hs_test_util.h"
 
 static uint8_t *ble_att_svr_test_attr_r_1;
-static int ble_att_svr_test_attr_r_1_len;
+static uint16_t ble_att_svr_test_attr_r_1_len;
 static uint8_t *ble_att_svr_test_attr_r_2;
-static int ble_att_svr_test_attr_r_2_len;
+static uint16_t ble_att_svr_test_attr_r_2_len;
 
 static uint8_t ble_att_svr_test_attr_w_1[1024];
-static int ble_att_svr_test_attr_w_1_len;
+static uint16_t ble_att_svr_test_attr_w_1_len;
 static uint8_t ble_att_svr_test_attr_w_2[1024];
-static int ble_att_svr_test_attr_w_2_len;
+static uint16_t ble_att_svr_test_attr_w_2_len;
 
 static uint16_t ble_att_svr_test_n_conn_handle;
 static uint16_t ble_att_svr_test_n_attr_handle;
 static uint8_t ble_att_svr_test_attr_n[1024];
-static int ble_att_svr_test_attr_n_len;
+static uint16_t ble_att_svr_test_attr_n_len;
 
 static int
 ble_att_svr_test_misc_gap_cb(struct ble_gap_event *event, void *arg)
@@ -48,11 +48,11 @@ ble_att_svr_test_misc_gap_cb(struct ble_gap_event *event, void *arg)
     case BLE_GAP_EVENT_NOTIFY_RX:
         ble_att_svr_test_n_conn_handle = event->notify_rx.conn_handle;
         ble_att_svr_test_n_attr_handle = event->notify_rx.attr_handle;
-        TEST_ASSERT_FATAL(event->notify_rx.attr_len <=
+        TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(event->notify_rx.om) <=
                           sizeof ble_att_svr_test_attr_n);
-        ble_att_svr_test_attr_n_len = event->notify_rx.attr_len;
-        memcpy(ble_att_svr_test_attr_n, event->notify_rx.attr_data,
-               event->notify_rx.attr_len);
+        ble_att_svr_test_attr_n_len = OS_MBUF_PKTLEN(event->notify_rx.om);
+        os_mbuf_copydata(event->notify_rx.om, 0, ble_att_svr_test_attr_n_len,
+                         ble_att_svr_test_attr_n);
         break;
 
     default:
@@ -99,18 +99,17 @@ ble_att_svr_test_misc_init(uint16_t mtu)
 
 static int
 ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
-                                  uint8_t *uuid128, uint8_t op,
-                                  struct ble_att_svr_access_ctxt *ctxt,
-                                  void *arg)
+                                  uint8_t op, uint16_t offset,
+                                  struct os_mbuf **om, void *arg)
 {
     switch (op) {
     case BLE_ATT_ACCESS_OP_READ:
-        if (ctxt->read.offset > ble_att_svr_test_attr_r_1_len) {
+        if (offset > ble_att_svr_test_attr_r_1_len) {
             return BLE_ATT_ERR_INVALID_OFFSET;
         }
 
-        ctxt->read.data = ble_att_svr_test_attr_r_1 + ctxt->read.offset;
-        ctxt->read.len = ble_att_svr_test_attr_r_1_len - ctxt->read.offset;
+        os_mbuf_append(*om, ble_att_svr_test_attr_r_1 + offset,
+                       ble_att_svr_test_attr_r_1_len - offset);
         return 0;
 
     default:
@@ -120,18 +119,18 @@ ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
 
 static int
 ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
-                                  uint8_t *uuid128, uint8_t op,
-                                  struct ble_att_svr_access_ctxt *ctxt,
-                                  void *arg)
+                                  uint8_t op, uint16_t offset,
+                                  struct os_mbuf **om, void *arg)
 {
 
     switch (op) {
     case BLE_ATT_ACCESS_OP_READ:
-        if (ctxt->read.offset > ble_att_svr_test_attr_r_2_len) {
+        if (offset > ble_att_svr_test_attr_r_2_len) {
             return BLE_ATT_ERR_INVALID_OFFSET;
         }
-        ctxt->read.data = ble_att_svr_test_attr_r_2 + ctxt->read.offset;
-        ctxt->read.len = ble_att_svr_test_attr_r_2_len - ctxt->read.offset;
+
+        os_mbuf_append(*om, ble_att_svr_test_attr_r_2 + offset,
+                       ble_att_svr_test_attr_r_2_len - offset);
         return 0;
 
     default:
@@ -144,11 +143,15 @@ ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
 
 static int
 ble_att_svr_test_misc_attr_fn_r_group(uint16_t conn_handle,
-                                      uint16_t attr_handle, uint8_t *uuid128,
+                                      uint16_t attr_handle,
                                       uint8_t op,
-                                      struct ble_att_svr_access_ctxt *ctxt,
+                                      uint16_t offset,
+                                      struct os_mbuf **om,
                                       void *arg)
 {
+    uint8_t *src;
+    int rc;
+
     /* Service 0x1122 from 1 to 5 */
     /* Service 0x2233 from 6 to 10 */
     /* Service 010203...0f from 11 to 24 */
@@ -189,11 +192,14 @@ ble_att_svr_test_misc_attr_fn_r_group(uint16_t conn_handle,
     TEST_ASSERT_FATAL(attr_handle >= 1 &&
                       attr_handle <= BLE_ATT_SVR_TEST_LAST_ATTR);
 
-    ctxt->read.data = vals + attr_handle;
-    if (memcmp(ctxt->read.data + 2, zeros, 14) == 0) {
-        ctxt->read.len = 2;
+    src = &vals[attr_handle][0];
+    if (memcmp(src + 2, zeros, 14) == 0) {
+        rc = os_mbuf_append(*om, src, 2);
     } else {
-        ctxt->read.len = 16;
+        rc = os_mbuf_append(*om, src, 16);
+    }
+    if (rc != 0) {
+        return BLE_ATT_ERR_INSUFFICIENT_RES;
     }
 
     return 0;
@@ -281,14 +287,14 @@ ble_att_svr_test_misc_register_group_attrs(void)
 
 static int
 ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
-                                  uint8_t *uuid128, uint8_t op,
-                                  struct ble_att_svr_access_ctxt *ctxt,
-                                  void *arg)
+                                  uint8_t op, uint16_t offset,
+                                  struct os_mbuf **om, void *arg)
 {
     switch (op) {
     case BLE_ATT_ACCESS_OP_WRITE:
-        memcpy(ble_att_svr_test_attr_w_1, ctxt->write.data, ctxt->write.len);
-        ble_att_svr_test_attr_w_1_len = ctxt->write.len;
+        os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+                         ble_att_svr_test_attr_w_1);
+        ble_att_svr_test_attr_w_1_len = OS_MBUF_PKTLEN(*om);
         return 0;
 
     default:
@@ -298,14 +304,14 @@ ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
 
 static int
 ble_att_svr_test_misc_attr_fn_w_2(uint16_t conn_handle, uint16_t attr_handle,
-                                  uint8_t *uuid128, uint8_t op,
-                                  struct ble_att_svr_access_ctxt *ctxt,
-                                  void *arg)
+                                  uint8_t op, uint16_t offset,
+                                  struct os_mbuf **om, void *arg)
 {
     switch (op) {
     case BLE_ATT_ACCESS_OP_WRITE:
-        memcpy(ble_att_svr_test_attr_w_2, ctxt->write.data, ctxt->write.len);
-        ble_att_svr_test_attr_w_2_len = ctxt->write.len;
+        os_mbuf_copydata(*om, 0, OS_MBUF_PKTLEN(*om),
+                         ble_att_svr_test_attr_w_2);
+        ble_att_svr_test_attr_w_2_len = OS_MBUF_PKTLEN(*om);
         return 0;
 
     default:
@@ -404,18 +410,17 @@ ble_att_svr_test_misc_rx_read_mult_req(uint16_t conn_handle,
 }
 
 static void
-ble_att_svr_test_misc_verify_tx_read_mult_rsp(uint16_t conn_handle,
-                                              struct ble_gatt_attr *attrs,
-                                              int num_attrs)
+ble_att_svr_test_misc_verify_tx_read_mult_rsp(
+    uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs,
+    int num_attrs)
 {
     struct ble_l2cap_chan *chan;
     struct os_mbuf *om;
+    uint16_t attr_len;
     uint16_t mtu;
-    const uint8_t *attr_value;
     uint8_t u8;
     int rc;
     int off;
-    int ii;
     int i;
 
     ble_hs_test_util_tx_all();
@@ -437,25 +442,21 @@ ble_att_svr_test_misc_verify_tx_read_mult_rsp(uint16_t conn_handle,
 
     off = 1;
     for (i = 0; i < num_attrs; i++) {
-        attr_value = attrs[i].value;
+        attr_len = min(attrs[i].value_len, mtu - off);
 
-        for (ii = 0; ii < attrs[i].value_len && off < mtu; ii++) {
-            rc = os_mbuf_copydata(om, off, 1, &u8);
-            TEST_ASSERT(rc == 0);
-            TEST_ASSERT(u8 == attr_value[ii]);
+        rc = os_mbuf_cmpf(om, off, attrs[i].value, attr_len);
+        TEST_ASSERT(rc == 0);
 
-            off++;
-        }
+        off += attr_len;
     }
 
-    rc = os_mbuf_copydata(om, off, 1, &u8);
-    TEST_ASSERT(rc != 0);
+    TEST_ASSERT(OS_MBUF_PKTLEN(om) == off);
 }
 
 static void
-ble_att_svr_test_misc_verify_all_read_mult(uint16_t conn_handle,
-                                           struct ble_gatt_attr *attrs,
-                                           int num_attrs)
+ble_att_svr_test_misc_verify_all_read_mult(
+    uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs,
+    int num_attrs)
 {
     uint16_t handles[256];
     int i;
@@ -809,6 +810,7 @@ ble_att_svr_test_misc_mtu_exchange(uint16_t my_mtu, uint16_t peer_sent,
     TEST_ASSERT(chan->blc_peer_mtu == peer_actual);
     TEST_ASSERT(ble_l2cap_chan_mtu(chan) == chan_mtu);
     ble_hs_unlock();
+
 }
 
 static void
@@ -995,12 +997,11 @@ TEST_CASE(ble_att_svr_test_read)
 {
     struct ble_att_read_req req;
     struct ble_hs_conn *conn;
+    struct os_mbuf *om;
     uint16_t conn_handle;
-    uint16_t attr_len;
     uint8_t buf[BLE_ATT_READ_REQ_SZ];
     uint8_t uuid_sec[16] = {1};
     uint8_t uuid[16] = {0};
-    const void *attr_data;
     int rc;
 
     conn_handle = ble_att_svr_test_misc_init(0);
@@ -1061,10 +1062,12 @@ TEST_CASE(ble_att_svr_test_read)
                                             BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
 
     /* Security check bypassed for local reads. */
-    rc = ble_att_svr_read_local(req.barq_handle, &attr_data, &attr_len);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(attr_len == ble_att_svr_test_attr_r_1_len);
-    TEST_ASSERT(attr_data == ble_att_svr_test_attr_r_1);
+    rc = ble_att_svr_read_local(req.barq_handle, &om);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(OS_MBUF_PKTLEN(om) == ble_att_svr_test_attr_r_1_len);
+    TEST_ASSERT(os_mbuf_cmpf(om, 0, ble_att_svr_test_attr_r_1,
+                               ble_att_svr_test_attr_r_1_len) == 0);
+    os_mbuf_free_chain(om);
 
     /* Ensure no response got sent. */
     ble_hs_test_util_tx_all();
@@ -1081,6 +1084,7 @@ TEST_CASE(ble_att_svr_test_read)
     TEST_ASSERT(rc == 0);
     ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_r_1,
                                         BLE_ATT_MTU_DFLT - 1);
+
 }
 
 TEST_CASE(ble_att_svr_test_read_blob)
@@ -1104,11 +1108,12 @@ TEST_CASE(ble_att_svr_test_read_blob)
     ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ, 0,
                                             BLE_ATT_ERR_INVALID_HANDLE);
 
-    /*** Short read failure. */
+
+    /*** Successful partial read. */
     ble_att_svr_test_attr_r_1 =
         (uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,
                     22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39};
-    ble_att_svr_test_attr_r_1_len = BLE_ATT_MTU_DFLT - 3;
+    ble_att_svr_test_attr_r_1_len = 40;
     rc = ble_att_svr_register(uuid, HA_FLAG_PERM_RW, &req.babq_handle,
                               ble_att_svr_test_misc_attr_fn_r_1, NULL);
     TEST_ASSERT(rc == 0);
@@ -1117,18 +1122,6 @@ TEST_CASE(ble_att_svr_test_read_blob)
 
     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
                                                 buf, sizeof buf);
-    TEST_ASSERT(rc != 0);
-    ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ,
-                                            req.babq_handle,
-                                            BLE_ATT_ERR_ATTR_NOT_LONG);
-
-    /*** Successful partial read. */
-    ble_att_svr_test_attr_r_1_len = 40;
-
-    ble_att_read_blob_req_write(buf, sizeof buf, &req);
-
-    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
-                                                buf, sizeof buf);
     TEST_ASSERT(rc == 0);
     ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
                                                   BLE_ATT_MTU_DFLT - 1);
@@ -1153,32 +1146,43 @@ TEST_CASE(ble_att_svr_test_read_blob)
     TEST_ASSERT(rc == 0);
     ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
                                                   0);
+
 }
 
 TEST_CASE(ble_att_svr_test_read_mult)
 {
-    struct ble_gatt_attr attr1;
-    struct ble_gatt_attr attr2;
     uint16_t conn_handle;
     int rc;
 
     conn_handle = ble_att_svr_test_misc_init(0);
 
-    attr1.value = (uint8_t[]){ 1, 2, 3, 4 };
-    attr1.value_len = 4;
-    ble_att_svr_test_attr_r_1 = (void *)attr1.value;
-    ble_att_svr_test_attr_r_1_len = attr1.value_len;
+    struct ble_hs_test_util_flat_attr attrs[2] = {
+        {
+            .handle = 0,
+            .offset = 0,
+            .value = { 1, 2, 3, 4 },
+            .value_len = 4,
+        },
+        {
+            .handle = 0,
+            .offset = 0,
+            .value = { 2, 3, 4, 5, 6 },
+            .value_len = 5,
+        },
+    };
+
+    ble_att_svr_test_attr_r_1 = attrs[0].value;
+    ble_att_svr_test_attr_r_1_len = attrs[0].value_len;
+    ble_att_svr_test_attr_r_2 = attrs[1].value;
+    ble_att_svr_test_attr_r_2_len = attrs[1].value_len;
+
     rc = ble_att_svr_register(BLE_UUID16(0x1111), HA_FLAG_PERM_RW,
-                              &attr1.handle,
+                              &attrs[0].handle,
                               ble_att_svr_test_misc_attr_fn_r_1, NULL);
     TEST_ASSERT(rc == 0);
 
-    attr2.value = (uint8_t[]){ 2, 3, 4, 5, 6 };
-    attr2.value_len = 5;
-    ble_att_svr_test_attr_r_2 = (void *)attr2.value;
-    ble_att_svr_test_attr_r_2_len = attr2.value_len;
     rc = ble_att_svr_register(BLE_UUID16(0x2222), HA_FLAG_PERM_RW,
-                              &attr2.handle,
+                              &attrs[1].handle,
                               ble_att_svr_test_misc_attr_fn_r_2, NULL);
     TEST_ASSERT(rc == 0);
 
@@ -1189,37 +1193,37 @@ TEST_CASE(ble_att_svr_test_read_mult)
                                             100, BLE_ATT_ERR_INVALID_HANDLE);
 
     /*** Single attribute. */
-    ble_att_svr_test_misc_verify_all_read_mult(conn_handle, &attr1, 1);
+    ble_att_svr_test_misc_verify_all_read_mult(conn_handle, &attrs[0], 1);
 
     /*** Two attributes. */
-    ble_att_svr_test_misc_verify_all_read_mult(
-        conn_handle, ((struct ble_gatt_attr[]) { attr1, attr2 }), 2);
+    ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
 
     /*** Reverse order. */
-    ble_att_svr_test_misc_verify_all_read_mult(
-        conn_handle, ((struct ble_gatt_attr[]) { attr2, attr1 }), 2);
+    ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
 
     /*** Second attribute nonexistent; verify only error txed. */
     ble_att_svr_test_misc_rx_read_mult_req(
-        conn_handle, ((uint16_t[]){ attr1.handle, 100 }), 2, 0);
+        conn_handle, ((uint16_t[]){ attrs[0].handle, 100 }), 2, 0);
     ble_att_svr_test_misc_verify_tx_err_rsp(BLE_ATT_OP_READ_MULT_REQ,
                                             100, BLE_ATT_ERR_INVALID_HANDLE);
 
     /*** Response too long; verify only MTU bytes sent. */
-    attr1.value =
-        (uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
-    attr1.value_len = 20;
-    ble_att_svr_test_attr_r_1 = (void *)attr1.value;
-    ble_att_svr_test_attr_r_1_len = attr1.value_len;
-
-    attr2.value =
-        (uint8_t[]){22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39};
-    attr2.value_len = 20;
-    ble_att_svr_test_attr_r_2 = (void *)attr2.value;
-    ble_att_svr_test_attr_r_2_len = attr2.value_len;
-
-    ble_att_svr_test_misc_verify_all_read_mult(
-        conn_handle, ((struct ble_gatt_attr[]) { attr1, attr2 }), 2);
+    attrs[0].value_len = 20;
+    memcpy(attrs[0].value,
+           ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}),
+           attrs[0].value_len);
+    ble_att_svr_test_attr_r_1_len = attrs[0].value_len;
+
+    attrs[1].value_len = 20;
+    memcpy(attrs[1].value,
+           ((uint8_t[]){
+                22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
+           }),
+           attrs[1].value_len);
+    ble_att_svr_test_attr_r_2_len = attrs[1].value_len;
+
+    ble_att_svr_test_misc_verify_all_read_mult(conn_handle, attrs, 2);
+
 }
 
 TEST_CASE(ble_att_svr_test_write)
@@ -1264,7 +1268,7 @@ TEST_CASE(ble_att_svr_test_write)
                                             BLE_ATT_ERR_WRITE_NOT_PERMITTED);
 
     /* Local write (success). */
-    rc = ble_att_svr_write_local(req.bawq_handle, buf, sizeof buf);
+    rc = ble_hs_test_util_write_local_flat(req.bawq_handle, buf, sizeof buf);
     TEST_ASSERT(rc == 0);
 
     /* Ensure no response got sent. */
@@ -1304,7 +1308,7 @@ TEST_CASE(ble_att_svr_test_write)
                                             BLE_ATT_ERR_INSUFFICIENT_AUTHEN);
 
     /* Security check bypassed for local writes. */
-    rc = ble_att_svr_write_local(req.bawq_handle, buf, sizeof buf);
+    rc = ble_hs_test_util_write_local_flat(req.bawq_handle, buf, sizeof buf);
     TEST_ASSERT(rc == 0);
 
     /* Ensure no response got sent. */
@@ -1474,6 +1478,7 @@ TEST_CASE(ble_att_svr_test_find_info)
         }, {
             .handle = 0,
         } }));
+
 }
 
 TEST_CASE(ble_att_svr_test_find_type_value)
@@ -1674,6 +1679,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
         }, {
             .first = 0,
         } }));
+
 }
 
 static void
@@ -1880,6 +1886,7 @@ ble_att_svr_test_misc_read_type(uint16_t mtu)
         }, {
             .handle = 0,
         } }));
+
 }
 
 TEST_CASE(ble_att_svr_test_read_type)
@@ -2059,6 +2066,7 @@ TEST_CASE(ble_att_svr_test_read_group_type)
         }, {
             .start_handle = 0,
         } }));
+
 }
 
 TEST_CASE(ble_att_svr_test_prep_write)
@@ -2068,7 +2076,7 @@ TEST_CASE(ble_att_svr_test_prep_write)
 
     static uint8_t data[1024];
 
-    conn_handle = ble_att_svr_test_misc_init(200);
+    conn_handle = ble_att_svr_test_misc_init(205);
 
     /* Initialize some attribute data. */
     for (i = 0; i < sizeof data; i++) {
@@ -2190,6 +2198,7 @@ TEST_CASE(ble_att_svr_test_notify)
     /* Attribute handle of 0. */
     ble_att_svr_test_misc_verify_notify(conn_handle, 0,
                                         (uint8_t[]) { 1, 2, 3 }, 3, 0);
+
 }
 
 TEST_CASE(ble_att_svr_test_indicate)
@@ -2212,10 +2221,13 @@ TEST_CASE(ble_att_svr_test_indicate)
     /* Attribute handle of 0. */
     ble_att_svr_test_misc_verify_indicate(conn_handle, 0,
                                           (uint8_t[]) { 1, 2, 3 }, 3, 0);
+
 }
 
 TEST_SUITE(ble_att_svr_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_att_svr_test_mtu();
     ble_att_svr_test_read();
     ble_att_svr_test_read_blob();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
index 7834d8a..86d0e6f 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -549,6 +549,8 @@ TEST_CASE(ble_gap_test_case_wl_good)
 
 TEST_SUITE(ble_gap_test_suite_wl)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_wl_good();
     ble_gap_test_case_wl_bad_args();
     ble_gap_test_case_wl_ctlr_fail();
@@ -688,6 +690,7 @@ TEST_CASE(ble_gap_test_case_disc_good)
         TEST_ASSERT(ble_gap_test_disc_desc.rssi == 0);
         TEST_ASSERT(memcmp(ble_gap_test_disc_desc.addr, desc.addr, 6) == 0);
         TEST_ASSERT(ble_gap_test_disc_arg == NULL);
+
     }
 }
 
@@ -738,6 +741,7 @@ TEST_CASE(ble_gap_test_case_disc_ltd_mismatch)
      * hears everything.
      */
     TEST_ASSERT(ble_gap_test_disc_event_type == BLE_GAP_EVENT_DISC);
+
 }
 
 TEST_CASE(ble_gap_test_case_disc_hci_fail)
@@ -817,6 +821,8 @@ TEST_CASE(ble_gap_test_case_disc_dflts)
 
 TEST_SUITE(ble_gap_test_suite_disc)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_disc_bad_args();
     ble_gap_test_case_disc_good();
     ble_gap_test_case_disc_ltd_mismatch();
@@ -940,6 +946,8 @@ TEST_CASE(ble_gap_test_case_conn_dir_dflt_params)
 
 TEST_SUITE(ble_gap_test_suite_conn_dir)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_conn_dir_good();
     ble_gap_test_case_conn_dir_bad_args();
     ble_gap_test_case_conn_dir_dflt_params();
@@ -1054,6 +1062,8 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
 
 TEST_SUITE(ble_gap_test_suite_conn_cancel)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_conn_cancel_good();
     ble_gap_test_case_conn_cancel_bad_args();
     ble_gap_test_case_conn_cancel_ctlr_fail();
@@ -1180,6 +1190,8 @@ TEST_CASE(ble_gap_test_case_conn_terminate_hci_fail)
 
 TEST_SUITE(ble_gap_test_suite_conn_terminate)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_conn_terminate_bad_args();
     ble_gap_test_case_conn_terminate_good();
     ble_gap_test_case_conn_terminate_ctlr_fail();
@@ -1289,6 +1301,8 @@ TEST_CASE(ble_gap_test_case_conn_find)
 
 TEST_SUITE(ble_gap_test_suite_conn_find)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_conn_find();
 }
 
@@ -1607,6 +1621,8 @@ TEST_CASE(ble_gap_test_case_adv_hci_fail)
 
 TEST_SUITE(ble_gap_test_suite_adv)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_adv_bad_args();
     ble_gap_test_case_adv_dflt_params();
     ble_gap_test_case_adv_good();
@@ -1684,6 +1700,8 @@ TEST_CASE(ble_gap_test_case_stop_adv_hci_fail)
 
 TEST_SUITE(ble_gap_test_suite_stop_adv)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_stop_adv_good();
     ble_gap_test_case_stop_adv_hci_fail();
 }
@@ -2248,6 +2266,8 @@ TEST_CASE(ble_gap_test_case_update_concurrent_hci_fail)
 
 TEST_SUITE(ble_gap_test_suite_update_conn)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gap_test_case_update_conn_good();
     ble_gap_test_case_update_conn_bad();
     ble_gap_test_case_update_conn_hci_fail();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_conn_test.c b/net/nimble/host/src/test/ble_gatt_conn_test.c
index 4c30425..be4a46d 100644
--- a/net/nimble/host/src/test/ble_gatt_conn_test.c
+++ b/net/nimble/host/src/test/ble_gatt_conn_test.c
@@ -36,16 +36,16 @@ struct ble_gatt_conn_test_cb_arg {
 
 static int
 ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
-                           uint8_t *uuid128, uint8_t op,
-                           struct ble_att_svr_access_ctxt *ctxt,
+                           uint8_t op, uint16_t offset, struct os_mbuf **om,
                            void *arg)
 {
-    static uint8_t data = 1;
+    uint8_t *buf;
 
     switch (op) {
     case BLE_ATT_ACCESS_OP_READ:
-        ctxt->read.data = &data;
-        ctxt->read.len = 1;
+        buf = os_mbuf_extend(*om, 1);
+        TEST_ASSERT_FATAL(buf != NULL);
+        *buf = 1;
         return 0;
 
     default:
@@ -201,7 +201,7 @@ ble_gatt_conn_test_disc_all_dscs_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_read_cb(uint16_t conn_handle,
                            const struct ble_gatt_error *error,
-                           const struct ble_gatt_attr *attr, void *arg)
+                           struct ble_gatt_attr *attr, void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
 
@@ -221,7 +221,7 @@ ble_gatt_conn_test_read_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
                                 const struct ble_gatt_error *error,
-                                const struct ble_gatt_attr *attr, void *arg)
+                                struct ble_gatt_attr *attr, void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
 
@@ -241,7 +241,7 @@ ble_gatt_conn_test_read_uuid_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
                                 const struct ble_gatt_error *error,
-                                const struct ble_gatt_attr *attr, void *arg)
+                                struct ble_gatt_attr *attr, void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
 
@@ -260,7 +260,7 @@ ble_gatt_conn_test_read_long_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
                                 const struct ble_gatt_error *error,
-                                const struct ble_gatt_attr *attr, void *arg)
+                                struct ble_gatt_attr *attr, void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
 
@@ -270,7 +270,7 @@ ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
     TEST_ASSERT(!cb_arg->called);
     TEST_ASSERT_FATAL(error != NULL);
     TEST_ASSERT(error->status == BLE_HS_ENOTCONN);
-    TEST_ASSERT(attr == NULL);
+    TEST_ASSERT(attr->om == NULL);
 
     cb_arg->called++;
 
@@ -280,7 +280,7 @@ ble_gatt_conn_test_read_mult_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_write_cb(uint16_t conn_handle,
                             const struct ble_gatt_error *error,
-                            const struct ble_gatt_attr *attr,
+                            struct ble_gatt_attr *attr,
                             void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
@@ -302,7 +302,7 @@ ble_gatt_conn_test_write_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
                                  const struct ble_gatt_error *error,
-                                 const struct ble_gatt_attr *attr, void *arg)
+                                 struct ble_gatt_attr *attr, void *arg)
 {
     struct ble_gatt_conn_test_cb_arg *cb_arg;
 
@@ -323,7 +323,7 @@ ble_gatt_conn_test_write_long_cb(uint16_t conn_handle,
 static int
 ble_gatt_conn_test_write_rel_cb(uint16_t conn_handle,
                                 const struct ble_gatt_error *error,
-                                const struct ble_gatt_attr *attrs,
+                                struct ble_gatt_attr *attrs,
                                 uint8_t num_attrs,
                                 void *arg)
 {
@@ -358,6 +358,7 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     struct ble_gatt_conn_test_cb_arg write_arg          = { 0 };
     struct ble_gatt_conn_test_cb_arg write_long_arg     = { 0 };
     struct ble_gatt_conn_test_cb_arg write_rel_arg      = { 0 };
+    struct ble_gatt_attr attr;
     uint16_t attr_handle;
     int rc;
 
@@ -439,25 +440,25 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     TEST_ASSERT_FATAL(rc == 0);
 
     write_arg.exp_conn_handle = 3;
-    rc = ble_gattc_write(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
-                         ble_gatt_conn_test_write_value,
-                         sizeof ble_gatt_conn_test_write_value,
-                         ble_gatt_conn_test_write_cb, &write_arg);
+    rc = ble_hs_test_util_gatt_write_flat(
+        3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+        ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+        ble_gatt_conn_test_write_cb, &write_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
     write_long_arg.exp_conn_handle = 3;
-    rc = ble_gattc_write_long(3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
-                              ble_gatt_conn_test_write_value,
-                              sizeof ble_gatt_conn_test_write_value,
-                              ble_gatt_conn_test_write_long_cb,
-                              &write_long_arg);
+    rc = ble_hs_test_util_gatt_write_long_flat(
+        3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+        ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+        ble_gatt_conn_test_write_long_cb, &write_long_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
+    attr.handle = 8;
+    attr.offset = 0;
+    attr.om = os_msys_get_pkthdr(0, 0);
     write_rel_arg.exp_conn_handle = 3;
-    rc = ble_gattc_write_reliable(3,
-                                  ((struct ble_gatt_attr[]){{8, 0, 0, NULL}}),
-                                  1, ble_gatt_conn_test_write_rel_cb,
-                                  &write_rel_arg);
+    rc = ble_gattc_write_reliable(
+        3, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
     /*** Start the procedures. */
@@ -518,6 +519,8 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
 
 TEST_SUITE(ble_gatt_break_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_conn_test_disconnect();
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_disc_c_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_disc_c_test.c b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
index 7db9350..a4eb67b 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_c_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_c_test.c
@@ -532,6 +532,8 @@ TEST_CASE(ble_gatt_disc_c_test_disc_uuid)
 
 TEST_SUITE(ble_gatt_disc_c_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_disc_c_test_disc_all();
     ble_gatt_disc_c_test_disc_uuid();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_disc_d_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_disc_d_test.c b/net/nimble/host/src/test/ble_gatt_disc_d_test.c
index 048ecb7..7e021e2 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_d_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_d_test.c
@@ -349,6 +349,8 @@ TEST_CASE(ble_gatt_disc_d_test_1)
 
 TEST_SUITE(ble_gatt_disc_d_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_disc_d_test_1();
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_disc_s_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_disc_s_test.c b/net/nimble/host/src/test/ble_gatt_disc_s_test.c
index 1275e38..2e278d6 100644
--- a/net/nimble/host/src/test/ble_gatt_disc_s_test.c
+++ b/net/nimble/host/src/test/ble_gatt_disc_s_test.c
@@ -391,6 +391,8 @@ TEST_CASE(ble_gatt_disc_s_test_disc_service_uuid)
 
 TEST_SUITE(ble_gatt_disc_s_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_disc_s_test_disc_all();
     ble_gatt_disc_s_test_disc_service_uuid();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_find_s_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_find_s_test.c b/net/nimble/host/src/test/ble_gatt_find_s_test.c
index cf988d6..c3ab93d 100644
--- a/net/nimble/host/src/test/ble_gatt_find_s_test.c
+++ b/net/nimble/host/src/test/ble_gatt_find_s_test.c
@@ -328,6 +328,8 @@ TEST_CASE(ble_gatt_find_s_test_1)
 
 TEST_SUITE(ble_gatt_find_s_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_find_s_test_1();
 }