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/13 20:55:48 UTC
[35/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/develop
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);