You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2025/02/25 15:30:17 UTC

(mynewt-nimble) branch master updated (25e54af0a -> f1379c78a)

This is an automated email from the ASF dual-hosted git repository.

andk pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


    from 25e54af0a nimble/ll: Make NRPA generation in active scan optional
     new e6f0aa124 nimble/ll: Fix transmitting fragmented HCI ACL data
     new f1379c78a nimble/ll: Fix HCI Number Of Completed Packets event

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 nimble/controller/include/controller/ble_ll_conn.h |  2 ++
 nimble/controller/src/ble_ll.c                     |  4 +--
 nimble/controller/src/ble_ll_conn.c                | 39 ++++++++++++++++++++--
 nimble/controller/src/ble_ll_conn_hci.c            |  6 +++-
 nimble/controller/src/ble_ll_dtm.c                 |  2 +-
 nimble/include/nimble/ble.h                        |  2 +-
 6 files changed, 47 insertions(+), 8 deletions(-)


(mynewt-nimble) 01/02: nimble/ll: Fix transmitting fragmented HCI ACL data

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit e6f0aa1243f6dbce21977f37203138efc01f1ae4
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Feb 20 18:04:30 2025 +0100

    nimble/ll: Fix transmitting fragmented HCI ACL data
    
    For whatever reason HCI ACL packets with empty payload are allowed, but
    at the same time we are not allowed to send and empty fragment with
    LLID=0b00 over the air. We need to wait for the 1st non-empty payload
    and "recombine" it with the empty payload(s) to form a proper payload
    with LLID=0b00.
    
    We don't really need to recombine payloads, instead we can just count
    and then discard initial empty payloads and the update non-empty payload
    accordingly.
    
    See Core 6.0, Vol 6, Part B, 2.4.1.
---
 nimble/controller/include/controller/ble_ll_conn.h |  1 +
 nimble/controller/src/ble_ll.c                     |  4 +--
 nimble/controller/src/ble_ll_conn.c                | 37 ++++++++++++++++++++--
 nimble/controller/src/ble_ll_dtm.c                 |  2 +-
 nimble/include/nimble/ble.h                        |  2 +-
 5 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index 1d29063bf..c0ba84afa 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -344,6 +344,7 @@ struct ble_ll_conn_sm
     /* Packet transmit queue */
     struct os_mbuf *cur_tx_pdu;
     STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq;
+    uint8_t conn_txq_num_zero_pkt;
 
     /* List entry for active/free connection pools */
     union {
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index 4e0a74c53..8c22c89fb 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -847,7 +847,7 @@ ble_ll_tx_pkt_in(void)
 
         /* Do some basic error checking */
         pb = handle & 0x3000;
-        if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) {
+        if ((pkthdr->omp_len != length) || (pb > 0x1000)) {
             /* This is a bad ACL packet. Count a stat and free it */
             STATS_INC(ble_ll_stats, bad_acl_hdr);
             os_mbuf_free_chain(om);
@@ -1548,7 +1548,7 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
 
     /* Set BLE transmit header */
     ble_hdr = BLE_MBUF_HDR_PTR(m);
-    ble_hdr->txinfo.flags = 0;
+    ble_hdr->txinfo.num_data_pkt = 0;
     ble_hdr->txinfo.offset = 0;
     ble_hdr->txinfo.pyld_len = pdulen;
     ble_hdr->txinfo.hdr_byte = hdr;
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 65ff4cb0d..dcaa3aae5 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -1301,7 +1301,7 @@ conn_tx_pdu:
         m->om_data = (uint8_t *)&empty_pdu;
         m->om_data += BLE_MBUF_MEMBLOCK_OVERHEAD;
         ble_hdr = &empty_pdu.ble_hdr;
-        ble_hdr->txinfo.flags = 0;
+        ble_hdr->txinfo.num_data_pkt = 0;
         ble_hdr->txinfo.offset = 0;
         ble_hdr->txinfo.pyld_len = 0;
     }
@@ -2034,6 +2034,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 
     /* Initialize transmit queue and ack/flow control elements */
     STAILQ_INIT(&connsm->conn_txq);
+    connsm->conn_txq_num_zero_pkt = 0;
     connsm->cur_tx_pdu = NULL;
     connsm->tx_seqnum = 0;
     connsm->next_exp_seqnum = 0;
@@ -3845,7 +3846,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
 #if (BLETEST_THROUGHPUT_TEST == 1)
                             bletest_completed_pkt(connsm->conn_handle);
 #endif
-                            ++connsm->completed_pkts;
+                            BLE_LL_ASSERT(txhdr->txinfo.num_data_pkt >= 1);
+                            connsm->completed_pkts += txhdr->txinfo.num_data_pkt;
                             if (connsm->completed_pkts > 2) {
                                 ble_ll_event_add(&g_ble_ll_data.ll_comp_pkt_ev);
                             }
@@ -3946,17 +3948,46 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
     os_sr_t sr;
     struct os_mbuf_pkthdr *pkthdr;
     struct ble_mbuf_hdr *ble_hdr;
+    uint8_t num_pkt;
     int lifo;
 
+    /* We cannot send empty payload with LLID=0b10. Instead, we need to wait for
+     * non-empty payload and combine it together. Since we don't really recombine
+     * fragments we just count number of consecutive empty payloads and use 1st
+     * non-empty as a start packet. Empty payloads can be freed immediately as
+     * we don't need to enqueue them.
+     *
+     * Reference: Core 6.0, Vol 6, Part B, 2.4.1
+     */
+    if ((length == 0) &&
+        ((hdr_byte == BLE_LL_LLID_DATA_START) || (connsm->conn_txq_num_zero_pkt > 0))) {
+        connsm->conn_txq_num_zero_pkt++;
+        os_mbuf_free_chain(om);
+        return;
+    }
+
     /* Set mbuf length and packet length if a control PDU */
     if (hdr_byte == BLE_LL_LLID_CTRL) {
         om->om_len = length;
         OS_MBUF_PKTHDR(om)->omp_len = length;
+        num_pkt = 0;
+    } else {
+        num_pkt = 1;
+
+        /* This is the 1st non-empty data fragment so adjust LLID accordingly.
+         * num_pkt is updated to make sure we send back proper numbber of
+         * completed packets back to host.
+         */
+        if (connsm->conn_txq_num_zero_pkt) {
+            hdr_byte = BLE_LL_LLID_DATA_START;
+            num_pkt += connsm->conn_txq_num_zero_pkt;
+            connsm->conn_txq_num_zero_pkt = 0;
+        }
     }
 
     /* Set BLE transmit header */
     ble_hdr = BLE_MBUF_HDR_PTR(om);
-    ble_hdr->txinfo.flags = 0;
+    ble_hdr->txinfo.num_data_pkt = num_pkt;
     ble_hdr->txinfo.offset = 0;
     ble_hdr->txinfo.hdr_byte = hdr_byte;
 
diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c
index c57a1357a..c7823e0f1 100644
--- a/nimble/controller/src/ble_ll_dtm.c
+++ b/nimble/controller/src/ble_ll_dtm.c
@@ -308,7 +308,7 @@ ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len,
 
     /* Set BLE transmit header */
     ble_hdr = BLE_MBUF_HDR_PTR(m);
-    ble_hdr->txinfo.flags = 0;
+    ble_hdr->txinfo.num_data_pkt = 0;
     ble_hdr->txinfo.offset = 0;
     ble_hdr->txinfo.pyld_len = len;
     ble_hdr->txinfo.hdr_byte = packet_payload;
diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h
index c42d5c5ba..a2add5d79 100644
--- a/nimble/include/nimble/ble.h
+++ b/nimble/include/nimble/ble.h
@@ -120,7 +120,7 @@ struct ble_mbuf_hdr_rxinfo
 /* Transmit info. NOTE: no flags defined */
 struct ble_mbuf_hdr_txinfo
 {
-    uint8_t flags;
+    uint8_t num_data_pkt;
     uint8_t hdr_byte;
     uint16_t offset;
     uint16_t pyld_len;


(mynewt-nimble) 02/02: nimble/ll: Fix HCI Number Of Completed Packets event

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit f1379c78a3829c9360f3e5d38906c4db7389df0e
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Feb 21 12:32:29 2025 +0100

    nimble/ll: Fix HCI Number Of Completed Packets event
    
    We can (and shall) keep sending nocp event with ncp=0 periodically but
    *only* if we have HCI data packets enqueued. Currently we check if txq
    is empty but that doesn't take into account that the only queued PDUs
    may be LL Control.
    
    This adds extra counter to track number of data PDUs queued in conn.
---
 nimble/controller/include/controller/ble_ll_conn.h | 1 +
 nimble/controller/src/ble_ll_conn.c                | 2 ++
 nimble/controller/src/ble_ll_conn_hci.c            | 6 +++++-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index c0ba84afa..347f4653e 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -344,6 +344,7 @@ struct ble_ll_conn_sm
     /* Packet transmit queue */
     struct os_mbuf *cur_tx_pdu;
     STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq;
+    uint8_t conn_txq_num_data_pkt;
     uint8_t conn_txq_num_zero_pkt;
 
     /* List entry for active/free connection pools */
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index dcaa3aae5..90d5a8cac 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -2034,6 +2034,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 
     /* Initialize transmit queue and ack/flow control elements */
     STAILQ_INIT(&connsm->conn_txq);
+    connsm->conn_txq_num_data_pkt = 0;
     connsm->conn_txq_num_zero_pkt = 0;
     connsm->cur_tx_pdu = NULL;
     connsm->tx_seqnum = 0;
@@ -4046,6 +4047,7 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
     } else {
         STAILQ_INSERT_TAIL(&connsm->conn_txq, pkthdr, omp_next);
     }
+    connsm->conn_txq_num_data_pkt += num_pkt;
     OS_EXIT_CRITICAL(sr);
 }
 
diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c
index 394db6f6b..fae4b31a9 100644
--- a/nimble/controller/src/ble_ll_conn_hci.c
+++ b/nimble/controller/src/ble_ll_conn_hci.c
@@ -310,6 +310,8 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm)
                 ev->completed[0].packets = htole16(connsm->completed_pkts);
                 hci_ev->length += sizeof(ev->completed[0]);
 
+                BLE_LL_ASSERT(connsm->conn_txq_num_data_pkt >= connsm->completed_pkts);
+                connsm->conn_txq_num_data_pkt -= connsm->completed_pkts;
                 connsm->completed_pkts = 0;
 
                 ble_ll_hci_event_send(hci_ev);
@@ -330,7 +332,7 @@ skip_conn:
          * event and that either has packets enqueued or has completed packets.
          */
         if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) &&
-            (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) {
+            (connsm->completed_pkts || connsm->conn_txq_num_data_pkt)) {
             /* If no buffer, get one, If cant get one, leave. */
             if (!hci_ev) {
                 hci_ev = ble_transport_alloc_evt(0);
@@ -351,6 +353,8 @@ skip_conn:
             hci_ev->length += sizeof(ev->completed[ev->count]);
             ev->count++;
 
+            BLE_LL_ASSERT(connsm->conn_txq_num_data_pkt >= connsm->completed_pkts);
+            connsm->conn_txq_num_data_pkt -= connsm->completed_pkts;
             connsm->completed_pkts = 0;
 
             /* Send now if the buffer is full. */