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/11/29 02:39:41 UTC

incubator-mynewt-core git commit: MYNEWT-324 BLE Host - Reuse rxbuf for MTU rsp.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop ea3347b27 -> 28c48007e


MYNEWT-324 BLE Host - Reuse rxbuf for MTU rsp.

More diligent reuse of reuest buffers.


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

Branch: refs/heads/develop
Commit: 28c48007e05eb3590d8104c13319968b8164226f
Parents: ea3347b
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Nov 28 16:17:25 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Nov 28 18:35:59 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_att_svr.c           | 109 ++++----
 net/nimble/host/test/src/ble_att_svr_test.c | 328 +++++++----------------
 net/nimble/host/test/src/ble_hs_test_util.c | 116 ++++++++
 net/nimble/host/test/src/ble_hs_test_util.h |  17 ++
 4 files changed, 286 insertions(+), 284 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/28c48007/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 5cbd2a7..f13105e 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -649,10 +649,10 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **rxom,
     mtu = chan->blc_my_mtu;
     ble_hs_unlock();
 
-    rc = ble_att_svr_pkt(rxom, &txom, att_err);
-    if (rc != 0) {
-        goto done;
-    }
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     dst = os_mbuf_extend(txom, BLE_ATT_MTU_CMD_SZ);
     if (dst == NULL) {
@@ -829,14 +829,10 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle,
     void *buf;
     int rc;
 
-    txom = NULL;
-
-    mtu = ble_att_mtu(conn_handle);
-
-    rc = ble_att_svr_pkt(rxom, &txom, att_err);
-    if (rc != 0) {
-        goto done;
-    }
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     /* Write the response base at the start of the buffer.  The format field is
      * unknown at this point; it will be filled in later.
@@ -853,6 +849,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle,
     /* Write the variable length Information Data field, populating the format
      * field as appropriate.
      */
+    mtu = ble_att_mtu(conn_handle);
     rc = ble_att_svr_fill_info(req, txom, mtu, txom->om_data + 1);
     if (rc != 0) {
         *att_err = BLE_ATT_ERR_ATTR_NOT_FOUND;
@@ -1266,13 +1263,10 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
     entry_written = 0;
     prev_attr_len = 0;
 
-    mtu = ble_att_mtu(conn_handle);
-
-    rc = ble_att_svr_pkt(rxom, &txom, att_err);
-    if (rc != 0) {
-        *err_handle = 0;
-        goto done;
-    }
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     /* Allocate space for the respose base, but don't fill in the fields.  They
      * get filled in at the end, when we know the value of the length field.
@@ -1285,6 +1279,8 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle,
         goto done;
     }
 
+    mtu = ble_att_mtu(conn_handle);
+
     /* Find all matching attributes, writing a record for each. */
     entry = NULL;
     while (1) {
@@ -1462,18 +1458,18 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
 
     rc = ble_att_svr_pullup_req_base(rxom, BLE_ATT_READ_REQ_SZ, &att_err);
     if (rc != 0) {
-        err_handle = 0;
         goto done;
     }
 
     ble_att_read_req_parse((*rxom)->om_data, (*rxom)->om_len, &req);
     BLE_ATT_LOG_CMD(0, "read req", conn_handle, ble_att_read_req_log, &req);
 
-    rc = ble_att_svr_pkt(rxom, &txom, &att_err);
-    if (rc != 0) {
-        err_handle = req.barq_handle;
-        goto done;
-    }
+    err_handle = req.barq_handle;
+
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     dptr = os_mbuf_extend(txom, 1);
     if (dptr == NULL) {
@@ -1486,7 +1482,6 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom)
     rc = ble_att_svr_read_handle(conn_handle, req.barq_handle, 0, txom,
                                  &att_err);
     if (rc != 0) {
-        err_handle = req.barq_handle;
         goto done;
     }
 
@@ -1517,7 +1512,6 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
 
     rc = ble_att_svr_pullup_req_base(rxom, BLE_ATT_READ_BLOB_REQ_SZ, &att_err);
     if (rc != 0) {
-        err_handle = 0;
         goto done;
     }
 
@@ -1525,16 +1519,16 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
     BLE_ATT_LOG_CMD(0, "read blob req", conn_handle, ble_att_read_blob_req_log,
                     &req);
 
-    rc = ble_att_svr_pkt(rxom, &txom, &att_err);
-    if (rc != 0) {
-        err_handle = req.babq_handle;
-        goto done;
-    }
+    err_handle = req.babq_handle;
+
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     dptr = os_mbuf_extend(txom, 1);
     if (dptr == NULL) {
         att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
-        err_handle = req.babq_handle;
         rc = BLE_HS_ENOMEM;
         goto done;
     }
@@ -1543,7 +1537,6 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom)
     rc = ble_att_svr_read_handle(conn_handle, req.babq_handle, req.babq_offset,
                                  txom, &att_err);
     if (rc != 0) {
-        err_handle = req.babq_handle;
         goto done;
     }
 
@@ -1680,13 +1673,13 @@ ble_att_svr_is_valid_group_type(uint8_t *uuid128)
 
 static int
 ble_att_svr_service_uuid(struct ble_att_svr_entry *entry, uint16_t *uuid16,
-                         uint8_t *uuid128)
+                         uint8_t *uuid128, uint8_t *out_att_err)
 {
     uint16_t attr_len;
     int rc;
 
     rc = ble_att_svr_read_flat(BLE_HS_CONN_HANDLE_NONE, entry, 0, 16, uuid128,
-                               &attr_len, NULL);
+                               &attr_len, out_att_err);
     if (rc != 0) {
         return rc;
     }
@@ -1776,10 +1769,10 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle,
 
     mtu = ble_att_mtu(conn_handle);
 
-    rc = ble_att_svr_pkt(rxom, &txom, att_err);
-    if (rc != 0) {
-        goto done;
-    }
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     /* Reserve space for the response base. */
     rsp_buf = os_mbuf_extend(txom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
@@ -1832,11 +1825,9 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle,
             if (memcmp(entry->ha_uuid, group_uuid128, 16) == 0) {
                 /* Found a group start.  Read the group UUID. */
                 rc = ble_att_svr_service_uuid(entry, &service_uuid16,
-                                              service_uuid128);
+                                              service_uuid128, att_err);
                 if (rc != 0) {
                     *err_handle = entry->ha_handle_id;
-                    *att_err = BLE_ATT_ERR_UNLIKELY;
-                    rc = BLE_HS_ENOTSUP;
                     goto done;
                 }
 
@@ -2007,10 +1998,19 @@ ble_att_svr_build_write_rsp(struct os_mbuf **rxom, struct os_mbuf **out_txom,
     uint8_t *dst;
     int rc;
 
-    /* Just reuse the request buffer for the response. */
-    txom = *rxom;
-    *rxom = NULL;
-    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
+    /* Just reuse the request buffer for the response if the application didn't
+     * retain it.
+     */
+    if (*rxom != NULL) {
+        txom = *rxom;
+        *rxom = NULL;
+        os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
+    } else {
+        rc = ble_att_svr_pkt(rxom, &txom, att_err);
+        if (rc != 0) {
+            goto done;
+        }
+    }
 
     dst = os_mbuf_extend(txom, BLE_ATT_WRITE_RSP_SZ);
     if (dst == NULL) {
@@ -2474,10 +2474,10 @@ ble_att_svr_build_exec_write_rsp(struct os_mbuf **rxom,
     uint8_t *dst;
     int rc;
 
-    rc = ble_att_svr_pkt(rxom, &txom, att_err);
-    if (rc != 0) {
-        goto done;
-    }
+    /* Just reuse the request buffer for the response. */
+    txom = *rxom;
+    *rxom = NULL;
+    os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom));
 
     dst = os_mbuf_extend(txom, BLE_ATT_EXEC_WRITE_RSP_SZ);
     if (dst == NULL) {
@@ -2670,7 +2670,12 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom)
         goto done;
     }
 
-    /* Ensure we can allocate a response before processing the indication. */
+    /* Ensure we can allocate a response before processing the indication. 
+     * We can't reuse the request mbuf because it contains the data that needs
+     * to be passed to the application callback.  The application may choose to
+     * retain the mbuf during the callback, so we can't just reuse the mbuf
+     * after executing the callback either.
+     */
     rc = ble_att_svr_build_indicate_rsp(rxom, &txom, &att_err);
     if (rc != 0) {
         goto done;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/28c48007/net/nimble/host/test/src/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_att_svr_test.c b/net/nimble/host/test/src/ble_att_svr_test.c
index b7553d7..5de166b 100644
--- a/net/nimble/host/test/src/ble_att_svr_test.c
+++ b/net/nimble/host/test/src/ble_att_svr_test.c
@@ -113,7 +113,7 @@ ble_att_svr_test_misc_attr_fn_r_1(uint16_t conn_handle, uint16_t attr_handle,
         return 0;
 
     default:
-        return -1;
+        return BLE_ATT_ERR_UNLIKELY;
     }
 }
 
@@ -134,7 +134,7 @@ ble_att_svr_test_misc_attr_fn_r_2(uint16_t conn_handle, uint16_t attr_handle,
         return 0;
 
     default:
-        return -1;
+        return BLE_ATT_ERR_UNLIKELY;
     }
 }
 
@@ -286,6 +286,32 @@ ble_att_svr_test_misc_register_group_attrs(void)
 }
 
 static int
+ble_att_svr_test_misc_attr_fn_rw_1(uint16_t conn_handle, uint16_t attr_handle,
+                                   uint8_t op, uint16_t offset,
+                                   struct os_mbuf **om, void *arg)
+{
+    switch (op) {
+    case BLE_ATT_ACCESS_OP_READ:
+        if (offset > ble_att_svr_test_attr_w_1_len) {
+            return BLE_ATT_ERR_INVALID_OFFSET;
+        }
+
+        os_mbuf_append(*om, ble_att_svr_test_attr_w_1 + offset,
+                       ble_att_svr_test_attr_w_1_len - offset);
+        return 0;
+
+    case BLE_ATT_ACCESS_OP_WRITE:
+        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:
+        return BLE_ATT_ERR_UNLIKELY;
+    }
+}
+
+static int
 ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
                                   uint8_t op, uint16_t offset,
                                   struct os_mbuf **om, void *arg)
@@ -298,7 +324,7 @@ ble_att_svr_test_misc_attr_fn_w_1(uint16_t conn_handle, uint16_t attr_handle,
         return 0;
 
     default:
-        return -1;
+        return BLE_ATT_ERR_UNLIKELY;
     }
 }
 
@@ -315,7 +341,7 @@ ble_att_svr_test_misc_attr_fn_w_2(uint16_t conn_handle, uint16_t attr_handle,
         return 0;
 
     default:
-        return -1;
+        return BLE_ATT_ERR_UNLIKELY;
     }
 }
 
@@ -343,32 +369,6 @@ ble_att_svr_test_misc_verify_w_2(void *data, int data_len)
 }
 
 static void
-ble_att_svr_test_misc_verify_tx_read_blob_rsp(uint8_t *attr_data, int attr_len)
-{
-    struct os_mbuf *om;
-    uint8_t u8;
-    int rc;
-    int i;
-
-    ble_hs_test_util_tx_all();
-
-    om = ble_hs_test_util_prev_tx_dequeue();
-
-    rc = os_mbuf_copydata(om, 0, 1, &u8);
-    TEST_ASSERT(rc == 0);
-    TEST_ASSERT(u8 == BLE_ATT_OP_READ_BLOB_RSP);
-
-    for (i = 0; i < attr_len; i++) {
-        rc = os_mbuf_copydata(om, i + 1, 1, &u8);
-        TEST_ASSERT(rc == 0);
-        TEST_ASSERT(u8 == attr_data[i]);
-    }
-
-    rc = os_mbuf_copydata(om, i + 1, 1, &u8);
-    TEST_ASSERT(rc != 0);
-}
-
-static void
 ble_att_svr_test_misc_rx_read_mult_req(uint16_t conn_handle,
                                        uint16_t *handles, int num_handles,
                                        int success)
@@ -450,92 +450,16 @@ ble_att_svr_test_misc_verify_all_read_mult(
 static void
 ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle)
 {
-    struct ble_att_mtu_cmd rsp;
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
-    struct os_mbuf *om;
-    uint8_t buf[BLE_ATT_MTU_CMD_SZ];
-    int rc;
-
-    ble_hs_test_util_tx_all();
-
-    om = ble_hs_test_util_prev_tx_dequeue();
-
-    rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
-    TEST_ASSERT(rc == 0);
-
-    ble_att_mtu_rsp_parse(buf, sizeof buf, &rsp);
+    uint16_t my_mtu;
 
     ble_hs_lock();
-    rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
-                                    &conn, &chan);
-    TEST_ASSERT_FATAL(rc == 0);
-    TEST_ASSERT(rsp.bamc_mtu == chan->blc_my_mtu);
+    ble_att_conn_chan_find(conn_handle, &conn, &chan);
+    my_mtu = chan->blc_my_mtu;
     ble_hs_unlock();
-}
-
-struct ble_att_svr_test_info_entry {
-    uint16_t handle;        /* 0 on last entry */
-    uint16_t uuid16;        /* 0 if not present. */
-    uint8_t uuid128[16];
-};
-
-static void
-ble_att_svr_test_misc_verify_tx_find_info_rsp(
-    struct ble_att_svr_test_info_entry *entries)
-{
-    struct ble_att_svr_test_info_entry *entry;
-    struct ble_att_find_info_rsp rsp;
-    struct os_mbuf *om;
-    uint16_t handle;
-    uint16_t uuid16;
-    uint8_t buf[BLE_ATT_FIND_INFO_RSP_BASE_SZ];
-    uint8_t uuid128[16];
-    int off;
-    int rc;
-
-    ble_hs_test_util_tx_all();
-
-    off = 0;
-
-    om = ble_hs_test_util_prev_tx_dequeue_pullup();
-
-    rc = os_mbuf_copydata(om, off, sizeof buf, buf);
-    TEST_ASSERT(rc == 0);
-    off += sizeof buf;
-
-    ble_att_find_info_rsp_parse(buf, sizeof buf, &rsp);
-
-    for (entry = entries; entry->handle != 0; entry++) {
-        rc = os_mbuf_copydata(om, off, 2, &handle);
-        TEST_ASSERT(rc == 0);
-        off += 2;
-
-        handle = le16toh((void *)&handle);
-        TEST_ASSERT(handle == entry->handle);
-
-        if (entry->uuid16 != 0) {
-            TEST_ASSERT(rsp.bafp_format ==
-                        BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT);
-            rc = os_mbuf_copydata(om, off, 2, &uuid16);
-            TEST_ASSERT(rc == 0);
-            off += 2;
-
-            uuid16 = le16toh((void *)&uuid16);
-            TEST_ASSERT(uuid16 == entry->uuid16);
-        } else {
-            TEST_ASSERT(rsp.bafp_format ==
-                        BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT);
-            rc = os_mbuf_copydata(om, off, 16, uuid128);
-            TEST_ASSERT(rc == 0);
-            off += 16;
 
-            TEST_ASSERT(memcmp(uuid128, entry->uuid128, 16) == 0);
-        }
-    }
-
-    /* Ensure there is no extra data in the response. */
-    TEST_ASSERT(off == OS_MBUF_PKTHDR(om)->omp_len);
+    ble_hs_test_util_verify_tx_mtu_cmd(0, my_mtu);
 }
 
 struct ble_att_svr_test_type_value_entry {
@@ -584,75 +508,7 @@ ble_att_svr_test_misc_verify_tx_find_type_value_rsp(
     TEST_ASSERT(off == OS_MBUF_PKTHDR(om)->omp_len);
 }
 
-struct ble_att_svr_test_group_type_entry {
-    uint16_t start_handle;  /* 0 on last entry */
-    uint16_t end_handle;    /* 0 on last entry */
-    uint16_t uuid16;        /* 0 if not present. */
-    uint8_t uuid128[16];
-};
-
 /** Returns the number of entries successfully verified. */
-static void
-ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
-    struct ble_att_svr_test_group_type_entry *entries)
-{
-    struct ble_att_svr_test_group_type_entry *entry;
-    struct ble_att_read_group_type_rsp rsp;
-    struct os_mbuf *om;
-    uint16_t u16;
-    uint8_t uuid128[16];
-    int off;
-    int rc;
-
-    ble_hs_test_util_tx_all();
-
-    om = ble_hs_test_util_prev_tx_dequeue_pullup();
-
-    ble_att_read_group_type_rsp_parse(om->om_data, om->om_len, &rsp);
-
-    off = BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ;
-    for (entry = entries; entry->start_handle != 0; entry++) {
-        if (entry->uuid16 != 0) {
-            TEST_ASSERT(rsp.bagp_length ==
-                        BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16);
-        } else {
-            TEST_ASSERT(rsp.bagp_length ==
-                        BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128);
-        }
-
-        rc = os_mbuf_copydata(om, off, 2, &u16);
-        TEST_ASSERT(rc == 0);
-        htole16(&u16, u16);
-        TEST_ASSERT(u16 == entry->start_handle);
-        off += 2;
-
-        rc = os_mbuf_copydata(om, off, 2, &u16);
-        TEST_ASSERT(rc == 0);
-        htole16(&u16, u16);
-        if (entry->start_handle == BLE_ATT_SVR_TEST_LAST_SVC) {
-            TEST_ASSERT(u16 == 0xffff);
-        } else {
-            TEST_ASSERT(u16 == entry->end_handle);
-        }
-        off += 2;
-
-        if (entry->uuid16 != 0) {
-            rc = os_mbuf_copydata(om, off, 2, &u16);
-            TEST_ASSERT(rc == 0);
-            htole16(&u16, u16);
-            TEST_ASSERT(u16 == entry->uuid16);
-            off += 2;
-        } else {
-            rc = os_mbuf_copydata(om, off, 16, uuid128);
-            TEST_ASSERT(rc == 0);
-            TEST_ASSERT(memcmp(uuid128, entry->uuid128, 16) == 0);
-            off += 16;
-        }
-    }
-
-    /* Ensure there is no extra data in the response. */
-    TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
-}
 
 struct ble_att_svr_test_type_entry {
     uint16_t handle;  /* 0 on last entry */
@@ -1030,14 +886,14 @@ TEST_CASE(ble_att_svr_test_read_blob)
 
     rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle, 0);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
+    ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
                                                   BLE_ATT_MTU_DFLT - 1);
 
     /*** Read remainder of attribute. */
     rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle,
                                            BLE_ATT_MTU_DFLT - 1);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_blob_rsp(
+    ble_hs_test_util_verify_tx_read_blob_rsp(
         ble_att_svr_test_attr_r_1 + BLE_ATT_MTU_DFLT - 1,
         40 - (BLE_ATT_MTU_DFLT - 1));
 
@@ -1045,7 +901,7 @@ TEST_CASE(ble_att_svr_test_read_blob)
     rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, attr_handle,
                                            ble_att_svr_test_attr_r_1_len);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
+    ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_r_1,
                                                   0);
 }
 
@@ -1261,8 +1117,8 @@ TEST_CASE(ble_att_svr_test_find_info)
     /*** One 128-bit entry. */
     rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle1);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_find_info_rsp(
-        ((struct ble_att_svr_test_info_entry[]) { {
+    ble_hs_test_util_verify_tx_find_info_rsp(
+        ((struct ble_hs_test_util_att_info_entry[]) { {
             .handle = handle1,
             .uuid128 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
         }, {
@@ -1276,8 +1132,8 @@ TEST_CASE(ble_att_svr_test_find_info)
 
     rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle2);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_find_info_rsp(
-        ((struct ble_att_svr_test_info_entry[]) { {
+    ble_hs_test_util_verify_tx_find_info_rsp(
+        ((struct ble_hs_test_util_att_info_entry[]) { {
             .handle = handle1,
             .uuid128 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
         }, {
@@ -1294,8 +1150,8 @@ TEST_CASE(ble_att_svr_test_find_info)
 
     rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle3);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_find_info_rsp(
-        ((struct ble_att_svr_test_info_entry[]) { {
+    ble_hs_test_util_verify_tx_find_info_rsp(
+        ((struct ble_hs_test_util_att_info_entry[]) { {
             .handle = handle1,
             .uuid128 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
         }, {
@@ -1308,8 +1164,8 @@ TEST_CASE(ble_att_svr_test_find_info)
     /*** Remaining 16-bit entry requested. */
     rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle3, handle3);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_find_info_rsp(
-        ((struct ble_att_svr_test_info_entry[]) { {
+    ble_hs_test_util_verify_tx_find_info_rsp(
+        ((struct ble_hs_test_util_att_info_entry[]) { {
             .handle = handle3,
             .uuid16 = 0x000f,
         }, {
@@ -1670,8 +1526,8 @@ TEST_CASE(ble_att_svr_test_read_group_type)
     rc = ble_hs_test_util_rx_att_read_group_type_req16(
         conn_handle, 1, 5, BLE_ATT_UUID_PRIMARY_SERVICE);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
-        ((struct ble_att_svr_test_group_type_entry[]) { {
+    ble_hs_test_util_verify_tx_read_group_type_rsp(
+        ((struct ble_hs_test_util_att_group_type_entry[]) { {
             .start_handle = 1,
             .end_handle = 5,
             .uuid16 = 0x1122,
@@ -1683,8 +1539,8 @@ TEST_CASE(ble_att_svr_test_read_group_type)
     rc = ble_hs_test_util_rx_att_read_group_type_req16(
         conn_handle, 1, 10, BLE_ATT_UUID_PRIMARY_SERVICE);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
-        ((struct ble_att_svr_test_group_type_entry[]) { {
+    ble_hs_test_util_verify_tx_read_group_type_rsp(
+        ((struct ble_hs_test_util_att_group_type_entry[]) { {
             .start_handle = 1,
             .end_handle = 5,
             .uuid16 = 0x1122,
@@ -1700,8 +1556,8 @@ TEST_CASE(ble_att_svr_test_read_group_type)
     rc = ble_hs_test_util_rx_att_read_group_type_req16(
         conn_handle, 1, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
-        ((struct ble_att_svr_test_group_type_entry[]) { {
+    ble_hs_test_util_verify_tx_read_group_type_rsp(
+        ((struct ble_hs_test_util_att_group_type_entry[]) { {
             .start_handle = 1,
             .end_handle = 5,
             .uuid16 = 0x1122,
@@ -1717,10 +1573,10 @@ TEST_CASE(ble_att_svr_test_read_group_type)
     rc = ble_hs_test_util_rx_att_read_group_type_req16(
         conn_handle, 11, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
     TEST_ASSERT(rc == 0);
-    ble_att_svr_test_misc_verify_tx_read_group_type_rsp(
-        ((struct ble_att_svr_test_group_type_entry[]) { {
+    ble_hs_test_util_verify_tx_read_group_type_rsp(
+        ((struct ble_hs_test_util_att_group_type_entry[]) { {
             .start_handle = 11,
-            .end_handle = 19,
+            .end_handle = 0xffff,
             .uuid128 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},
         }, {
             .start_handle = 0,
@@ -1938,35 +1794,40 @@ TEST_CASE(ble_att_svr_test_oom)
 
     conn_handle = ble_att_svr_test_misc_init(0);
 
-    /* Register an attribute for incoming read commands. */
-    ble_att_svr_test_misc_register_uuid16(0x1234, HA_FLAG_PERM_RW, 1,
-                                          ble_att_svr_test_misc_attr_fn_w_1);
+    /* Register an attribute (primary service) for incoming read commands. */
+    ble_att_svr_test_misc_register_uuid16(BLE_ATT_UUID_PRIMARY_SERVICE,
+                                          HA_FLAG_PERM_RW, 1,
+                                          ble_att_svr_test_misc_attr_fn_rw_1);
+    ble_att_svr_test_attr_w_1_len = 2;
+    ble_att_svr_test_attr_w_1[0] = 0x12;
+    ble_att_svr_test_attr_w_1[1] = 0x34;
 
     /* Exhaust the msys pool.  Leave one mbuf for the forthcoming request. */
     oms = ble_hs_test_util_mbuf_alloc_all_but(1);
 
-    /*** MTU. */
+    /*** MTU; always respond affirmatively, even when no mbufs. */
 
     /* Receive a request. */
     rc = ble_hs_test_util_rx_att_mtu_cmd(conn_handle, 1, 100);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    /* Ensure we were able to send an error response. */
-    ble_hs_test_util_tx_all();
-    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_MTU_REQ, 0,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+    /* Ensure we were able to send a real response. */
+    ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle);
 
-    /*** Find information. */
+    /*** Find information; always respond affirmatively, even when no mbufs. */
     ble_hs_test_util_prev_tx_dequeue();
 
     /* Receive a request. */
     rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 1, 100);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    /* Ensure we were able to send an error response. */
+    /* Ensure we were able to send a real response. */
     ble_hs_test_util_tx_all();
-    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_FIND_INFO_REQ, 1,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+    ble_hs_test_util_verify_tx_find_info_rsp(
+        (struct ble_hs_test_util_att_info_entry[]) {
+            { .handle = 1, .uuid16 = BLE_ATT_UUID_PRIMARY_SERVICE },
+            { 0 },
+        });
 
     /*** Find by type value. */
     ble_hs_test_util_prev_tx_dequeue();
@@ -1981,42 +1842,42 @@ TEST_CASE(ble_att_svr_test_oom)
     ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_FIND_TYPE_VALUE_REQ, 1,
                                        BLE_ATT_ERR_INSUFFICIENT_RES);
 
-    /*** Read by type. */
+    /*** Read by type; always respond affirmatively, even when no mbufs. */
     ble_hs_test_util_prev_tx_dequeue();
 
     /* Receive a request. */
-    rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 1, 0xffff,
+    rc = ble_hs_test_util_rx_att_read_type_req16(conn_handle, 100, 0xffff,
                                                  BLE_ATT_UUID_PRIMARY_SERVICE);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
 
-    /* Ensure we were able to send an error response. */
+    /* Ensure we were able to send a non-OOM error response. */
     ble_hs_test_util_tx_all();
-    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_TYPE_REQ, 0,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_TYPE_REQ, 100,
+                                       BLE_ATT_ERR_ATTR_NOT_FOUND);
 
-    /*** Read. */
+    /*** Read; always respond affirmatively, even when no mbufs. */
     ble_hs_test_util_prev_tx_dequeue();
 
     /* Receive a request. */
     rc = ble_hs_test_util_rx_att_read_req(conn_handle, 1);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    /* Ensure we were able to send an error response. */
+    /* Ensure we were able to send a real response. */
     ble_hs_test_util_tx_all();
-    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_REQ, 1,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+    ble_hs_test_util_verify_tx_read_rsp(ble_att_svr_test_attr_w_1,
+                                        ble_att_svr_test_attr_w_1_len);
 
-    /*** Read blob. */
+    /*** Read blob; always respond affirmatively, even when no mbufs. */
     ble_hs_test_util_prev_tx_dequeue();
 
     /* Receive a request. */
     rc = ble_hs_test_util_rx_att_read_blob_req(conn_handle, 1, 0);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    /* Ensure we were able to send an error response. */
+    /* Ensure we were able to send a real response. */
     ble_hs_test_util_tx_all();
-    ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_BLOB_REQ, 1,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+    ble_hs_test_util_verify_tx_read_blob_rsp(ble_att_svr_test_attr_w_1,
+                                             ble_att_svr_test_attr_w_1_len);
 
 
     /*** Read multiple. */
@@ -2034,18 +1895,21 @@ TEST_CASE(ble_att_svr_test_oom)
                                        BLE_ATT_ERR_INSUFFICIENT_RES);
 
 
-    /*** Read multiple. */
+    /***
+     * Read by group type; always respond affirmatively, even when no
+     * mbufs.
+     */
     ble_hs_test_util_prev_tx_dequeue();
 
     /* Receive a request. */
     rc = ble_hs_test_util_rx_att_read_group_type_req16(
         conn_handle, 11, 100, BLE_ATT_UUID_PRIMARY_SERVICE);
-    TEST_ASSERT_FATAL(rc == BLE_HS_ENOMEM);
+    TEST_ASSERT_FATAL(rc == BLE_HS_ENOENT);
 
-    /* Ensure we were able to send an error response. */
+    /* Ensure we were able to send a non-OOM error response. */
     ble_hs_test_util_tx_all();
     ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_READ_GROUP_TYPE_REQ, 11,
-                                       BLE_ATT_ERR_INSUFFICIENT_RES);
+                                       BLE_ATT_ERR_ATTR_NOT_FOUND);
 
     /*** Write; always respond affirmatively, even when no mbufs. */
     ble_hs_test_util_prev_tx_dequeue();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/28c48007/net/nimble/host/test/src/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_test_util.c b/net/nimble/host/test/src/ble_hs_test_util.c
index ce7e2af..9515e02 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.c
+++ b/net/nimble/host/test/src/ble_hs_test_util.c
@@ -1526,6 +1526,122 @@ ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu)
 }
 
 void
+ble_hs_test_util_verify_tx_find_info_rsp(
+    struct ble_hs_test_util_att_info_entry *entries)
+{
+    struct ble_hs_test_util_att_info_entry *entry;
+    struct ble_att_find_info_rsp rsp;
+    struct os_mbuf *om;
+    uint16_t handle;
+    uint16_t uuid16;
+    uint8_t buf[BLE_ATT_FIND_INFO_RSP_BASE_SZ];
+    uint8_t uuid128[16];
+    int off;
+    int rc;
+
+    ble_hs_test_util_tx_all();
+
+    off = 0;
+
+    om = ble_hs_test_util_prev_tx_dequeue_pullup();
+
+    rc = os_mbuf_copydata(om, off, sizeof buf, buf);
+    TEST_ASSERT(rc == 0);
+    off += sizeof buf;
+
+    ble_att_find_info_rsp_parse(buf, sizeof buf, &rsp);
+
+    for (entry = entries; entry->handle != 0; entry++) {
+        rc = os_mbuf_copydata(om, off, 2, &handle);
+        TEST_ASSERT(rc == 0);
+        off += 2;
+
+        handle = le16toh((void *)&handle);
+        TEST_ASSERT(handle == entry->handle);
+
+        if (entry->uuid16 != 0) {
+            TEST_ASSERT(rsp.bafp_format ==
+                        BLE_ATT_FIND_INFO_RSP_FORMAT_16BIT);
+            rc = os_mbuf_copydata(om, off, 2, &uuid16);
+            TEST_ASSERT(rc == 0);
+            off += 2;
+
+            uuid16 = le16toh((void *)&uuid16);
+            TEST_ASSERT(uuid16 == entry->uuid16);
+        } else {
+            TEST_ASSERT(rsp.bafp_format ==
+                        BLE_ATT_FIND_INFO_RSP_FORMAT_128BIT);
+            rc = os_mbuf_copydata(om, off, 16, uuid128);
+            TEST_ASSERT(rc == 0);
+            off += 16;
+
+            TEST_ASSERT(memcmp(uuid128, entry->uuid128, 16) == 0);
+        }
+    }
+
+    /* Ensure there is no extra data in the response. */
+    TEST_ASSERT(off == OS_MBUF_PKTHDR(om)->omp_len);
+}
+
+void
+ble_hs_test_util_verify_tx_read_group_type_rsp(
+    struct ble_hs_test_util_att_group_type_entry *entries)
+{
+    struct ble_hs_test_util_att_group_type_entry *entry;
+    struct ble_att_read_group_type_rsp rsp;
+    struct os_mbuf *om;
+    uint16_t u16;
+    uint8_t uuid128[16];
+    int off;
+    int rc;
+
+    ble_hs_test_util_tx_all();
+
+    om = ble_hs_test_util_prev_tx_dequeue_pullup();
+
+    ble_att_read_group_type_rsp_parse(om->om_data, om->om_len, &rsp);
+
+    off = BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ;
+    for (entry = entries; entry->start_handle != 0; entry++) {
+        if (entry->uuid16 != 0) {
+            TEST_ASSERT(rsp.bagp_length ==
+                        BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16);
+        } else {
+            TEST_ASSERT(rsp.bagp_length ==
+                        BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128);
+        }
+
+        rc = os_mbuf_copydata(om, off, 2, &u16);
+        TEST_ASSERT(rc == 0);
+        htole16(&u16, u16);
+        TEST_ASSERT(u16 == entry->start_handle);
+        off += 2;
+
+        rc = os_mbuf_copydata(om, off, 2, &u16);
+        TEST_ASSERT(rc == 0);
+        htole16(&u16, u16);
+        TEST_ASSERT(u16 == entry->end_handle);
+        off += 2;
+
+        if (entry->uuid16 != 0) {
+            rc = os_mbuf_copydata(om, off, 2, &u16);
+            TEST_ASSERT(rc == 0);
+            htole16(&u16, u16);
+            TEST_ASSERT(u16 == entry->uuid16);
+            off += 2;
+        } else {
+            rc = os_mbuf_copydata(om, off, 16, uuid128);
+            TEST_ASSERT(rc == 0);
+            TEST_ASSERT(memcmp(uuid128, entry->uuid128, 16) == 0);
+            off += 16;
+        }
+    }
+
+    /* Ensure there is no extra data in the response. */
+    TEST_ASSERT(off == OS_MBUF_PKTLEN(om));
+}
+
+void
 ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
                                    uint8_t error_code)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/28c48007/net/nimble/host/test/src/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_test_util.h b/net/nimble/host/test/src/ble_hs_test_util.h
index ab214cb..35fbd7a 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.h
+++ b/net/nimble/host/test/src/ble_hs_test_util.h
@@ -54,6 +54,19 @@ struct ble_hs_test_util_mbuf_params {
     unsigned prep_list:1;
 };
 
+struct ble_hs_test_util_att_info_entry {
+    uint16_t handle;        /* 0 on last entry */
+    uint16_t uuid16;        /* 0 if not present. */
+    uint8_t uuid128[16];
+};
+
+struct ble_hs_test_util_att_group_type_entry {
+    uint16_t start_handle;  /* 0 on last entry */
+    uint16_t end_handle;    /* 0 on last entry */
+    uint16_t uuid16;        /* 0 if not present. */
+    uint8_t uuid128[16];
+};
+
 #define BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(handle, pb, len) \
     ((struct hci_data_hdr) {                            \
         .hdh_handle_pb_bc = ((handle)  << 0) |          \
@@ -217,7 +230,11 @@ 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_verify_tx_write_rsp(void);
+void ble_hs_test_util_verify_tx_find_info_rsp(
+    struct ble_hs_test_util_att_info_entry *entries);
 void ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu);
+void ble_hs_test_util_verify_tx_read_group_type_rsp(
+    struct ble_hs_test_util_att_group_type_entry *entries);
 void ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
                                         uint8_t error_code);
 uint8_t ble_hs_test_util_verify_tx_l2cap_update_req(