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:33 UTC

[06/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/test/ble_gatt_read_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_read_test.c b/net/nimble/host/src/test/ble_gatt_read_test.c
index 606a554..0c9f1cb 100644
--- a/net/nimble/host/src/test/ble_gatt_read_test.c
+++ b/net/nimble/host/src/test/ble_gatt_read_test.c
@@ -58,7 +58,7 @@ ble_gatt_read_test_misc_init(void)
 
 static int
 ble_gatt_read_test_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_read_test_attr *dst;
     int *stop_after;
@@ -83,12 +83,12 @@ ble_gatt_read_test_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
                       BLE_GATT_READ_TEST_MAX_ATTRS);
     dst = ble_gatt_read_test_attrs + ble_gatt_read_test_num_attrs++;
 
-    TEST_ASSERT_FATAL(attr->value_len <= sizeof dst->value);
+    TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <= sizeof dst->value);
 
     dst->conn_handle = conn_handle;
     dst->handle = attr->handle;
-    dst->value_len = attr->value_len;
-    memcpy(dst->value, attr->value, attr->value_len);
+    dst->value_len = OS_MBUF_PKTLEN(attr->om);
+    os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om), dst->value);
 
     if (stop_after != NULL && *stop_after > 0) {
         (*stop_after)--;
@@ -106,7 +106,7 @@ ble_gatt_read_test_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
 static int
 ble_gatt_read_test_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_read_test_attr *dst;
     int *reads_left;
@@ -129,7 +129,8 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle,
 
     dst = ble_gatt_read_test_attrs + 0;
 
-    TEST_ASSERT_FATAL(attr->value_len <= dst->value_len + sizeof dst->value);
+    TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(attr->om) <=
+        dst->value_len + sizeof dst->value);
     TEST_ASSERT(attr->offset == dst->value_len);
 
     if (attr->offset == 0) {
@@ -139,8 +140,9 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle,
         TEST_ASSERT(conn_handle == dst->conn_handle);
         TEST_ASSERT(attr->handle == dst->handle);
     }
-    memcpy(dst->value + dst->value_len, attr->value, attr->value_len);
-    dst->value_len += attr->value_len;
+    os_mbuf_copydata(attr->om, 0, OS_MBUF_PKTLEN(attr->om),
+                     dst->value + dst->value_len);
+    dst->value_len += OS_MBUF_PKTLEN(attr->om);
 
     if (reads_left != NULL && *reads_left > 0) {
         (*reads_left)--;
@@ -176,7 +178,7 @@ ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle,
 
 static void
 ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle,
-                                    struct ble_gatt_attr *attr)
+                                    struct ble_hs_test_util_flat_attr *attr)
 {
     ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, BLE_ATT_OP_READ_RSP,
                                             attr->value,
@@ -195,8 +197,8 @@ ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle,
 }
 
 static int
-ble_gatt_read_test_misc_uuid_rx_rsp_good(uint16_t conn_handle,
-                                         struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_uuid_rx_rsp_good(
+    uint16_t conn_handle, struct ble_hs_test_util_flat_attr *attrs)
 {
     struct ble_att_read_type_rsp rsp;
     uint8_t buf[1024];
@@ -238,7 +240,7 @@ ble_gatt_read_test_misc_uuid_rx_rsp_good(uint16_t conn_handle,
 }
 
 static void
-ble_gatt_read_test_misc_verify_good(struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr)
 {
     int rc;
 
@@ -261,7 +263,7 @@ ble_gatt_read_test_misc_verify_good(struct ble_gatt_attr *attr)
 
 static void
 ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
-                                   struct ble_gatt_attr *attr)
+                                   struct ble_hs_test_util_flat_attr *attr)
 {
     int rc;
 
@@ -282,10 +284,9 @@ ble_gatt_read_test_misc_verify_bad(uint8_t att_status,
 }
 
 static void
-ble_gatt_read_test_misc_uuid_verify_good(uint16_t start_handle,
-                                         uint16_t end_handle, void *uuid128,
-                                         int stop_after,
-                                         struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_uuid_verify_good(
+    uint16_t start_handle, uint16_t end_handle, void *uuid128,
+    int stop_after, struct ble_hs_test_util_flat_attr *attrs)
 {
     int num_read;
     int idx;
@@ -329,8 +330,8 @@ ble_gatt_read_test_misc_uuid_verify_good(uint16_t start_handle,
 }
 
 static void
-ble_gatt_read_test_misc_long_verify_good(int max_reads,
-                                         struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_long_verify_good(
+    int max_reads, struct ble_hs_test_util_flat_attr *attr)
 {
     int reads_left;
     int chunk_sz;
@@ -382,8 +383,8 @@ ble_gatt_read_test_misc_long_verify_good(int max_reads,
 }
 
 static void
-ble_gatt_read_test_misc_long_verify_bad(uint8_t att_status,
-                                        struct ble_gatt_attr *attr)
+ble_gatt_read_test_misc_long_verify_bad(
+    uint8_t att_status, struct ble_hs_test_util_flat_attr *attr)
 {
     int rc;
 
@@ -405,8 +406,8 @@ ble_gatt_read_test_misc_long_verify_bad(uint8_t att_status,
 }
 
 static int
-ble_gatt_read_test_misc_extract_handles(struct ble_gatt_attr *attrs,
-                                        uint16_t *handles)
+ble_gatt_read_test_misc_extract_handles(
+    struct ble_hs_test_util_flat_attr *attrs, uint16_t *handles)
 {
     int i;
 
@@ -417,7 +418,8 @@ ble_gatt_read_test_misc_extract_handles(struct ble_gatt_attr *attrs,
 }
 
 static void
-ble_gatt_read_test_misc_mult_verify_good(struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_mult_verify_good(
+    struct ble_hs_test_util_flat_attr *attrs)
 {
     uint8_t expected_value[512];
     uint16_t handles[256];
@@ -463,9 +465,9 @@ ble_gatt_read_test_misc_mult_verify_good(struct ble_gatt_attr *attrs)
 }
 
 static void
-ble_gatt_read_test_misc_mult_verify_bad(uint8_t att_status,
-                                        uint16_t err_handle,
-                                        struct ble_gatt_attr *attrs)
+ble_gatt_read_test_misc_mult_verify_bad(
+    uint8_t att_status, uint16_t err_handle,
+    struct ble_hs_test_util_flat_attr *attrs)
 {
     uint16_t handles[256];
     int num_attrs;
@@ -493,39 +495,39 @@ ble_gatt_read_test_misc_mult_verify_bad(uint8_t att_status,
 TEST_CASE(ble_gatt_read_test_by_handle)
 {
     /* Read a seven-byte attribute. */
-    ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+        .value = { 1,2,3,4,5,6,7 },
         .value_len = 7
     } });
 
     /* Read a one-byte attribute. */
-    ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 0x5432,
-        .value = (uint8_t[]){ 0xff },
+        .value = { 0xff },
         .value_len = 1
     } });
 
     /* Read a 200-byte attribute. */
-    ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 815,
-        .value = (uint8_t[200]){ 0 },
+        .value = { 0 },
         .value_len = 200,
     } });
 
     /* Fail due to attribute not found. */
     ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 719,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         } });
 
     /* Fail due to invalid PDU. */
     ble_gatt_read_test_misc_verify_bad(BLE_ATT_ERR_INVALID_PDU,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 65,
-            .value = (uint8_t[]){ 0xfa, 0x4c },
+            .value = { 0xfa, 0x4c },
             .value_len = 2
         } });
 }
@@ -534,9 +536,9 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
 {
     /* Read a single seven-byte attribute. */
     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 43,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         }, {
             0,
@@ -544,13 +546,13 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
 
     /* Read two seven-byte attributes; one response. */
     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 43,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         }, {
             .handle = 44,
-            .value = (uint8_t[]){ 2,3,4,5,6,7,8 },
+            .value = { 2,3,4,5,6,7,8 },
             .value_len = 7
         }, {
             0,
@@ -558,13 +560,13 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
 
     /* Read two attributes; two responses. */
     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 0,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 43,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         }, {
             .handle = 44,
-            .value = (uint8_t[]){ 2,3,4 },
+            .value = { 2,3,4 },
             .value_len = 3
         }, {
             0,
@@ -572,25 +574,25 @@ TEST_CASE(ble_gatt_read_test_by_uuid)
 
     /* Stop after three reads. */
     ble_gatt_read_test_misc_uuid_verify_good(1, 100, BLE_UUID16(0x1234), 3,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 43,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         }, {
             .handle = 44,
-            .value = (uint8_t[]){ 2,3,4 },
+            .value = { 2,3,4 },
             .value_len = 3
         }, {
             .handle = 45,
-            .value = (uint8_t[]){ 2,3,4 },
+            .value = { 2,3,4 },
             .value_len = 3
         }, {
             .handle = 46,
-            .value = (uint8_t[]){ 3,4,5,6 },
+            .value = { 3,4,5,6 },
             .value_len = 4
         }, {
             .handle = 47,
-            .value = (uint8_t[]){ 2,3,4 },
+            .value = { 2,3,4 },
             .value_len = 3
         }, {
             0,
@@ -607,38 +609,52 @@ TEST_CASE(ble_gatt_read_test_long)
     }
 
     /* Read a seven-byte attribute. */
-    ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_long_verify_good(0,
+        (struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = data512,
+        .value = { 1,2,3,4,5,6,7 },
         .value_len = 7
     } });
 
     /* Read a zero-byte attribute. */
-    ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_long_verify_good(0,
+        (struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = NULL,
+        .value = { 0 },
         .value_len = 0
     } });
 
     /* Read a 60-byte attribute; three requests. */
-    ble_gatt_read_test_misc_long_verify_good(0, (struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_long_verify_good(0,
+        (struct ble_hs_test_util_flat_attr[]) { {
         .handle = 34,
-        .value = data512,
+        .value = {
+            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, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+            49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
+        },
         .value_len = 60
     } });
 
     /* Stop after two reads. */
-    ble_gatt_read_test_misc_long_verify_good(2, (struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_long_verify_good(2,
+        (struct ble_hs_test_util_flat_attr[]) { {
         .handle = 34,
-        .value = data512,
+        .value = {
+            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, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+            49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
+        },
         .value_len = 60
     } });
 
     /* Fail due to attribute not found. */
     ble_gatt_read_test_misc_long_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 719,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1, 2, 3, 4, 5, 6, 7 }, 
             .value_len = 7
         } });
 }
@@ -653,60 +669,60 @@ TEST_CASE(ble_gatt_read_test_mult)
     }
 
     /* Read one attribute. */
-    ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_mult_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = data512,
+        .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
         .value_len = 7
     }, {
         0
     } });
 
     /* Read two attributes. */
-    ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_mult_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = data512,
+        .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
         .value_len = 7,
     }, {
         .handle = 44,
-        .value = data512 + 7,
+        .value = { 8, 9, 10, 11 },
         .value_len = 4,
     }, {
         0
     } });
 
     /* Read two attributes (swap order). */
-    ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_mult_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 44,
-        .value = data512 + 7,
+        .value = { 8, 9, 10, 11 },
         .value_len = 4,
     }, {
         .handle = 43,
-        .value = data512,
+        .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
         .value_len = 7,
     }, {
         0
     } });
 
     /* Read five attributes. */
-    ble_gatt_read_test_misc_mult_verify_good((struct ble_gatt_attr[]) { {
+    ble_gatt_read_test_misc_mult_verify_good((struct ble_hs_test_util_flat_attr[]) { {
         .handle = 43,
-        .value = data512,
+        .value = { 0, 1, 2, 3, 4, 5, 6, 7 },
         .value_len = 7,
     }, {
         .handle = 44,
-        .value = data512 + 7,
+        .value = { 8, 9, 10, 11 },
         .value_len = 4,
     }, {
         .handle = 145,
-        .value = data512 + 11,
+        .value = { 12, 13 },
         .value_len = 2,
     }, {
         .handle = 191,
-        .value = data512 + 13,
+        .value = { 14, 15, 16 },
         .value_len = 3,
     }, {
         .handle = 352,
-        .value = data512 + 16,
+        .value = { 17, 18, 19, 20 },
         .value_len = 4,
     }, {
         0
@@ -714,9 +730,9 @@ TEST_CASE(ble_gatt_read_test_mult)
 
     /* Fail due to attribute not found. */
     ble_gatt_read_test_misc_mult_verify_bad(BLE_ATT_ERR_ATTR_NOT_FOUND, 719,
-        (struct ble_gatt_attr[]) { {
+        (struct ble_hs_test_util_flat_attr[]) { {
             .handle = 719,
-            .value = (uint8_t[]){ 1,2,3,4,5,6,7 },
+            .value = { 1,2,3,4,5,6,7 },
             .value_len = 7
         }, {
             0
@@ -725,7 +741,6 @@ TEST_CASE(ble_gatt_read_test_mult)
 
 TEST_CASE(ble_gatt_read_test_concurrent)
 {
-    struct ble_gatt_attr attrs[3];
     int rc;
     int i;
 
@@ -738,24 +753,31 @@ TEST_CASE(ble_gatt_read_test_concurrent)
      * matched up with its corresponding GATT procedure.
      */
 
-    attrs[0].handle = 1;
-    attrs[0].offset = 0;
-    attrs[0].value_len = 3;
-    attrs[0].value = (uint8_t[3]){ 1, 2, 3 };
+    struct ble_hs_test_util_flat_attr attrs[3] = {
+        {
+            .handle = 1,
+            .offset = 0,
+            .value_len = 3,
+            .value = { 1, 2, 3 },
+        },
+        {
+            .handle = 2,
+            .offset = 0,
+            .value_len = 4,
+            .value = { 2, 3, 4, 5 },
+        },
+        {
+            .handle = 3,
+            .offset = 0,
+            .value_len = 5,
+            .value = { 3, 4, 5, 6, 7 },
+        },
+    };
+
     rc = ble_gattc_read(2, attrs[0].handle, ble_gatt_read_test_cb, NULL);
     TEST_ASSERT_FATAL(rc == 0);
-
-    attrs[1].handle = 2;
-    attrs[1].offset = 0;
-    attrs[1].value_len = 4;
-    attrs[1].value = (uint8_t[4]){ 2, 3, 4, 5 };
     rc = ble_gattc_read(2, attrs[1].handle, ble_gatt_read_test_cb, NULL);
     TEST_ASSERT_FATAL(rc == 0);
-
-    attrs[2].handle = 3;
-    attrs[2].offset = 0;
-    attrs[2].value_len = 5;
-    attrs[2].value = (uint8_t[5]){ 3, 4, 5, 6, 7 };
     rc = ble_gattc_read(2, attrs[2].handle, ble_gatt_read_test_cb, NULL);
     TEST_ASSERT_FATAL(rc == 0);
 
@@ -776,6 +798,8 @@ TEST_CASE(ble_gatt_read_test_concurrent)
 
 TEST_SUITE(ble_gatt_read_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_read_test_by_handle();
     ble_gatt_read_test_by_uuid();
     ble_gatt_read_test_long();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatt_write_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_write_test.c b/net/nimble/host/src/test/ble_gatt_write_test.c
index 0581524..f145ea8 100644
--- a/net/nimble/host/src/test/ble_gatt_write_test.c
+++ b/net/nimble/host/src/test/ble_gatt_write_test.c
@@ -33,7 +33,7 @@ static int ble_gatt_write_test_cb_called;
 static uint8_t ble_gatt_write_test_attr_value[BLE_ATT_ATTR_MAX_LEN];
 static struct ble_gatt_error ble_gatt_write_test_error;
 
-static const struct ble_gatt_attr *
+static struct ble_hs_test_util_flat_attr
 ble_gatt_write_test_attrs[BLE_GATT_WRITE_TEST_MAX_ATTRS];
 static int ble_gatt_write_test_num_attrs;
 
@@ -54,7 +54,7 @@ ble_gatt_write_test_init(void)
 static int
 ble_gatt_write_test_cb_good(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)
 {
     int *attr_len;
 
@@ -132,9 +132,9 @@ ble_gatt_write_test_misc_long_good(int attr_len)
     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
                                  NULL, NULL);
 
-    rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
-                              attr_len, ble_gatt_write_test_cb_good,
-                              &attr_len);
+    rc = ble_hs_test_util_gatt_write_long_flat(
+        2, 100, ble_gatt_write_test_attr_value, attr_len,
+        ble_gatt_write_test_cb_good, &attr_len);
     TEST_ASSERT(rc == 0);
 
     off = 0;
@@ -182,8 +182,9 @@ ble_gatt_write_test_misc_long_bad(int attr_len,
     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
                                  NULL, NULL);
 
-    rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
-                              attr_len, ble_gatt_write_test_cb_good, NULL);
+    rc = ble_hs_test_util_gatt_write_long_flat(
+        2, 100, ble_gatt_write_test_attr_value, attr_len,
+        ble_gatt_write_test_cb_good, NULL);
     TEST_ASSERT(rc == 0);
 
     fail_now = 0;
@@ -258,7 +259,7 @@ ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle,
 static int
 ble_gatt_write_test_reliable_cb_good(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)
 {
     int i;
@@ -269,7 +270,8 @@ ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
 
     ble_gatt_write_test_num_attrs = num_attrs;
     for (i = 0; i < num_attrs; i++) {
-        ble_gatt_write_test_attrs[i] = attrs + i;
+        ble_hs_test_util_attr_to_flat(ble_gatt_write_test_attrs + i,
+                                      attrs + i);
     }
 
     ble_gatt_write_test_cb_called = 1;
@@ -278,8 +280,10 @@ ble_gatt_write_test_reliable_cb_good(uint16_t conn_handle,
 }
 
 static void
-ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
+ble_gatt_write_test_misc_reliable_good(
+    struct ble_hs_test_util_flat_attr *flat_attrs)
 {
+    struct ble_gatt_attr attrs[16];
     int num_attrs;
     int attr_idx;
     int rc;
@@ -287,8 +291,11 @@ ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
 
     ble_gatt_write_test_init();
 
-    for (num_attrs = 0; attrs[num_attrs].handle != 0; num_attrs++)
-        ;
+    for (num_attrs = 0; flat_attrs[num_attrs].handle != 0; num_attrs++) {
+        TEST_ASSERT_FATAL(num_attrs < sizeof attrs / sizeof attrs[0]);
+        ble_hs_test_util_attr_from_flat(attrs + num_attrs,
+                                        flat_attrs + num_attrs);
+    }
 
     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
                                  NULL, NULL);
@@ -302,9 +309,9 @@ ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
         ble_hs_test_util_tx_all();
 
         /* Receive Prep Write response. */
-        ble_gatt_write_test_rx_prep_rsp(2, attrs[attr_idx].handle, 0,
-                                        attrs[attr_idx].value,
-                                        attrs[attr_idx].value_len);
+        ble_gatt_write_test_rx_prep_rsp(2, flat_attrs[attr_idx].handle, 0,
+                                        flat_attrs[attr_idx].value,
+                                        flat_attrs[attr_idx].value_len);
 
         /* Verify callback hasn't gotten called. */
         TEST_ASSERT(!ble_gatt_write_test_cb_called);
@@ -318,7 +325,9 @@ ble_gatt_write_test_misc_reliable_good(struct ble_gatt_attr *attrs)
     TEST_ASSERT(ble_gatt_write_test_cb_called);
     TEST_ASSERT(ble_gatt_write_test_num_attrs == num_attrs);
     for (i = 0; i < num_attrs; i++) {
-        TEST_ASSERT(ble_gatt_write_test_attrs[i] == attrs + i);
+        rc = ble_hs_test_util_flat_attr_cmp(
+            ble_gatt_write_test_attrs + i, flat_attrs + i);
+        TEST_ASSERT(rc == 0);
     }
 }
 
@@ -333,8 +342,8 @@ TEST_CASE(ble_gatt_write_test_no_rsp)
                                  NULL, NULL);
 
     attr_len = 4;
-    rc = ble_gattc_write_no_rsp(2, 100, ble_gatt_write_test_attr_value,
-                                attr_len);
+    rc = ble_hs_test_util_gatt_write_no_rsp_flat(
+        2, 100, ble_gatt_write_test_attr_value, attr_len);
     TEST_ASSERT(rc == 0);
 
     /* Send the pending ATT Write Command. */
@@ -354,8 +363,9 @@ TEST_CASE(ble_gatt_write_test_rsp)
                                  NULL, NULL);
 
     attr_len = 4;
-    ble_gattc_write(2, 100, ble_gatt_write_test_attr_value, attr_len,
-                    ble_gatt_write_test_cb_good, &attr_len);
+    ble_hs_test_util_gatt_write_flat(2, 100, ble_gatt_write_test_attr_value,
+                                     attr_len, ble_gatt_write_test_cb_good,
+                                     &attr_len);
 
     /* Send the pending ATT Write Command. */
     ble_hs_test_util_tx_all();
@@ -460,42 +470,42 @@ TEST_CASE(ble_gatt_write_test_reliable_good)
 {
     /*** 1 attribute. */
     ble_gatt_write_test_misc_reliable_good(
-        ((struct ble_gatt_attr[]) { {
+        ((struct ble_hs_test_util_flat_attr[]) { {
             .handle = 100,
             .value_len = 2,
-            .value = (uint8_t[]){ 1, 2 },
+            .value = { 1, 2 },
         }, {
             0
         } }));
 
     /*** 2 attributes. */
     ble_gatt_write_test_misc_reliable_good(
-        ((struct ble_gatt_attr[]) { {
+        ((struct ble_hs_test_util_flat_attr[]) { {
             .handle = 100,
             .value_len = 2,
-            .value = (uint8_t[]){ 1,2 },
+            .value = { 1,2 },
         }, {
             .handle = 113,
             .value_len = 6,
-            .value = (uint8_t[]){ 5,6,7,8,9,10 },
+            .value = { 5,6,7,8,9,10 },
         }, {
             0
         } }));
 
     /*** 3 attributes. */
     ble_gatt_write_test_misc_reliable_good(
-        ((struct ble_gatt_attr[]) { {
+        ((struct ble_hs_test_util_flat_attr[]) { {
             .handle = 100,
             .value_len = 2,
-            .value = (uint8_t[]){ 1,2 },
+            .value = { 1,2 },
         }, {
             .handle = 113,
             .value_len = 6,
-            .value = (uint8_t[]){ 5,6,7,8,9,10 },
+            .value = { 5,6,7,8,9,10 },
         }, {
             .handle = 144,
             .value_len = 1,
-            .value = (uint8_t[]){ 0xff },
+            .value = { 0xff },
         }, {
             0
         } }));
@@ -513,8 +523,9 @@ TEST_CASE(ble_gatt_write_test_long_queue_full)
     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
                                  NULL, NULL);
 
-    rc = ble_gattc_write_long(2, 100, ble_gatt_write_test_attr_value,
-                              128, ble_gatt_write_test_cb_good, NULL);
+    rc = ble_hs_test_util_gatt_write_long_flat(
+        2, 100, ble_gatt_write_test_attr_value, 128,
+        ble_gatt_write_test_cb_good, NULL);
     TEST_ASSERT(rc == 0);
 
     off = 0;
@@ -554,6 +565,8 @@ TEST_CASE(ble_gatt_write_test_long_queue_full)
 
 TEST_SUITE(ble_gatt_write_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatt_write_test_no_rsp();
     ble_gatt_write_test_rsp();
     ble_gatt_write_test_long_good();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatts_notify_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatts_notify_test.c b/net/nimble/host/src/test/ble_gatts_notify_test.c
index b859132..4516e66 100644
--- a/net/nimble/host/src/test/ble_gatts_notify_test.c
+++ b/net/nimble/host/src/test/ble_gatts_notify_test.c
@@ -378,21 +378,25 @@ ble_gatts_notify_test_misc_access(uint16_t conn_handle,
                                   struct ble_gatt_access_ctxt *ctxt,
                                   void *arg)
 {
+    int rc;
+
     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
     TEST_ASSERT(conn_handle == 0xffff);
 
     if (attr_handle == ble_gatts_notify_test_chr_1_def_handle + 1) {
         TEST_ASSERT(ctxt->chr ==
                     &ble_gatts_notify_test_svcs[0].characteristics[0]);
-        ctxt->att->read.data = ble_gatts_notify_test_chr_1_val;
-        ctxt->att->read.len = ble_gatts_notify_test_chr_1_len;
+        rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_1_val,
+                              ble_gatts_notify_test_chr_1_len);
+        TEST_ASSERT_FATAL(rc == 0);
     } else if (attr_handle == ble_gatts_notify_test_chr_2_def_handle + 1) {
         TEST_ASSERT(ctxt->chr ==
                     &ble_gatts_notify_test_svcs[0].characteristics[1]);
-        ctxt->att->read.data = ble_gatts_notify_test_chr_2_val;
-        ctxt->att->read.len = ble_gatts_notify_test_chr_2_len;
+        rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_2_val,
+                              ble_gatts_notify_test_chr_2_len);
+        TEST_ASSERT_FATAL(rc == 0);
     } else {
-        TEST_ASSERT(0);
+        TEST_ASSERT_FATAL(0);
     }
 
     return 0;
@@ -954,6 +958,8 @@ TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)
 
 TEST_SUITE(ble_gatts_notify_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatts_notify_test_n();
     ble_gatts_notify_test_i();
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatts_read_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatts_read_test.c b/net/nimble/host/src/test/ble_gatts_read_test.c
index 0f889f9..cef9f92 100644
--- a/net/nimble/host/src/test/ble_gatts_read_test.c
+++ b/net/nimble/host/src/test/ble_gatts_read_test.c
@@ -128,15 +128,17 @@ ble_gatts_read_test_util_access_1(uint16_t conn_handle,
                                   struct ble_gatt_access_ctxt *ctxt,
                                   void *arg)
 {
+    int rc;
+
     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
     TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_1_val_handle);
 
     TEST_ASSERT(ctxt->chr ==
                 &ble_gatts_read_test_svcs[0].characteristics[0]);
-    ctxt->att->read.data = ble_gatts_read_test_chr_1_val +
-                           ctxt->att->read.offset;
-    ctxt->att->read.len = ble_gatts_read_test_chr_1_len -
-                          ctxt->att->read.offset;
+
+    rc = os_mbuf_append(ctxt->om, ble_gatts_read_test_chr_1_val,
+                        ble_gatts_read_test_chr_1_len);
+    TEST_ASSERT(rc == 0);
 
     return 0;
 }
@@ -147,22 +149,23 @@ ble_gatts_read_test_util_access_2(uint16_t conn_handle,
                                   struct ble_gatt_access_ctxt *ctxt,
                                   void *arg)
 {
+    uint8_t *buf;
+
     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
     TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_2_def_handle + 1);
 
     TEST_ASSERT(ctxt->chr ==
                 &ble_gatts_read_test_svcs[0].characteristics[1]);
 
-    TEST_ASSERT_FATAL(ctxt->att->read.data == ctxt->att->read.buf);
-    TEST_ASSERT(ctxt->att->read.max_data_len == BLE_ATT_MTU_DFLT - 1);
+    buf = os_mbuf_extend(ctxt->om, 6);
+    TEST_ASSERT_FATAL(buf != NULL);
 
-    ctxt->att->read.buf[0] = 0;
-    ctxt->att->read.buf[1] = 10;
-    ctxt->att->read.buf[2] = 20;
-    ctxt->att->read.buf[3] = 30;
-    ctxt->att->read.buf[4] = 40;
-    ctxt->att->read.buf[5] = 50;
-    ctxt->att->read.len = 6;
+    buf[0] = 0;
+    buf[1] = 10;
+    buf[2] = 20;
+    buf[3] = 30;
+    buf[4] = 40;
+    buf[5] = 50;
 
     return 0;
 }
@@ -251,6 +254,8 @@ TEST_CASE(ble_gatts_read_test_case_long)
 
 TEST_SUITE(ble_gatts_read_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatts_read_test_case_basic();
     ble_gatts_read_test_case_long();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_gatts_reg_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatts_reg_test.c b/net/nimble/host/src/test/ble_gatts_reg_test.c
index f15dfef..963800a 100644
--- a/net/nimble/host/src/test/ble_gatts_reg_test.c
+++ b/net/nimble/host/src/test/ble_gatts_reg_test.c
@@ -697,6 +697,8 @@ TEST_CASE(ble_gatts_reg_test_dsc_cb)
 
 TEST_SUITE(ble_gatts_reg_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_gatts_reg_test_svc_return();
     ble_gatts_reg_test_chr_return();
     ble_gatts_reg_test_dsc_return();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_host_hci_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_host_hci_test.c b/net/nimble/host/src/test/ble_host_hci_test.c
index 52837bd..a8e8d82 100644
--- a/net/nimble/host/src/test/ble_host_hci_test.c
+++ b/net/nimble/host/src/test/ble_host_hci_test.c
@@ -82,6 +82,8 @@ TEST_CASE(ble_host_hci_test_rssi)
 
 TEST_SUITE(ble_host_hci_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_host_hci_test_event_bad();
     ble_host_hci_test_rssi();
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_hs_adv_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_adv_test.c b/net/nimble/host/src/test/ble_hs_adv_test.c
index dec9736..89c61a2 100644
--- a/net/nimble/host/src/test/ble_hs_adv_test.c
+++ b/net/nimble/host/src/test/ble_hs_adv_test.c
@@ -1469,6 +1469,8 @@ TEST_CASE(ble_hs_adv_test_case_user_full_payload)
 
 TEST_SUITE(ble_hs_adv_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_hs_adv_test_case_flags();
     ble_hs_adv_test_case_user();
     ble_hs_adv_test_case_user_rsp();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_hs_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_conn_test.c b/net/nimble/host/src/test/ble_hs_conn_test.c
index 87df5b1..0e896f4 100644
--- a/net/nimble/host/src/test/ble_hs_conn_test.c
+++ b/net/nimble/host/src/test/ble_hs_conn_test.c
@@ -204,6 +204,8 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
 
 TEST_SUITE(conn_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_hs_conn_test_direct_connect_success();
     ble_hs_conn_test_direct_connectable_success();
     ble_hs_conn_test_undirect_connectable_success();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index 65b428a..d517f86 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -719,6 +719,8 @@ ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
     conn = ble_hs_conn_find(conn_handle);
     if (conn != NULL) {
         rc = ble_l2cap_rx(conn, hci_hdr, om, &rx_cb, &rx_buf);
+    } else {
+        os_mbuf_free_chain(om);
     }
 
     ble_hs_unlock();
@@ -746,7 +748,7 @@ ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
     struct os_mbuf *om;
     int rc;
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     rc = os_mbuf_append(om, data, len);
@@ -982,6 +984,206 @@ ble_hs_test_util_set_static_rnd_addr(void)
     ble_hs_test_util_get_first_hci_tx();
 }
 
+struct os_mbuf *
+ble_hs_test_util_om_from_flat(const void *buf, uint16_t len)
+{
+    struct os_mbuf *om;
+
+    om = ble_hs_mbuf_from_flat(buf, len);
+    TEST_ASSERT_FATAL(om != NULL);
+
+    return om;
+}
+
+int
+ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a,
+                               const struct ble_hs_test_util_flat_attr *b)
+{
+    if (a->handle != b->handle) {
+        return -1;
+    }
+    if (a->offset != b->offset) {
+        return -1;
+    }
+    if (a->value_len != b->value_len) {
+        return -1;
+    }
+    return memcmp(a->value, b->value, a->value_len);
+}
+
+void
+ble_hs_test_util_attr_to_flat(struct ble_hs_test_util_flat_attr *flat,
+                              const struct ble_gatt_attr *attr)
+{
+    int rc;
+
+    flat->handle = attr->handle;
+    flat->offset = attr->offset;
+    rc = ble_hs_mbuf_to_flat(attr->om, flat->value, sizeof flat->value,
+                           &flat->value_len);
+    TEST_ASSERT_FATAL(rc == 0);
+}
+
+void
+ble_hs_test_util_attr_from_flat(struct ble_gatt_attr *attr,
+                                const struct ble_hs_test_util_flat_attr *flat)
+{
+    attr->handle = flat->handle;
+    attr->offset = flat->offset;
+    attr->om = ble_hs_test_util_om_from_flat(flat->value, flat->value_len);
+}
+
+int
+ble_hs_test_util_read_local_flat(uint16_t attr_handle, uint16_t max_len,
+                                 void *buf, uint16_t *out_len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    rc = ble_att_svr_read_local(attr_handle, &om);
+    if (rc != 0) {
+        return rc;
+    }
+
+    TEST_ASSERT_FATAL(OS_MBUF_PKTLEN(om) <= max_len);
+
+    rc = os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), buf);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    *out_len = OS_MBUF_PKTLEN(om);
+
+    os_mbuf_free_chain(om);
+    return 0;
+}
+
+int
+ble_hs_test_util_write_local_flat(uint16_t attr_handle,
+                                  const void *buf, uint16_t buf_len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_test_util_om_from_flat(buf, buf_len);
+    rc = ble_att_svr_write_local(attr_handle, &om);
+    TEST_ASSERT(om == NULL);
+    return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_flat(uint16_t conn_handle, uint16_t attr_handle,
+                                 const void *data, uint16_t data_len,
+                                 ble_gatt_attr_fn *cb, void *cb_arg)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_test_util_om_from_flat(data, data_len);
+    rc = ble_gattc_write(conn_handle, attr_handle, &om, cb, cb_arg);
+    TEST_ASSERT(om == NULL);
+
+    return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_no_rsp_flat(uint16_t conn_handle,
+                                        uint16_t attr_handle,
+                                        const void *data, uint16_t data_len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_test_util_om_from_flat(data, data_len);
+    rc = ble_gattc_write_no_rsp(conn_handle, attr_handle, &om);
+    TEST_ASSERT(om == NULL);
+
+    return rc;
+}
+
+int
+ble_hs_test_util_gatt_write_long_flat(uint16_t conn_handle,
+                                      uint16_t attr_handle,
+                                      const void *data, uint16_t data_len,
+                                      ble_gatt_attr_fn *cb, void *cb_arg)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = ble_hs_test_util_om_from_flat(data, data_len);
+    rc = ble_gattc_write_long(conn_handle, attr_handle, &om, cb, cb_arg);
+    TEST_ASSERT(om == NULL);
+    return rc;
+}
+
+static int
+ble_hs_test_util_mbuf_chain_len(const struct os_mbuf *om)
+{
+    int count;
+
+    count = 0;
+    while (om != NULL) {
+        count++;
+        om = SLIST_NEXT(om, om_next);
+    }
+
+    return count;
+}
+
+int
+ble_hs_test_util_mbuf_count(void)
+{
+    const struct ble_att_prep_entry *prep;
+    const struct os_mbuf_pkthdr *omp;
+    const struct ble_l2cap_chan *chan;
+    const struct ble_hs_conn *conn;
+    const struct os_mbuf *om;
+    int count;
+    int i;
+
+    count = ble_hs_test_util_mbuf_mpool.mp_num_free;
+    count += ble_hs_test_util_mbuf_chain_len(ble_hs_test_util_prev_tx_cur);
+
+    ble_hs_process_tx_data_queue();
+    ble_hs_process_rx_data_queue();
+    STAILQ_FOREACH(omp, &ble_hs_test_util_prev_tx_queue, omp_next) {
+        om = OS_MBUF_PKTHDR_TO_MBUF(omp);
+        count += ble_hs_test_util_mbuf_chain_len(om);
+    }
+
+    ble_hs_lock();
+    for (i = 0; ; i++) {
+        conn = ble_hs_conn_find_by_idx(i);
+        if (conn == NULL) {
+            break;
+        }
+
+        SLIST_FOREACH(chan, &conn->bhc_channels, blc_next) {
+            count += ble_hs_test_util_mbuf_chain_len(chan->blc_rx_buf);
+        }
+
+        SLIST_FOREACH(prep, &conn->bhc_att_svr.basc_prep_list, bape_next) {
+            count += ble_hs_test_util_mbuf_chain_len(prep->bape_value);
+        }
+    }
+    ble_hs_unlock();
+
+    return count;
+}
+
+void
+ble_hs_test_util_assert_mbufs_freed(void)
+{
+    int count;
+
+    count = ble_hs_test_util_mbuf_count();
+    TEST_ASSERT(count == ble_hs_test_util_mbuf_mpool.mp_num_blocks);
+}
+
+void
+ble_hs_test_util_post_test(void *arg)
+{
+    ble_hs_test_util_assert_mbufs_freed();
+}
+
 void
 ble_hs_test_util_init(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.h b/net/nimble/host/src/test/ble_hs_test_util.h
index 3b4fe94..b663ce2 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -36,6 +36,13 @@ struct ble_hs_test_util_num_completed_pkts_entry {
     uint16_t num_pkts;
 };
 
+struct ble_hs_test_util_flat_attr {
+    uint16_t handle;
+    uint16_t offset;
+    uint8_t value[BLE_ATT_ATTR_MAX_LEN];
+    uint16_t value_len;
+};
+
 void ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om);
 struct os_mbuf *ble_hs_test_util_prev_tx_dequeue(void);
 struct os_mbuf *ble_hs_test_util_prev_tx_dequeue_pullup(void);
@@ -122,6 +129,32 @@ void ble_hs_test_util_verify_tx_read_rsp(uint8_t *attr_data, int attr_len);
 void ble_hs_test_util_verify_tx_read_blob_rsp(uint8_t *attr_data,
                                               int attr_len);
 void ble_hs_test_util_set_static_rnd_addr(void);
+struct os_mbuf *ble_hs_test_util_om_from_flat(const void *buf, uint16_t len);
+int ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a,
+                                   const struct ble_hs_test_util_flat_attr *b);
+void ble_hs_test_util_attr_to_flat(struct ble_hs_test_util_flat_attr *flat,
+                                   const struct ble_gatt_attr *attr);
+void ble_hs_test_util_attr_from_flat(
+    struct ble_gatt_attr *attr, const struct ble_hs_test_util_flat_attr *flat);
+int ble_hs_test_util_read_local_flat(uint16_t attr_handle, uint16_t max_len,
+                                     void *buf, uint16_t *out_len);
+int ble_hs_test_util_write_local_flat(uint16_t attr_handle,
+                                      const void *buf, uint16_t buf_len);
+int ble_hs_test_util_gatt_write_flat(uint16_t conn_handle,
+                                     uint16_t attr_handle,
+                                     const void *data, uint16_t data_len,
+                                     ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_hs_test_util_gatt_write_no_rsp_flat(uint16_t conn_handle,
+                                            uint16_t attr_handle,
+                                            const void *data,
+                                            uint16_t data_len);
+int ble_hs_test_util_gatt_write_long_flat(uint16_t conn_handle,
+                                          uint16_t attr_handle,
+                                          const void *data, uint16_t data_len,
+                                          ble_gatt_attr_fn *cb, void *cb_arg);
+int ble_hs_test_util_mbuf_count(void);
+void ble_hs_test_util_assert_mbufs_freed(void);
+void ble_hs_test_util_post_test(void *arg);
 void ble_hs_test_util_init(void);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_l2cap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_l2cap_test.c b/net/nimble/host/src/test/ble_l2cap_test.c
index b651325..118d04f 100644
--- a/net/nimble/host/src/test/ble_l2cap_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_test.c
@@ -242,7 +242,7 @@ ble_l2cap_test_util_rx_first_frag(uint16_t conn_handle,
     void *v;
     int rc;
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     v = os_mbuf_extend(om, l2cap_frag_len);
@@ -266,7 +266,7 @@ ble_l2cap_test_util_rx_next_frag(uint16_t conn_handle, uint16_t hci_len)
     void *v;
     int rc;
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     v = os_mbuf_extend(om, hci_len);
@@ -374,7 +374,7 @@ TEST_CASE(ble_l2cap_test_case_frag_single)
     /*** HCI header specifies middle fragment without start. */
     hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     om = ble_l2cap_prepend_hdr(om, 0, 5);
@@ -666,6 +666,8 @@ TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_bad_id)
 
 TEST_SUITE(ble_l2cap_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_l2cap_test_case_bad_header();
     ble_l2cap_test_case_frag_single();
     ble_l2cap_test_case_frag_multiple();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_os_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_os_test.c b/net/nimble/host/src/test/ble_os_test.c
index 193cab1..1ab8e0a 100644
--- a/net/nimble/host/src/test/ble_os_test.c
+++ b/net/nimble/host/src/test/ble_os_test.c
@@ -385,6 +385,8 @@ TEST_CASE(ble_gap_terminate_test_case)
 
 TEST_SUITE(ble_os_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_os_disc_test_case();
     ble_gap_direct_connect_test_case();
     ble_gap_terminate_test_case();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_sm_lgcy_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_lgcy_test.c b/net/nimble/host/src/test/ble_sm_lgcy_test.c
index 59dceab..9a61087 100644
--- a/net/nimble/host/src/test/ble_sm_lgcy_test.c
+++ b/net/nimble/host/src/test/ble_sm_lgcy_test.c
@@ -822,6 +822,8 @@ TEST_CASE(ble_sm_lgcy_peer_pk_iio4_rio4_b1_iat0_rat0_ik7_rk7)
 
 TEST_SUITE(ble_sm_lgcy_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     /*** No privacy. */
 
     /* Peer as initiator. */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_sm_sc_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_sc_test.c b/net/nimble/host/src/test/ble_sm_sc_test.c
index 4d60f0c..f69c60e 100644
--- a/net/nimble/host/src/test/ble_sm_sc_test.c
+++ b/net/nimble/host/src/test/ble_sm_sc_test.c
@@ -4879,6 +4879,8 @@ TEST_CASE(ble_sm_sc_us_pk_iio2_rio0_b1_iat2_rat2_ik7_rk3)
 
 TEST_SUITE(ble_sm_sc_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     /*** No privacy. */
 
     /* Peer as initiator. */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_sm_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_test.c b/net/nimble/host/src/test/ble_sm_test.c
index d890996..26efea9 100644
--- a/net/nimble/host/src/test/ble_sm_test.c
+++ b/net/nimble/host/src/test/ble_sm_test.c
@@ -648,6 +648,8 @@ TEST_CASE(ble_sm_test_case_us_fail_inval)
 
 TEST_SUITE(ble_sm_gen_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_sm_test_case_f4();
     ble_sm_test_case_f5();
     ble_sm_test_case_f6();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_sm_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_sm_test_util.c b/net/nimble/host/src/test/ble_sm_test_util.c
index 29c2aa5..1c052fb 100644
--- a/net/nimble/host/src/test/ble_sm_test_util.c
+++ b/net/nimble/host/src/test/ble_sm_test_util.c
@@ -307,7 +307,7 @@ ble_sm_test_util_rx_pair_cmd(uint16_t conn_handle, uint8_t op,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_CMD_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_CMD_SZ;
@@ -354,7 +354,7 @@ ble_sm_test_util_rx_confirm(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_CONFIRM_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_CONFIRM_SZ;
@@ -384,7 +384,7 @@ ble_sm_test_util_rx_random(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PAIR_RANDOM_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_PAIR_RANDOM_SZ;
@@ -413,7 +413,7 @@ ble_sm_test_util_rx_sec_req(uint16_t conn_handle, struct ble_sm_sec_req *cmd,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_SEC_REQ_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_SEC_REQ_SZ;
@@ -442,7 +442,7 @@ ble_sm_test_util_rx_public_key(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_PUBLIC_KEY_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_PUBLIC_KEY_SZ;
@@ -472,7 +472,7 @@ ble_sm_test_util_rx_dhkey_check(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_DHKEY_CHECK_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_DHKEY_CHECK_SZ;
@@ -502,7 +502,7 @@ ble_sm_test_util_rx_enc_info(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ENC_INFO_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_ENC_INFO_SZ;
@@ -532,7 +532,7 @@ ble_sm_test_util_rx_master_id(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_MASTER_ID_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_MASTER_ID_SZ;
@@ -562,7 +562,7 @@ ble_sm_test_util_rx_id_info(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ID_INFO_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_ID_INFO_SZ;
@@ -592,7 +592,7 @@ ble_sm_test_util_rx_id_addr_info(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_ID_ADDR_INFO_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_ID_ADDR_INFO_SZ;
@@ -622,7 +622,7 @@ ble_sm_test_util_rx_sign_info(uint16_t conn_handle,
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_SM_HDR_SZ + BLE_SM_SIGN_INFO_SZ);
 
-    om = ble_hs_misc_pkthdr();
+    om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
 
     payload_len = BLE_SM_HDR_SZ + BLE_SM_SIGN_INFO_SZ;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/host/src/test/ble_uuid_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_uuid_test.c b/net/nimble/host/src/test/ble_uuid_test.c
index ecb3505..1011303 100644
--- a/net/nimble/host/src/test/ble_uuid_test.c
+++ b/net/nimble/host/src/test/ble_uuid_test.c
@@ -19,9 +19,10 @@
 
 #include <stddef.h>
 #include <string.h>
-#include "host/ble_hs_test.h"
 #include "testutil/testutil.h"
+#include "host/ble_hs_test.h"
 #include "host/ble_uuid.h"
+#include "ble_hs_test_util.h"
 
 TEST_CASE(ble_uuid_test_128_to_16)
 {
@@ -78,6 +79,8 @@ TEST_CASE(ble_uuid_test_128_to_16)
 
 TEST_SUITE(ble_uuid_test_suite)
 {
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
     ble_uuid_test_128_to_16();
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ef7abf7d/net/nimble/include/nimble/nimble_opt.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/nimble_opt.h b/net/nimble/include/nimble/nimble_opt.h
index dd007e2..319c08d 100644
--- a/net/nimble/include/nimble/nimble_opt.h
+++ b/net/nimble/include/nimble/nimble_opt.h
@@ -138,6 +138,14 @@
 #define NIMBLE_OPT_GATT_INDICATE                1
 #endif
 
+/** HOST: GATT options. */
+
+/* The maximum number of attributes that can be written with a single GATT
+ * Reliable Write procedure.
+ */
+#ifndef NIMBLE_OPT_GATT_WRITE_MAX_ATTRS
+#define NIMBLE_OPT_GATT_WRITE_MAX_ATTRS         4
+#endif
 
 /** HOST: Supported server ATT commands. */