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/11 23:50:37 UTC

[47/50] [abbrv] incubator-mynewt-core git commit: BLE Host - ACL data packet fragmentation.

BLE Host - ACL data packet fragmentation.


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/cd66efc0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/cd66efc0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/cd66efc0

Branch: refs/heads/ble_hs_api
Commit: cd66efc0120d6a8a26a4c62ac82869d0de9b0b6e
Parents: 4cb430a
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Jul 8 19:54:22 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Jul 11 16:43:35 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/src/ble_hci_priv.h          |   2 +
 net/nimble/host/src/ble_hci_util.c          |  19 ++++
 net/nimble/host/src/host_hci.c              | 138 +++++++++++++++++------
 net/nimble/host/src/test/ble_hs_test.c      |   2 -
 net/nimble/host/src/test/ble_hs_test_util.c |  58 +++++++++-
 net/nimble/host/src/test/ble_sm_test_util.c |   2 +-
 6 files changed, 179 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/net/nimble/host/src/ble_hci_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hci_priv.h b/net/nimble/host/src/ble_hci_priv.h
index 1526a20..7bc019f 100644
--- a/net/nimble/host/src/ble_hci_priv.h
+++ b/net/nimble/host/src/ble_hci_priv.h
@@ -45,5 +45,7 @@ int ble_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi);
 int ble_hci_util_set_random_addr(const uint8_t *addr);
 int ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
                               uint16_t tx_time);
+int ble_hci_util_data_hdr_strip(struct os_mbuf *om,
+                                struct hci_data_hdr *out_hdr);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/net/nimble/host/src/ble_hci_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hci_util.c b/net/nimble/host/src/ble_hci_util.c
index 3850903..caf36e2 100644
--- a/net/nimble/host/src/ble_hci_util.c
+++ b/net/nimble/host/src/ble_hci_util.c
@@ -157,3 +157,22 @@ ble_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
 
     return 0;
 }
+
+int
+ble_hci_util_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *out_hdr)
+{
+    int rc;
+
+    rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
+    if (rc != 0) {
+        return BLE_HS_ECONTROLLER;
+    }
+
+    /* Strip HCI ACL data header from the front of the packet. */
+    os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
+
+    out_hdr->hdh_handle_pb_bc = le16toh(&out_hdr->hdh_handle_pb_bc);
+    out_hdr->hdh_len = le16toh(&out_hdr->hdh_len);
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/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 29c71a1..b7b1bd1 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -677,24 +677,6 @@ ble_hci_transport_ctlr_event_send(uint8_t *hci_ev)
     return 0;
 }
 
-static int
-host_hci_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *hdr)
-{
-    int rc;
-
-    rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, hdr);
-    if (rc != 0) {
-        return BLE_HS_ECONTROLLER;
-    }
-
-    /* Strip HCI ACL data header from the front of the packet. */
-    os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);
-
-    hdr->hdh_handle_pb_bc = le16toh(&hdr->hdh_handle_pb_bc);
-    hdr->hdh_len = le16toh(&hdr->hdh_len);
-
-    return 0;
-}
 
 /**
  * Called when a data packet is received from the controller.  This function
@@ -715,7 +697,7 @@ host_hci_data_rx(struct os_mbuf *om)
     uint16_t handle;
     int rc;
 
-    rc = host_hci_data_hdr_strip(om, &hci_hdr);
+    rc = ble_hci_util_data_hdr_strip(om, &hci_hdr);
     if (rc == 0) {
 #if (BLETEST_THROUGHPUT_TEST == 0)
         BLE_HS_LOG(DEBUG, "host_hci_data_rx(): handle=%u pb=%x len=%u data=",
@@ -782,33 +764,121 @@ host_hci_data_hdr_prepend(struct os_mbuf *om, uint16_t handle, uint8_t pb_flag)
 }
 
 /**
+ * Splits an appropriately-sized fragment from the front of an outgoing ACL
+ * data packet, if necessary.  If the packet size is within the controller's
+ * buffer size requirements, no splitting is performed.  The fragment data is
+ * removed from the data packet mbuf.
+ *
+ * @param om                    The ACL data packet.
+ * @param out_frag              On success, this points to the fragment to
+ *                                  send.  If the entire packet can fit within
+ *                                  a single fragment, this will point to the
+ *                                  ACL data packet itself ('om').
+ *
+ * @return                      BLE_HS_EDONE: success; this is the final
+ *                                  fragment.
+ *                              BLE_HS_EAGAIN: success; more data remains in
+ *                                  the original mbuf.
+ *                              Other BLE host core return code on error.
+ */
+int
+host_hci_split_frag(struct os_mbuf *om, struct os_mbuf **out_frag)
+{
+    struct os_mbuf *frag;
+    int rc;
+
+    if (OS_MBUF_PKTLEN(om) <= host_hci_buffer_sz) {
+        /* Final fragment. */
+        *out_frag = om;
+        return BLE_HS_EDONE;
+    }
+
+    frag = os_msys_get_pkthdr(host_hci_buffer_sz, 0);
+    if (frag == NULL) {
+        rc = BLE_HS_ENOMEM;
+        goto err;
+    }
+
+    /* Move data from the front of the packet into the fragment mbuf. */
+    rc = os_mbuf_appendfrom(frag, om, 0, host_hci_buffer_sz);
+    if (rc != 0) {
+        rc = BLE_HS_ENOMEM;
+        goto err;
+    }
+    os_mbuf_adj(om, host_hci_buffer_sz);
+
+    /* More fragments to follow. */
+    *out_frag = frag;
+    return BLE_HS_EAGAIN;
+
+err:
+    os_mbuf_free_chain(frag);
+    return rc;
+}
+
+/**
  * Transmits an HCI ACL data packet.  This function consumes the supplied mbuf,
  * regardless of the outcome.
+ *
+ * XXX: Ensure the controller has sufficient buffer capacity for the outgoing
+ * fragments.
  */
 int
 host_hci_data_tx(struct ble_hs_conn *connection, struct os_mbuf *om)
 {
+    struct os_mbuf *frag;
+    uint8_t pb;
+    int done;
     int rc;
 
-    /* XXX: Different transport mechanisms have different fragmentation
-     * requirements.  For now, never fragment.
+    /* 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.
      */
-    om = host_hci_data_hdr_prepend(om, connection->bhc_handle,
-                                   BLE_HCI_PB_FIRST_NON_FLUSH);
-    if (om == NULL) {
-        return BLE_HS_ENOMEM;
-    }
+    pb = BLE_HCI_PB_FIRST_NON_FLUSH;
+
+    /* Send fragments until the entire packet has been sent. */
+    done = 0;
+    while (!done) {
+        rc = host_hci_split_frag(om, &frag);
+        switch (rc) {
+        case BLE_HS_EDONE:
+            /* This is the final fragment. */
+            done = 1;
+            break;
+
+        case BLE_HS_EAGAIN:
+            /* More fragments to follow. */
+            break;
+
+        default:
+            goto err;
+        }
+
+        frag = host_hci_data_hdr_prepend(frag, connection->bhc_handle, pb);
+        if (frag == NULL) {
+            rc = BLE_HS_ENOMEM;
+            goto err;
+        }
+        pb = BLE_HCI_PB_MIDDLE;
 
-    BLE_HS_LOG(DEBUG, "host_hci_data_tx(): ");
-    ble_hs_misc_log_mbuf(om);
-    BLE_HS_LOG(DEBUG, "\n");
+        BLE_HS_LOG(DEBUG, "host_hci_data_tx(): ");
+        ble_hs_misc_log_mbuf(frag);
+        BLE_HS_LOG(DEBUG, "\n");
 
-    rc = ble_hs_tx_data(om);
-    if (rc != 0) {
-        return rc;
-    }
+        rc = ble_hs_tx_data(frag);
+        if (rc != 0) {
+            goto err;
+        }
 
-    connection->bhc_outstanding_pkts++;
+        connection->bhc_outstanding_pkts++;
+    }
 
     return 0;
+
+err:
+    BLE_HS_DBG_ASSERT(rc != 0);
+
+    os_mbuf_free_chain(om);
+    return rc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/net/nimble/host/src/test/ble_hs_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test.c b/net/nimble/host/src/test/ble_hs_test.c
index feabb72..388d449 100644
--- a/net/nimble/host/src/test/ble_hs_test.c
+++ b/net/nimble/host/src/test/ble_hs_test.c
@@ -29,8 +29,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN] = { 0x0a, 0x54, 0xab, 0x49, 0x7f, 0x06 };
 void
 ble_hs_test_pkt_txed(struct os_mbuf *om)
 {
-    /* XXX: For now, just strip the HCI ACL data and L2CAP headers. */
-    os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ + BLE_L2CAP_HDR_SZ);
     ble_hs_test_util_prev_tx_enqueue(om);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/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 9723b90..895a608 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -82,20 +82,65 @@ ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om)
     }
 }
 
+static struct os_mbuf *
+ble_hs_test_util_prev_tx_dequeue_once(struct hci_data_hdr *out_hci_hdr)
+{
+    struct os_mbuf_pkthdr *omp;
+    struct os_mbuf *om;
+    int rc;
+
+    omp = STAILQ_FIRST(&ble_hs_test_util_prev_tx_queue);
+    if (omp == NULL) {
+        return NULL;
+    }
+    STAILQ_REMOVE_HEAD(&ble_hs_test_util_prev_tx_queue, omp_next);
+
+    om = OS_MBUF_PKTHDR_TO_MBUF(omp);
+
+    rc = ble_hci_util_data_hdr_strip(om, out_hci_hdr);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT_FATAL(out_hci_hdr->hdh_len == OS_MBUF_PKTLEN(om));
+
+    return om;
+}
+
 struct os_mbuf *
 ble_hs_test_util_prev_tx_dequeue(void)
 {
-    struct os_mbuf_pkthdr *omp;
+    struct ble_l2cap_hdr l2cap_hdr;
+    struct hci_data_hdr hci_hdr;
+    struct os_mbuf *om;
+    uint8_t pb;
+    int rc;
 
     os_mbuf_free_chain(ble_hs_test_util_prev_tx_cur);
 
-    omp = STAILQ_FIRST(&ble_hs_test_util_prev_tx_queue);
-    if (omp != NULL) {
-        STAILQ_REMOVE_HEAD(&ble_hs_test_util_prev_tx_queue, omp_next);
-        ble_hs_test_util_prev_tx_cur = OS_MBUF_PKTHDR_TO_MBUF(omp);
+    om = ble_hs_test_util_prev_tx_dequeue_once(&hci_hdr);
+    if (om != NULL) {
+        pb = BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc);
+        TEST_ASSERT_FATAL(pb == BLE_HCI_PB_FIRST_NON_FLUSH);
+
+        rc = ble_l2cap_parse_hdr(om, 0, &l2cap_hdr);
+        TEST_ASSERT_FATAL(rc == 0);
+
+        os_mbuf_adj(om, BLE_L2CAP_HDR_SZ);
+
+        ble_hs_test_util_prev_tx_cur = om;
+        while (OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx_cur) <
+               l2cap_hdr.blh_len) {
+
+            om = ble_hs_test_util_prev_tx_dequeue_once(&hci_hdr);
+            TEST_ASSERT_FATAL(om != NULL);
+
+            pb = BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc);
+            TEST_ASSERT_FATAL(pb == BLE_HCI_PB_MIDDLE);
+
+            os_mbuf_concat(ble_hs_test_util_prev_tx_cur, om);
+        }
     } else {
         ble_hs_test_util_prev_tx_cur = NULL;
     }
+
     return ble_hs_test_util_prev_tx_cur;
 }
 
@@ -963,4 +1008,7 @@ ble_hs_test_util_init(void)
     ble_hs_test_util_prev_hci_tx_clear();
 
     ble_hs_id_set_pub(g_dev_addr);
+
+    /* Use a very low buffer size (16) to test fragmentation. */
+    host_hci_set_buf_size(16, 64);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cd66efc0/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 57080dd..fae524a 100644
--- a/net/nimble/host/src/test/ble_sm_test_util.c
+++ b/net/nimble/host/src/test/ble_sm_test_util.c
@@ -638,7 +638,7 @@ ble_sm_test_util_verify_tx_hdr(uint8_t sm_op, uint16_t payload_len)
 {
     struct os_mbuf *om;
 
-    om = ble_hs_test_util_prev_tx_dequeue();
+    om = ble_hs_test_util_prev_tx_dequeue_pullup();
     TEST_ASSERT_FATAL(om != NULL);
 
     TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_SM_HDR_SZ + payload_len);